@pipeline-builder/pipeline-core 3.1.0

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 (54) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +32 -0
  3. package/lib/config/app-config.d.ts +81 -0
  4. package/lib/config/app-config.js +151 -0
  5. package/lib/config/billing-config.d.ts +17 -0
  6. package/lib/config/billing-config.js +95 -0
  7. package/lib/config/config-types.d.ts +213 -0
  8. package/lib/config/config-types.js +5 -0
  9. package/lib/config/infrastructure-config.d.ts +55 -0
  10. package/lib/config/infrastructure-config.js +200 -0
  11. package/lib/config/server-config.d.ts +53 -0
  12. package/lib/config/server-config.js +180 -0
  13. package/lib/core/artifact-manager.d.ts +62 -0
  14. package/lib/core/artifact-manager.js +86 -0
  15. package/lib/core/id-generator.d.ts +26 -0
  16. package/lib/core/id-generator.js +44 -0
  17. package/lib/core/metadata-builder.d.ts +13 -0
  18. package/lib/core/metadata-builder.js +81 -0
  19. package/lib/core/network-types.d.ts +200 -0
  20. package/lib/core/network-types.js +5 -0
  21. package/lib/core/network.d.ts +20 -0
  22. package/lib/core/network.js +84 -0
  23. package/lib/core/pipeline-helpers.d.ts +53 -0
  24. package/lib/core/pipeline-helpers.js +273 -0
  25. package/lib/core/pipeline-types.d.ts +136 -0
  26. package/lib/core/pipeline-types.js +140 -0
  27. package/lib/core/role-types.d.ts +254 -0
  28. package/lib/core/role-types.js +5 -0
  29. package/lib/core/role.d.ts +14 -0
  30. package/lib/core/role.js +118 -0
  31. package/lib/core/security-group-types.d.ts +84 -0
  32. package/lib/core/security-group-types.js +5 -0
  33. package/lib/core/security-group.d.ts +14 -0
  34. package/lib/core/security-group.js +34 -0
  35. package/lib/handlers/plugin-lookup-handler.d.ts +32 -0
  36. package/lib/handlers/plugin-lookup-handler.js +313 -0
  37. package/lib/handlers/pnpm-lock.yaml +12 -0
  38. package/lib/index.d.ts +54 -0
  39. package/lib/index.js +112 -0
  40. package/lib/pipeline/pipeline-builder.d.ts +82 -0
  41. package/lib/pipeline/pipeline-builder.js +292 -0
  42. package/lib/pipeline/pipeline-configuration.d.ts +72 -0
  43. package/lib/pipeline/pipeline-configuration.js +196 -0
  44. package/lib/pipeline/plugin-lookup.d.ts +100 -0
  45. package/lib/pipeline/plugin-lookup.js +247 -0
  46. package/lib/pipeline/source-builder.d.ts +47 -0
  47. package/lib/pipeline/source-builder.js +111 -0
  48. package/lib/pipeline/source-types.d.ts +191 -0
  49. package/lib/pipeline/source-types.js +5 -0
  50. package/lib/pipeline/stage-builder.d.ts +71 -0
  51. package/lib/pipeline/stage-builder.js +118 -0
  52. package/lib/pipeline/step-types.d.ts +307 -0
  53. package/lib/pipeline/step-types.js +5 -0
  54. package/package.json +137 -0
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ // Copyright 2026 Pipeline Builder Contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.handler = void 0;
39
+ exports._resetCredentialsCache = _resetCredentialsCache;
40
+ const client_secrets_manager_1 = require("@aws-sdk/client-secrets-manager");
41
+ const axios_1 = __importStar(require("axios"));
42
+ const app_config_1 = require("../config/app-config");
43
+ /**
44
+ * Structured logger for Lambda (outputs JSON to CloudWatch).
45
+ * Debug messages only emitted when LOG_LEVEL=debug.
46
+ */
47
+ function logEntry(level, tag, message, data) {
48
+ const line = JSON.stringify({ level, tag, message, data, ts: new Date().toISOString() });
49
+ switch (level) {
50
+ case 'ERROR':
51
+ console.error(line);
52
+ break;
53
+ case 'DEBUG':
54
+ if (process.env.LOG_LEVEL === 'debug')
55
+ console.debug(line);
56
+ break;
57
+ default: console.log(line);
58
+ }
59
+ }
60
+ const lambdaLog = {
61
+ info: (tag, message, data) => logEntry('INFO', tag, message, data),
62
+ error: (tag, message, data) => logEntry('ERROR', tag, message, data),
63
+ debug: (tag, message, data) => logEntry('DEBUG', tag, message, data),
64
+ };
65
+ const RETRYABLE_STATUSES = new Set([429, 502, 503, 504]);
66
+ const RETRYABLE_CODES = new Set(['ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT']);
67
+ function sleep(ms) {
68
+ return new Promise(resolve => setTimeout(resolve, ms));
69
+ }
70
+ /** Platform secret name — injected as PLATFORM_SECRET_NAME env var by PluginLookup construct. */
71
+ const PLATFORM_SECRET_NAME = process.env.PLATFORM_SECRET_NAME;
72
+ if (!PLATFORM_SECRET_NAME) {
73
+ throw new Error('PLATFORM_SECRET_NAME environment variable is required');
74
+ }
75
+ /** Cached token to avoid repeated Secrets Manager calls within a single invocation. */
76
+ let cachedToken = null;
77
+ /** @internal Reset cached token (for testing only). */
78
+ function _resetCredentialsCache() { cachedToken = null; }
79
+ /**
80
+ * Fetch JWT token from AWS Secrets Manager.
81
+ * Caches the result for the lifetime of the Lambda execution context.
82
+ *
83
+ * The secret name is set via PLATFORM_SECRET_NAME env var (e.g. `{prefix}/{orgId}/platform`)
84
+ * Create it with: `pipeline-manager store-token`
85
+ */
86
+ async function getToken() {
87
+ if (cachedToken)
88
+ return cachedToken;
89
+ lambdaLog.info('AUTH', `Fetching token from Secrets Manager: ${PLATFORM_SECRET_NAME}`);
90
+ const client = new client_secrets_manager_1.SecretsManagerClient({});
91
+ const response = await client.send(new client_secrets_manager_1.GetSecretValueCommand({ SecretId: PLATFORM_SECRET_NAME }));
92
+ if (!response.SecretString) {
93
+ throw new Error(`Secret "${PLATFORM_SECRET_NAME}" is empty`);
94
+ }
95
+ const parsed = JSON.parse(response.SecretString);
96
+ if (!parsed.accessToken) {
97
+ throw new Error(`Secret "${PLATFORM_SECRET_NAME}" missing accessToken — run "pipeline-manager store-token" to generate`);
98
+ }
99
+ cachedToken = parsed.accessToken;
100
+ lambdaLog.info('AUTH', 'Token retrieved from Secrets Manager');
101
+ return cachedToken;
102
+ }
103
+ /**
104
+ * Creates a pre-configured Axios instance for API requests.
105
+ *
106
+ * @param baseURL - Base URL of the target API
107
+ * @param token - JWT token for authorization
108
+ * @returns Configured Axios instance
109
+ */
110
+ function create(baseURL, token) {
111
+ return axios_1.default.create({
112
+ baseURL,
113
+ timeout: app_config_1.CoreConstants.HANDLER_TIMEOUT_MS,
114
+ headers: {
115
+ 'Content-Type': 'application/json',
116
+ 'Authorization': `Bearer ${token}`,
117
+ },
118
+ });
119
+ }
120
+ /**
121
+ * Fetches plugin configuration from the external API with retry logic.
122
+ * Retries on transient failures (429, 502, 503, 504, network errors)
123
+ * with exponential backoff.
124
+ *
125
+ * @param api - Configured Axios instance
126
+ * @param pluginFilter - Filter criteria for the plugin lookup
127
+ * @returns The plugin data returned by the API
128
+ * @throws Error on persistent failure, timeout or invalid response
129
+ */
130
+ async function fetch(api, pluginFilter) {
131
+ lambdaLog.debug('FETCH', 'Starting plugin fetch', { filter: pluginFilter });
132
+ let lastError;
133
+ for (let attempt = 0; attempt <= app_config_1.CoreConstants.HANDLER_MAX_RETRIES; attempt++) {
134
+ if (attempt > 0) {
135
+ const delay = app_config_1.CoreConstants.HANDLER_RETRY_DELAY_MS * Math.pow(2, attempt - 1);
136
+ lambdaLog.info('RETRY', `Attempt ${attempt + 1}/${app_config_1.CoreConstants.HANDLER_MAX_RETRIES + 1} after ${delay}ms`);
137
+ await sleep(delay);
138
+ }
139
+ try {
140
+ const { data, status } = await api.post('/api/plugins/lookup', {
141
+ filter: pluginFilter,
142
+ });
143
+ if (!data) {
144
+ throw new Error('Empty response data from API');
145
+ }
146
+ lambdaLog.info('FETCH', 'Plugin fetched successfully', {
147
+ status,
148
+ plugin: data.name,
149
+ version: data.version,
150
+ id: data.id,
151
+ });
152
+ return data;
153
+ }
154
+ catch (error) {
155
+ if (error instanceof axios_1.AxiosError) {
156
+ if (error.code === 'ECONNABORTED') {
157
+ lambdaLog.error('FETCH', `Plugin lookup timed out after ${app_config_1.CoreConstants.HANDLER_TIMEOUT_MS}ms`);
158
+ throw new Error(`Plugin lookup timed out after ${app_config_1.CoreConstants.HANDLER_TIMEOUT_MS}ms`);
159
+ }
160
+ const retryable = error.response
161
+ ? RETRYABLE_STATUSES.has(error.response.status)
162
+ : RETRYABLE_CODES.has(error.code ?? '');
163
+ const msg = error.response
164
+ ? `API error ${error.response.status}: ${error.response.statusText}`
165
+ : error.code || error.message;
166
+ if (retryable && attempt < app_config_1.CoreConstants.HANDLER_MAX_RETRIES) {
167
+ lambdaLog.info('RETRY', `Retryable error: ${msg}`, { attempt: attempt + 1 });
168
+ lastError = new Error(`Failed to fetch plugin: ${msg}`);
169
+ continue;
170
+ }
171
+ lambdaLog.error('FETCH', msg, { responseData: error.response?.data });
172
+ throw new Error(`Failed to fetch plugin: ${msg}`);
173
+ }
174
+ throw error instanceof Error ? error : new Error('Unknown error during plugin fetch');
175
+ }
176
+ }
177
+ throw lastError ?? new Error('Failed to fetch plugin after retries');
178
+ }
179
+ /**
180
+ * Validates the plugin filter object
181
+ *
182
+ * @param pluginFilter - Filter to validate
183
+ * @returns true if valid
184
+ * @throws Error if invalid
185
+ */
186
+ function validatePluginFilter(pluginFilter) {
187
+ if (!pluginFilter || typeof pluginFilter !== 'object') {
188
+ throw new Error('Missing or invalid pluginFilter');
189
+ }
190
+ const filter = pluginFilter;
191
+ if (!filter.name && !filter.id && !filter.version && !filter.orgId) {
192
+ throw new Error('PluginFilter must have at least one criterion (name, id, version, or orgId)');
193
+ }
194
+ return true;
195
+ }
196
+ /**
197
+ * Lambda handler for CloudFormation Custom Resource that performs plugin lookup.
198
+ *
199
+ * Authenticates using JWT token from AWS Secrets Manager (PLATFORM_SECRET_NAME env var).
200
+ * Create the secret with: `pipeline-manager store-token`
201
+ *
202
+ * Request Types:
203
+ * - Create/Update: fetches and returns plugin configuration from API
204
+ * - Delete: no-op (always succeeds)
205
+ *
206
+ * Response:
207
+ * - Success: Returns base64-encoded plugin JSON in Data.ResultValue
208
+ * - Failure: Returns error message in Reason
209
+ *
210
+ * @param event - CloudFormation custom resource event
211
+ * @returns CloudFormation response
212
+ *
213
+ * @example
214
+ * Custom Resource Properties:
215
+ * ```json
216
+ * {
217
+ * "baseURL": "https://api.example.com",
218
+ * "pluginFilter": {
219
+ * "name": "nodejs-build",
220
+ * "version": "1.0.0",
221
+ * "isActive": true
222
+ * }
223
+ * }
224
+ * ```
225
+ */
226
+ const handler = async (event) => {
227
+ lambdaLog.info('START', `${event.RequestType} request received`, {
228
+ logicalResourceId: event.LogicalResourceId,
229
+ requestId: event.RequestId,
230
+ stackId: event.StackId,
231
+ });
232
+ const baseResponse = {
233
+ StackId: event.StackId,
234
+ RequestId: event.RequestId,
235
+ LogicalResourceId: event.LogicalResourceId,
236
+ PhysicalResourceId: event.LogicalResourceId,
237
+ };
238
+ try {
239
+ // Handle Delete - always succeed (no-op)
240
+ if (event.RequestType === 'Delete') {
241
+ lambdaLog.info('DELETE', 'No-op - returning SUCCESS');
242
+ return {
243
+ ...baseResponse,
244
+ Status: 'SUCCESS',
245
+ Reason: 'Delete completed (no-op)',
246
+ };
247
+ }
248
+ // Extract and validate properties
249
+ const pluginFilter = event.ResourceProperties.pluginFilter;
250
+ const baseURL = event.ResourceProperties.baseURL || app_config_1.CoreConstants.HANDLER_DEFAULT_BASE_URL;
251
+ if (!baseURL.startsWith('https://') && !baseURL.startsWith('http://')) {
252
+ throw new Error(`Invalid baseURL: "${baseURL}" — must start with http:// or https://`);
253
+ }
254
+ lambdaLog.info('CONFIG', 'Configuration loaded', { baseURL, pluginFilter });
255
+ validatePluginFilter(pluginFilter);
256
+ // Get token from Secrets Manager and create API client
257
+ const token = await getToken();
258
+ const api = create(baseURL, token);
259
+ // Fetch plugin
260
+ lambdaLog.info('FETCH', 'Initiating plugin lookup...');
261
+ const plugin = await fetch(api, pluginFilter);
262
+ lambdaLog.info('FETCH', 'Plugin retrieved successfully', {
263
+ name: plugin.name,
264
+ version: plugin.version,
265
+ id: plugin.id,
266
+ });
267
+ // Strip large fields to stay within CloudFormation's 4096-byte Data limit.
268
+ // CDK constructs only need the fields used by createCodeBuildStep().
269
+ const slim = {
270
+ id: plugin.id,
271
+ name: plugin.name,
272
+ version: plugin.version,
273
+ pluginType: plugin.pluginType,
274
+ computeType: plugin.computeType,
275
+ commands: plugin.commands,
276
+ installCommands: plugin.installCommands,
277
+ env: plugin.env,
278
+ metadata: plugin.metadata,
279
+ primaryOutputDirectory: plugin.primaryOutputDirectory,
280
+ secrets: plugin.secrets,
281
+ failureBehavior: plugin.failureBehavior,
282
+ timeout: plugin.timeout,
283
+ imageTag: plugin.imageTag,
284
+ };
285
+ const encoded = Buffer.from(JSON.stringify(slim), 'utf-8').toString('base64');
286
+ lambdaLog.debug('ENCODE', 'Encoded plugin data', { length: encoded.length });
287
+ return {
288
+ ...baseResponse,
289
+ Status: 'SUCCESS',
290
+ Reason: `Plugin '${plugin.name}' (v${plugin.version}) retrieved successfully`,
291
+ Data: {
292
+ ResultValue: encoded,
293
+ },
294
+ };
295
+ }
296
+ catch (error) {
297
+ const reason = error instanceof Error ? error.message : 'Unexpected error occurred';
298
+ lambdaLog.error('ERROR', 'Handler failed', {
299
+ reason,
300
+ stack: error instanceof Error ? error.stack : undefined,
301
+ });
302
+ return {
303
+ ...baseResponse,
304
+ Status: 'FAILED',
305
+ Reason: reason,
306
+ };
307
+ }
308
+ finally {
309
+ lambdaLog.info('END', 'Custom resource execution completed');
310
+ }
311
+ };
312
+ exports.handler = handler;
313
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWxvb2t1cC1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hhbmRsZXJzL3BsdWdpbi1sb29rdXAtaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQStDO0FBQy9DLHNDQUFzQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNEN0Qyx3REFBc0U7QUExQ3RFLDRFQUE4RjtBQUc5RiwrQ0FBeUQ7QUFDekQscURBQXFEO0FBRXJEOzs7R0FHRztBQUNILFNBQVMsUUFBUSxDQUFDLEtBQWEsRUFBRSxHQUFXLEVBQUUsT0FBZSxFQUFFLElBQWM7SUFDM0UsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDekYsUUFBUSxLQUFLLEVBQUUsQ0FBQztRQUNkLEtBQUssT0FBTztZQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFBQyxNQUFNO1FBQ3pDLEtBQUssT0FBTztZQUFFLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxTQUFTLEtBQUssT0FBTztnQkFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQUMsTUFBTTtRQUNoRixPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLENBQUM7QUFDSCxDQUFDO0FBRUQsTUFBTSxTQUFTLEdBQUc7SUFDaEIsSUFBSSxFQUFFLENBQUMsR0FBVyxFQUFFLE9BQWUsRUFBRSxJQUFjLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUM7SUFDNUYsS0FBSyxFQUFFLENBQUMsR0FBVyxFQUFFLE9BQWUsRUFBRSxJQUFjLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUM7SUFDOUYsS0FBSyxFQUFFLENBQUMsR0FBVyxFQUFFLE9BQWUsRUFBRSxJQUFjLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUM7Q0FDL0YsQ0FBQztBQUVGLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQ3pELE1BQU0sZUFBZSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsWUFBWSxFQUFFLGNBQWMsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO0FBRTdFLFNBQVMsS0FBSyxDQUFDLEVBQVU7SUFDdkIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUN6RCxDQUFDO0FBRUQsaUdBQWlHO0FBQ2pHLE1BQU0sb0JBQW9CLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQztBQUM5RCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztJQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7QUFDM0UsQ0FBQztBQUVELHVGQUF1RjtBQUN2RixJQUFJLFdBQVcsR0FBa0IsSUFBSSxDQUFDO0FBRXRDLHVEQUF1RDtBQUN2RCxTQUFnQixzQkFBc0IsS0FBVyxXQUFXLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUV0RTs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsUUFBUTtJQUNyQixJQUFJLFdBQVc7UUFBRSxPQUFPLFdBQVcsQ0FBQztJQUVwQyxTQUFTLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSx3Q0FBd0Msb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO0lBRXZGLE1BQU0sTUFBTSxHQUFHLElBQUksNkNBQW9CLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksOENBQXFCLENBQUMsRUFBRSxRQUFRLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFbEcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLFdBQVcsb0JBQW9CLFlBQVksQ0FBQyxDQUFDO0lBQy9ELENBQUM7SUFFRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQTJCLENBQUM7SUFDM0UsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLFdBQVcsb0JBQW9CLHdFQUF3RSxDQUFDLENBQUM7SUFDM0gsQ0FBQztJQUVELFdBQVcsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDO0lBQ2pDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLHNDQUFzQyxDQUFDLENBQUM7SUFDL0QsT0FBTyxXQUFXLENBQUM7QUFDckIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsTUFBTSxDQUFDLE9BQWUsRUFBRSxLQUFhO0lBQzVDLE9BQU8sZUFBSyxDQUFDLE1BQU0sQ0FBQztRQUNsQixPQUFPO1FBQ1AsT0FBTyxFQUFFLDBCQUFhLENBQUMsa0JBQWtCO1FBQ3pDLE9BQU8sRUFBRTtZQUNQLGNBQWMsRUFBRSxrQkFBa0I7WUFDbEMsZUFBZSxFQUFFLFVBQVUsS0FBSyxFQUFFO1NBQ25DO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILEtBQUssVUFBVSxLQUFLLENBQUMsR0FBa0IsRUFBRSxZQUEwQjtJQUNqRSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO0lBRTVFLElBQUksU0FBNEIsQ0FBQztJQUVqQyxLQUFLLElBQUksT0FBTyxHQUFHLENBQUMsRUFBRSxPQUFPLElBQUksMEJBQWEsQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQzlFLElBQUksT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2hCLE1BQU0sS0FBSyxHQUFHLDBCQUFhLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzlFLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFdBQVcsT0FBTyxHQUFHLENBQUMsSUFBSSwwQkFBYSxDQUFDLG1CQUFtQixHQUFHLENBQUMsVUFBVSxLQUFLLElBQUksQ0FBQyxDQUFDO1lBQzVHLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3JCLENBQUM7UUFFRCxJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBUyxxQkFBcUIsRUFBRTtnQkFDckUsTUFBTSxFQUFFLFlBQVk7YUFDckIsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztZQUNsRCxDQUFDO1lBRUQsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsNkJBQTZCLEVBQUU7Z0JBQ3JELE1BQU07Z0JBQ04sTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJO2dCQUNqQixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU87Z0JBQ3JCLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTthQUNaLENBQUMsQ0FBQztZQUVILE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixJQUFJLEtBQUssWUFBWSxrQkFBVSxFQUFFLENBQUM7Z0JBQ2hDLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxjQUFjLEVBQUUsQ0FBQztvQkFDbEMsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsaUNBQWlDLDBCQUFhLENBQUMsa0JBQWtCLElBQUksQ0FBQyxDQUFDO29CQUNoRyxNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQywwQkFBYSxDQUFDLGtCQUFrQixJQUFJLENBQUMsQ0FBQztnQkFDekYsQ0FBQztnQkFFRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsUUFBUTtvQkFDOUIsQ0FBQyxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztvQkFDL0MsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztnQkFFMUMsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLFFBQVE7b0JBQ3hCLENBQUMsQ0FBQyxhQUFhLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLEtBQUssQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFO29CQUNwRSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDO2dCQUVoQyxJQUFJLFNBQVMsSUFBSSxPQUFPLEdBQUcsMEJBQWEsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO29CQUM3RCxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxvQkFBb0IsR0FBRyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQzdFLFNBQVMsR0FBRyxJQUFJLEtBQUssQ0FBQywyQkFBMkIsR0FBRyxFQUFFLENBQUMsQ0FBQztvQkFDeEQsU0FBUztnQkFDWCxDQUFDO2dCQUVELFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ3RFLE1BQU0sSUFBSSxLQUFLLENBQUMsMkJBQTJCLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDcEQsQ0FBQztZQUVELE1BQU0sS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO1FBQ3hGLENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxTQUFTLElBQUksSUFBSSxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQztBQUN2RSxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBUyxvQkFBb0IsQ0FBQyxZQUFxQjtJQUNqRCxJQUFJLENBQUMsWUFBWSxJQUFJLE9BQU8sWUFBWSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3RELE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsWUFBdUMsQ0FBQztJQUN2RCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ25FLE1BQU0sSUFBSSxLQUFLLENBQUMsNkVBQTZFLENBQUMsQ0FBQztJQUNqRyxDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNkJHO0FBQ0ksTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUMxQixLQUF3QyxFQUNPLEVBQUU7SUFDakQsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUMsV0FBVyxtQkFBbUIsRUFBRTtRQUMvRCxpQkFBaUIsRUFBRSxLQUFLLENBQUMsaUJBQWlCO1FBQzFDLFNBQVMsRUFBRSxLQUFLLENBQUMsU0FBUztRQUMxQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87S0FDdkIsQ0FBQyxDQUFDO0lBRUgsTUFBTSxZQUFZLEdBQWtEO1FBQ2xFLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztRQUN0QixTQUFTLEVBQUUsS0FBSyxDQUFDLFNBQVM7UUFDMUIsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtRQUMxQyxrQkFBa0IsRUFBRSxLQUFLLENBQUMsaUJBQWlCO0tBQzVDLENBQUM7SUFFRixJQUFJLENBQUM7UUFDSCx5Q0FBeUM7UUFDekMsSUFBSSxLQUFLLENBQUMsV0FBVyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ25DLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLDJCQUEyQixDQUFDLENBQUM7WUFDdEQsT0FBTztnQkFDTCxHQUFHLFlBQVk7Z0JBQ2YsTUFBTSxFQUFFLFNBQVM7Z0JBQ2pCLE1BQU0sRUFBRSwwQkFBMEI7YUFDSyxDQUFDO1FBQzVDLENBQUM7UUFFRCxrQ0FBa0M7UUFDbEMsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLGtCQUFrQixDQUFDLFlBQVksQ0FBQztRQUMzRCxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsT0FBTyxJQUFJLDBCQUFhLENBQUMsd0JBQXdCLENBQUM7UUFFM0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDdEUsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsT0FBTyx5Q0FBeUMsQ0FBQyxDQUFDO1FBQ3pGLENBQUM7UUFFRCxTQUFTLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxzQkFBc0IsRUFBRSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsQ0FBQyxDQUFDO1FBRTVFLG9CQUFvQixDQUFDLFlBQVksQ0FBQyxDQUFDO1FBRW5DLHVEQUF1RDtRQUN2RCxNQUFNLEtBQUssR0FBRyxNQUFNLFFBQVEsRUFBRSxDQUFDO1FBQy9CLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFbkMsZUFBZTtRQUNmLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLDZCQUE2QixDQUFDLENBQUM7UUFDdkQsTUFBTSxNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzlDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLCtCQUErQixFQUFFO1lBQ3ZELElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtZQUNqQixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87WUFDdkIsRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFO1NBQ2QsQ0FBQyxDQUFDO1FBRUgsMkVBQTJFO1FBQzNFLHFFQUFxRTtRQUNyRSxNQUFNLElBQUksR0FBRztZQUNYLEVBQUUsRUFBRSxNQUFNLENBQUMsRUFBRTtZQUNiLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtZQUNqQixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87WUFDdkIsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO1lBQzdCLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztZQUMvQixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVE7WUFDekIsZUFBZSxFQUFFLE1BQU0sQ0FBQyxlQUFlO1lBQ3ZDLEdBQUcsRUFBRSxNQUFNLENBQUMsR0FBRztZQUNmLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtZQUN6QixzQkFBc0IsRUFBRSxNQUFNLENBQUMsc0JBQXNCO1lBQ3JELE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztZQUN2QixlQUFlLEVBQUUsTUFBTSxDQUFDLGVBQWU7WUFDdkMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO1lBQ3ZCLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtTQUMxQixDQUFDO1FBRUYsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM5RSxTQUFTLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxxQkFBcUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUU3RSxPQUFPO1lBQ0wsR0FBRyxZQUFZO1lBQ2YsTUFBTSxFQUFFLFNBQVM7WUFDakIsTUFBTSxFQUFFLFdBQVcsTUFBTSxDQUFDLElBQUksT0FBTyxNQUFNLENBQUMsT0FBTywwQkFBMEI7WUFDN0UsSUFBSSxFQUFFO2dCQUNKLFdBQVcsRUFBRSxPQUFPO2FBQ3JCO1NBQ3NDLENBQUM7SUFDNUMsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLE1BQU0sR0FBRyxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQywyQkFBMkIsQ0FBQztRQUNwRixTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRTtZQUN6QyxNQUFNO1lBQ04sS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVM7U0FDeEQsQ0FBQyxDQUFDO1FBRUgsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLE1BQU0sRUFBRSxRQUFRO1lBQ2hCLE1BQU0sRUFBRSxNQUFNO1NBQ3lCLENBQUM7SUFDNUMsQ0FBQztZQUFTLENBQUM7UUFDVCxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxxQ0FBcUMsQ0FBQyxDQUFDO0lBQy9ELENBQUM7QUFDSCxDQUFDLENBQUM7QUFqR1csUUFBQSxPQUFPLFdBaUdsQiIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBHZXRTZWNyZXRWYWx1ZUNvbW1hbmQsIFNlY3JldHNNYW5hZ2VyQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXNlY3JldHMtbWFuYWdlcic7XG5pbXBvcnQgeyBQbHVnaW5GaWx0ZXIsIFBsdWdpbiB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWRhdGEnO1xuaW1wb3J0IHsgQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LCBDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlUmVzcG9uc2UgfSBmcm9tICdhd3MtbGFtYmRhJztcbmltcG9ydCBheGlvcywgeyBBeGlvc0luc3RhbmNlLCBBeGlvc0Vycm9yIH0gZnJvbSAnYXhpb3MnO1xuaW1wb3J0IHsgQ29yZUNvbnN0YW50cyB9IGZyb20gJy4uL2NvbmZpZy9hcHAtY29uZmlnJztcblxuLyoqXG4gKiBTdHJ1Y3R1cmVkIGxvZ2dlciBmb3IgTGFtYmRhIChvdXRwdXRzIEpTT04gdG8gQ2xvdWRXYXRjaCkuXG4gKiBEZWJ1ZyBtZXNzYWdlcyBvbmx5IGVtaXR0ZWQgd2hlbiBMT0dfTEVWRUw9ZGVidWcuXG4gKi9cbmZ1bmN0aW9uIGxvZ0VudHJ5KGxldmVsOiBzdHJpbmcsIHRhZzogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcsIGRhdGE/OiB1bmtub3duKSB7XG4gIGNvbnN0IGxpbmUgPSBKU09OLnN0cmluZ2lmeSh7IGxldmVsLCB0YWcsIG1lc3NhZ2UsIGRhdGEsIHRzOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkgfSk7XG4gIHN3aXRjaCAobGV2ZWwpIHtcbiAgICBjYXNlICdFUlJPUic6IGNvbnNvbGUuZXJyb3IobGluZSk7IGJyZWFrO1xuICAgIGNhc2UgJ0RFQlVHJzogaWYgKHByb2Nlc3MuZW52LkxPR19MRVZFTCA9PT0gJ2RlYnVnJykgY29uc29sZS5kZWJ1ZyhsaW5lKTsgYnJlYWs7XG4gICAgZGVmYXVsdDogY29uc29sZS5sb2cobGluZSk7XG4gIH1cbn1cblxuY29uc3QgbGFtYmRhTG9nID0ge1xuICBpbmZvOiAodGFnOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IHVua25vd24pID0+IGxvZ0VudHJ5KCdJTkZPJywgdGFnLCBtZXNzYWdlLCBkYXRhKSxcbiAgZXJyb3I6ICh0YWc6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogdW5rbm93bikgPT4gbG9nRW50cnkoJ0VSUk9SJywgdGFnLCBtZXNzYWdlLCBkYXRhKSxcbiAgZGVidWc6ICh0YWc6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogdW5rbm93bikgPT4gbG9nRW50cnkoJ0RFQlVHJywgdGFnLCBtZXNzYWdlLCBkYXRhKSxcbn07XG5cbmNvbnN0IFJFVFJZQUJMRV9TVEFUVVNFUyA9IG5ldyBTZXQoWzQyOSwgNTAyLCA1MDMsIDUwNF0pO1xuY29uc3QgUkVUUllBQkxFX0NPREVTID0gbmV3IFNldChbJ0VDT05OUkVTRVQnLCAnRUNPTk5SRUZVU0VEJywgJ0VUSU1FRE9VVCddKTtcblxuZnVuY3Rpb24gc2xlZXAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSk7XG59XG5cbi8qKiBQbGF0Zm9ybSBzZWNyZXQgbmFtZSDigJQgaW5qZWN0ZWQgYXMgUExBVEZPUk1fU0VDUkVUX05BTUUgZW52IHZhciBieSBQbHVnaW5Mb29rdXAgY29uc3RydWN0LiAqL1xuY29uc3QgUExBVEZPUk1fU0VDUkVUX05BTUUgPSBwcm9jZXNzLmVudi5QTEFURk9STV9TRUNSRVRfTkFNRTtcbmlmICghUExBVEZPUk1fU0VDUkVUX05BTUUpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdQTEFURk9STV9TRUNSRVRfTkFNRSBlbnZpcm9ubWVudCB2YXJpYWJsZSBpcyByZXF1aXJlZCcpO1xufVxuXG4vKiogQ2FjaGVkIHRva2VuIHRvIGF2b2lkIHJlcGVhdGVkIFNlY3JldHMgTWFuYWdlciBjYWxscyB3aXRoaW4gYSBzaW5nbGUgaW52b2NhdGlvbi4gKi9cbmxldCBjYWNoZWRUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbi8qKiBAaW50ZXJuYWwgUmVzZXQgY2FjaGVkIHRva2VuIChmb3IgdGVzdGluZyBvbmx5KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfcmVzZXRDcmVkZW50aWFsc0NhY2hlKCk6IHZvaWQgeyBjYWNoZWRUb2tlbiA9IG51bGw7IH1cblxuLyoqXG4gKiBGZXRjaCBKV1QgdG9rZW4gZnJvbSBBV1MgU2VjcmV0cyBNYW5hZ2VyLlxuICogQ2FjaGVzIHRoZSByZXN1bHQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgTGFtYmRhIGV4ZWN1dGlvbiBjb250ZXh0LlxuICpcbiAqIFRoZSBzZWNyZXQgbmFtZSBpcyBzZXQgdmlhIFBMQVRGT1JNX1NFQ1JFVF9OQU1FIGVudiB2YXIgKGUuZy4gYHtwcmVmaXh9L3tvcmdJZH0vcGxhdGZvcm1gKVxuICogQ3JlYXRlIGl0IHdpdGg6IGBwaXBlbGluZS1tYW5hZ2VyIHN0b3JlLXRva2VuYFxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRUb2tlbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICBpZiAoY2FjaGVkVG9rZW4pIHJldHVybiBjYWNoZWRUb2tlbjtcblxuICBsYW1iZGFMb2cuaW5mbygnQVVUSCcsIGBGZXRjaGluZyB0b2tlbiBmcm9tIFNlY3JldHMgTWFuYWdlcjogJHtQTEFURk9STV9TRUNSRVRfTkFNRX1gKTtcblxuICBjb25zdCBjbGllbnQgPSBuZXcgU2VjcmV0c01hbmFnZXJDbGllbnQoe30pO1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5zZW5kKG5ldyBHZXRTZWNyZXRWYWx1ZUNvbW1hbmQoeyBTZWNyZXRJZDogUExBVEZPUk1fU0VDUkVUX05BTUUgfSkpO1xuXG4gIGlmICghcmVzcG9uc2UuU2VjcmV0U3RyaW5nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBTZWNyZXQgXCIke1BMQVRGT1JNX1NFQ1JFVF9OQU1FfVwiIGlzIGVtcHR5YCk7XG4gIH1cblxuICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJlc3BvbnNlLlNlY3JldFN0cmluZykgYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgaWYgKCFwYXJzZWQuYWNjZXNzVG9rZW4pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFNlY3JldCBcIiR7UExBVEZPUk1fU0VDUkVUX05BTUV9XCIgbWlzc2luZyBhY2Nlc3NUb2tlbiDigJQgcnVuIFwicGlwZWxpbmUtbWFuYWdlciBzdG9yZS10b2tlblwiIHRvIGdlbmVyYXRlYCk7XG4gIH1cblxuICBjYWNoZWRUb2tlbiA9IHBhcnNlZC5hY2Nlc3NUb2tlbjtcbiAgbGFtYmRhTG9nLmluZm8oJ0FVVEgnLCAnVG9rZW4gcmV0cmlldmVkIGZyb20gU2VjcmV0cyBNYW5hZ2VyJyk7XG4gIHJldHVybiBjYWNoZWRUb2tlbjtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgcHJlLWNvbmZpZ3VyZWQgQXhpb3MgaW5zdGFuY2UgZm9yIEFQSSByZXF1ZXN0cy5cbiAqXG4gKiBAcGFyYW0gYmFzZVVSTCAtIEJhc2UgVVJMIG9mIHRoZSB0YXJnZXQgQVBJXG4gKiBAcGFyYW0gdG9rZW4gLSBKV1QgdG9rZW4gZm9yIGF1dGhvcml6YXRpb25cbiAqIEByZXR1cm5zIENvbmZpZ3VyZWQgQXhpb3MgaW5zdGFuY2VcbiAqL1xuZnVuY3Rpb24gY3JlYXRlKGJhc2VVUkw6IHN0cmluZywgdG9rZW46IHN0cmluZyk6IEF4aW9zSW5zdGFuY2Uge1xuICByZXR1cm4gYXhpb3MuY3JlYXRlKHtcbiAgICBiYXNlVVJMLFxuICAgIHRpbWVvdXQ6IENvcmVDb25zdGFudHMuSEFORExFUl9USU1FT1VUX01TLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICAnQXV0aG9yaXphdGlvbic6IGBCZWFyZXIgJHt0b2tlbn1gLFxuICAgIH0sXG4gIH0pO1xufVxuXG4vKipcbiAqIEZldGNoZXMgcGx1Z2luIGNvbmZpZ3VyYXRpb24gZnJvbSB0aGUgZXh0ZXJuYWwgQVBJIHdpdGggcmV0cnkgbG9naWMuXG4gKiBSZXRyaWVzIG9uIHRyYW5zaWVudCBmYWlsdXJlcyAoNDI5LCA1MDIsIDUwMywgNTA0LCBuZXR3b3JrIGVycm9ycylcbiAqIHdpdGggZXhwb25lbnRpYWwgYmFja29mZi5cbiAqXG4gKiBAcGFyYW0gYXBpIC0gQ29uZmlndXJlZCBBeGlvcyBpbnN0YW5jZVxuICogQHBhcmFtIHBsdWdpbkZpbHRlciAtIEZpbHRlciBjcml0ZXJpYSBmb3IgdGhlIHBsdWdpbiBsb29rdXBcbiAqIEByZXR1cm5zIFRoZSBwbHVnaW4gZGF0YSByZXR1cm5lZCBieSB0aGUgQVBJXG4gKiBAdGhyb3dzIEVycm9yIG9uIHBlcnNpc3RlbnQgZmFpbHVyZSwgdGltZW91dCBvciBpbnZhbGlkIHJlc3BvbnNlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZldGNoKGFwaTogQXhpb3NJbnN0YW5jZSwgcGx1Z2luRmlsdGVyOiBQbHVnaW5GaWx0ZXIpOiBQcm9taXNlPFBsdWdpbj4ge1xuICBsYW1iZGFMb2cuZGVidWcoJ0ZFVENIJywgJ1N0YXJ0aW5nIHBsdWdpbiBmZXRjaCcsIHsgZmlsdGVyOiBwbHVnaW5GaWx0ZXIgfSk7XG5cbiAgbGV0IGxhc3RFcnJvcjogRXJyb3IgfCB1bmRlZmluZWQ7XG5cbiAgZm9yIChsZXQgYXR0ZW1wdCA9IDA7IGF0dGVtcHQgPD0gQ29yZUNvbnN0YW50cy5IQU5ETEVSX01BWF9SRVRSSUVTOyBhdHRlbXB0KyspIHtcbiAgICBpZiAoYXR0ZW1wdCA+IDApIHtcbiAgICAgIGNvbnN0IGRlbGF5ID0gQ29yZUNvbnN0YW50cy5IQU5ETEVSX1JFVFJZX0RFTEFZX01TICogTWF0aC5wb3coMiwgYXR0ZW1wdCAtIDEpO1xuICAgICAgbGFtYmRhTG9nLmluZm8oJ1JFVFJZJywgYEF0dGVtcHQgJHthdHRlbXB0ICsgMX0vJHtDb3JlQ29uc3RhbnRzLkhBTkRMRVJfTUFYX1JFVFJJRVMgKyAxfSBhZnRlciAke2RlbGF5fW1zYCk7XG4gICAgICBhd2FpdCBzbGVlcChkZWxheSk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgZGF0YSwgc3RhdHVzIH0gPSBhd2FpdCBhcGkucG9zdDxQbHVnaW4+KCcvYXBpL3BsdWdpbnMvbG9va3VwJywge1xuICAgICAgICBmaWx0ZXI6IHBsdWdpbkZpbHRlcixcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbXB0eSByZXNwb25zZSBkYXRhIGZyb20gQVBJJyk7XG4gICAgICB9XG5cbiAgICAgIGxhbWJkYUxvZy5pbmZvKCdGRVRDSCcsICdQbHVnaW4gZmV0Y2hlZCBzdWNjZXNzZnVsbHknLCB7XG4gICAgICAgIHN0YXR1cyxcbiAgICAgICAgcGx1Z2luOiBkYXRhLm5hbWUsXG4gICAgICAgIHZlcnNpb246IGRhdGEudmVyc2lvbixcbiAgICAgICAgaWQ6IGRhdGEuaWQsXG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEF4aW9zRXJyb3IpIHtcbiAgICAgICAgaWYgKGVycm9yLmNvZGUgPT09ICdFQ09OTkFCT1JURUQnKSB7XG4gICAgICAgICAgbGFtYmRhTG9nLmVycm9yKCdGRVRDSCcsIGBQbHVnaW4gbG9va3VwIHRpbWVkIG91dCBhZnRlciAke0NvcmVDb25zdGFudHMuSEFORExFUl9USU1FT1VUX01TfW1zYCk7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQbHVnaW4gbG9va3VwIHRpbWVkIG91dCBhZnRlciAke0NvcmVDb25zdGFudHMuSEFORExFUl9USU1FT1VUX01TfW1zYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXRyeWFibGUgPSBlcnJvci5yZXNwb25zZVxuICAgICAgICAgID8gUkVUUllBQkxFX1NUQVRVU0VTLmhhcyhlcnJvci5yZXNwb25zZS5zdGF0dXMpXG4gICAgICAgICAgOiBSRVRSWUFCTEVfQ09ERVMuaGFzKGVycm9yLmNvZGUgPz8gJycpO1xuXG4gICAgICAgIGNvbnN0IG1zZyA9IGVycm9yLnJlc3BvbnNlXG4gICAgICAgICAgPyBgQVBJIGVycm9yICR7ZXJyb3IucmVzcG9uc2Uuc3RhdHVzfTogJHtlcnJvci5yZXNwb25zZS5zdGF0dXNUZXh0fWBcbiAgICAgICAgICA6IGVycm9yLmNvZGUgfHwgZXJyb3IubWVzc2FnZTtcblxuICAgICAgICBpZiAocmV0cnlhYmxlICYmIGF0dGVtcHQgPCBDb3JlQ29uc3RhbnRzLkhBTkRMRVJfTUFYX1JFVFJJRVMpIHtcbiAgICAgICAgICBsYW1iZGFMb2cuaW5mbygnUkVUUlknLCBgUmV0cnlhYmxlIGVycm9yOiAke21zZ31gLCB7IGF0dGVtcHQ6IGF0dGVtcHQgKyAxIH0pO1xuICAgICAgICAgIGxhc3RFcnJvciA9IG5ldyBFcnJvcihgRmFpbGVkIHRvIGZldGNoIHBsdWdpbjogJHttc2d9YCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBsYW1iZGFMb2cuZXJyb3IoJ0ZFVENIJywgbXNnLCB7IHJlc3BvbnNlRGF0YTogZXJyb3IucmVzcG9uc2U/LmRhdGEgfSk7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGZldGNoIHBsdWdpbjogJHttc2d9YCk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvciA6IG5ldyBFcnJvcignVW5rbm93biBlcnJvciBkdXJpbmcgcGx1Z2luIGZldGNoJyk7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbGFzdEVycm9yID8/IG5ldyBFcnJvcignRmFpbGVkIHRvIGZldGNoIHBsdWdpbiBhZnRlciByZXRyaWVzJyk7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIHRoZSBwbHVnaW4gZmlsdGVyIG9iamVjdFxuICpcbiAqIEBwYXJhbSBwbHVnaW5GaWx0ZXIgLSBGaWx0ZXIgdG8gdmFsaWRhdGVcbiAqIEByZXR1cm5zIHRydWUgaWYgdmFsaWRcbiAqIEB0aHJvd3MgRXJyb3IgaWYgaW52YWxpZFxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZVBsdWdpbkZpbHRlcihwbHVnaW5GaWx0ZXI6IHVua25vd24pOiBwbHVnaW5GaWx0ZXIgaXMgUGx1Z2luRmlsdGVyIHtcbiAgaWYgKCFwbHVnaW5GaWx0ZXIgfHwgdHlwZW9mIHBsdWdpbkZpbHRlciAhPT0gJ29iamVjdCcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01pc3Npbmcgb3IgaW52YWxpZCBwbHVnaW5GaWx0ZXInKTtcbiAgfVxuXG4gIGNvbnN0IGZpbHRlciA9IHBsdWdpbkZpbHRlciBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgaWYgKCFmaWx0ZXIubmFtZSAmJiAhZmlsdGVyLmlkICYmICFmaWx0ZXIudmVyc2lvbiAmJiAhZmlsdGVyLm9yZ0lkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQbHVnaW5GaWx0ZXIgbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBjcml0ZXJpb24gKG5hbWUsIGlkLCB2ZXJzaW9uLCBvciBvcmdJZCknKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIExhbWJkYSBoYW5kbGVyIGZvciBDbG91ZEZvcm1hdGlvbiBDdXN0b20gUmVzb3VyY2UgdGhhdCBwZXJmb3JtcyBwbHVnaW4gbG9va3VwLlxuICpcbiAqIEF1dGhlbnRpY2F0ZXMgdXNpbmcgSldUIHRva2VuIGZyb20gQVdTIFNlY3JldHMgTWFuYWdlciAoUExBVEZPUk1fU0VDUkVUX05BTUUgZW52IHZhcikuXG4gKiBDcmVhdGUgdGhlIHNlY3JldCB3aXRoOiBgcGlwZWxpbmUtbWFuYWdlciBzdG9yZS10b2tlbmBcbiAqXG4gKiBSZXF1ZXN0IFR5cGVzOlxuICogLSBDcmVhdGUvVXBkYXRlOiBmZXRjaGVzIGFuZCByZXR1cm5zIHBsdWdpbiBjb25maWd1cmF0aW9uIGZyb20gQVBJXG4gKiAtIERlbGV0ZTogbm8tb3AgKGFsd2F5cyBzdWNjZWVkcylcbiAqXG4gKiBSZXNwb25zZTpcbiAqIC0gU3VjY2VzczogUmV0dXJucyBiYXNlNjQtZW5jb2RlZCBwbHVnaW4gSlNPTiBpbiBEYXRhLlJlc3VsdFZhbHVlXG4gKiAtIEZhaWx1cmU6IFJldHVybnMgZXJyb3IgbWVzc2FnZSBpbiBSZWFzb25cbiAqXG4gKiBAcGFyYW0gZXZlbnQgLSBDbG91ZEZvcm1hdGlvbiBjdXN0b20gcmVzb3VyY2UgZXZlbnRcbiAqIEByZXR1cm5zIENsb3VkRm9ybWF0aW9uIHJlc3BvbnNlXG4gKlxuICogQGV4YW1wbGVcbiAqIEN1c3RvbSBSZXNvdXJjZSBQcm9wZXJ0aWVzOlxuICogYGBganNvblxuICoge1xuICogICBcImJhc2VVUkxcIjogXCJodHRwczovL2FwaS5leGFtcGxlLmNvbVwiLFxuICogICBcInBsdWdpbkZpbHRlclwiOiB7XG4gKiAgICAgXCJuYW1lXCI6IFwibm9kZWpzLWJ1aWxkXCIsXG4gKiAgICAgXCJ2ZXJzaW9uXCI6IFwiMS4wLjBcIixcbiAqICAgICBcImlzQWN0aXZlXCI6IHRydWVcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBjb25zdCBoYW5kbGVyID0gYXN5bmMgKFxuICBldmVudDogQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUV2ZW50LFxuKTogUHJvbWlzZTxDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlUmVzcG9uc2U+ID0+IHtcbiAgbGFtYmRhTG9nLmluZm8oJ1NUQVJUJywgYCR7ZXZlbnQuUmVxdWVzdFR5cGV9IHJlcXVlc3QgcmVjZWl2ZWRgLCB7XG4gICAgbG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgIHJlcXVlc3RJZDogZXZlbnQuUmVxdWVzdElkLFxuICAgIHN0YWNrSWQ6IGV2ZW50LlN0YWNrSWQsXG4gIH0pO1xuXG4gIGNvbnN0IGJhc2VSZXNwb25zZTogUGFydGlhbDxDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlUmVzcG9uc2U+ID0ge1xuICAgIFN0YWNrSWQ6IGV2ZW50LlN0YWNrSWQsXG4gICAgUmVxdWVzdElkOiBldmVudC5SZXF1ZXN0SWQsXG4gICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogZXZlbnQuTG9naWNhbFJlc291cmNlSWQsXG4gIH07XG5cbiAgdHJ5IHtcbiAgICAvLyBIYW5kbGUgRGVsZXRlIC0gYWx3YXlzIHN1Y2NlZWQgKG5vLW9wKVxuICAgIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0RlbGV0ZScpIHtcbiAgICAgIGxhbWJkYUxvZy5pbmZvKCdERUxFVEUnLCAnTm8tb3AgLSByZXR1cm5pbmcgU1VDQ0VTUycpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uYmFzZVJlc3BvbnNlLFxuICAgICAgICBTdGF0dXM6ICdTVUNDRVNTJyxcbiAgICAgICAgUmVhc29uOiAnRGVsZXRlIGNvbXBsZXRlZCAobm8tb3ApJyxcbiAgICAgIH0gYXMgQ2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZVJlc3BvbnNlO1xuICAgIH1cblxuICAgIC8vIEV4dHJhY3QgYW5kIHZhbGlkYXRlIHByb3BlcnRpZXNcbiAgICBjb25zdCBwbHVnaW5GaWx0ZXIgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMucGx1Z2luRmlsdGVyO1xuICAgIGNvbnN0IGJhc2VVUkwgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuYmFzZVVSTCB8fCBDb3JlQ29uc3RhbnRzLkhBTkRMRVJfREVGQVVMVF9CQVNFX1VSTDtcblxuICAgIGlmICghYmFzZVVSTC5zdGFydHNXaXRoKCdodHRwczovLycpICYmICFiYXNlVVJMLnN0YXJ0c1dpdGgoJ2h0dHA6Ly8nKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGJhc2VVUkw6IFwiJHtiYXNlVVJMfVwiIOKAlCBtdXN0IHN0YXJ0IHdpdGggaHR0cDovLyBvciBodHRwczovL2ApO1xuICAgIH1cblxuICAgIGxhbWJkYUxvZy5pbmZvKCdDT05GSUcnLCAnQ29uZmlndXJhdGlvbiBsb2FkZWQnLCB7IGJhc2VVUkwsIHBsdWdpbkZpbHRlciB9KTtcblxuICAgIHZhbGlkYXRlUGx1Z2luRmlsdGVyKHBsdWdpbkZpbHRlcik7XG5cbiAgICAvLyBHZXQgdG9rZW4gZnJvbSBTZWNyZXRzIE1hbmFnZXIgYW5kIGNyZWF0ZSBBUEkgY2xpZW50XG4gICAgY29uc3QgdG9rZW4gPSBhd2FpdCBnZXRUb2tlbigpO1xuICAgIGNvbnN0IGFwaSA9IGNyZWF0ZShiYXNlVVJMLCB0b2tlbik7XG5cbiAgICAvLyBGZXRjaCBwbHVnaW5cbiAgICBsYW1iZGFMb2cuaW5mbygnRkVUQ0gnLCAnSW5pdGlhdGluZyBwbHVnaW4gbG9va3VwLi4uJyk7XG4gICAgY29uc3QgcGx1Z2luID0gYXdhaXQgZmV0Y2goYXBpLCBwbHVnaW5GaWx0ZXIpO1xuICAgIGxhbWJkYUxvZy5pbmZvKCdGRVRDSCcsICdQbHVnaW4gcmV0cmlldmVkIHN1Y2Nlc3NmdWxseScsIHtcbiAgICAgIG5hbWU6IHBsdWdpbi5uYW1lLFxuICAgICAgdmVyc2lvbjogcGx1Z2luLnZlcnNpb24sXG4gICAgICBpZDogcGx1Z2luLmlkLFxuICAgIH0pO1xuXG4gICAgLy8gU3RyaXAgbGFyZ2UgZmllbGRzIHRvIHN0YXkgd2l0aGluIENsb3VkRm9ybWF0aW9uJ3MgNDA5Ni1ieXRlIERhdGEgbGltaXQuXG4gICAgLy8gQ0RLIGNvbnN0cnVjdHMgb25seSBuZWVkIHRoZSBmaWVsZHMgdXNlZCBieSBjcmVhdGVDb2RlQnVpbGRTdGVwKCkuXG4gICAgY29uc3Qgc2xpbSA9IHtcbiAgICAgIGlkOiBwbHVnaW4uaWQsXG4gICAgICBuYW1lOiBwbHVnaW4ubmFtZSxcbiAgICAgIHZlcnNpb246IHBsdWdpbi52ZXJzaW9uLFxuICAgICAgcGx1Z2luVHlwZTogcGx1Z2luLnBsdWdpblR5cGUsXG4gICAgICBjb21wdXRlVHlwZTogcGx1Z2luLmNvbXB1dGVUeXBlLFxuICAgICAgY29tbWFuZHM6IHBsdWdpbi5jb21tYW5kcyxcbiAgICAgIGluc3RhbGxDb21tYW5kczogcGx1Z2luLmluc3RhbGxDb21tYW5kcyxcbiAgICAgIGVudjogcGx1Z2luLmVudixcbiAgICAgIG1ldGFkYXRhOiBwbHVnaW4ubWV0YWRhdGEsXG4gICAgICBwcmltYXJ5T3V0cHV0RGlyZWN0b3J5OiBwbHVnaW4ucHJpbWFyeU91dHB1dERpcmVjdG9yeSxcbiAgICAgIHNlY3JldHM6IHBsdWdpbi5zZWNyZXRzLFxuICAgICAgZmFpbHVyZUJlaGF2aW9yOiBwbHVnaW4uZmFpbHVyZUJlaGF2aW9yLFxuICAgICAgdGltZW91dDogcGx1Z2luLnRpbWVvdXQsXG4gICAgICBpbWFnZVRhZzogcGx1Z2luLmltYWdlVGFnLFxuICAgIH07XG5cbiAgICBjb25zdCBlbmNvZGVkID0gQnVmZmVyLmZyb20oSlNPTi5zdHJpbmdpZnkoc2xpbSksICd1dGYtOCcpLnRvU3RyaW5nKCdiYXNlNjQnKTtcbiAgICBsYW1iZGFMb2cuZGVidWcoJ0VOQ09ERScsICdFbmNvZGVkIHBsdWdpbiBkYXRhJywgeyBsZW5ndGg6IGVuY29kZWQubGVuZ3RoIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmJhc2VSZXNwb25zZSxcbiAgICAgIFN0YXR1czogJ1NVQ0NFU1MnLFxuICAgICAgUmVhc29uOiBgUGx1Z2luICcke3BsdWdpbi5uYW1lfScgKHYke3BsdWdpbi52ZXJzaW9ufSkgcmV0cmlldmVkIHN1Y2Nlc3NmdWxseWAsXG4gICAgICBEYXRhOiB7XG4gICAgICAgIFJlc3VsdFZhbHVlOiBlbmNvZGVkLFxuICAgICAgfSxcbiAgICB9IGFzIENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VSZXNwb25zZTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zdCByZWFzb24gPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6ICdVbmV4cGVjdGVkIGVycm9yIG9jY3VycmVkJztcbiAgICBsYW1iZGFMb2cuZXJyb3IoJ0VSUk9SJywgJ0hhbmRsZXIgZmFpbGVkJywge1xuICAgICAgcmVhc29uLFxuICAgICAgc3RhY2s6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5zdGFjayA6IHVuZGVmaW5lZCxcbiAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5iYXNlUmVzcG9uc2UsXG4gICAgICBTdGF0dXM6ICdGQUlMRUQnLFxuICAgICAgUmVhc29uOiByZWFzb24sXG4gICAgfSBhcyBDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlUmVzcG9uc2U7XG4gIH0gZmluYWxseSB7XG4gICAgbGFtYmRhTG9nLmluZm8oJ0VORCcsICdDdXN0b20gcmVzb3VyY2UgZXhlY3V0aW9uIGNvbXBsZXRlZCcpO1xuICB9XG59O1xuIl19
@@ -0,0 +1,12 @@
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ importers:
8
+
9
+ .:
10
+ dependencies: {}
11
+
12
+ packages: {}
package/lib/index.d.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @module @pipeline-builder/pipeline-core
3
+ *
4
+ * Application configuration, pipeline domain types, and CDK constructs.
5
+ *
6
+ * **Config**
7
+ * - Config — application configuration singleton (environment-driven)
8
+ * - ConfigTypes — typed configuration interfaces
9
+ *
10
+ * **Types**
11
+ * - PipelineType, ComputeType, AccessModifier, PluginType — pipeline domain enums
12
+ * - NetworkTypes, RoleTypes, SecurityGroupTypes — infrastructure type definitions
13
+ * - SourceTypes, StepTypes — pipeline source and step configuration types
14
+ * - IdGenerator — deterministic ID generation
15
+ *
16
+ * **CDK Constructs**
17
+ * - PipelineBuilder — top-level CDK pipeline construct
18
+ * - StageBuilder — pipeline stage composition
19
+ * - PipelineConfiguration — pipeline config resolution
20
+ * - PluginLookup — plugin resolution for pipeline steps
21
+ * - ArtifactManager — build artifact management
22
+ *
23
+ * **Helpers**
24
+ * - replaceNonAlphanumeric, extractMetadataEnv — string and metadata utilities
25
+ * - buildConfigFromMetadata, metadataForCodePipeline, etc. — metadata builders
26
+ *
27
+ * **Re-exports from api-core**
28
+ * - ErrorCode, createLogger
29
+ *
30
+ * **Re-exports from pipeline-data**
31
+ * - db, schema, getConnection, closeConnection — database access
32
+ * - CrudService, BaseEntity — CRUD service infrastructure
33
+ * - All query condition builders and filter types
34
+ * - Compliance domain types (RuleSeverity, RuleTarget, etc.)
35
+ * - drizzleRows, drizzleCount — type helpers
36
+ */
37
+ export * from './config/app-config';
38
+ export * from './config/config-types';
39
+ export * from './core/pipeline-types';
40
+ export * from './core/network-types';
41
+ export * from './core/role-types';
42
+ export * from './core/security-group-types';
43
+ export * from './core/id-generator';
44
+ export { replaceNonAlphanumeric, extractMetadataEnv } from './core/pipeline-helpers';
45
+ export { buildConfigFromMetadata, metadataForCodePipeline, metadataForCodeBuildStep, metadataForShellStep, metadataForBuildEnvironment, } from './core/metadata-builder';
46
+ export * from './core/artifact-manager';
47
+ export { ErrorCode, createLogger, } from '@pipeline-builder/api-core';
48
+ export { db, getConnection, closeConnection, schema, buildPluginConditions, buildPipelineConditions, buildMessageConditions, validateMessageFilter, buildCompliancePolicyConditions, buildComplianceRuleConditions, buildComplianceExemptionConditions, buildComplianceAuditConditions, buildComplianceScanConditions, buildPublishedRuleCatalogConditions, buildComplianceRuleSubscriptionConditions, type PluginFilter, type PipelineFilter, type MessageFilter, type CompliancePolicyFilter, type ComplianceRuleFilter, type ComplianceExemptionFilter, type ComplianceAuditFilter, type ComplianceScanFilter, type ComplianceRuleSubscriptionFilter, type PluginSecret, type RuleSeverity, type RuleTarget, type RuleOperator, type RuleConditionMode, type RuleScope, type RuleCondition, type ComplianceRoleType, CrudService, type BaseEntity, drizzleRows, drizzleCount, } from '@pipeline-builder/pipeline-data';
49
+ export * from './pipeline/source-types';
50
+ export * from './pipeline/step-types';
51
+ export * from './pipeline/stage-builder';
52
+ export * from './pipeline/pipeline-builder';
53
+ export * from './pipeline/plugin-lookup';
54
+ export { PipelineConfiguration } from './pipeline/pipeline-configuration';
package/lib/index.js ADDED
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ // Copyright 2026 Pipeline Builder Contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.PipelineConfiguration = exports.drizzleCount = exports.drizzleRows = exports.CrudService = exports.buildComplianceRuleSubscriptionConditions = exports.buildPublishedRuleCatalogConditions = exports.buildComplianceScanConditions = exports.buildComplianceAuditConditions = exports.buildComplianceExemptionConditions = exports.buildComplianceRuleConditions = exports.buildCompliancePolicyConditions = exports.validateMessageFilter = exports.buildMessageConditions = exports.buildPipelineConditions = exports.buildPluginConditions = exports.schema = exports.closeConnection = exports.getConnection = exports.db = exports.createLogger = exports.ErrorCode = exports.metadataForBuildEnvironment = exports.metadataForShellStep = exports.metadataForCodeBuildStep = exports.metadataForCodePipeline = exports.buildConfigFromMetadata = exports.extractMetadataEnv = exports.replaceNonAlphanumeric = void 0;
20
+ /**
21
+ * @module @pipeline-builder/pipeline-core
22
+ *
23
+ * Application configuration, pipeline domain types, and CDK constructs.
24
+ *
25
+ * **Config**
26
+ * - Config — application configuration singleton (environment-driven)
27
+ * - ConfigTypes — typed configuration interfaces
28
+ *
29
+ * **Types**
30
+ * - PipelineType, ComputeType, AccessModifier, PluginType — pipeline domain enums
31
+ * - NetworkTypes, RoleTypes, SecurityGroupTypes — infrastructure type definitions
32
+ * - SourceTypes, StepTypes — pipeline source and step configuration types
33
+ * - IdGenerator — deterministic ID generation
34
+ *
35
+ * **CDK Constructs**
36
+ * - PipelineBuilder — top-level CDK pipeline construct
37
+ * - StageBuilder — pipeline stage composition
38
+ * - PipelineConfiguration — pipeline config resolution
39
+ * - PluginLookup — plugin resolution for pipeline steps
40
+ * - ArtifactManager — build artifact management
41
+ *
42
+ * **Helpers**
43
+ * - replaceNonAlphanumeric, extractMetadataEnv — string and metadata utilities
44
+ * - buildConfigFromMetadata, metadataForCodePipeline, etc. — metadata builders
45
+ *
46
+ * **Re-exports from api-core**
47
+ * - ErrorCode, createLogger
48
+ *
49
+ * **Re-exports from pipeline-data**
50
+ * - db, schema, getConnection, closeConnection — database access
51
+ * - CrudService, BaseEntity — CRUD service infrastructure
52
+ * - All query condition builders and filter types
53
+ * - Compliance domain types (RuleSeverity, RuleTarget, etc.)
54
+ * - drizzleRows, drizzleCount — type helpers
55
+ */
56
+ // Configuration
57
+ __exportStar(require("./config/app-config"), exports);
58
+ __exportStar(require("./config/config-types"), exports);
59
+ // Core types (public surface)
60
+ __exportStar(require("./core/pipeline-types"), exports);
61
+ __exportStar(require("./core/network-types"), exports);
62
+ __exportStar(require("./core/role-types"), exports);
63
+ __exportStar(require("./core/security-group-types"), exports);
64
+ __exportStar(require("./core/id-generator"), exports);
65
+ var pipeline_helpers_1 = require("./core/pipeline-helpers");
66
+ Object.defineProperty(exports, "replaceNonAlphanumeric", { enumerable: true, get: function () { return pipeline_helpers_1.replaceNonAlphanumeric; } });
67
+ Object.defineProperty(exports, "extractMetadataEnv", { enumerable: true, get: function () { return pipeline_helpers_1.extractMetadataEnv; } });
68
+ var metadata_builder_1 = require("./core/metadata-builder");
69
+ Object.defineProperty(exports, "buildConfigFromMetadata", { enumerable: true, get: function () { return metadata_builder_1.buildConfigFromMetadata; } });
70
+ Object.defineProperty(exports, "metadataForCodePipeline", { enumerable: true, get: function () { return metadata_builder_1.metadataForCodePipeline; } });
71
+ Object.defineProperty(exports, "metadataForCodeBuildStep", { enumerable: true, get: function () { return metadata_builder_1.metadataForCodeBuildStep; } });
72
+ Object.defineProperty(exports, "metadataForShellStep", { enumerable: true, get: function () { return metadata_builder_1.metadataForShellStep; } });
73
+ Object.defineProperty(exports, "metadataForBuildEnvironment", { enumerable: true, get: function () { return metadata_builder_1.metadataForBuildEnvironment; } });
74
+ __exportStar(require("./core/artifact-manager"), exports);
75
+ // Re-export from api-core (only items consumed by external packages)
76
+ var api_core_1 = require("@pipeline-builder/api-core");
77
+ Object.defineProperty(exports, "ErrorCode", { enumerable: true, get: function () { return api_core_1.ErrorCode; } });
78
+ Object.defineProperty(exports, "createLogger", { enumerable: true, get: function () { return api_core_1.createLogger; } });
79
+ // Re-export database layer from pipeline-data (only items consumed externally)
80
+ var pipeline_data_1 = require("@pipeline-builder/pipeline-data");
81
+ // Database connection
82
+ Object.defineProperty(exports, "db", { enumerable: true, get: function () { return pipeline_data_1.db; } });
83
+ Object.defineProperty(exports, "getConnection", { enumerable: true, get: function () { return pipeline_data_1.getConnection; } });
84
+ Object.defineProperty(exports, "closeConnection", { enumerable: true, get: function () { return pipeline_data_1.closeConnection; } });
85
+ // Schema & tables
86
+ Object.defineProperty(exports, "schema", { enumerable: true, get: function () { return pipeline_data_1.schema; } });
87
+ // Query builders
88
+ Object.defineProperty(exports, "buildPluginConditions", { enumerable: true, get: function () { return pipeline_data_1.buildPluginConditions; } });
89
+ Object.defineProperty(exports, "buildPipelineConditions", { enumerable: true, get: function () { return pipeline_data_1.buildPipelineConditions; } });
90
+ Object.defineProperty(exports, "buildMessageConditions", { enumerable: true, get: function () { return pipeline_data_1.buildMessageConditions; } });
91
+ Object.defineProperty(exports, "validateMessageFilter", { enumerable: true, get: function () { return pipeline_data_1.validateMessageFilter; } });
92
+ Object.defineProperty(exports, "buildCompliancePolicyConditions", { enumerable: true, get: function () { return pipeline_data_1.buildCompliancePolicyConditions; } });
93
+ Object.defineProperty(exports, "buildComplianceRuleConditions", { enumerable: true, get: function () { return pipeline_data_1.buildComplianceRuleConditions; } });
94
+ Object.defineProperty(exports, "buildComplianceExemptionConditions", { enumerable: true, get: function () { return pipeline_data_1.buildComplianceExemptionConditions; } });
95
+ Object.defineProperty(exports, "buildComplianceAuditConditions", { enumerable: true, get: function () { return pipeline_data_1.buildComplianceAuditConditions; } });
96
+ Object.defineProperty(exports, "buildComplianceScanConditions", { enumerable: true, get: function () { return pipeline_data_1.buildComplianceScanConditions; } });
97
+ Object.defineProperty(exports, "buildPublishedRuleCatalogConditions", { enumerable: true, get: function () { return pipeline_data_1.buildPublishedRuleCatalogConditions; } });
98
+ Object.defineProperty(exports, "buildComplianceRuleSubscriptionConditions", { enumerable: true, get: function () { return pipeline_data_1.buildComplianceRuleSubscriptionConditions; } });
99
+ // CRUD service
100
+ Object.defineProperty(exports, "CrudService", { enumerable: true, get: function () { return pipeline_data_1.CrudService; } });
101
+ // Drizzle type helpers
102
+ Object.defineProperty(exports, "drizzleRows", { enumerable: true, get: function () { return pipeline_data_1.drizzleRows; } });
103
+ Object.defineProperty(exports, "drizzleCount", { enumerable: true, get: function () { return pipeline_data_1.drizzleCount; } });
104
+ // Pipeline (CDK constructs)
105
+ __exportStar(require("./pipeline/source-types"), exports);
106
+ __exportStar(require("./pipeline/step-types"), exports);
107
+ __exportStar(require("./pipeline/stage-builder"), exports);
108
+ __exportStar(require("./pipeline/pipeline-builder"), exports);
109
+ __exportStar(require("./pipeline/plugin-lookup"), exports);
110
+ var pipeline_configuration_1 = require("./pipeline/pipeline-configuration");
111
+ Object.defineProperty(exports, "PipelineConfiguration", { enumerable: true, get: function () { return pipeline_configuration_1.PipelineConfiguration; } });
112
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRXRDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1DRztBQUVILGdCQUFnQjtBQUNoQixzREFBb0M7QUFDcEMsd0RBQXNDO0FBRXRDLDhCQUE4QjtBQUM5Qix3REFBc0M7QUFDdEMsdURBQXFDO0FBQ3JDLG9EQUFrQztBQUNsQyw4REFBNEM7QUFDNUMsc0RBQW9DO0FBQ3BDLDREQUFxRjtBQUE1RSwwSEFBQSxzQkFBc0IsT0FBQTtBQUFFLHNIQUFBLGtCQUFrQixPQUFBO0FBQ25ELDREQU1pQztBQUwvQiwySEFBQSx1QkFBdUIsT0FBQTtBQUN2QiwySEFBQSx1QkFBdUIsT0FBQTtBQUN2Qiw0SEFBQSx3QkFBd0IsT0FBQTtBQUN4Qix3SEFBQSxvQkFBb0IsT0FBQTtBQUNwQiwrSEFBQSwyQkFBMkIsT0FBQTtBQUU3QiwwREFBd0M7QUFFeEMscUVBQXFFO0FBQ3JFLHVEQUdvQztBQUZsQyxxR0FBQSxTQUFTLE9BQUE7QUFDVCx3R0FBQSxZQUFZLE9BQUE7QUFHZCwrRUFBK0U7QUFDL0UsaUVBb0R5QztBQW5EdkMsc0JBQXNCO0FBQ3RCLG1HQUFBLEVBQUUsT0FBQTtBQUNGLDhHQUFBLGFBQWEsT0FBQTtBQUNiLGdIQUFBLGVBQWUsT0FBQTtBQUVmLGtCQUFrQjtBQUNsQix1R0FBQSxNQUFNLE9BQUE7QUFFTixpQkFBaUI7QUFDakIsc0hBQUEscUJBQXFCLE9BQUE7QUFDckIsd0hBQUEsdUJBQXVCLE9BQUE7QUFDdkIsdUhBQUEsc0JBQXNCLE9BQUE7QUFDdEIsc0hBQUEscUJBQXFCLE9BQUE7QUFDckIsZ0lBQUEsK0JBQStCLE9BQUE7QUFDL0IsOEhBQUEsNkJBQTZCLE9BQUE7QUFDN0IsbUlBQUEsa0NBQWtDLE9BQUE7QUFDbEMsK0hBQUEsOEJBQThCLE9BQUE7QUFDOUIsOEhBQUEsNkJBQTZCLE9BQUE7QUFDN0Isb0lBQUEsbUNBQW1DLE9BQUE7QUFDbkMsMElBQUEseUNBQXlDLE9BQUE7QUF5QnpDLGVBQWU7QUFDZiw0R0FBQSxXQUFXLE9BQUE7QUFHWCx1QkFBdUI7QUFDdkIsNEdBQUEsV0FBVyxPQUFBO0FBQ1gsNkdBQUEsWUFBWSxPQUFBO0FBR2QsNEJBQTRCO0FBQzVCLDBEQUF3QztBQUN4Qyx3REFBc0M7QUFDdEMsMkRBQXlDO0FBQ3pDLDhEQUE0QztBQUM1QywyREFBeUM7QUFDekMsNEVBQTBFO0FBQWpFLCtIQUFBLHFCQUFxQixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogQG1vZHVsZSBAcGlwZWxpbmUtYnVpbGRlci9waXBlbGluZS1jb3JlXG4gKlxuICogQXBwbGljYXRpb24gY29uZmlndXJhdGlvbiwgcGlwZWxpbmUgZG9tYWluIHR5cGVzLCBhbmQgQ0RLIGNvbnN0cnVjdHMuXG4gKlxuICogKipDb25maWcqKlxuICogLSBDb25maWcg4oCUIGFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb24gc2luZ2xldG9uIChlbnZpcm9ubWVudC1kcml2ZW4pXG4gKiAtIENvbmZpZ1R5cGVzIOKAlCB0eXBlZCBjb25maWd1cmF0aW9uIGludGVyZmFjZXNcbiAqXG4gKiAqKlR5cGVzKipcbiAqIC0gUGlwZWxpbmVUeXBlLCBDb21wdXRlVHlwZSwgQWNjZXNzTW9kaWZpZXIsIFBsdWdpblR5cGUg4oCUIHBpcGVsaW5lIGRvbWFpbiBlbnVtc1xuICogLSBOZXR3b3JrVHlwZXMsIFJvbGVUeXBlcywgU2VjdXJpdHlHcm91cFR5cGVzIOKAlCBpbmZyYXN0cnVjdHVyZSB0eXBlIGRlZmluaXRpb25zXG4gKiAtIFNvdXJjZVR5cGVzLCBTdGVwVHlwZXMg4oCUIHBpcGVsaW5lIHNvdXJjZSBhbmQgc3RlcCBjb25maWd1cmF0aW9uIHR5cGVzXG4gKiAtIElkR2VuZXJhdG9yIOKAlCBkZXRlcm1pbmlzdGljIElEIGdlbmVyYXRpb25cbiAqXG4gKiAqKkNESyBDb25zdHJ1Y3RzKipcbiAqIC0gUGlwZWxpbmVCdWlsZGVyIOKAlCB0b3AtbGV2ZWwgQ0RLIHBpcGVsaW5lIGNvbnN0cnVjdFxuICogLSBTdGFnZUJ1aWxkZXIg4oCUIHBpcGVsaW5lIHN0YWdlIGNvbXBvc2l0aW9uXG4gKiAtIFBpcGVsaW5lQ29uZmlndXJhdGlvbiDigJQgcGlwZWxpbmUgY29uZmlnIHJlc29sdXRpb25cbiAqIC0gUGx1Z2luTG9va3VwIOKAlCBwbHVnaW4gcmVzb2x1dGlvbiBmb3IgcGlwZWxpbmUgc3RlcHNcbiAqIC0gQXJ0aWZhY3RNYW5hZ2VyIOKAlCBidWlsZCBhcnRpZmFjdCBtYW5hZ2VtZW50XG4gKlxuICogKipIZWxwZXJzKipcbiAqIC0gcmVwbGFjZU5vbkFscGhhbnVtZXJpYywgZXh0cmFjdE1ldGFkYXRhRW52IOKAlCBzdHJpbmcgYW5kIG1ldGFkYXRhIHV0aWxpdGllc1xuICogLSBidWlsZENvbmZpZ0Zyb21NZXRhZGF0YSwgbWV0YWRhdGFGb3JDb2RlUGlwZWxpbmUsIGV0Yy4g4oCUIG1ldGFkYXRhIGJ1aWxkZXJzXG4gKlxuICogKipSZS1leHBvcnRzIGZyb20gYXBpLWNvcmUqKlxuICogLSBFcnJvckNvZGUsIGNyZWF0ZUxvZ2dlclxuICpcbiAqICoqUmUtZXhwb3J0cyBmcm9tIHBpcGVsaW5lLWRhdGEqKlxuICogLSBkYiwgc2NoZW1hLCBnZXRDb25uZWN0aW9uLCBjbG9zZUNvbm5lY3Rpb24g4oCUIGRhdGFiYXNlIGFjY2Vzc1xuICogLSBDcnVkU2VydmljZSwgQmFzZUVudGl0eSDigJQgQ1JVRCBzZXJ2aWNlIGluZnJhc3RydWN0dXJlXG4gKiAtIEFsbCBxdWVyeSBjb25kaXRpb24gYnVpbGRlcnMgYW5kIGZpbHRlciB0eXBlc1xuICogLSBDb21wbGlhbmNlIGRvbWFpbiB0eXBlcyAoUnVsZVNldmVyaXR5LCBSdWxlVGFyZ2V0LCBldGMuKVxuICogLSBkcml6emxlUm93cywgZHJpenpsZUNvdW50IOKAlCB0eXBlIGhlbHBlcnNcbiAqL1xuXG4vLyBDb25maWd1cmF0aW9uXG5leHBvcnQgKiBmcm9tICcuL2NvbmZpZy9hcHAtY29uZmlnJztcbmV4cG9ydCAqIGZyb20gJy4vY29uZmlnL2NvbmZpZy10eXBlcyc7XG5cbi8vIENvcmUgdHlwZXMgKHB1YmxpYyBzdXJmYWNlKVxuZXhwb3J0ICogZnJvbSAnLi9jb3JlL3BpcGVsaW5lLXR5cGVzJztcbmV4cG9ydCAqIGZyb20gJy4vY29yZS9uZXR3b3JrLXR5cGVzJztcbmV4cG9ydCAqIGZyb20gJy4vY29yZS9yb2xlLXR5cGVzJztcbmV4cG9ydCAqIGZyb20gJy4vY29yZS9zZWN1cml0eS1ncm91cC10eXBlcyc7XG5leHBvcnQgKiBmcm9tICcuL2NvcmUvaWQtZ2VuZXJhdG9yJztcbmV4cG9ydCB7IHJlcGxhY2VOb25BbHBoYW51bWVyaWMsIGV4dHJhY3RNZXRhZGF0YUVudiB9IGZyb20gJy4vY29yZS9waXBlbGluZS1oZWxwZXJzJztcbmV4cG9ydCB7XG4gIGJ1aWxkQ29uZmlnRnJvbU1ldGFkYXRhLFxuICBtZXRhZGF0YUZvckNvZGVQaXBlbGluZSxcbiAgbWV0YWRhdGFGb3JDb2RlQnVpbGRTdGVwLFxuICBtZXRhZGF0YUZvclNoZWxsU3RlcCxcbiAgbWV0YWRhdGFGb3JCdWlsZEVudmlyb25tZW50LFxufSBmcm9tICcuL2NvcmUvbWV0YWRhdGEtYnVpbGRlcic7XG5leHBvcnQgKiBmcm9tICcuL2NvcmUvYXJ0aWZhY3QtbWFuYWdlcic7XG5cbi8vIFJlLWV4cG9ydCBmcm9tIGFwaS1jb3JlIChvbmx5IGl0ZW1zIGNvbnN1bWVkIGJ5IGV4dGVybmFsIHBhY2thZ2VzKVxuZXhwb3J0IHtcbiAgRXJyb3JDb2RlLFxuICBjcmVhdGVMb2dnZXIsXG59IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcblxuLy8gUmUtZXhwb3J0IGRhdGFiYXNlIGxheWVyIGZyb20gcGlwZWxpbmUtZGF0YSAob25seSBpdGVtcyBjb25zdW1lZCBleHRlcm5hbGx5KVxuZXhwb3J0IHtcbiAgLy8gRGF0YWJhc2UgY29ubmVjdGlvblxuICBkYixcbiAgZ2V0Q29ubmVjdGlvbixcbiAgY2xvc2VDb25uZWN0aW9uLFxuXG4gIC8vIFNjaGVtYSAmIHRhYmxlc1xuICBzY2hlbWEsXG5cbiAgLy8gUXVlcnkgYnVpbGRlcnNcbiAgYnVpbGRQbHVnaW5Db25kaXRpb25zLFxuICBidWlsZFBpcGVsaW5lQ29uZGl0aW9ucyxcbiAgYnVpbGRNZXNzYWdlQ29uZGl0aW9ucyxcbiAgdmFsaWRhdGVNZXNzYWdlRmlsdGVyLFxuICBidWlsZENvbXBsaWFuY2VQb2xpY3lDb25kaXRpb25zLFxuICBidWlsZENvbXBsaWFuY2VSdWxlQ29uZGl0aW9ucyxcbiAgYnVpbGRDb21wbGlhbmNlRXhlbXB0aW9uQ29uZGl0aW9ucyxcbiAgYnVpbGRDb21wbGlhbmNlQXVkaXRDb25kaXRpb25zLFxuICBidWlsZENvbXBsaWFuY2VTY2FuQ29uZGl0aW9ucyxcbiAgYnVpbGRQdWJsaXNoZWRSdWxlQ2F0YWxvZ0NvbmRpdGlvbnMsXG4gIGJ1aWxkQ29tcGxpYW5jZVJ1bGVTdWJzY3JpcHRpb25Db25kaXRpb25zLFxuXG4gIC8vIFF1ZXJ5IGZpbHRlciB0eXBlc1xuICB0eXBlIFBsdWdpbkZpbHRlcixcbiAgdHlwZSBQaXBlbGluZUZpbHRlcixcbiAgdHlwZSBNZXNzYWdlRmlsdGVyLFxuICB0eXBlIENvbXBsaWFuY2VQb2xpY3lGaWx0ZXIsXG4gIHR5cGUgQ29tcGxpYW5jZVJ1bGVGaWx0ZXIsXG4gIHR5cGUgQ29tcGxpYW5jZUV4ZW1wdGlvbkZpbHRlcixcbiAgdHlwZSBDb21wbGlhbmNlQXVkaXRGaWx0ZXIsXG4gIHR5cGUgQ29tcGxpYW5jZVNjYW5GaWx0ZXIsXG4gIHR5cGUgQ29tcGxpYW5jZVJ1bGVTdWJzY3JpcHRpb25GaWx0ZXIsXG5cbiAgLy8gUGx1Z2luIHR5cGVzXG4gIHR5cGUgUGx1Z2luU2VjcmV0LFxuXG4gIC8vIENvbXBsaWFuY2UgdHlwZXNcbiAgdHlwZSBSdWxlU2V2ZXJpdHksXG4gIHR5cGUgUnVsZVRhcmdldCxcbiAgdHlwZSBSdWxlT3BlcmF0b3IsXG4gIHR5cGUgUnVsZUNvbmRpdGlvbk1vZGUsXG4gIHR5cGUgUnVsZVNjb3BlLFxuICB0eXBlIFJ1bGVDb25kaXRpb24sXG4gIHR5cGUgQ29tcGxpYW5jZVJvbGVUeXBlLFxuXG4gIC8vIENSVUQgc2VydmljZVxuICBDcnVkU2VydmljZSxcbiAgdHlwZSBCYXNlRW50aXR5LFxuXG4gIC8vIERyaXp6bGUgdHlwZSBoZWxwZXJzXG4gIGRyaXp6bGVSb3dzLFxuICBkcml6emxlQ291bnQsXG59IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWRhdGEnO1xuXG4vLyBQaXBlbGluZSAoQ0RLIGNvbnN0cnVjdHMpXG5leHBvcnQgKiBmcm9tICcuL3BpcGVsaW5lL3NvdXJjZS10eXBlcyc7XG5leHBvcnQgKiBmcm9tICcuL3BpcGVsaW5lL3N0ZXAtdHlwZXMnO1xuZXhwb3J0ICogZnJvbSAnLi9waXBlbGluZS9zdGFnZS1idWlsZGVyJztcbmV4cG9ydCAqIGZyb20gJy4vcGlwZWxpbmUvcGlwZWxpbmUtYnVpbGRlcic7XG5leHBvcnQgKiBmcm9tICcuL3BpcGVsaW5lL3BsdWdpbi1sb29rdXAnO1xuZXhwb3J0IHsgUGlwZWxpbmVDb25maWd1cmF0aW9uIH0gZnJvbSAnLi9waXBlbGluZS9waXBlbGluZS1jb25maWd1cmF0aW9uJztcbiJdfQ==
@@ -0,0 +1,82 @@
1
+ import { CodePipeline } from 'aws-cdk-lib/pipelines';
2
+ import { Construct } from 'constructs';
3
+ import { PipelineConfiguration } from './pipeline-configuration';
4
+ import type { StageOptions, SynthOptions } from './step-types';
5
+ import type { CodeBuildDefaults } from '../core/network-types';
6
+ import type { MetaDataType } from '../core/pipeline-types';
7
+ import type { RoleConfig } from '../core/role-types';
8
+ /**
9
+ * Configuration properties for the PipelineBuilder construct
10
+ */
11
+ export interface BuilderProps {
12
+ /** Project identifier (will be sanitized to lowercase alphanumeric with underscores) */
13
+ readonly project: string;
14
+ /** Organization identifier (will be sanitized to lowercase alphanumeric with underscores) */
15
+ readonly organization: string;
16
+ /** Tenant identifier for resolving per-org secrets from AWS Secrets Manager */
17
+ readonly orgId?: string;
18
+ /** Pipeline database record ID — injected as PIPELINE_ID env var for autonomous synth */
19
+ readonly pipelineId?: string;
20
+ /** Optional custom pipeline name. Defaults to: {organization}-{project}-pipeline */
21
+ readonly pipelineName?: string;
22
+ /** Global metadata inherited by all pipeline steps */
23
+ readonly global?: MetaDataType;
24
+ /**
25
+ * Pipeline-level CodeBuild defaults applied to all CodeBuild actions
26
+ * (synth, self-mutation, asset publishing) via `codeBuildDefaults`.
27
+ */
28
+ readonly defaults?: CodeBuildDefaults;
29
+ /**
30
+ * Optional IAM role for the CodePipeline.
31
+ * When provided, resolves to a CDK IRole and is passed to the CodePipeline construct.
32
+ * When omitted, CDK auto-creates a role with the correct codepipeline.amazonaws.com principal.
33
+ */
34
+ readonly role?: RoleConfig;
35
+ /** Synthesis configuration including source and plugin details */
36
+ readonly synth: SynthOptions;
37
+ /**
38
+ * Optional pipeline stages, each containing one or more CodeBuild steps.
39
+ * Stages are added as waves to the CodePipeline after the synth step.
40
+ */
41
+ readonly stages?: StageOptions[];
42
+ /** Optional cron/rate expression for scheduled pipeline execution. */
43
+ readonly schedule?: string;
44
+ /** Custom tags applied to all pipeline resources. */
45
+ readonly tags?: Record<string, string>;
46
+ }
47
+ /**
48
+ * CDK construct that creates and configures a CodePipeline for continuous deployment.
49
+ *
50
+ * Features:
51
+ * - Multi-source support (S3, GitHub, CodeStar)
52
+ * - Plugin-based build steps
53
+ * - Metadata-driven configuration
54
+ * - Automatic tagging
55
+ * - Automatic sanitization of project and organization names
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * new PipelineBuilder(this, 'MyPipeline', {
60
+ * project: 'my-app',
61
+ * organization: 'my-org',
62
+ * synth: {
63
+ * source: {
64
+ * type: 'github',
65
+ * options: { repo: 'owner/repo', branch: 'main' }
66
+ * },
67
+ * plugin: { name: 'synth' }
68
+ * }
69
+ * });
70
+ * ```
71
+ */
72
+ export declare class PipelineBuilder extends Construct {
73
+ readonly pipeline: CodePipeline;
74
+ readonly config: PipelineConfiguration;
75
+ constructor(scope: Construct, id: string, props: BuilderProps);
76
+ /**
77
+ * Resolves CodeBuildDefaults into the shape expected by CDK's codeBuildDefaults.
78
+ * Combines network config, security groups, and pipeline-level environment variables
79
+ * (PIPELINE_ID, EXECUTION_ID, PLATFORM_BASE_URL) available to all CodeBuild actions.
80
+ */
81
+ private resolveDefaults;
82
+ }