@pipeline-builder/pipeline-manager 3.4.125 → 3.4.126
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/store-token.d.ts.map +1 -1
- package/dist/commands/store-token.js +96 -2
- package/dist/lambda/token-renew-handler.d.ts +2 -0
- package/dist/lambda/token-renew-handler.d.ts.map +1 -0
- package/dist/lambda/token-renew-handler.js +126 -0
- package/dist/templates/token-renew-stack.json +103 -0
- package/dist/utils/cron.d.ts +28 -0
- package/dist/utils/cron.d.ts.map +1 -0
- package/dist/utils/cron.js +115 -0
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-token.d.ts","sourceRoot":"","sources":["../../src/commands/store-token.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store-token.d.ts","sourceRoot":"","sources":["../../src/commands/store-token.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuFpC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAuMjD"}
|
|
@@ -1,14 +1,84 @@
|
|
|
1
1
|
// Copyright 2026 Pipeline Builder Contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { execFileSync } from 'child_process';
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import * as os from 'os';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { LambdaClient, UpdateFunctionCodeCommand } from '@aws-sdk/client-lambda';
|
|
3
9
|
import { Command } from 'commander';
|
|
4
10
|
import { validateNumber } from '../config/cli.constants.js';
|
|
5
11
|
import { auditLog } from '../utils/audit-log.js';
|
|
6
12
|
import { decodeTokenPayload } from '../utils/auth-guard.js';
|
|
7
13
|
import { upsertSecret, getSecretArn } from '../utils/aws-secrets.js';
|
|
8
14
|
import { createAuthenticatedClientAsync, printCommandHeader, printSslWarning } from '../utils/command-utils.js';
|
|
15
|
+
import { toEventBridgeCron } from '../utils/cron.js';
|
|
9
16
|
import { ERROR_CODES, handleError } from '../utils/error-handler.js';
|
|
10
17
|
import { printInfo, printKeyValue, printSection, printSuccess } from '../utils/output-utils.js';
|
|
11
18
|
import { ensurePlatformToken, resolveSecretName } from '../utils/platform-secret.js';
|
|
19
|
+
// ESM has no __dirname; derive it from this module's URL.
|
|
20
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const RENEW_STACK_NAME = 'pipeline-builder-token-renew';
|
|
22
|
+
// CFN-managed Lambda function name — keep in sync with token-renew-stack.json.
|
|
23
|
+
const RENEW_LAMBDA_NAME = 'pipeline-builder-token-renew';
|
|
24
|
+
// Default 5-field cron (daily at midnight) when neither --cron nor TOKEN_RENEW_SCHEDULE is set.
|
|
25
|
+
const DEFAULT_RENEW_CRON = '0 0 * * *';
|
|
26
|
+
/**
|
|
27
|
+
* Deploy (or update) the once-a-day token-renewal stack: a scheduled Lambda that
|
|
28
|
+
* re-mints the platform JWT in this same secret before it expires. Mirrors
|
|
29
|
+
* setup-events — `aws cloudformation deploy` for the infra, then a direct
|
|
30
|
+
* UpdateFunctionCode with the self-contained handler compiled alongside this CLI.
|
|
31
|
+
*/
|
|
32
|
+
async function deployRenewSchedule(opts) {
|
|
33
|
+
const scheduleExpression = toEventBridgeCron(opts.fiveFieldCron); // validates + 15-min guard
|
|
34
|
+
printSection('Schedule Renewal');
|
|
35
|
+
printInfo('Parameters', {
|
|
36
|
+
stack: RENEW_STACK_NAME,
|
|
37
|
+
schedule: opts.fiveFieldCron,
|
|
38
|
+
eventbridge: scheduleExpression,
|
|
39
|
+
renewDays: opts.days,
|
|
40
|
+
});
|
|
41
|
+
// Step 1: infra (Lambda gets placeholder code on first create).
|
|
42
|
+
const templatePath = path.join(__dirname, '../templates/token-renew-stack.json');
|
|
43
|
+
const cfnArgs = [
|
|
44
|
+
'cloudformation', 'deploy',
|
|
45
|
+
'--stack-name', RENEW_STACK_NAME,
|
|
46
|
+
'--template-file', templatePath,
|
|
47
|
+
'--parameter-overrides',
|
|
48
|
+
`PlatformBaseUrl=${opts.platformUrl}`,
|
|
49
|
+
`PlatformSecretName=${opts.secretName}`,
|
|
50
|
+
`RenewDays=${opts.days}`,
|
|
51
|
+
`ScheduleExpression=${scheduleExpression}`,
|
|
52
|
+
'--capabilities', 'CAPABILITY_NAMED_IAM',
|
|
53
|
+
'--no-fail-on-empty-changeset',
|
|
54
|
+
'--region', opts.region,
|
|
55
|
+
];
|
|
56
|
+
if (opts.profile)
|
|
57
|
+
cfnArgs.push('--profile', opts.profile);
|
|
58
|
+
execFileSync('aws', cfnArgs, { stdio: 'inherit' });
|
|
59
|
+
// Step 2: upload the real handler. It's ESM, so the zip entry must be index.mjs
|
|
60
|
+
// (Handler stays index.handler — nodejs24.x resolves the .mjs extension).
|
|
61
|
+
const handlerSrc = path.join(__dirname, '../lambda/token-renew-handler.js');
|
|
62
|
+
if (!fs.existsSync(handlerSrc)) {
|
|
63
|
+
throw new Error(`Token-renew handler not found at ${handlerSrc} — was the package built?`);
|
|
64
|
+
}
|
|
65
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'token-renew-'));
|
|
66
|
+
try {
|
|
67
|
+
fs.copyFileSync(handlerSrc, path.join(tmpDir, 'index.mjs'));
|
|
68
|
+
const zipPath = path.join(tmpDir, 'index.zip');
|
|
69
|
+
execFileSync('zip', ['-j', zipPath, 'index.mjs'], { cwd: tmpDir, stdio: 'pipe' });
|
|
70
|
+
const lambdaClient = new LambdaClient({ region: opts.region });
|
|
71
|
+
await lambdaClient.send(new UpdateFunctionCodeCommand({
|
|
72
|
+
FunctionName: RENEW_LAMBDA_NAME,
|
|
73
|
+
ZipFile: fs.readFileSync(zipPath),
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
78
|
+
}
|
|
79
|
+
printSuccess(`Renewal scheduled (${scheduleExpression})`);
|
|
80
|
+
return scheduleExpression;
|
|
81
|
+
}
|
|
12
82
|
/**
|
|
13
83
|
* Registers the `store-token` command with the CLI program.
|
|
14
84
|
*
|
|
@@ -37,6 +107,8 @@ export function storeToken(program) {
|
|
|
37
107
|
.option('--secret-name <name>', 'Secrets Manager secret name (default: derived from token org)')
|
|
38
108
|
.option('--region <region>', 'AWS region (defaults to AWS_REGION env)')
|
|
39
109
|
.option('--profile <profile>', 'AWS CLI profile', 'default')
|
|
110
|
+
.option('--cron <expr>', 'Renewal schedule as a 5-field cron (default: TOKEN_RENEW_SCHEDULE env or "0 0 * * *"; min every 15 minutes)')
|
|
111
|
+
.option('--no-schedule', 'Skip deploying the daily token-renewal stack (it is installed by default)')
|
|
40
112
|
.option('--json', 'Output result as JSON', false)
|
|
41
113
|
.option('--verify-ssl', 'Enable SSL certificate verification')
|
|
42
114
|
.option('--no-verify-ssl', 'Disable SSL certificate verification')
|
|
@@ -135,6 +207,21 @@ export function storeToken(program) {
|
|
|
135
207
|
const description = `Platform JWT token (renew by ${expiresAt})`;
|
|
136
208
|
await upsertSecret(secretName, secretValue, description, { region, profile: options.profile });
|
|
137
209
|
const arn = await getSecretArn(secretName, { region, profile: options.profile });
|
|
210
|
+
// Install the once-a-day renewal stack so this token never lapses (default
|
|
211
|
+
// on; opt out with --no-schedule). commander sets options.schedule=false for
|
|
212
|
+
// --no-schedule, true otherwise.
|
|
213
|
+
let scheduleExpression;
|
|
214
|
+
if (options.schedule !== false) {
|
|
215
|
+
const fiveFieldCron = options.cron || process.env.TOKEN_RENEW_SCHEDULE || DEFAULT_RENEW_CRON;
|
|
216
|
+
scheduleExpression = await deployRenewSchedule({
|
|
217
|
+
platformUrl: client.getBaseUrl(),
|
|
218
|
+
secretName,
|
|
219
|
+
days,
|
|
220
|
+
fiveFieldCron,
|
|
221
|
+
region,
|
|
222
|
+
profile: options.profile,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
138
225
|
if (options.json) {
|
|
139
226
|
console.log(JSON.stringify({
|
|
140
227
|
success: true,
|
|
@@ -143,6 +230,7 @@ export function storeToken(program) {
|
|
|
143
230
|
region,
|
|
144
231
|
expiresInDays: days,
|
|
145
232
|
expiresAt,
|
|
233
|
+
schedule: scheduleExpression ?? null,
|
|
146
234
|
}, null, 2));
|
|
147
235
|
}
|
|
148
236
|
else {
|
|
@@ -154,6 +242,7 @@ export function storeToken(program) {
|
|
|
154
242
|
'Region': region,
|
|
155
243
|
'Expires In': `${days} days`,
|
|
156
244
|
'Renew By': expiresAt,
|
|
245
|
+
'Auto-Renew': scheduleExpression ? `✓ ${scheduleExpression}` : 'disabled (--no-schedule)',
|
|
157
246
|
'Status': '✓ Stored',
|
|
158
247
|
});
|
|
159
248
|
console.log('');
|
|
@@ -161,7 +250,12 @@ export function storeToken(program) {
|
|
|
161
250
|
printInfo(` export PLATFORM_SECRET_NAME=${secretName}`);
|
|
162
251
|
printInfo(' pipeline-manager synth --id <pipeline-id> --store-tokens');
|
|
163
252
|
console.log('');
|
|
164
|
-
|
|
253
|
+
if (scheduleExpression) {
|
|
254
|
+
printInfo(`Auto-renewal is active (${scheduleExpression}); the secret refreshes before ${expiresAt}.`);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
printInfo(`Renew before ${expiresAt} with: pipeline-manager store-token --days ${days}`);
|
|
258
|
+
}
|
|
165
259
|
}
|
|
166
260
|
}
|
|
167
261
|
catch (error) {
|
|
@@ -177,4 +271,4 @@ export function storeToken(program) {
|
|
|
177
271
|
}
|
|
178
272
|
});
|
|
179
273
|
}
|
|
180
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUtdG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc3RvcmUtdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsOEJBQThCLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDaEgsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFckY7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLE9BQWdCO0lBQ3pDLE9BQU87U0FDSixPQUFPLENBQUMsYUFBYSxDQUFDO1NBQ3RCLFdBQVcsQ0FBQyx5RUFBeUUsQ0FBQztTQUN0RixNQUFNLENBQUMscUJBQXFCLEVBQUUsZ0RBQWdELENBQUM7U0FDL0UsTUFBTSxDQUFDLDJCQUEyQixFQUFFLG9DQUFvQyxDQUFDO1NBQ3pFLE1BQU0sQ0FBQyxlQUFlLEVBQUUsd0JBQXdCLEVBQUUsSUFBSSxDQUFDO1NBQ3ZELE1BQU0sQ0FBQyxXQUFXLEVBQUUs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IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCB7IHZhbGlkYXRlTnVtYmVyIH0gZnJvbSAnLi4vY29uZmlnL2NsaS5jb25zdGFudHMuanMnO1xuaW1wb3J0IHsgYXVkaXRMb2cgfSBmcm9tICcuLi91dGlscy9hdWRpdC1sb2cuanMnO1xuaW1wb3J0IHsgZGVjb2RlVG9rZW5QYXlsb2FkIH0gZnJvbSAnLi4vdXRpbHMvYXV0aC1ndWFyZC5qcyc7XG5pbXBvcnQgeyB1cHNlcnRTZWNyZXQsIGdldFNlY3JldEFybiB9IGZyb20gJy4uL3V0aWxzL2F3cy1zZWNyZXRzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYywgcHJpbnRDb21tYW5kSGVhZGVyLCBwcmludFNzbFdhcm5pbmcgfSBmcm9tICcuLi91dGlscy9jb21tYW5kLXV0aWxzLmpzJztcbmltcG9ydCB7IEVSUk9SX0NPREVTLCBoYW5kbGVFcnJvciB9IGZyb20gJy4uL3V0aWxzL2Vycm9yLWhhbmRsZXIuanMnO1xuaW1wb3J0IHsgcHJpbnRJbmZvLCBwcmludEtleVZhbHVlLCBwcmludFNlY3Rpb24sIHByaW50U3VjY2VzcyB9IGZyb20gJy4uL3V0aWxzL291dHB1dC11dGlscy5qcyc7XG5pbXBvcnQgeyBlbnN1cmVQbGF0Zm9ybVRva2VuLCByZXNvbHZlU2VjcmV0TmFtZSB9IGZyb20gJy4uL3V0aWxzL3BsYXRmb3JtLXNlY3JldC5qcyc7XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBgc3RvcmUtdG9rZW5gIGNvbW1hbmQgd2l0aCB0aGUgQ0xJIHByb2dyYW0uXG4gKlxuICogR2VuZXJhdGVzIGEgbG9uZy1saXZlZCBKV1QgdG9rZW4gdmlhIHRoZSBwbGF0Zm9ybSBBUEkgYW5kIHN0b3JlcyBpdFxuICogaW4gQVdTIFNlY3JldHMgTWFuYWdlciBmb3IgdXNlIGJ5IHRoZSBzeW50aC9kZXBsb3kgLS1zdG9yZS10b2tlbnMgZmxhZy5cbiAqXG4gKiBSZXF1aXJlcyBQTEFURk9STV9UT0tFTiB0byBiZSBzZXQsIG9yIHVzZSAtLWVtYWlsLy0tcGFzc3dvcmQgdG8gbG9naW4gaW5saW5lLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBiYXNoXG4gKiBwaXBlbGluZS1tYW5hZ2VyIHN0b3JlLXRva2VuIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogcGlwZWxpbmUtbWFuYWdlciBzdG9yZS10b2tlbiAtLWRheXMgOTAgLS1yZWdpb24gdXMtZWFzdC0xXG4gKiBwaXBlbGluZS1tYW5hZ2VyIHN0b3JlLXRva2VuIC0tZGF5cyA3IC0tc2VjcmV0LW5hbWUgbXktY3VzdG9tLXNlY3JldCAtLW5vLXZlcmlmeS1zc2xcbiAqIHBpcGVsaW5lLW1hbmFnZXIgc3RvcmUtdG9rZW4gLS1kcnktcnVuXG4gKiBwaXBlbGluZS1tYW5hZ2VyIHN0b3JlLXRva2VuIC1lIGFkbWluIC1wICcqKionIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdG9yZVRva2VuKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKCdzdG9yZS10b2tlbicpXG4gICAgLmRlc2NyaXB0aW9uKCdHZW5lcmF0ZSBKV1QgdG9rZW4gYW5kIHN0b3JlIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIENESyBkZXBsb3ltZW50cycpXG4gICAgLm9wdGlvbignLWUsIC0tZW1haWwgPGVtYWlsPicsICdMb2dpbiBlbWFpbCAoc2tpcHMgUExBVEZPUk1fVE9LRU4gcmVxdWlyZW1lbnQpJylcbiAgICAub3B0aW9uKCctcCwgLS1wYXNzd29yZCA8cGFzc3dvcmQ+JywgJ0xvZ2luIHBhc3N3b3JkICh1c2VkIHdpdGggLS1lbWFpbCknKVxuICAgIC5vcHRpb24oJy0tZGF5cyA8ZGF5cz4nLCAnVG9rZW4gbGlmZXRpbWUgaW4gZGF5cycsICczMCcpXG4gICAgLm9wdGlvbignLS1kcnktcnVuJywgJ1Nob3cgd2hhdCB3b3VsZCBiZSBzdG9yZWQgd2l0aG91dCB3cml0aW5nIHRvIFNlY3JldHMgTWFuYWdlcicsIGZhbHNlKVxuICAgIC5vcHRpb24oJy0tc2VjcmV0LW5hbWUgPG5hbWU+JywgJ1NlY3JldHMgTWFuYWdlciBzZWNyZXQgbmFtZSAoZGVmYXVsdDogZGVyaXZlZCBmcm9tIHRva2VuIG9yZyknKVxuICAgIC5vcHRpb24oJy0tcmVnaW9uIDxyZWdpb24+JywgJ0FXUyByZWdpb24gKGRlZmF1bHRzIHRvIEFXU19SRUdJT04gZW52KScpXG4gICAgLm9wdGlvbignLS1wcm9maWxlIDxwcm9maWxlPicsICdBV1MgQ0xJIHByb2ZpbGUnLCAnZGVmYXVsdCcpXG4gICAgLm9wdGlvbignLS1qc29uJywgJ091dHB1dCByZXN1bHQgYXMgSlNPTicsIGZhbHNlKVxuICAgIC5vcHRpb24oJy0tdmVyaWZ5LXNzbCcsICdFbmFibGUgU1NMIGNlcnRpZmljYXRlIHZlcmlmaWNhdGlvbicpXG4gICAgLm9wdGlvbignLS1uby12ZXJpZnktc3NsJywgJ0Rpc2FibGUgU1NMIGNlcnRpZmljYXRlIHZlcmlmaWNhdGlvbicpXG4gICAgLmFjdGlvbihhc3luYyAob3B0aW9ucykgPT4ge1xuICAgICAgY29uc3QgZXhlY3V0aW9uSWQgPSBwcmludENvbW1hbmRIZWFkZXIoJ1N0b3JlIFRva2VuJyk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHByaW50U3NsV2FybmluZyhvcHRpb25zLnZlcmlmeVNzbCk7XG5cbiAgICAgICAgY29uc3QgcmVnaW9uID0gb3B0aW9ucy5yZWdpb24gfHwgcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTiB8fCBwcm9jZXNzLmVudi5DREtfREVGQVVMVF9SRUdJT04gfHwgJ3VzLWVhc3QtMSc7XG5cbiAgICAgICAgY29uc3QgZGF5cyA9IHZhbGlkYXRlTnVtYmVyKG9wdGlvbnMuZGF5cywgJ2RheXMnLCAxLCAzNjUpO1xuICAgICAgICBjb25zdCBleHBpcmVzSW5TZWNvbmRzID0gZGF5cyAqIDI0ICogNjAgKiA2MDtcblxuICAgICAgICAvLyBTdGVwIDA6IGxvZyBpbiBmaXJzdCB3aGVuIGNyZWRzIGFyZSBhdmFpbGFibGUgYW5kIG5vIFBMQVRGT1JNX1RPS0VOIGlzIHNldFxuICAgICAgICAvLyAoc2hhcmVkIHdpdGggc2V0dXAtZXZlbnRzKS4gQ3JlZHMgY29tZSBmcm9tIC0tZW1haWwvLS1wYXNzd29yZCBPUiB0aGUgZW52XG4gICAgICAgIC8vIHZhcnMgUExBVEZPUk1fSURFTlRJRklFUi9QTEFURk9STV9QQVNTV09SRCDigJQgdGhlIGVudiBwYXRoIGxldHMgY2FsbGVycyBsaWtlXG4gICAgICAgIC8vIGBwcm92aXNpb24gLS13aXRoLWV2ZW50c2AgcGFzcyB0aGVtIHdpdGhvdXQgcHV0dGluZyB0aGUgcGFzc3dvcmQgb24gdGhlXG4gICAgICAgIC8vIGNvbW1hbmQgbGluZSAod2hlcmUgaXQgd291bGQgc2hvdyBpbiBwbGFucy9sb2dzKS5cbiAgICAgICAgYXdhaXQgZW5zdXJlUGxhdGZvcm1Ub2tlbihvcHRpb25zKTtcblxuICAgICAgICAvLyBTdGVwIDE6IEF1dGhlbnRpY2F0ZSBhbmQgZ2VuZXJhdGUgbG9uZy1saXZlZCB0b2tlblxuICAgICAgICBwcmludFNlY3Rpb24oJ0dlbmVyYXRlIFRva2VuJyk7XG5cbiAgICAgICAgY29uc3QgY2xpZW50ID0gYXdhaXQgY3JlYXRlQXV0aGVudGljYXRlZENsaWVudEFzeW5jKG9wdGlvbnMpO1xuXG4gICAgICAgIC8vIFJlc29sdmUgc2VjcmV0IG5hbWUgZnJvbSB0b2tlbidzIG9yZ2FuaXphdGlvbklkICh1bmxlc3MgLS1zZWNyZXQtbmFtZSB3YXMgZXhwbGljaXRseSBzZXQpXG4gICAgICAgIGNvbnN0IHNlY3JldE5hbWUgPSBvcHRpb25zLnNlY3JldE5hbWUgfHwgcmVzb2x2ZVNlY3JldE5hbWUocHJvY2Vzcy5lbnYuUExBVEZPUk1fVE9LRU4hKTtcblxuICAgICAgICBhdWRpdExvZygnc3RvcmUtdG9rZW4nLCB7IGV4ZWN1dGlvbklkLCBzZWNyZXROYW1lLCBkYXlzOiBvcHRpb25zLmRheXMsIGRyeVJ1bjogb3B0aW9ucy5kcnlSdW4gfSk7XG5cbiAgICAgICAgcHJpbnRJbmZvKCdQYXJhbWV0ZXJzJywge1xuICAgICAgICAgIHNlY3JldE5hbWUsXG4gICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgIGRheXMsXG4gICAgICAgICAgZXhwaXJlc0luOiBgJHtleHBpcmVzSW5TZWNvbmRzfXNgLFxuICAgICAgICAgIGRyeVJ1bjogb3B0aW9ucy5kcnlSdW4sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByaW50SW5mbygnUmVxdWVzdGluZyB0b2tlbicsIHsgZXhwaXJlc0luOiBgJHtleHBpcmVzSW5TZWNvbmRzfXMgKCR7ZGF5c30gZGF5cylgIH0pO1xuXG4gICAgICAgIGNvbnN0IHRva2VuUmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdDxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgICAgICAgJy9hcGkvdXNlci9nZW5lcmF0ZS10b2tlbicsXG4gICAgICAgICAgeyBleHBpcmVzSW46IGV4cGlyZXNJblNlY29uZHMgfSxcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCB0b2tlbkRhdGEgPSAodG9rZW5SZXNwb25zZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik/LmRhdGEgPz8gdG9rZW5SZXNwb25zZTtcbiAgICAgICAgY29uc3QgYWNjZXNzVG9rZW4gPSAodG9rZW5EYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KT8uYWNjZXNzVG9rZW4gYXMgc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCByZWZyZXNoVG9rZW4gPSAodG9rZW5EYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KT8ucmVmcmVzaFRva2VuIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgYWN0dWFsRXhwaXJlc0luID0gKCh0b2tlbkRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pPy5leHBpcmVzSW4gYXMgbnVtYmVyKSA/PyBleHBpcmVzSW5TZWNvbmRzO1xuXG4gICAgICAgIGlmICghYWNjZXNzVG9rZW4pIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Rva2VuIGdlbmVyYXRpb24gZmFpbGVkIOKAlCBubyBhY2Nlc3MgdG9rZW4gaW4gcmVzcG9uc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByaW50U3VjY2VzcyhgVG9rZW4gZ2VuZXJhdGVkIChleHBpcmVzIGluICR7YWN0dWFsRXhwaXJlc0lufXMpYCk7XG5cbiAgICAgICAgY29uc3QgZXhwaXJlc0F0ID0gbmV3IERhdGUoRGF0ZS5ub3coKSArIGFjdHVhbEV4cGlyZXNJbiAqIDEwMDApLnRvSVNPU3RyaW5nKCk7XG5cbiAgICAgICAgLy8gU2NoZW1hOiB7IHVzZXJuYW1lOiBvcmdJZCwgcGFzc3dvcmQ6IEpXVCwgLi4ubWV0YWRhdGEgfVxuICAgICAgICAvLyAtIHVzZXJuYW1lL3Bhc3N3b3JkIGZpZWxkcyBzYXRpc2Z5IENvZGVCdWlsZCdzIGBzZWNyZXRzTWFuYWdlckNyZWRlbnRpYWxzYFxuICAgICAgICAvLyAgIChIVFRQIEJhc2ljLCBzZW50IHRvIHBpcGVsaW5lLWltYWdlLXJlZ2lzdHJ5J3MgL3Rva2VuIGVuZHBvaW50KVxuICAgICAgICAvLyAtIFRoZSBzYW1lIEpXVCBpcyBjb25zdW1lZCBieSB0aGUgcGx1Z2luLWxvb2t1cCBMYW1iZGEgYnkgcmVhZGluZ1xuICAgICAgICAvLyAgIHRoZSBgcGFzc3dvcmRgIGZpZWxkXG4gICAgICAgIC8vIC0gT25lIFNlY3JldCBwZXIgY3VzdG9tZXIgYWNjb3VudCByZXBsYWNlcyB0aGUgcHJldmlvdXMgdHdvLXNlY3JldCBtb2RlbFxuICAgICAgICAvLyBEZWNvZGUgSldUIGZvciBvcmdJZCDigJQgaXQncyBhIHN0YWJsZSBpZGVudGlmaWVyIGZvciB0aGUgdXNlcm5hbWUgZmllbGQ7XG4gICAgICAgIC8vIHRoZSBhY3R1YWwgYXV0aCB1c2VzIHRoZSBwYXNzd29yZCAoSldUKSB3aGljaCB0aGUgdG9rZW4gc2VydmljZSB2ZXJpZmllcy5cbiAgICAgICAgLy8gYHx8YCAobm90IGA/P2ApOiBhbiBFTVBUWS1zdHJpbmcgb3JnYW5pemF0aW9uSWQgbXVzdCBhbHNvIGZhbGwgYmFjay4gQVxuICAgICAgICAvLyBzeXNhZG1pbi9zeXN0ZW0gdG9rZW4gb2Z0ZW4gY2FycmllcyBvcmdhbml6YXRpb25JZD1cIlwiLCBhbmQgQ29kZUJ1aWxkXG4gICAgICAgIC8vIHJlamVjdHMgYSByZWdpc3RyeSBjcmVkZW50aWFsIHdob3NlIGB1c2VybmFtZWAgZmllbGQgaXMgZW1wdHkgd2l0aFxuICAgICAgICAvLyBcIkF1dGhvcml6YXRpb25EYXRhIGlzIG1hbGZvcm1lZCwgZW1wdHkgZmllbGRcIiDigJQgc28gdXNlcm5hbWUgbXVzdCBhbHdheXNcbiAgICAgICAgLy8gYmUgYSBub24tZW1wdHkgdmFsdWUuXG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSBkZWNvZGVUb2tlblBheWxvYWQoYWNjZXNzVG9rZW4pO1xuICAgICAgICBjb25zdCBvcmdJZCA9IHBheWxvYWQ/Lm9yZ2FuaXphdGlvbklkPy50cmltKCkgfHwgJ3Vua25vd24tb3JnJztcblxuICAgICAgICBjb25zdCBzZWNyZXRWYWx1ZSA9IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICB1c2VybmFtZTogb3JnSWQsXG4gICAgICAgICAgcGFzc3dvcmQ6IGFjY2Vzc1Rva2VuLFxuICAgICAgICAgIC4uLihyZWZyZXNoVG9rZW4gJiYgeyByZWZyZXNoVG9rZW4gfSksXG4gICAgICAgICAgcGxhdGZvcm1Vcmw6IGNsaWVudC5nZXRCYXNlVXJsKCksXG4gICAgICAgICAgZXhwaXJlc0luOiBhY3R1YWxFeHBpcmVzSW4sXG4gICAgICAgICAgZXhwaXJlc0F0LFxuICAgICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBEcnktcnVuOiBzaG93IHdoYXQgd291bGQgYmUgc3RvcmVkXG4gICAgICAgIGlmIChvcHRpb25zLmRyeVJ1bikge1xuICAgICAgICAgIGlmIChvcHRpb25zLmpzb24pIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgICAgZHJ5UnVuOiB0cnVlLFxuICAgICAgICAgICAgICBzZWNyZXROYW1lLFxuICAgICAgICAgICAgICByZWdpb24sXG4gICAgICAgICAgICAgIGV4cGlyZXNJbkRheXM6IGRheXMsXG4gICAgICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICAgICAgdG9rZW5MZW5ndGg6IGFjY2Vzc1Rva2VuLmxlbmd0aCxcbiAgICAgICAgICAgICAgaGFzUmVmcmVzaFRva2VuOiAhIXJlZnJlc2hUb2tlbixcbiAgICAgICAgICAgIH0sIG51bGwsIDIpKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgICAgcHJpbnRTZWN0aW9uKCdEcnkgUnVuIOKAlCBObyBDaGFuZ2VzIE1hZGUnKTtcbiAgICAgICAgICAgIHByaW50S2V5VmFsdWUoe1xuICAgICAgICAgICAgICAnU2VjcmV0IE5hbWUnOiBzZWNyZXROYW1lLFxuICAgICAgICAgICAgICAnUmVnaW9uJzogcmVnaW9uLFxuICAgICAgICAgICAgICAnRXhwaXJlcyBJbic6IGAke2RheXN9IGRheXNgLFxuICAgICAgICAgICAgICAnUmVuZXcgQnknOiBleHBpcmVzQXQsXG4gICAgICAgICAgICAgICdUb2tlbiBMZW5ndGgnOiBgJHthY2Nlc3NUb2tlbi5sZW5ndGh9IGNoYXJzYCxcbiAgICAgICAgICAgICAgJ0hhcyBSZWZyZXNoIFRva2VuJzogcmVmcmVzaFRva2VuID8gJ1llcycgOiAnTm8nLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwcmludFN1Y2Nlc3MoJ0RyeSBydW4gY29tcGxldGUg4oCUIG5vIHNlY3JldCB3YXMgY3JlYXRlZCBvciB1cGRhdGVkJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0ZXAgMjogU3RvcmUgdG9rZW4gaW4gU2VjcmV0cyBNYW5hZ2VyXG4gICAgICAgIHByaW50U2VjdGlvbignU3RvcmUgVG9rZW4nKTtcblxuICAgICAgICBjb25zdCBkZXNjcmlwdGlvbiA9IGBQbGF0Zm9ybSBKV1QgdG9rZW4gKHJlbmV3IGJ5ICR7ZXhwaXJlc0F0fSlgO1xuICAgICAgICBhd2FpdCB1cHNlcnRTZWNyZXQoc2VjcmV0TmFtZSwgc2VjcmV0VmFsdWUsIGRlc2NyaXB0aW9uLCB7IHJlZ2lvbiwgcHJvZmlsZTogb3B0aW9ucy5wcm9maWxlIH0pO1xuXG4gICAgICAgIGNvbnN0IGFybiA9IGF3YWl0IGdldFNlY3JldEFybihzZWNyZXROYW1lLCB7IHJlZ2lvbiwgcHJvZmlsZTogb3B0aW9ucy5wcm9maWxlIH0pO1xuXG4gICAgICAgIGlmIChvcHRpb25zLmpzb24pIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgIHNlY3JldEFybjogYXJuLFxuICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgZXhwaXJlc0luRGF5czogZGF5cyxcbiAgICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICB9LCBudWxsLCAyKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U2VjdGlvbignVG9rZW4gU3RvcmVkJyk7XG5cbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICdTZWNyZXQgTmFtZSc6IHNlY3JldE5hbWUsXG4gICAgICAgICAgICAnU2VjcmV0IEFSTic6IGFybixcbiAgICAgICAgICAgICdSZWdpb24nOiByZWdpb24sXG4gICAgICAgICAgICAnRXhwaXJlcyBJbic6IGAke2RheXN9IGRheXNgLFxuICAgICAgICAgICAgJ1JlbmV3IEJ5JzogZXhwaXJlc0F0LFxuICAgICAgICAgICAgJ1N0YXR1cyc6ICfinJMgU3RvcmVkJyxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICBwcmludFN1Y2Nlc3MoJ1Rva2VuIHN0b3JlZC4gVG8gdXNlIHdpdGggc3ludGgvZGVwbG95OicpO1xuICAgICAgICAgIHByaW50SW5mbyhgICBleHBvcnQgUExBVEZPUk1fU0VDUkVUX05BTUU9JHtzZWNyZXROYW1lfWApO1xuICAgICAgICAgIHByaW50SW5mbygnICBwaXBlbGluZS1tYW5hZ2VyIHN5bnRoIC0taWQgPHBpcGVsaW5lLWlkPiAtLXN0b3JlLXRva2VucycpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICBwcmludEluZm8oYFJlbmV3IGJlZm9yZSAke2V4cGlyZXNBdH0gd2l0aDogcGlwZWxpbmUtbWFuYWdlciBzdG9yZS10b2tlbiAtLWRheXMgJHtkYXlzfWApO1xuICAgICAgICB9XG5cbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGhhbmRsZUVycm9yKGVycm9yLCBFUlJPUl9DT0RFUy5BUElfUkVRVUVTVCwge1xuICAgICAgICAgIGRlYnVnOiBwcm9ncmFtLm9wdHMoKS5kZWJ1ZyxcbiAgICAgICAgICBleGl0OiB0cnVlLFxuICAgICAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgICAgIGNvbW1hbmQ6ICdzdG9yZS10b2tlbicsXG4gICAgICAgICAgICBleGVjdXRpb25JZCxcbiAgICAgICAgICAgIHNlY3JldE5hbWU6IG9wdGlvbnMuc2VjcmV0TmFtZSB8fCAnKGRlcml2ZWQgZnJvbSB0b2tlbiknLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xufVxuIl19
|
|
274
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUtdG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29tbWFuZHMvc3RvcmUtdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sS0FBSyxFQUFFLE1BQU0sSUFBSSxDQUFDO0FBQ3pCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDekMsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQ3hCLE9BQU8sRUFBRSxZQUFZLEVBQUUseUJBQXlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNqRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3BDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDakQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDNUQsT0FBTyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsOEJBQThCLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDaEgsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDckQsT0FBTyxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFckYsMERBQTBEO0FBQzFELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUUvRCxNQUFNLGdCQUFnQixHQUFHLDhCQUE4QixDQUFDO0FBQ3hELCtFQUErRTtBQUMvRSxNQUFNLGlCQUFpQixHQUFHLDhCQUE4QixDQUFDO0FBQ3pELGdHQUFnRztBQUNoRyxNQUFNLGtCQUFrQixHQUFHLFdBQVcsQ0FBQztBQUV2Qzs7Ozs7R0FLRztBQUNILEtBQUssVUFBVSxtQkFBbUIsQ0FBQyxJQU9sQztJQUNDLE1BQU0sa0JBQWtCLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsMkJBQTJCO0lBRTdGLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ2pDLFNBQVMsQ0FBQyxZQUFZLEVBQUU7UUFDdEIsS0FBSyxFQUFFLGdCQUFnQjtRQUN2QixRQUFRLEVBQUUsSUFBSSxDQUFDLGFBQWE7UUFDNUIsV0FBVyxFQUFFLGtCQUFrQjtRQUMvQixTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUk7S0FDckIsQ0FBQyxDQUFDO0lBRUgsZ0VBQWdFO0lBQ2hFLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLHFDQUFxQyxDQUFDLENBQUM7SUFDakYsTUFBTSxPQUFPLEdBQUc7UUFDZCxnQkFBZ0IsRUFBRSxRQUFRO1FBQzFCLGNBQWMsRUFBRSxnQkFBZ0I7UUFDaEMsaUJBQWlCLEVBQUUsWUFBWTtRQUMvQix1QkFBdUI7UUFDdkIsbUJBQW1CLElBQUksQ0FBQyxXQUFXLEVBQUU7UUFDckMsc0JBQXNCLElBQUksQ0FBQyxVQUFVLEVBQUU7UUFDdkMsYUFBYSxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQ3hCLHNCQUFzQixrQkFBa0IsRUFBRTtRQUMxQyxnQkFBZ0IsRUFBRSxzQkFBc0I7UUFDeEMsOEJBQThCO1FBQzlCLFVBQVUsRUFBRSxJQUFJLENBQUMsTUFBTTtLQUN4QixDQUFDO0lBQ0YsSUFBSSxJQUFJLENBQUMsT0FBTztRQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxRCxZQUFZLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBRW5ELGdGQUFnRjtJQUNoRiwwRUFBMEU7SUFDMUUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztJQUM1RSxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQy9CLE1BQU0sSUFBSSxLQUFLLENBQUMsb0NBQW9DLFVBQVUsMkJBQTJCLENBQUMsQ0FBQztJQUM3RixDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3RFLElBQUksQ0FBQztRQUNILEVBQUUsQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7UUFDNUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUM7UUFDL0MsWUFBWSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsV0FBVyxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBRWxGLE1BQU0sWUFBWSxHQUFHLElBQUksWUFBWSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQy9ELE1BQU0sWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLHlCQUF5QixDQUFDO1lBQ3BELFlBQVksRUFBRSxpQkFBaUI7WUFDL0IsT0FBTyxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDO1NBQ2xDLENBQUMsQ0FBQyxDQUFDO0lBQ04sQ0FBQztZQUFTLENBQUM7UUFDVCxFQUFFLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVELFlBQVksQ0FBQyxzQkFBc0Isa0JBQWtCLEdBQUcsQ0FBQyxDQUFDO0lBQzFELE9BQU8sa0JBQWtCLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxPQUFnQjtJQUN6QyxPQUFPO1NBQ0osT0FBTyxDQUFDLGFBQWEsQ0FBQztTQUN0QixXQUFXLENBQUMseUVBQXlFLENBQUM7U0FDdEYsTUFBTSxDQUFDLHFCQUFxQixFQUFFLGdEQUFnRCxDQUFDO1NBQy9FLE1BQU0sQ0FBQywyQkFBMkIsRUFBRSxvQ0FBb0MsQ0FBQztTQUN6RSxNQUFNLENBQUMsZUFBZSxFQUFFLHdCQUF3QixFQUFFLElBQUksQ0FBQztTQUN2RCxNQUFNLENBQUMsV0FBVyxFQUFFLDhEQUE4RCxFQUFFLEtBQUssQ0FBQztTQUMxRixNQUFNLENBQUMsc0JBQXNCLEVBQUUsK0RBQStELENBQUM7U0FDL0YsTUFBTSxDQUFDLG1CQUFtQixFQUFFLHlDQUF5QyxDQUFDO1NBQ3RFLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLENBQUM7U0FDM0QsTUFBTSxDQUFDLGVBQWUsRUFBRSw2R0FBNkcsQ0FBQztTQUN0SSxNQUFNLENBQUMsZUFBZSxFQUFFLDJFQUEyRSxDQUFDO1NBQ3BHLE1BQU0sQ0FBQyxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsS0FBSyxDQUFDO1NBQ2hELE1BQU0sQ0FBQyxjQUFjLEVBQUUscUNBQXFDLENBQUM7U0FDN0QsTUFBTSxDQUFDLGlCQUFpQixFQUFFLHNDQUFzQyxDQUFDO1NBQ2pFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7UUFDeEIsTUFBTSxXQUFXLEdBQUcsa0JBQWtCLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFdEQsSUFBSSxDQUFDO1lBQ0gsZUFBZSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUVuQyxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLElBQUksV0FBVyxDQUFDO1lBRXpHLE1BQU0sSUFBSSxHQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDMUQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFFN0MsNkVBQTZFO1lBQzdFLDRFQUE0RTtZQUM1RSw4RUFBOEU7WUFDOUUsMEVBQTBFO1lBQzFFLG9EQUFvRDtZQUNwRCxNQUFNLG1CQUFtQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRW5DLHFEQUFxRDtZQUNyRCxZQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUUvQixNQUFNLE1BQU0sR0FBRyxNQUFNLDhCQUE4QixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRTdELDRGQUE0RjtZQUM1RixNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsVUFBVSxJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBZSxDQUFDLENBQUM7WUFFeEYsUUFBUSxDQUFDLGFBQWEsRUFBRSxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1lBRWpHLFNBQVMsQ0FBQyxZQUFZLEVBQUU7Z0JBQ3RCLFVBQVU7Z0JBQ1YsTUFBTTtnQkFDTixJQUFJO2dCQUNKLFNBQVMsRUFBRSxHQUFHLGdCQUFnQixHQUFHO2dCQUNqQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07YUFDdkIsQ0FBQyxDQUFDO1lBRUgsU0FBUyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsU0FBUyxFQUFFLEdBQUcsZ0JBQWdCLE1BQU0sSUFBSSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBRXBGLE1BQU0sYUFBYSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FDckMsMEJBQTBCLEVBQzFCLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLENBQ2hDLENBQUM7WUFFRixNQUFNLFNBQVMsR0FBSSxhQUF5QyxFQUFFLElBQUksSUFBSSxhQUFhLENBQUM7WUFDcEYsTUFBTSxXQUFXLEdBQUksU0FBcUMsRUFBRSxXQUFpQyxDQUFDO1lBQzlGLE1BQU0sWUFBWSxHQUFJLFNBQXFDLEVBQUUsWUFBa0MsQ0FBQztZQUNoRyxNQUFNLGVBQWUsR0FBSyxTQUFxQyxFQUFFLFNBQW9CLElBQUksZ0JBQWdCLENBQUM7WUFFMUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7WUFDM0UsQ0FBQztZQUVELFlBQVksQ0FBQywrQkFBK0IsZUFBZSxJQUFJLENBQUMsQ0FBQztZQUVqRSxNQUFNLFNBQVMsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsZUFBZSxHQUFHLElBQUksQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBRTlFLDBEQUEwRDtZQUMxRCw2RUFBNkU7WUFDN0Usb0VBQW9FO1lBQ3BFLG9FQUFvRTtZQUNwRSx5QkFBeUI7WUFDekIsMkVBQTJFO1lBQzNFLDBFQUEwRTtZQUMxRSw0RUFBNEU7WUFDNUUseUVBQXlFO1lBQ3pFLHVFQUF1RTtZQUN2RSxxRUFBcUU7WUFDckUsMEVBQTBFO1lBQzFFLHdCQUF3QjtZQUN4QixNQUFNLE9BQU8sR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNoRCxNQUFNLEtBQUssR0FBRyxPQUFPLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxJQUFJLGFBQWEsQ0FBQztZQUUvRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNqQyxRQUFRLEVBQUUsS0FBSztnQkFDZixRQUFRLEVBQUUsV0FBVztnQkFDckIsR0FBRyxDQUFDLFlBQVksSUFBSSxFQUFFLFlBQVksRUFBRSxDQUFDO2dCQUNyQyxXQUFXLEVBQUUsTUFBTSxDQUFDLFVBQVUsRUFBRTtnQkFDaEMsU0FBUyxFQUFFLGVBQWU7Z0JBQzFCLFNBQVM7Z0JBQ1QsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO2FBQ3BDLENBQUMsQ0FBQztZQUVILHFDQUFxQztZQUNyQyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDbkIsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQ2pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQzt3QkFDekIsT0FBTyxFQUFFLElBQUk7d0JBQ2IsTUFBTSxFQUFFLElBQUk7d0JBQ1osVUFBVTt3QkFDVixNQUFNO3dCQUNOLGFBQWEsRUFBRSxJQUFJO3dCQUNuQixTQUFTO3dCQUNULFdBQVcsRUFBRSxXQUFXLENBQUMsTUFBTTt3QkFDL0IsZUFBZSxFQUFFLENBQUMsQ0FBQyxZQUFZO3FCQUNoQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNmLENBQUM7cUJBQU0sQ0FBQztvQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO29CQUNoQixZQUFZLENBQUMsMkJBQTJCLENBQUMsQ0FBQztvQkFDMUMsYUFBYSxDQUFDO3dCQUNaLGFBQWEsRUFBRSxVQUFVO3dCQUN6QixRQUFRLEVBQUUsTUFBTTt3QkFDaEIsWUFBWSxFQUFFLEdBQUcsSUFBSSxPQUFPO3dCQUM1QixVQUFVLEVBQUUsU0FBUzt3QkFDckIsY0FBYyxFQUFFLEdBQUcsV0FBVyxDQUFDLE1BQU0sUUFBUTt3QkFDN0MsbUJBQW1CLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7cUJBQ2pELENBQUMsQ0FBQztvQkFDSCxZQUFZLENBQUMscURBQXFELENBQUMsQ0FBQztnQkFDdEUsQ0FBQztnQkFDRCxPQUFPO1lBQ1QsQ0FBQztZQUVELHlDQUF5QztZQUN6QyxZQUFZLENBQUMsYUFBYSxDQUFDLENBQUM7WUFFNUIsTUFBTSxXQUFXLEdBQUcsZ0NBQWdDLFNBQVMsR0FBRyxDQUFDO1lBQ2pFLE1BQU0sWUFBWSxDQUFDLFVBQVUsRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUUvRixNQUFNLEdBQUcsR0FBRyxNQUFNLFlBQVksQ0FBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBRWpGLDJFQUEyRTtZQUMzRSw2RUFBNkU7WUFDN0UsaUNBQWlDO1lBQ2pDLElBQUksa0JBQXNDLENBQUM7WUFDM0MsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLEtBQUssRUFBRSxDQUFDO2dCQUMvQixNQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLElBQUksa0JBQWtCLENBQUM7Z0JBQzdGLGtCQUFrQixHQUFHLE1BQU0sbUJBQW1CLENBQUM7b0JBQzdDLFdBQVcsRUFBRSxNQUFNLENBQUMsVUFBVSxFQUFFO29CQUNoQyxVQUFVO29CQUNWLElBQUk7b0JBQ0osYUFBYTtvQkFDYixNQUFNO29CQUNOLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztpQkFDekIsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUVELElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNqQixPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQ3pCLE9BQU8sRUFBRSxJQUFJO29CQUNiLFVBQVU7b0JBQ1YsU0FBUyxFQUFFLEdBQUc7b0JBQ2QsTUFBTTtvQkFDTixhQUFhLEVBQUUsSUFBSTtvQkFDbkIsU0FBUztvQkFDVCxRQUFRLEVBQUUsa0JBQWtCLElBQUksSUFBSTtpQkFDckMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNmLENBQUM7aUJBQU0sQ0FBQztnQkFDTixPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQixZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBRTdCLGFBQWEsQ0FBQztvQkFDWixhQUFhLEVBQUUsVUFBVTtvQkFDekIsWUFBWSxFQUFFLEdBQUc7b0JBQ2pCLFFBQVEsRUFBRSxNQUFNO29CQUNoQixZQUFZLEVBQUUsR0FBRyxJQUFJLE9BQU87b0JBQzVCLFVBQVUsRUFBRSxTQUFTO29CQUNyQixZQUFZLEVBQUUsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLEtBQUssa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUMsMEJBQTBCO29CQUN6RixRQUFRLEVBQUUsVUFBVTtpQkFDckIsQ0FBQyxDQUFDO2dCQUVILE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ2hCLFlBQVksQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO2dCQUN4RCxTQUFTLENBQUMsaUNBQWlDLFVBQVUsRUFBRSxDQUFDLENBQUM7Z0JBQ3pELFNBQVMsQ0FBQyw0REFBNEQsQ0FBQyxDQUFDO2dCQUN4RSxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNoQixJQUFJLGtCQUFrQixFQUFFLENBQUM7b0JBQ3ZCLFNBQVMsQ0FBQywyQkFBMkIsa0JBQWtCLGtDQUFrQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO2dCQUN6RyxDQUFDO3FCQUFNLENBQUM7b0JBQ04sU0FBUyxDQUFDLGdCQUFnQixTQUFTLDhDQUE4QyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUMzRixDQUFDO1lBQ0gsQ0FBQztRQUVILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsV0FBVyxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUMsV0FBVyxFQUFFO2dCQUMxQyxLQUFLLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLEtBQUs7Z0JBQzNCLElBQUksRUFBRSxJQUFJO2dCQUNWLE9BQU8sRUFBRTtvQkFDUCxPQUFPLEVBQUUsYUFBYTtvQkFDdEIsV0FBVztvQkFDWCxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVUsSUFBSSxzQkFBc0I7aUJBQ3pEO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBleGVjRmlsZVN5bmMgfSBmcm9tICdjaGlsZF9wcm9jZXNzJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCB7IGZpbGVVUkxUb1BhdGggfSBmcm9tICdub2RlOnVybCc7XG5pbXBvcnQgKiBhcyBvcyBmcm9tICdvcyc7XG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IExhbWJkYUNsaWVudCwgVXBkYXRlRnVuY3Rpb25Db2RlQ29tbWFuZCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1sYW1iZGEnO1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gJ2NvbW1hbmRlcic7XG5pbXBvcnQgeyB2YWxpZGF0ZU51bWJlciB9IGZyb20gJy4uL2NvbmZpZy9jbGkuY29uc3RhbnRzLmpzJztcbmltcG9ydCB7IGF1ZGl0TG9nIH0gZnJvbSAnLi4vdXRpbHMvYXVkaXQtbG9nLmpzJztcbmltcG9ydCB7IGRlY29kZVRva2VuUGF5bG9hZCB9IGZyb20gJy4uL3V0aWxzL2F1dGgtZ3VhcmQuanMnO1xuaW1wb3J0IHsgdXBzZXJ0U2VjcmV0LCBnZXRTZWNyZXRBcm4gfSBmcm9tICcuLi91dGlscy9hd3Mtc2VjcmV0cy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVBdXRoZW50aWNhdGVkQ2xpZW50QXN5bmMsIHByaW50Q29tbWFuZEhlYWRlciwgcHJpbnRTc2xXYXJuaW5nIH0gZnJvbSAnLi4vdXRpbHMvY29tbWFuZC11dGlscy5qcyc7XG5pbXBvcnQgeyB0b0V2ZW50QnJpZGdlQ3JvbiB9IGZyb20gJy4uL3V0aWxzL2Nyb24uanMnO1xuaW1wb3J0IHsgRVJST1JfQ09ERVMsIGhhbmRsZUVycm9yIH0gZnJvbSAnLi4vdXRpbHMvZXJyb3ItaGFuZGxlci5qcyc7XG5pbXBvcnQgeyBwcmludEluZm8sIHByaW50S2V5VmFsdWUsIHByaW50U2VjdGlvbiwgcHJpbnRTdWNjZXNzIH0gZnJvbSAnLi4vdXRpbHMvb3V0cHV0LXV0aWxzLmpzJztcbmltcG9ydCB7IGVuc3VyZVBsYXRmb3JtVG9rZW4sIHJlc29sdmVTZWNyZXROYW1lIH0gZnJvbSAnLi4vdXRpbHMvcGxhdGZvcm0tc2VjcmV0LmpzJztcblxuLy8gRVNNIGhhcyBubyBfX2Rpcm5hbWU7IGRlcml2ZSBpdCBmcm9tIHRoaXMgbW9kdWxlJ3MgVVJMLlxuY29uc3QgX19kaXJuYW1lID0gcGF0aC5kaXJuYW1lKGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKSk7XG5cbmNvbnN0IFJFTkVXX1NUQUNLX05BTUUgPSAncGlwZWxpbmUtYnVpbGRlci10b2tlbi1yZW5ldyc7XG4vLyBDRk4tbWFuYWdlZCBMYW1iZGEgZnVuY3Rpb24gbmFtZSDigJQga2VlcCBpbiBzeW5jIHdpdGggdG9rZW4tcmVuZXctc3RhY2suanNvbi5cbmNvbnN0IFJFTkVXX0xBTUJEQV9OQU1FID0gJ3BpcGVsaW5lLWJ1aWxkZXItdG9rZW4tcmVuZXcnO1xuLy8gRGVmYXVsdCA1LWZpZWxkIGNyb24gKGRhaWx5IGF0IG1pZG5pZ2h0KSB3aGVuIG5laXRoZXIgLS1jcm9uIG5vciBUT0tFTl9SRU5FV19TQ0hFRFVMRSBpcyBzZXQuXG5jb25zdCBERUZBVUxUX1JFTkVXX0NST04gPSAnMCAwICogKiAqJztcblxuLyoqXG4gKiBEZXBsb3kgKG9yIHVwZGF0ZSkgdGhlIG9uY2UtYS1kYXkgdG9rZW4tcmVuZXdhbCBzdGFjazogYSBzY2hlZHVsZWQgTGFtYmRhIHRoYXRcbiAqIHJlLW1pbnRzIHRoZSBwbGF0Zm9ybSBKV1QgaW4gdGhpcyBzYW1lIHNlY3JldCBiZWZvcmUgaXQgZXhwaXJlcy4gTWlycm9yc1xuICogc2V0dXAtZXZlbnRzIOKAlCBgYXdzIGNsb3VkZm9ybWF0aW9uIGRlcGxveWAgZm9yIHRoZSBpbmZyYSwgdGhlbiBhIGRpcmVjdFxuICogVXBkYXRlRnVuY3Rpb25Db2RlIHdpdGggdGhlIHNlbGYtY29udGFpbmVkIGhhbmRsZXIgY29tcGlsZWQgYWxvbmdzaWRlIHRoaXMgQ0xJLlxuICovXG5hc3luYyBmdW5jdGlvbiBkZXBsb3lSZW5ld1NjaGVkdWxlKG9wdHM6IHtcbiAgcGxhdGZvcm1Vcmw6IHN0cmluZztcbiAgc2VjcmV0TmFtZTogc3RyaW5nO1xuICBkYXlzOiBudW1iZXI7XG4gIGZpdmVGaWVsZENyb246IHN0cmluZztcbiAgcmVnaW9uOiBzdHJpbmc7XG4gIHByb2ZpbGU/OiBzdHJpbmc7XG59KTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3Qgc2NoZWR1bGVFeHByZXNzaW9uID0gdG9FdmVudEJyaWRnZUNyb24ob3B0cy5maXZlRmllbGRDcm9uKTsgLy8gdmFsaWRhdGVzICsgMTUtbWluIGd1YXJkXG5cbiAgcHJpbnRTZWN0aW9uKCdTY2hlZHVsZSBSZW5ld2FsJyk7XG4gIHByaW50SW5mbygnUGFyYW1ldGVycycsIHtcbiAgICBzdGFjazogUkVORVdfU1RBQ0tfTkFNRSxcbiAgICBzY2hlZHVsZTogb3B0cy5maXZlRmllbGRDcm9uLFxuICAgIGV2ZW50YnJpZGdlOiBzY2hlZHVsZUV4cHJlc3Npb24sXG4gICAgcmVuZXdEYXlzOiBvcHRzLmRheXMsXG4gIH0pO1xuXG4gIC8vIFN0ZXAgMTogaW5mcmEgKExhbWJkYSBnZXRzIHBsYWNlaG9sZGVyIGNvZGUgb24gZmlyc3QgY3JlYXRlKS5cbiAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL3RlbXBsYXRlcy90b2tlbi1yZW5ldy1zdGFjay5qc29uJyk7XG4gIGNvbnN0IGNmbkFyZ3MgPSBbXG4gICAgJ2Nsb3VkZm9ybWF0aW9uJywgJ2RlcGxveScsXG4gICAgJy0tc3RhY2stbmFtZScsIFJFTkVXX1NUQUNLX05BTUUsXG4gICAgJy0tdGVtcGxhdGUtZmlsZScsIHRlbXBsYXRlUGF0aCxcbiAgICAnLS1wYXJhbWV0ZXItb3ZlcnJpZGVzJyxcbiAgICBgUGxhdGZvcm1CYXNlVXJsPSR7b3B0cy5wbGF0Zm9ybVVybH1gLFxuICAgIGBQbGF0Zm9ybVNlY3JldE5hbWU9JHtvcHRzLnNlY3JldE5hbWV9YCxcbiAgICBgUmVuZXdEYXlzPSR7b3B0cy5kYXlzfWAsXG4gICAgYFNjaGVkdWxlRXhwcmVzc2lvbj0ke3NjaGVkdWxlRXhwcmVzc2lvbn1gLFxuICAgICctLWNhcGFiaWxpdGllcycsICdDQVBBQklMSVRZX05BTUVEX0lBTScsXG4gICAgJy0tbm8tZmFpbC1vbi1lbXB0eS1jaGFuZ2VzZXQnLFxuICAgICctLXJlZ2lvbicsIG9wdHMucmVnaW9uLFxuICBdO1xuICBpZiAob3B0cy5wcm9maWxlKSBjZm5BcmdzLnB1c2goJy0tcHJvZmlsZScsIG9wdHMucHJvZmlsZSk7XG4gIGV4ZWNGaWxlU3luYygnYXdzJywgY2ZuQXJncywgeyBzdGRpbzogJ2luaGVyaXQnIH0pO1xuXG4gIC8vIFN0ZXAgMjogdXBsb2FkIHRoZSByZWFsIGhhbmRsZXIuIEl0J3MgRVNNLCBzbyB0aGUgemlwIGVudHJ5IG11c3QgYmUgaW5kZXgubWpzXG4gIC8vIChIYW5kbGVyIHN0YXlzIGluZGV4LmhhbmRsZXIg4oCUIG5vZGVqczI0LnggcmVzb2x2ZXMgdGhlIC5tanMgZXh0ZW5zaW9uKS5cbiAgY29uc3QgaGFuZGxlclNyYyA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi9sYW1iZGEvdG9rZW4tcmVuZXctaGFuZGxlci5qcycpO1xuICBpZiAoIWZzLmV4aXN0c1N5bmMoaGFuZGxlclNyYykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRva2VuLXJlbmV3IGhhbmRsZXIgbm90IGZvdW5kIGF0ICR7aGFuZGxlclNyY30g4oCUIHdhcyB0aGUgcGFja2FnZSBidWlsdD9gKTtcbiAgfVxuICBjb25zdCB0bXBEaXIgPSBmcy5ta2R0ZW1wU3luYyhwYXRoLmpvaW4ob3MudG1wZGlyKCksICd0b2tlbi1yZW5ldy0nKSk7XG4gIHRyeSB7XG4gICAgZnMuY29weUZpbGVTeW5jKGhhbmRsZXJTcmMsIHBhdGguam9pbih0bXBEaXIsICdpbmRleC5tanMnKSk7XG4gICAgY29uc3QgemlwUGF0aCA9IHBhdGguam9pbih0bXBEaXIsICdpbmRleC56aXAnKTtcbiAgICBleGVjRmlsZVN5bmMoJ3ppcCcsIFsnLWonLCB6aXBQYXRoLCAnaW5kZXgubWpzJ10sIHsgY3dkOiB0bXBEaXIsIHN0ZGlvOiAncGlwZScgfSk7XG5cbiAgICBjb25zdCBsYW1iZGFDbGllbnQgPSBuZXcgTGFtYmRhQ2xpZW50KHsgcmVnaW9uOiBvcHRzLnJlZ2lvbiB9KTtcbiAgICBhd2FpdCBsYW1iZGFDbGllbnQuc2VuZChuZXcgVXBkYXRlRnVuY3Rpb25Db2RlQ29tbWFuZCh7XG4gICAgICBGdW5jdGlvbk5hbWU6IFJFTkVXX0xBTUJEQV9OQU1FLFxuICAgICAgWmlwRmlsZTogZnMucmVhZEZpbGVTeW5jKHppcFBhdGgpLFxuICAgIH0pKTtcbiAgfSBmaW5hbGx5IHtcbiAgICBmcy5ybVN5bmModG1wRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gIH1cblxuICBwcmludFN1Y2Nlc3MoYFJlbmV3YWwgc2NoZWR1bGVkICgke3NjaGVkdWxlRXhwcmVzc2lvbn0pYCk7XG4gIHJldHVybiBzY2hlZHVsZUV4cHJlc3Npb247XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBgc3RvcmUtdG9rZW5gIGNvbW1hbmQgd2l0aCB0aGUgQ0xJIHByb2dyYW0uXG4gKlxuICogR2VuZXJhdGVzIGEgbG9uZy1saXZlZCBKV1QgdG9rZW4gdmlhIHRoZSBwbGF0Zm9ybSBBUEkgYW5kIHN0b3JlcyBpdFxuICogaW4gQVdTIFNlY3JldHMgTWFuYWdlciBmb3IgdXNlIGJ5IHRoZSBzeW50aC9kZXBsb3kgLS1zdG9yZS10b2tlbnMgZmxhZy5cbiAqXG4gKiBSZXF1aXJlcyBQTEFURk9STV9UT0tFTiB0byBiZSBzZXQsIG9yIHVzZSAtLWVtYWlsLy0tcGFzc3dvcmQgdG8gbG9naW4gaW5saW5lLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGBiYXNoXG4gKiBwaXBlbGluZS1tYW5hZ2VyIHN0b3JlLXRva2VuIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogcGlwZWxpbmUtbWFuYWdlciBzdG9yZS10b2tlbiAtLWRheXMgOTAgLS1yZWdpb24gdXMtZWFzdC0xXG4gKiBwaXBlbGluZS1tYW5hZ2VyIHN0b3JlLXRva2VuIC0tZGF5cyA3IC0tc2VjcmV0LW5hbWUgbXktY3VzdG9tLXNlY3JldCAtLW5vLXZlcmlmeS1zc2xcbiAqIHBpcGVsaW5lLW1hbmFnZXIgc3RvcmUtdG9rZW4gLS1kcnktcnVuXG4gKiBwaXBlbGluZS1tYW5hZ2VyIHN0b3JlLXRva2VuIC1lIGFkbWluIC1wICcqKionIC0tcmVnaW9uIHVzLWVhc3QtMVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdG9yZVRva2VuKHByb2dyYW06IENvbW1hbmQpOiB2b2lkIHtcbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKCdzdG9yZS10b2tlbicpXG4gICAgLmRlc2NyaXB0aW9uKCdHZW5lcmF0ZSBKV1QgdG9rZW4gYW5kIHN0b3JlIGluIEFXUyBTZWNyZXRzIE1hbmFnZXIgZm9yIENESyBkZXBsb3ltZW50cycpXG4gICAgLm9wdGlvbignLWUsIC0tZW1haWwgPGVtYWlsPicsICdMb2dpbiBlbWFpbCAoc2tpcHMgUExBVEZPUk1fVE9LRU4gcmVxdWlyZW1lbnQpJylcbiAgICAub3B0aW9uKCctcCwgLS1wYXNzd29yZCA8cGFzc3dvcmQ+JywgJ0xvZ2luIHBhc3N3b3JkICh1c2VkIHdpdGggLS1lbWFpbCknKVxuICAgIC5vcHRpb24oJy0tZGF5cyA8ZGF5cz4nLCAnVG9rZW4gbGlmZXRpbWUgaW4gZGF5cycsICczMCcpXG4gICAgLm9wdGlvbignLS1kcnktcnVuJywgJ1Nob3cgd2hhdCB3b3VsZCBiZSBzdG9yZWQgd2l0aG91dCB3cml0aW5nIHRvIFNlY3JldHMgTWFuYWdlcicsIGZhbHNlKVxuICAgIC5vcHRpb24oJy0tc2VjcmV0LW5hbWUgPG5hbWU+JywgJ1NlY3JldHMgTWFuYWdlciBzZWNyZXQgbmFtZSAoZGVmYXVsdDogZGVyaXZlZCBmcm9tIHRva2VuIG9yZyknKVxuICAgIC5vcHRpb24oJy0tcmVnaW9uIDxyZWdpb24+JywgJ0FXUyByZWdpb24gKGRlZmF1bHRzIHRvIEFXU19SRUdJT04gZW52KScpXG4gICAgLm9wdGlvbignLS1wcm9maWxlIDxwcm9maWxlPicsICdBV1MgQ0xJIHByb2ZpbGUnLCAnZGVmYXVsdCcpXG4gICAgLm9wdGlvbignLS1jcm9uIDxleHByPicsICdSZW5ld2FsIHNjaGVkdWxlIGFzIGEgNS1maWVsZCBjcm9uIChkZWZhdWx0OiBUT0tFTl9SRU5FV19TQ0hFRFVMRSBlbnYgb3IgXCIwIDAgKiAqICpcIjsgbWluIGV2ZXJ5IDE1IG1pbnV0ZXMpJylcbiAgICAub3B0aW9uKCctLW5vLXNjaGVkdWxlJywgJ1NraXAgZGVwbG95aW5nIHRoZSBkYWlseSB0b2tlbi1yZW5ld2FsIHN0YWNrIChpdCBpcyBpbnN0YWxsZWQgYnkgZGVmYXVsdCknKVxuICAgIC5vcHRpb24oJy0tanNvbicsICdPdXRwdXQgcmVzdWx0IGFzIEpTT04nLCBmYWxzZSlcbiAgICAub3B0aW9uKCctLXZlcmlmeS1zc2wnLCAnRW5hYmxlIFNTTCBjZXJ0aWZpY2F0ZSB2ZXJpZmljYXRpb24nKVxuICAgIC5vcHRpb24oJy0tbm8tdmVyaWZ5LXNzbCcsICdEaXNhYmxlIFNTTCBjZXJ0aWZpY2F0ZSB2ZXJpZmljYXRpb24nKVxuICAgIC5hY3Rpb24oYXN5bmMgKG9wdGlvbnMpID0+IHtcbiAgICAgIGNvbnN0IGV4ZWN1dGlvbklkID0gcHJpbnRDb21tYW5kSGVhZGVyKCdTdG9yZSBUb2tlbicpO1xuXG4gICAgICB0cnkge1xuICAgICAgICBwcmludFNzbFdhcm5pbmcob3B0aW9ucy52ZXJpZnlTc2wpO1xuXG4gICAgICAgIGNvbnN0IHJlZ2lvbiA9IG9wdGlvbnMucmVnaW9uIHx8IHByb2Nlc3MuZW52LkFXU19SRUdJT04gfHwgcHJvY2Vzcy5lbnYuQ0RLX0RFRkFVTFRfUkVHSU9OIHx8ICd1cy1lYXN0LTEnO1xuXG4gICAgICAgIGNvbnN0IGRheXMgPSB2YWxpZGF0ZU51bWJlcihvcHRpb25zLmRheXMsICdkYXlzJywgMSwgMzY1KTtcbiAgICAgICAgY29uc3QgZXhwaXJlc0luU2Vjb25kcyA9IGRheXMgKiAyNCAqIDYwICogNjA7XG5cbiAgICAgICAgLy8gU3RlcCAwOiBsb2cgaW4gZmlyc3Qgd2hlbiBjcmVkcyBhcmUgYXZhaWxhYmxlIGFuZCBubyBQTEFURk9STV9UT0tFTiBpcyBzZXRcbiAgICAgICAgLy8gKHNoYXJlZCB3aXRoIHNldHVwLWV2ZW50cykuIENyZWRzIGNvbWUgZnJvbSAtLWVtYWlsLy0tcGFzc3dvcmQgT1IgdGhlIGVudlxuICAgICAgICAvLyB2YXJzIFBMQVRGT1JNX0lERU5USUZJRVIvUExBVEZPUk1fUEFTU1dPUkQg4oCUIHRoZSBlbnYgcGF0aCBsZXRzIGNhbGxlcnMgbGlrZVxuICAgICAgICAvLyBgcHJvdmlzaW9uIC0td2l0aC1ldmVudHNgIHBhc3MgdGhlbSB3aXRob3V0IHB1dHRpbmcgdGhlIHBhc3N3b3JkIG9uIHRoZVxuICAgICAgICAvLyBjb21tYW5kIGxpbmUgKHdoZXJlIGl0IHdvdWxkIHNob3cgaW4gcGxhbnMvbG9ncykuXG4gICAgICAgIGF3YWl0IGVuc3VyZVBsYXRmb3JtVG9rZW4ob3B0aW9ucyk7XG5cbiAgICAgICAgLy8gU3RlcCAxOiBBdXRoZW50aWNhdGUgYW5kIGdlbmVyYXRlIGxvbmctbGl2ZWQgdG9rZW5cbiAgICAgICAgcHJpbnRTZWN0aW9uKCdHZW5lcmF0ZSBUb2tlbicpO1xuXG4gICAgICAgIGNvbnN0IGNsaWVudCA9IGF3YWl0IGNyZWF0ZUF1dGhlbnRpY2F0ZWRDbGllbnRBc3luYyhvcHRpb25zKTtcblxuICAgICAgICAvLyBSZXNvbHZlIHNlY3JldCBuYW1lIGZyb20gdG9rZW4ncyBvcmdhbml6YXRpb25JZCAodW5sZXNzIC0tc2VjcmV0LW5hbWUgd2FzIGV4cGxpY2l0bHkgc2V0KVxuICAgICAgICBjb25zdCBzZWNyZXROYW1lID0gb3B0aW9ucy5zZWNyZXROYW1lIHx8IHJlc29sdmVTZWNyZXROYW1lKHByb2Nlc3MuZW52LlBMQVRGT1JNX1RPS0VOISk7XG5cbiAgICAgICAgYXVkaXRMb2coJ3N0b3JlLXRva2VuJywgeyBleGVjdXRpb25JZCwgc2VjcmV0TmFtZSwgZGF5czogb3B0aW9ucy5kYXlzLCBkcnlSdW46IG9wdGlvbnMuZHJ5UnVuIH0pO1xuXG4gICAgICAgIHByaW50SW5mbygnUGFyYW1ldGVycycsIHtcbiAgICAgICAgICBzZWNyZXROYW1lLFxuICAgICAgICAgIHJlZ2lvbixcbiAgICAgICAgICBkYXlzLFxuICAgICAgICAgIGV4cGlyZXNJbjogYCR7ZXhwaXJlc0luU2Vjb25kc31zYCxcbiAgICAgICAgICBkcnlSdW46IG9wdGlvbnMuZHJ5UnVuLFxuICAgICAgICB9KTtcblxuICAgICAgICBwcmludEluZm8oJ1JlcXVlc3RpbmcgdG9rZW4nLCB7IGV4cGlyZXNJbjogYCR7ZXhwaXJlc0luU2Vjb25kc31zICgke2RheXN9IGRheXMpYCB9KTtcblxuICAgICAgICBjb25zdCB0b2tlblJlc3BvbnNlID0gYXdhaXQgY2xpZW50LnBvc3Q8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KFxuICAgICAgICAgICcvYXBpL3VzZXIvZ2VuZXJhdGUtdG9rZW4nLFxuICAgICAgICAgIHsgZXhwaXJlc0luOiBleHBpcmVzSW5TZWNvbmRzIH0sXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgdG9rZW5EYXRhID0gKHRva2VuUmVzcG9uc2UgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pPy5kYXRhID8/IHRva2VuUmVzcG9uc2U7XG4gICAgICAgIGNvbnN0IGFjY2Vzc1Rva2VuID0gKHRva2VuRGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik/LmFjY2Vzc1Rva2VuIGFzIHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgY29uc3QgcmVmcmVzaFRva2VuID0gKHRva2VuRGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik/LnJlZnJlc2hUb2tlbiBhcyBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGNvbnN0IGFjdHVhbEV4cGlyZXNJbiA9ICgodG9rZW5EYXRhIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KT8uZXhwaXJlc0luIGFzIG51bWJlcikgPz8gZXhwaXJlc0luU2Vjb25kcztcblxuICAgICAgICBpZiAoIWFjY2Vzc1Rva2VuKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUb2tlbiBnZW5lcmF0aW9uIGZhaWxlZCDigJQgbm8gYWNjZXNzIHRva2VuIGluIHJlc3BvbnNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBwcmludFN1Y2Nlc3MoYFRva2VuIGdlbmVyYXRlZCAoZXhwaXJlcyBpbiAke2FjdHVhbEV4cGlyZXNJbn1zKWApO1xuXG4gICAgICAgIGNvbnN0IGV4cGlyZXNBdCA9IG5ldyBEYXRlKERhdGUubm93KCkgKyBhY3R1YWxFeHBpcmVzSW4gKiAxMDAwKS50b0lTT1N0cmluZygpO1xuXG4gICAgICAgIC8vIFNjaGVtYTogeyB1c2VybmFtZTogb3JnSWQsIHBhc3N3b3JkOiBKV1QsIC4uLm1ldGFkYXRhIH1cbiAgICAgICAgLy8gLSB1c2VybmFtZS9wYXNzd29yZCBmaWVsZHMgc2F0aXNmeSBDb2RlQnVpbGQncyBgc2VjcmV0c01hbmFnZXJDcmVkZW50aWFsc2BcbiAgICAgICAgLy8gICAoSFRUUCBCYXNpYywgc2VudCB0byBwaXBlbGluZS1pbWFnZS1yZWdpc3RyeSdzIC90b2tlbiBlbmRwb2ludClcbiAgICAgICAgLy8gLSBUaGUgc2FtZSBKV1QgaXMgY29uc3VtZWQgYnkgdGhlIHBsdWdpbi1sb29rdXAgTGFtYmRhIGJ5IHJlYWRpbmdcbiAgICAgICAgLy8gICB0aGUgYHBhc3N3b3JkYCBmaWVsZFxuICAgICAgICAvLyAtIE9uZSBTZWNyZXQgcGVyIGN1c3RvbWVyIGFjY291bnQgcmVwbGFjZXMgdGhlIHByZXZpb3VzIHR3by1zZWNyZXQgbW9kZWxcbiAgICAgICAgLy8gRGVjb2RlIEpXVCBmb3Igb3JnSWQg4oCUIGl0J3MgYSBzdGFibGUgaWRlbnRpZmllciBmb3IgdGhlIHVzZXJuYW1lIGZpZWxkO1xuICAgICAgICAvLyB0aGUgYWN0dWFsIGF1dGggdXNlcyB0aGUgcGFzc3dvcmQgKEpXVCkgd2hpY2ggdGhlIHRva2VuIHNlcnZpY2UgdmVyaWZpZXMuXG4gICAgICAgIC8vIGB8fGAgKG5vdCBgPz9gKTogYW4gRU1QVFktc3RyaW5nIG9yZ2FuaXphdGlvbklkIG11c3QgYWxzbyBmYWxsIGJhY2suIEFcbiAgICAgICAgLy8gc3lzYWRtaW4vc3lzdGVtIHRva2VuIG9mdGVuIGNhcnJpZXMgb3JnYW5pemF0aW9uSWQ9XCJcIiwgYW5kIENvZGVCdWlsZFxuICAgICAgICAvLyByZWplY3RzIGEgcmVnaXN0cnkgY3JlZGVudGlhbCB3aG9zZSBgdXNlcm5hbWVgIGZpZWxkIGlzIGVtcHR5IHdpdGhcbiAgICAgICAgLy8gXCJBdXRob3JpemF0aW9uRGF0YSBpcyBtYWxmb3JtZWQsIGVtcHR5IGZpZWxkXCIg4oCUIHNvIHVzZXJuYW1lIG11c3QgYWx3YXlzXG4gICAgICAgIC8vIGJlIGEgbm9uLWVtcHR5IHZhbHVlLlxuICAgICAgICBjb25zdCBwYXlsb2FkID0gZGVjb2RlVG9rZW5QYXlsb2FkKGFjY2Vzc1Rva2VuKTtcbiAgICAgICAgY29uc3Qgb3JnSWQgPSBwYXlsb2FkPy5vcmdhbml6YXRpb25JZD8udHJpbSgpIHx8ICd1bmtub3duLW9yZyc7XG5cbiAgICAgICAgY29uc3Qgc2VjcmV0VmFsdWUgPSBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgdXNlcm5hbWU6IG9yZ0lkLFxuICAgICAgICAgIHBhc3N3b3JkOiBhY2Nlc3NUb2tlbixcbiAgICAgICAgICAuLi4ocmVmcmVzaFRva2VuICYmIHsgcmVmcmVzaFRva2VuIH0pLFxuICAgICAgICAgIHBsYXRmb3JtVXJsOiBjbGllbnQuZ2V0QmFzZVVybCgpLFxuICAgICAgICAgIGV4cGlyZXNJbjogYWN0dWFsRXhwaXJlc0luLFxuICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRHJ5LXJ1bjogc2hvdyB3aGF0IHdvdWxkIGJlIHN0b3JlZFxuICAgICAgICBpZiAob3B0aW9ucy5kcnlSdW4pIHtcbiAgICAgICAgICBpZiAob3B0aW9ucy5qc29uKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICAgIGRyeVJ1bjogdHJ1ZSxcbiAgICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgICBleHBpcmVzSW5EYXlzOiBkYXlzLFxuICAgICAgICAgICAgICBleHBpcmVzQXQsXG4gICAgICAgICAgICAgIHRva2VuTGVuZ3RoOiBhY2Nlc3NUb2tlbi5sZW5ndGgsXG4gICAgICAgICAgICAgIGhhc1JlZnJlc2hUb2tlbjogISFyZWZyZXNoVG9rZW4sXG4gICAgICAgICAgICB9LCBudWxsLCAyKSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCcnKTtcbiAgICAgICAgICAgIHByaW50U2VjdGlvbignRHJ5IFJ1biDigJQgTm8gQ2hhbmdlcyBNYWRlJyk7XG4gICAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICAgJ1NlY3JldCBOYW1lJzogc2VjcmV0TmFtZSxcbiAgICAgICAgICAgICAgJ1JlZ2lvbic6IHJlZ2lvbixcbiAgICAgICAgICAgICAgJ0V4cGlyZXMgSW4nOiBgJHtkYXlzfSBkYXlzYCxcbiAgICAgICAgICAgICAgJ1JlbmV3IEJ5JzogZXhwaXJlc0F0LFxuICAgICAgICAgICAgICAnVG9rZW4gTGVuZ3RoJzogYCR7YWNjZXNzVG9rZW4ubGVuZ3RofSBjaGFyc2AsXG4gICAgICAgICAgICAgICdIYXMgUmVmcmVzaCBUb2tlbic6IHJlZnJlc2hUb2tlbiA/ICdZZXMnIDogJ05vJyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcHJpbnRTdWNjZXNzKCdEcnkgcnVuIGNvbXBsZXRlIOKAlCBubyBzZWNyZXQgd2FzIGNyZWF0ZWQgb3IgdXBkYXRlZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdGVwIDI6IFN0b3JlIHRva2VuIGluIFNlY3JldHMgTWFuYWdlclxuICAgICAgICBwcmludFNlY3Rpb24oJ1N0b3JlIFRva2VuJyk7XG5cbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb24gPSBgUGxhdGZvcm0gSldUIHRva2VuIChyZW5ldyBieSAke2V4cGlyZXNBdH0pYDtcbiAgICAgICAgYXdhaXQgdXBzZXJ0U2VjcmV0KHNlY3JldE5hbWUsIHNlY3JldFZhbHVlLCBkZXNjcmlwdGlvbiwgeyByZWdpb24sIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSB9KTtcblxuICAgICAgICBjb25zdCBhcm4gPSBhd2FpdCBnZXRTZWNyZXRBcm4oc2VjcmV0TmFtZSwgeyByZWdpb24sIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSB9KTtcblxuICAgICAgICAvLyBJbnN0YWxsIHRoZSBvbmNlLWEtZGF5IHJlbmV3YWwgc3RhY2sgc28gdGhpcyB0b2tlbiBuZXZlciBsYXBzZXMgKGRlZmF1bHRcbiAgICAgICAgLy8gb247IG9wdCBvdXQgd2l0aCAtLW5vLXNjaGVkdWxlKS4gY29tbWFuZGVyIHNldHMgb3B0aW9ucy5zY2hlZHVsZT1mYWxzZSBmb3JcbiAgICAgICAgLy8gLS1uby1zY2hlZHVsZSwgdHJ1ZSBvdGhlcndpc2UuXG4gICAgICAgIGxldCBzY2hlZHVsZUV4cHJlc3Npb246IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKG9wdGlvbnMuc2NoZWR1bGUgIT09IGZhbHNlKSB7XG4gICAgICAgICAgY29uc3QgZml2ZUZpZWxkQ3JvbiA9IG9wdGlvbnMuY3JvbiB8fCBwcm9jZXNzLmVudi5UT0tFTl9SRU5FV19TQ0hFRFVMRSB8fCBERUZBVUxUX1JFTkVXX0NST047XG4gICAgICAgICAgc2NoZWR1bGVFeHByZXNzaW9uID0gYXdhaXQgZGVwbG95UmVuZXdTY2hlZHVsZSh7XG4gICAgICAgICAgICBwbGF0Zm9ybVVybDogY2xpZW50LmdldEJhc2VVcmwoKSxcbiAgICAgICAgICAgIHNlY3JldE5hbWUsXG4gICAgICAgICAgICBkYXlzLFxuICAgICAgICAgICAgZml2ZUZpZWxkQ3JvbixcbiAgICAgICAgICAgIHJlZ2lvbixcbiAgICAgICAgICAgIHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmpzb24pIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBzdWNjZXNzOiB0cnVlLFxuICAgICAgICAgICAgc2VjcmV0TmFtZSxcbiAgICAgICAgICAgIHNlY3JldEFybjogYXJuLFxuICAgICAgICAgICAgcmVnaW9uLFxuICAgICAgICAgICAgZXhwaXJlc0luRGF5czogZGF5cyxcbiAgICAgICAgICAgIGV4cGlyZXNBdCxcbiAgICAgICAgICAgIHNjaGVkdWxlOiBzY2hlZHVsZUV4cHJlc3Npb24gPz8gbnVsbCxcbiAgICAgICAgICB9LCBudWxsLCAyKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJycpO1xuICAgICAgICAgIHByaW50U2VjdGlvbignVG9rZW4gU3RvcmVkJyk7XG5cbiAgICAgICAgICBwcmludEtleVZhbHVlKHtcbiAgICAgICAgICAgICdTZWNyZXQgTmFtZSc6IHNlY3JldE5hbWUsXG4gICAgICAgICAgICAnU2VjcmV0IEFSTic6IGFybixcbiAgICAgICAgICAgICdSZWdpb24nOiByZWdpb24sXG4gICAgICAgICAgICAnRXhwaXJlcyBJbic6IGAke2RheXN9IGRheXNgLFxuICAgICAgICAgICAgJ1JlbmV3IEJ5JzogZXhwaXJlc0F0LFxuICAgICAgICAgICAgJ0F1dG8tUmVuZXcnOiBzY2hlZHVsZUV4cHJlc3Npb24gPyBg4pyTICR7c2NoZWR1bGVFeHByZXNzaW9ufWAgOiAnZGlzYWJsZWQgKC0tbm8tc2NoZWR1bGUpJyxcbiAgICAgICAgICAgICdTdGF0dXMnOiAn4pyTIFN0b3JlZCcsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgcHJpbnRTdWNjZXNzKCdUb2tlbiBzdG9yZWQuIFRvIHVzZSB3aXRoIHN5bnRoL2RlcGxveTonKTtcbiAgICAgICAgICBwcmludEluZm8oYCAgZXhwb3J0IFBMQVRGT1JNX1NFQ1JFVF9OQU1FPSR7c2VjcmV0TmFtZX1gKTtcbiAgICAgICAgICBwcmludEluZm8oJyAgcGlwZWxpbmUtbWFuYWdlciBzeW50aCAtLWlkIDxwaXBlbGluZS1pZD4gLS1zdG9yZS10b2tlbnMnKTtcbiAgICAgICAgICBjb25zb2xlLmxvZygnJyk7XG4gICAgICAgICAgaWYgKHNjaGVkdWxlRXhwcmVzc2lvbikge1xuICAgICAgICAgICAgcHJpbnRJbmZvKGBBdXRvLXJlbmV3YWwgaXMgYWN0aXZlICgke3NjaGVkdWxlRXhwcmVzc2lvbn0pOyB0aGUgc2VjcmV0IHJlZnJlc2hlcyBiZWZvcmUgJHtleHBpcmVzQXR9LmApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwcmludEluZm8oYFJlbmV3IGJlZm9yZSAke2V4cGlyZXNBdH0gd2l0aDogcGlwZWxpbmUtbWFuYWdlciBzdG9yZS10b2tlbiAtLWRheXMgJHtkYXlzfWApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBoYW5kbGVFcnJvcihlcnJvciwgRVJST1JfQ09ERVMuQVBJX1JFUVVFU1QsIHtcbiAgICAgICAgICBkZWJ1ZzogcHJvZ3JhbS5vcHRzKCkuZGVidWcsXG4gICAgICAgICAgZXhpdDogdHJ1ZSxcbiAgICAgICAgICBjb250ZXh0OiB7XG4gICAgICAgICAgICBjb21tYW5kOiAnc3RvcmUtdG9rZW4nLFxuICAgICAgICAgICAgZXhlY3V0aW9uSWQsXG4gICAgICAgICAgICBzZWNyZXROYW1lOiBvcHRpb25zLnNlY3JldE5hbWUgfHwgJyhkZXJpdmVkIGZyb20gdG9rZW4pJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-renew-handler.d.ts","sourceRoot":"","sources":["../../src/lambda/token-renew-handler.ts"],"names":[],"mappings":"AA4FA,eAAO,MAAM,OAAO,QAAa,OAAO,CAAC,IAAI,CAqD5C,CAAC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Lambda handler that re-mints the platform JWT in Secrets Manager so it never
|
|
5
|
+
* lapses. Deployed + scheduled by `pipeline-manager store-token` (default once a
|
|
6
|
+
* day). Self-contained on purpose — only `@aws-sdk/client-secrets-manager` (which
|
|
7
|
+
* the Lambda Node runtime provides) and node built-ins — so it can be zipped and
|
|
8
|
+
* uploaded as a single file with no bundling.
|
|
9
|
+
*
|
|
10
|
+
* Each run: read the secret's current JWT → ask the platform for a fresh
|
|
11
|
+
* long-lived token (`/api/user/generate-token`, falling back to `/auth/refresh`
|
|
12
|
+
* if the current token has expired) → write it back in store-token's schema.
|
|
13
|
+
* The new token is validated before it overwrites the still-valid one.
|
|
14
|
+
*
|
|
15
|
+
* Env: PLATFORM_SECRET_NAME, PLATFORM_BASE_URL, RENEW_DAYS (default 30).
|
|
16
|
+
*/
|
|
17
|
+
import { request as httpsRequest } from 'node:https';
|
|
18
|
+
import { SecretsManagerClient, GetSecretValueCommand, PutSecretValueCommand, } from '@aws-sdk/client-secrets-manager';
|
|
19
|
+
/** Minimal JSON POST. Honours NODE_TLS_REJECT_UNAUTHORIZED via the node runtime. */
|
|
20
|
+
function postJson(url, body, bearer) {
|
|
21
|
+
const u = new URL(url);
|
|
22
|
+
const payload = JSON.stringify(body);
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const req = httpsRequest({
|
|
25
|
+
method: 'POST',
|
|
26
|
+
hostname: u.hostname,
|
|
27
|
+
port: u.port || 443,
|
|
28
|
+
path: u.pathname + u.search,
|
|
29
|
+
headers: {
|
|
30
|
+
'content-type': 'application/json',
|
|
31
|
+
'content-length': Buffer.byteLength(payload),
|
|
32
|
+
...(bearer ? { authorization: `Bearer ${bearer}` } : {}),
|
|
33
|
+
},
|
|
34
|
+
timeout: 20_000,
|
|
35
|
+
}, (res) => {
|
|
36
|
+
let data = '';
|
|
37
|
+
res.on('data', (c) => (data += c));
|
|
38
|
+
res.on('end', () => {
|
|
39
|
+
let json = undefined;
|
|
40
|
+
try {
|
|
41
|
+
json = data ? JSON.parse(data) : undefined;
|
|
42
|
+
}
|
|
43
|
+
catch { /* leave undefined */ }
|
|
44
|
+
resolve({ status: res.statusCode ?? 0, json });
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
req.on('error', reject);
|
|
48
|
+
req.on('timeout', () => req.destroy(new Error('request timed out')));
|
|
49
|
+
req.write(payload);
|
|
50
|
+
req.end();
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Unwrap the platform's `{ success, data: {...} }` envelope (or a bare body). */
|
|
54
|
+
function unwrap(json) {
|
|
55
|
+
const j = json;
|
|
56
|
+
return (j?.data ?? j);
|
|
57
|
+
}
|
|
58
|
+
/** Basic JWT sanity: decodes, must carry an org and a future `exp`. */
|
|
59
|
+
function looksValid(jwt) {
|
|
60
|
+
const parts = jwt.split('.');
|
|
61
|
+
if (parts.length !== 3)
|
|
62
|
+
return false;
|
|
63
|
+
try {
|
|
64
|
+
const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString('utf-8'));
|
|
65
|
+
if (!payload.exp || payload.exp * 1000 <= Date.now())
|
|
66
|
+
return false;
|
|
67
|
+
return typeof payload.organizationId === 'string';
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export const handler = async () => {
|
|
74
|
+
const secretName = required('PLATFORM_SECRET_NAME');
|
|
75
|
+
const platformUrl = required('PLATFORM_BASE_URL').replace(/\/$/, '');
|
|
76
|
+
const days = parseInt(process.env.RENEW_DAYS || '30', 10);
|
|
77
|
+
const expiresIn = days * 24 * 60 * 60;
|
|
78
|
+
const region = process.env.AWS_REGION;
|
|
79
|
+
const sm = new SecretsManagerClient({ region });
|
|
80
|
+
const current = await sm.send(new GetSecretValueCommand({ SecretId: secretName }));
|
|
81
|
+
if (!current.SecretString)
|
|
82
|
+
throw new Error(`Secret "${secretName}" is empty`);
|
|
83
|
+
const secret = JSON.parse(current.SecretString);
|
|
84
|
+
if (!secret.password)
|
|
85
|
+
throw new Error(`Secret "${secretName}" missing password (JWT)`);
|
|
86
|
+
// 1. Try generate-token with the current JWT.
|
|
87
|
+
let bearer = secret.password;
|
|
88
|
+
let res = await postJson(`${platformUrl}/api/user/generate-token`, { expiresIn }, bearer);
|
|
89
|
+
// 2. If unauthorized, refresh the access token first, then retry.
|
|
90
|
+
if (res.status === 401 && secret.refreshToken) {
|
|
91
|
+
const refreshed = unwrap((await postJson(`${platformUrl}/auth/refresh`, { refreshToken: secret.refreshToken })).json);
|
|
92
|
+
if (refreshed.accessToken) {
|
|
93
|
+
bearer = refreshed.accessToken;
|
|
94
|
+
res = await postJson(`${platformUrl}/api/user/generate-token`, { expiresIn }, bearer);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (res.status < 200 || res.status >= 300) {
|
|
98
|
+
throw new Error(`generate-token failed (HTTP ${res.status})`);
|
|
99
|
+
}
|
|
100
|
+
const token = unwrap(res.json);
|
|
101
|
+
if (!token.accessToken || !looksValid(token.accessToken)) {
|
|
102
|
+
// Do NOT overwrite a still-valid secret with a bad response.
|
|
103
|
+
throw new Error('generate-token returned no usable access token; leaving existing secret untouched');
|
|
104
|
+
}
|
|
105
|
+
// 3. Write the renewed secret in store-token's schema.
|
|
106
|
+
const actualExpiresIn = token.expiresIn ?? expiresIn;
|
|
107
|
+
const next = {
|
|
108
|
+
username: secret.username,
|
|
109
|
+
password: token.accessToken,
|
|
110
|
+
...(token.refreshToken ? { refreshToken: token.refreshToken } : (secret.refreshToken ? { refreshToken: secret.refreshToken } : {})),
|
|
111
|
+
platformUrl: secret.platformUrl ?? platformUrl,
|
|
112
|
+
expiresIn: actualExpiresIn,
|
|
113
|
+
expiresAt: new Date(Date.now() + actualExpiresIn * 1000).toISOString(),
|
|
114
|
+
createdAt: new Date().toISOString(),
|
|
115
|
+
};
|
|
116
|
+
await sm.send(new PutSecretValueCommand({ SecretId: secretName, SecretString: JSON.stringify(next) }));
|
|
117
|
+
// eslint-disable-next-line no-console
|
|
118
|
+
console.log(JSON.stringify({ level: 'INFO', msg: 'platform token renewed', secretName, expiresAt: next.expiresAt }));
|
|
119
|
+
};
|
|
120
|
+
function required(name) {
|
|
121
|
+
const v = process.env[name];
|
|
122
|
+
if (!v)
|
|
123
|
+
throw new Error(`${name} environment variable is required`);
|
|
124
|
+
return v;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tcmVuZXctaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sYW1iZGEvdG9rZW4tcmVuZXctaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxPQUFPLEVBQUUsT0FBTyxJQUFJLFlBQVksRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNyRCxPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLHFCQUFxQixFQUNyQixxQkFBcUIsR0FDdEIsTUFBTSxpQ0FBaUMsQ0FBQztBQWdCekMsb0ZBQW9GO0FBQ3BGLFNBQVMsUUFBUSxDQUFDLEdBQVcsRUFBRSxJQUFhLEVBQUUsTUFBZTtJQUMzRCxNQUFNLENBQUMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsTUFBTSxHQUFHLEdBQUcsWUFBWSxDQUN0QjtZQUNFLE1BQU0sRUFBRSxNQUFNO1lBQ2QsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRO1lBQ3BCLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxJQUFJLEdBQUc7WUFDbkIsSUFBSSxFQUFFLENBQUMsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxDQUFDLE1BQU07WUFDM0IsT0FBTyxFQUFFO2dCQUNQLGNBQWMsRUFBRSxrQkFBa0I7Z0JBQ2xDLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDO2dCQUM1QyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLGFBQWEsRUFBRSxVQUFVLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQzthQUN6RDtZQUNE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QVcsRUFBRTtRQUN0RSxTQUFTLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7S0FDcEMsQ0FBQztJQUNGLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLHFCQUFxQixDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUV2RyxzQ0FBc0M7SUFDdEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsd0JBQXdCLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3ZILENBQUMsQ0FBQztBQUVGLFNBQVMsUUFBUSxDQUFDLElBQVk7SUFDNUIsTUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QixJQUFJLENBQUMsQ0FBQztRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsR0FBRyxJQUFJLG1DQUFtQyxDQUFDLENBQUM7SUFDcEUsT0FBTyxDQUFDLENBQUM7QUFDWCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogTGFtYmRhIGhhbmRsZXIgdGhhdCByZS1taW50cyB0aGUgcGxhdGZvcm0gSldUIGluIFNlY3JldHMgTWFuYWdlciBzbyBpdCBuZXZlclxuICogbGFwc2VzLiBEZXBsb3llZCArIHNjaGVkdWxlZCBieSBgcGlwZWxpbmUtbWFuYWdlciBzdG9yZS10b2tlbmAgKGRlZmF1bHQgb25jZSBhXG4gKiBkYXkpLiBTZWxmLWNvbnRhaW5lZCBvbiBwdXJwb3NlIOKAlCBvbmx5IGBAYXdzLXNkay9jbGllbnQtc2VjcmV0cy1tYW5hZ2VyYCAod2hpY2hcbiAqIHRoZSBMYW1iZGEgTm9kZSBydW50aW1lIHByb3ZpZGVzKSBhbmQgbm9kZSBidWlsdC1pbnMg4oCUIHNvIGl0IGNhbiBiZSB6aXBwZWQgYW5kXG4gKiB1cGxvYWRlZCBhcyBhIHNpbmdsZSBmaWxlIHdpdGggbm8gYnVuZGxpbmcuXG4gKlxuICogRWFjaCBydW46IHJlYWQgdGhlIHNlY3JldCdzIGN1cnJlbnQgSldUIOKGkiBhc2sgdGhlIHBsYXRmb3JtIGZvciBhIGZyZXNoXG4gKiBsb25nLWxpdmVkIHRva2VuIChgL2FwaS91c2VyL2dlbmVyYXRlLXRva2VuYCwgZmFsbGluZyBiYWNrIHRvIGAvYXV0aC9yZWZyZXNoYFxuICogaWYgdGhlIGN1cnJlbnQgdG9rZW4gaGFzIGV4cGlyZWQpIOKGkiB3cml0ZSBpdCBiYWNrIGluIHN0b3JlLXRva2VuJ3Mgc2NoZW1hLlxuICogVGhlIG5ldyB0b2tlbiBpcyB2YWxpZGF0ZWQgYmVmb3JlIGl0IG92ZXJ3cml0ZXMgdGhlIHN0aWxsLXZhbGlkIG9uZS5cbiAqXG4gKiBFbnY6IFBMQVRGT1JNX1NFQ1JFVF9OQU1FLCBQTEFURk9STV9CQVNFX1VSTCwgUkVORVdfREFZUyAoZGVmYXVsdCAzMCkuXG4gKi9cbmltcG9ydCB7IHJlcXVlc3QgYXMgaHR0cHNSZXF1ZXN0IH0gZnJvbSAnbm9kZTpodHRwcyc7XG5pbXBvcnQge1xuICBTZWNyZXRzTWFuYWdlckNsaWVudCxcbiAgR2V0U2VjcmV0VmFsdWVDb21tYW5kLFxuICBQdXRTZWNyZXRWYWx1ZUNvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zZWNyZXRzLW1hbmFnZXInO1xuXG5pbnRlcmZhY2UgU2VjcmV0UGF5bG9hZCB7XG4gIHVzZXJuYW1lPzogc3RyaW5nO1xuICBwYXNzd29yZD86IHN0cmluZzsgICAgICAgLy8gdGhlIHBsYXRmb3JtIEpXVFxuICByZWZyZXNoVG9rZW4/OiBzdHJpbmc7XG4gIHBsYXRmb3JtVXJsPzogc3RyaW5nO1xuICBbazogc3RyaW5nXTogdW5rbm93bjtcbn1cblxuaW50ZXJmYWNlIFRva2VuUmVzcG9uc2Uge1xuICBhY2Nlc3NUb2tlbj86IHN0cmluZztcbiAgcmVmcmVzaFRva2VuPzogc3RyaW5nO1xuICBleHBpcmVzSW4/OiBudW1iZXI7XG59XG5cbi8qKiBNaW5pbWFsIEpTT04gUE9TVC4gSG9ub3VycyBOT0RFX1RMU19SRUpFQ1RfVU5BVVRIT1JJWkVEIHZpYSB0aGUgbm9kZSBydW50aW1lLiAqL1xuZnVuY3Rpb24gcG9zdEpzb24odXJsOiBzdHJpbmcsIGJvZHk6IHVua25vd24sIGJlYXJlcj86IHN0cmluZyk6IFByb21pc2U8eyBzdGF0dXM6IG51bWJlcjsganNvbjogdW5rbm93biB9PiB7XG4gIGNvbnN0IHUgPSBuZXcgVVJMKHVybCk7XG4gIGNvbnN0IHBheWxvYWQgPSBKU09OLnN0cmluZ2lmeShib2R5KTtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCByZXEgPSBodHRwc1JlcXVlc3QoXG4gICAgICB7XG4gICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICBob3N0bmFtZTogdS5ob3N0bmFtZSxcbiAgICAgICAgcG9ydDogdS5wb3J0IHx8IDQ0MyxcbiAgICAgICAgcGF0aDogdS5wYXRobmFtZSArIHUuc2VhcmNoLFxuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgJ2NvbnRlbnQtdHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAnY29udGVudC1sZW5ndGgnOiBCdWZmZXIuYnl0ZUxlbmd0aChwYXlsb2FkKSxcbiAgICAgICAgICAuLi4oYmVhcmVyID8geyBhdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YmVhcmVyfWAgfSA6IHt9KSxcbiAgICAgICAgfSxcbiAgICAgICAgdGltZW91dDogMjBfMDAwLFxuICAgICAgfSxcbiAgICAgIChyZXMpID0+IHtcbiAgICAgICAgbGV0IGRhdGEgPSAnJztcbiAgICAgICAgcmVzLm9uKCdkYXRhJywgKGMpID0+IChkYXRhICs9IGMpKTtcbiAgICAgICAgcmVzLm9uKCdlbmQnLCAoKSA9PiB7XG4gICAgICAgICAgbGV0IGpzb246IHVua25vd24gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgdHJ5IHsganNvbiA9IGRhdGEgPyBKU09OLnBhcnNlKGRhdGEpIDogdW5kZWZpbmVkOyB9IGNhdGNoIHsgLyogbGVhdmUgdW5kZWZpbmVkICovIH1cbiAgICAgICAgICByZXNvbHZlKHsgc3RhdHVzOiByZXMuc3RhdHVzQ29kZSA/PyAwLCBqc29uIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgKTtcbiAgICByZXEub24oJ2Vycm9yJywgcmVqZWN0KTtcbiAgICByZXEub24oJ3RpbWVvdXQnLCAoKSA9PiByZXEuZGVzdHJveShuZXcgRXJyb3IoJ3JlcXVlc3QgdGltZWQgb3V0JykpKTtcbiAgICByZXEud3JpdGUocGF5bG9hZCk7XG4gICAgcmVxLmVuZCgpO1xuICB9KTtcbn1cblxuLyoqIFVud3JhcCB0aGUgcGxhdGZvcm0ncyBgeyBzdWNjZXNzLCBkYXRhOiB7Li4ufSB9YCBlbnZlbG9wZSAob3IgYSBiYXJlIGJvZHkpLiAqL1xuZnVuY3Rpb24gdW53cmFwPFQ+KGpzb246IHVua25vd24pOiBUIHtcbiAgY29uc3QgaiA9IGpzb24gYXMgeyBkYXRhPzogVCB9IHwgVDtcbiAgcmV0dXJuICgoaiBhcyB7IGRhdGE/OiBUIH0pPy5kYXRhID8/IGopIGFzIFQ7XG59XG5cbi8qKiBCYXNpYyBKV1Qgc2FuaXR5OiBkZWNvZGVzLCBtdXN0IGNhcnJ5IGFuIG9yZyBhbmQgYSBmdXR1cmUgYGV4cGAuICovXG5mdW5jdGlvbiBsb29rc1ZhbGlkKGp3dDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IHBhcnRzID0gand0LnNwbGl0KCcuJyk7XG4gIGlmIChwYXJ0cy5sZW5ndGggIT09IDMpIHJldHVybiBmYWxzZTtcbiAgdHJ5IHtcbiAgICBjb25zdCBwYXlsb2FkID0gSlNPTi5wYXJzZShCdWZmZXIuZnJvbShwYXJ0c1sxXSEsICdiYXNlNjR1cmwnKS50b1N0cmluZygndXRmLTgnKSkgYXMgeyBleHA/OiBudW1iZXI7IG9yZ2FuaXphdGlvbklkPzogc3RyaW5nIH07XG4gICAgaWYgKCFwYXlsb2FkLmV4cCB8fCBwYXlsb2FkLmV4cCAqIDEwMDAgPD0gRGF0ZS5ub3coKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0eXBlb2YgcGF5bG9hZC5vcmdhbml6YXRpb25JZCA9PT0gJ3N0cmluZyc7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgaGFuZGxlciA9IGFzeW5jICgpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc3Qgc2VjcmV0TmFtZSA9IHJlcXVpcmVkKCdQTEFURk9STV9TRUNSRVRfTkFNRScpO1xuICBjb25zdCBwbGF0Zm9ybVVybCA9IHJlcXVpcmVkKCdQTEFURk9STV9CQVNFX1VSTCcpLnJlcGxhY2UoL1xcLyQvLCAnJyk7XG4gIGNvbnN0IGRheXMgPSBwYXJzZUludChwcm9jZXNzLmVudi5SRU5FV19EQVlTIHx8ICczMCcsIDEwKTtcbiAgY29uc3QgZXhwaXJlc0luID0gZGF5cyAqIDI0ICogNjAgKiA2MDtcbiAgY29uc3QgcmVnaW9uID0gcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTjtcblxuICBjb25zdCBzbSA9IG5ldyBTZWNyZXRzTWFuYWdlckNsaWVudCh7IHJlZ2lvbiB9KTtcbiAgY29uc3QgY3VycmVudCA9IGF3YWl0IHNtLnNlbmQobmV3IEdldFNlY3JldFZhbHVlQ29tbWFuZCh7IFNlY3JldElkOiBzZWNyZXROYW1lIH0pKTtcbiAgaWYgKCFjdXJyZW50LlNlY3JldFN0cmluZykgdGhyb3cgbmV3IEVycm9yKGBTZWNyZXQgXCIke3NlY3JldE5hbWV9XCIgaXMgZW1wdHlgKTtcbiAgY29uc3Qgc2VjcmV0ID0gSlNPTi5wYXJzZShjdXJyZW50LlNlY3JldFN0cmluZykgYXMgU2VjcmV0UGF5bG9hZDtcbiAgaWYgKCFzZWNyZXQucGFzc3dvcmQpIHRocm93IG5ldyBFcnJvcihgU2VjcmV0IFwiJHtzZWNyZXROYW1lfVwiIG1pc3NpbmcgcGFzc3dvcmQgKEpXVClgKTtcblxuICAvLyAxLiBUcnkgZ2VuZXJhdGUtdG9rZW4gd2l0aCB0aGUgY3VycmVudCBKV1QuXG4gIGxldCBiZWFyZXIgPSBzZWNyZXQucGFzc3dvcmQ7XG4gIGxldCByZXMgPSBhd2FpdCBwb3N0SnNvbihgJHtwbGF0Zm9ybVVybH0vYXBpL3VzZXIvZ2VuZXJhdGUtdG9rZW5gLCB7IGV4cGlyZXNJbiB9LCBiZWFyZXIpO1xuXG4gIC8vIDIuIElmIHVuYXV0aG9yaXplZCwgcmVmcmVzaCB0aGUgYWNjZXNzIHRva2VuIGZpcnN0LCB0aGVuIHJldHJ5LlxuICBpZiAocmVzLnN0YXR1cyA9PT0gNDAxICYmIHNlY3JldC5yZWZyZXNoVG9rZW4pIHtcbiAgICBjb25zdCByZWZyZXNoZWQgPSB1bndyYXA8VG9rZW5SZXNwb25zZT4oXG4gICAgICAoYXdhaXQgcG9zdEpzb24oYCR7cGxhdGZvcm1Vcmx9L2F1dGgvcmVmcmVzaGAsIHsgcmVmcmVzaFRva2VuOiBzZWNyZXQucmVmcmVzaFRva2VuIH0pKS5qc29uLFxuICAgICk7XG4gICAgaWYgKHJlZnJlc2hlZC5hY2Nlc3NUb2tlbikge1xuICAgICAgYmVhcmVyID0gcmVmcmVzaGVkLmFjY2Vzc1Rva2VuO1xuICAgICAgcmVzID0gYXdhaXQgcG9zdEpzb24oYCR7cGxhdGZvcm1Vcmx9L2FwaS91c2VyL2dlbmVyYXRlLXRva2VuYCwgeyBleHBpcmVzSW4gfSwgYmVhcmVyKTtcbiAgICB9XG4gIH1cblxuICBpZiAocmVzLnN0YXR1cyA8IDIwMCB8fCByZXMuc3RhdHVzID49IDMwMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgZ2VuZXJhdGUtdG9rZW4gZmFpbGVkIChIVFRQICR7cmVzLnN0YXR1c30pYCk7XG4gIH1cblxuICBjb25zdCB0b2tlbiA9IHVud3JhcDxUb2tlblJlc3BvbnNlPihyZXMuanNvbik7XG4gIGlmICghdG9rZW4uYWNjZXNzVG9rZW4gfHwgIWxvb2tzVmFsaWQodG9rZW4uYWNjZXNzVG9rZW4pKSB7XG4gICAgLy8gRG8gTk9UIG92ZXJ3cml0ZSBhIHN0aWxsLXZhbGlkIHNlY3JldCB3aXRoIGEgYmFkIHJlc3BvbnNlLlxuICAgIHRocm93IG5ldyBFcnJvcignZ2VuZXJhdGUtdG9rZW4gcmV0dXJuZWQgbm8gdXNhYmxlIGFjY2VzcyB0b2tlbjsgbGVhdmluZyBleGlzdGluZyBzZWNyZXQgdW50b3VjaGVkJyk7XG4gIH1cblxuICAvLyAzLiBXcml0ZSB0aGUgcmVuZXdlZCBzZWNyZXQgaW4gc3RvcmUtdG9rZW4ncyBzY2hlbWEuXG4gIGNvbnN0IGFjdHVhbEV4cGlyZXNJbiA9IHRva2VuLmV4cGlyZXNJbiA/PyBleHBpcmVzSW47XG4gIGNvbnN0IG5leHQ6IFNlY3JldFBheWxvYWQgPSB7XG4gICAgdXNlcm5hbWU6IHNlY3JldC51c2VybmFtZSxcbiAgICBwYXNzd29yZDogdG9rZW4uYWNjZXNzVG9rZW4sXG4gICAgLi4uKHRva2VuLnJlZnJlc2hUb2tlbiA/IHsgcmVmcmVzaFRva2VuOiB0b2tlbi5yZWZyZXNoVG9rZW4gfSA6IChzZWNyZXQucmVmcmVzaFRva2VuID8geyByZWZyZXNoVG9rZW46IHNlY3JldC5yZWZyZXNoVG9rZW4gfSA6IHt9KSksXG4gICAgcGxhdGZvcm1Vcmw6IHNlY3JldC5wbGF0Zm9ybVVybCA/PyBwbGF0Zm9ybVVybCxcbiAgICBleHBpcmVzSW46IGFjdHVhbEV4cGlyZXNJbixcbiAgICBleHBpcmVzQXQ6IG5ldyBEYXRlKERhdGUubm93KCkgKyBhY3R1YWxFeHBpcmVzSW4gKiAxMDAwKS50b0lTT1N0cmluZygpLFxuICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICB9O1xuICBhd2FpdCBzbS5zZW5kKG5ldyBQdXRTZWNyZXRWYWx1ZUNvbW1hbmQoeyBTZWNyZXRJZDogc2VjcmV0TmFtZSwgU2VjcmV0U3RyaW5nOiBKU09OLnN0cmluZ2lmeShuZXh0KSB9KSk7XG5cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoeyBsZXZlbDogJ0lORk8nLCBtc2c6ICdwbGF0Zm9ybSB0b2tlbiByZW5ld2VkJywgc2VjcmV0TmFtZSwgZXhwaXJlc0F0OiBuZXh0LmV4cGlyZXNBdCB9KSk7XG59O1xuXG5mdW5jdGlvbiByZXF1aXJlZChuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCB2ID0gcHJvY2Vzcy5lbnZbbmFtZV07XG4gIGlmICghdikgdGhyb3cgbmV3IEVycm9yKGAke25hbWV9IGVudmlyb25tZW50IHZhcmlhYmxlIGlzIHJlcXVpcmVkYCk7XG4gIHJldHVybiB2O1xufVxuIl19
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"AWSTemplateFormatVersion": "2010-09-09",
|
|
3
|
+
"Description": "Pipeline Builder platform-token renewal — a scheduled Lambda that re-mints the platform JWT in Secrets Manager before it expires, so CodeBuild/Lambda credentials never lapse. Lambda code is deployed separately via pipeline-manager store-token.",
|
|
4
|
+
"Parameters": {
|
|
5
|
+
"PlatformBaseUrl": {
|
|
6
|
+
"Type": "String",
|
|
7
|
+
"Description": "Base URL of the platform (e.g. https://app.example.com)"
|
|
8
|
+
},
|
|
9
|
+
"PlatformSecretName": {
|
|
10
|
+
"Type": "String",
|
|
11
|
+
"Description": "Secrets Manager secret name holding the platform JWT (e.g. pipeline-builder/{orgId}/platform)"
|
|
12
|
+
},
|
|
13
|
+
"RenewDays": {
|
|
14
|
+
"Type": "Number",
|
|
15
|
+
"Default": 30,
|
|
16
|
+
"MinValue": 1,
|
|
17
|
+
"MaxValue": 365,
|
|
18
|
+
"Description": "Lifetime in days requested for each renewed token"
|
|
19
|
+
},
|
|
20
|
+
"ScheduleExpression": {
|
|
21
|
+
"Type": "String",
|
|
22
|
+
"Default": "cron(0 0 * * ? *)",
|
|
23
|
+
"Description": "EventBridge schedule expression for the renewal (default: daily at 00:00 UTC)"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"Resources": {
|
|
27
|
+
"LambdaRole": {
|
|
28
|
+
"Type": "AWS::IAM::Role",
|
|
29
|
+
"Properties": {
|
|
30
|
+
"RoleName": "pipeline-builder-token-renew",
|
|
31
|
+
"AssumeRolePolicyDocument": {
|
|
32
|
+
"Version": "2012-10-17",
|
|
33
|
+
"Statement": [{
|
|
34
|
+
"Effect": "Allow",
|
|
35
|
+
"Principal": { "Service": "lambda.amazonaws.com" },
|
|
36
|
+
"Action": "sts:AssumeRole"
|
|
37
|
+
}]
|
|
38
|
+
},
|
|
39
|
+
"ManagedPolicyArns": [
|
|
40
|
+
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
41
|
+
],
|
|
42
|
+
"Policies": [{
|
|
43
|
+
"PolicyName": "token-renew",
|
|
44
|
+
"PolicyDocument": {
|
|
45
|
+
"Statement": [{
|
|
46
|
+
"Effect": "Allow",
|
|
47
|
+
"Action": ["secretsmanager:GetSecretValue", "secretsmanager:PutSecretValue"],
|
|
48
|
+
"Resource": { "Fn::Sub": "arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:pipeline-builder/*/platform-*" }
|
|
49
|
+
}]
|
|
50
|
+
}
|
|
51
|
+
}]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"TokenRenewHandler": {
|
|
55
|
+
"Type": "AWS::Lambda::Function",
|
|
56
|
+
"Properties": {
|
|
57
|
+
"FunctionName": "pipeline-builder-token-renew",
|
|
58
|
+
"Runtime": "nodejs24.x",
|
|
59
|
+
"Handler": "index.handler",
|
|
60
|
+
"Code": {
|
|
61
|
+
"ZipFile": "exports.handler=async()=>{console.log('Placeholder handler — run pipeline-manager store-token to deploy real code');return{statusCode:200}}"
|
|
62
|
+
},
|
|
63
|
+
"Role": { "Fn::GetAtt": ["LambdaRole", "Arn"] },
|
|
64
|
+
"Timeout": 60,
|
|
65
|
+
"MemorySize": 256,
|
|
66
|
+
"Environment": {
|
|
67
|
+
"Variables": {
|
|
68
|
+
"PLATFORM_BASE_URL": { "Ref": "PlatformBaseUrl" },
|
|
69
|
+
"PLATFORM_SECRET_NAME": { "Ref": "PlatformSecretName" },
|
|
70
|
+
"RENEW_DAYS": { "Ref": "RenewDays" }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"ScheduleRule": {
|
|
76
|
+
"Type": "AWS::Events::Rule",
|
|
77
|
+
"Properties": {
|
|
78
|
+
"Name": "pipeline-builder-token-renew",
|
|
79
|
+
"Description": "Scheduled platform-token renewal",
|
|
80
|
+
"State": "ENABLED",
|
|
81
|
+
"ScheduleExpression": { "Ref": "ScheduleExpression" },
|
|
82
|
+
"Targets": [{
|
|
83
|
+
"Id": "token-renew-lambda",
|
|
84
|
+
"Arn": { "Fn::GetAtt": ["TokenRenewHandler", "Arn"] }
|
|
85
|
+
}]
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"InvokePermission": {
|
|
89
|
+
"Type": "AWS::Lambda::Permission",
|
|
90
|
+
"Properties": {
|
|
91
|
+
"FunctionName": { "Ref": "TokenRenewHandler" },
|
|
92
|
+
"Action": "lambda:InvokeFunction",
|
|
93
|
+
"Principal": "events.amazonaws.com",
|
|
94
|
+
"SourceArn": { "Fn::GetAtt": ["ScheduleRule", "Arn"] }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"Outputs": {
|
|
99
|
+
"LambdaFunctionArn": { "Value": { "Fn::GetAtt": ["TokenRenewHandler", "Arn"] } },
|
|
100
|
+
"ScheduleRuleName": { "Value": { "Ref": "ScheduleRule" } },
|
|
101
|
+
"ScheduleExpression": { "Value": { "Ref": "ScheduleExpression" } }
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a standard 5-field cron expression into an AWS EventBridge cron
|
|
3
|
+
* expression, and guard against schedules that fire more often than every
|
|
4
|
+
* 15 minutes.
|
|
5
|
+
*
|
|
6
|
+
* Standard cron: `minute hour day-of-month month day-of-week`
|
|
7
|
+
* EventBridge cron: `cron(minute hour day-of-month month day-of-week year)`
|
|
8
|
+
*
|
|
9
|
+
* The non-obvious differences EventBridge imposes:
|
|
10
|
+
* - a 6th field (year), which we always set to `*`;
|
|
11
|
+
* - day-of-month and day-of-week may NOT both be `*` — exactly one must be `?`;
|
|
12
|
+
* - day-of-week is 1–7 with 1 = Sunday, whereas standard cron is 0–6 (or 7)
|
|
13
|
+
* with 0/7 = Sunday — so numeric day-of-week values must be remapped.
|
|
14
|
+
*/
|
|
15
|
+
/** Minimum allowed spacing between fires, in minutes. */
|
|
16
|
+
export declare const MIN_SCHEDULE_INTERVAL_MIN = 15;
|
|
17
|
+
/**
|
|
18
|
+
* Throw if `fiveField` would fire more often than every {@link MIN_SCHEDULE_INTERVAL_MIN}
|
|
19
|
+
* minutes. Conservative: the smallest cyclic gap in the minute field is the worst-case
|
|
20
|
+
* spacing (it's only ever larger once the hour/day fields restrict things further).
|
|
21
|
+
*/
|
|
22
|
+
export declare function assertScheduleInterval(fiveField: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Convert a validated 5-field cron expression to an AWS EventBridge `cron(...)`
|
|
25
|
+
* expression. Also enforces the 15-minute guard.
|
|
26
|
+
*/
|
|
27
|
+
export declare function toEventBridgeCron(fiveField: string): string;
|
|
28
|
+
//# sourceMappingURL=cron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/utils/cron.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AAEH,yDAAyD;AACzD,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAgC5C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAuB9D;AAaD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAmB3D"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Convert a standard 5-field cron expression into an AWS EventBridge cron
|
|
5
|
+
* expression, and guard against schedules that fire more often than every
|
|
6
|
+
* 15 minutes.
|
|
7
|
+
*
|
|
8
|
+
* Standard cron: `minute hour day-of-month month day-of-week`
|
|
9
|
+
* EventBridge cron: `cron(minute hour day-of-month month day-of-week year)`
|
|
10
|
+
*
|
|
11
|
+
* The non-obvious differences EventBridge imposes:
|
|
12
|
+
* - a 6th field (year), which we always set to `*`;
|
|
13
|
+
* - day-of-month and day-of-week may NOT both be `*` — exactly one must be `?`;
|
|
14
|
+
* - day-of-week is 1–7 with 1 = Sunday, whereas standard cron is 0–6 (or 7)
|
|
15
|
+
* with 0/7 = Sunday — so numeric day-of-week values must be remapped.
|
|
16
|
+
*/
|
|
17
|
+
/** Minimum allowed spacing between fires, in minutes. */
|
|
18
|
+
export const MIN_SCHEDULE_INTERVAL_MIN = 15;
|
|
19
|
+
/** Expand a cron minute field (wildcard, step "/n", ranges "a-b", lists "a,b") to the sorted set of minutes it fires on. */
|
|
20
|
+
function expandMinuteField(field) {
|
|
21
|
+
const out = new Set();
|
|
22
|
+
for (const part of field.split(',')) {
|
|
23
|
+
const slash = part.split('/');
|
|
24
|
+
const rangePart = slash[0] ?? '';
|
|
25
|
+
const stepPart = slash[1];
|
|
26
|
+
const step = stepPart !== undefined ? parseInt(stepPart, 10) : 1;
|
|
27
|
+
if (stepPart !== undefined && (!Number.isInteger(step) || step < 1)) {
|
|
28
|
+
throw new Error(`Invalid step in minute field: "${part}"`);
|
|
29
|
+
}
|
|
30
|
+
let lo;
|
|
31
|
+
let hi;
|
|
32
|
+
if (rangePart === '*') {
|
|
33
|
+
lo = 0;
|
|
34
|
+
hi = 59;
|
|
35
|
+
}
|
|
36
|
+
else if (rangePart.includes('-')) {
|
|
37
|
+
const ends = rangePart.split('-');
|
|
38
|
+
lo = parseInt(ends[0] ?? '', 10);
|
|
39
|
+
hi = parseInt(ends[1] ?? '', 10);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
lo = hi = parseInt(rangePart, 10);
|
|
43
|
+
}
|
|
44
|
+
if (!Number.isInteger(lo) || !Number.isInteger(hi) || lo < 0 || hi > 59 || lo > hi) {
|
|
45
|
+
throw new Error(`Invalid minute field: "${part}"`);
|
|
46
|
+
}
|
|
47
|
+
for (let m = lo; m <= hi; m += step)
|
|
48
|
+
out.add(m);
|
|
49
|
+
}
|
|
50
|
+
return [...out].sort((a, b) => a - b);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Throw if `fiveField` would fire more often than every {@link MIN_SCHEDULE_INTERVAL_MIN}
|
|
54
|
+
* minutes. Conservative: the smallest cyclic gap in the minute field is the worst-case
|
|
55
|
+
* spacing (it's only ever larger once the hour/day fields restrict things further).
|
|
56
|
+
*/
|
|
57
|
+
export function assertScheduleInterval(fiveField) {
|
|
58
|
+
const parts = fiveField.trim().split(/\s+/);
|
|
59
|
+
if (parts.length !== 5) {
|
|
60
|
+
throw new Error(`Schedule must be a 5-field cron ("minute hour day-of-month month day-of-week"), got: "${fiveField}"`);
|
|
61
|
+
}
|
|
62
|
+
const minutes = expandMinuteField(parts[0]);
|
|
63
|
+
if (minutes.length === 0)
|
|
64
|
+
throw new Error(`Minute field matches nothing: "${parts[0]}"`);
|
|
65
|
+
// Smallest cyclic gap across the hour boundary (e.g. {0,50} → gaps 50 and 10).
|
|
66
|
+
let minGap = 60;
|
|
67
|
+
if (minutes.length > 1) {
|
|
68
|
+
for (let i = 0; i < minutes.length; i++) {
|
|
69
|
+
const cur = minutes[i];
|
|
70
|
+
const next = minutes[(i + 1) % minutes.length];
|
|
71
|
+
const gap = (next - cur + 60) % 60 || 60;
|
|
72
|
+
minGap = Math.min(minGap, gap);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (minGap < MIN_SCHEDULE_INTERVAL_MIN) {
|
|
76
|
+
throw new Error(`Schedule "${fiveField}" fires every ${minGap} minute(s); the minimum is ${MIN_SCHEDULE_INTERVAL_MIN}. ` +
|
|
77
|
+
`Use a sparser schedule (e.g. "0 0 * * *" for daily, "*/15 * * * *" for the densest allowed).`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Remap a standard cron day-of-week token (0–7, 0/7=Sun) to EventBridge (1–7, 1=Sun). Passes through names and `*`/`?`. */
|
|
81
|
+
function remapDayOfWeek(field) {
|
|
82
|
+
if (field === '*' || field === '?')
|
|
83
|
+
return field;
|
|
84
|
+
// Token may contain lists/ranges/steps of numbers and/or 3-letter names.
|
|
85
|
+
return field.replace(/\d+/g, (n) => {
|
|
86
|
+
const v = parseInt(n, 10);
|
|
87
|
+
if (v < 0 || v > 7)
|
|
88
|
+
throw new Error(`Invalid day-of-week value: "${n}"`);
|
|
89
|
+
return String((v % 7) + 1); // 0→1 (Sun), 6→7 (Sat), 7→1 (Sun)
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Convert a validated 5-field cron expression to an AWS EventBridge `cron(...)`
|
|
94
|
+
* expression. Also enforces the 15-minute guard.
|
|
95
|
+
*/
|
|
96
|
+
export function toEventBridgeCron(fiveField) {
|
|
97
|
+
assertScheduleInterval(fiveField); // also validates the 5-field shape
|
|
98
|
+
const f = fiveField.trim().split(/\s+/);
|
|
99
|
+
const [minute, hour, domRaw, month, dowRaw] = [f[0], f[1], f[2], f[3], f[4]];
|
|
100
|
+
let dom = domRaw;
|
|
101
|
+
let dow = remapDayOfWeek(dowRaw);
|
|
102
|
+
// EventBridge: exactly one of day-of-month / day-of-week must be `?`.
|
|
103
|
+
if (dom === '*' && dow === '*') {
|
|
104
|
+
dow = '?'; // unrestricted both → pin day-of-week to ?
|
|
105
|
+
}
|
|
106
|
+
else if (dom !== '*' && dow === '*') {
|
|
107
|
+
dow = '?'; // specific day-of-month → day-of-week must be ?
|
|
108
|
+
}
|
|
109
|
+
else if (dom === '*' && dow !== '*') {
|
|
110
|
+
dom = '?'; // specific day-of-week → day-of-month must be ?
|
|
111
|
+
}
|
|
112
|
+
// (both specific is left as-is; EventBridge rejects it, surfacing a clear error)
|
|
113
|
+
return `cron(${minute} ${hour} ${dom} ${month} ${dow} *)`;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3Jvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9jcm9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUVILHlEQUF5RDtBQUN6RCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxFQUFFLENBQUM7QUFFNUMsNEhBQTRIO0FBQzVILFNBQVMsaUJBQWlCLENBQUMsS0FBYTtJQUN0QyxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQzlCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDOUIsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNqQyxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUIsTUFBTSxJQUFJLEdBQUcsUUFBUSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pFLElBQUksUUFBUSxLQUFLLFNBQVMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNwRSxNQUFNLElBQUksS0FBSyxDQUFDLGtDQUFrQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQzdELENBQUM7UUFDRCxJQUFJLEVBQVUsQ0FBQztRQUNmLElBQUksRUFBVSxDQUFDO1FBQ2YsSUFBSSxTQUFTLEtBQUssR0FBRyxFQUFFLENBQUM7WUFDdEIsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUFDLEVB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LEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRWpDLHNFQUFzRTtJQUN0RSxJQUFJLEdBQUcsS0FBSyxHQUFHLElBQUksR0FBRyxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQy9CLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQywyQ0FBMkM7SUFDeEQsQ0FBQztTQUFNLElBQUksR0FBRyxLQUFLLEdBQUcsSUFBSSxHQUFHLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDdEMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDLGdEQUFnRDtJQUM3RCxDQUFDO1NBQU0sSUFBSSxHQUFHLEtBQUssR0FBRyxJQUFJLEdBQUcsS0FBSyxHQUFHLEVBQUUsQ0FBQztRQUN0QyxHQUFHLEdBQUcsR0FBRyxDQUFDLENBQUMsZ0RBQWdEO0lBQzdELENBQUM7SUFDRCxpRkFBaUY7SUFFakYsT0FBTyxRQUFRLE1BQU0sSUFBSSxJQUFJLElBQUksR0FBRyxJQUFJLEtBQUssSUFBSSxHQUFHLEtBQUssQ0FBQztBQUM1RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogQ29udmVydCBhIHN0YW5kYXJkIDUtZmllbGQgY3JvbiBleHByZXNzaW9uIGludG8gYW4gQVdTIEV2ZW50QnJpZGdlIGNyb25cbiAqIGV4cHJlc3Npb24sIGFuZCBndWFyZCBhZ2FpbnN0IHNjaGVkdWxlcyB0aGF0IGZpcmUgbW9yZSBvZnRlbiB0aGFuIGV2ZXJ5XG4gKiAxNSBtaW51dGVzLlxuICpcbiAqIFN0YW5kYXJkIGNyb246ICAgIGBtaW51dGUgaG91ciBkYXktb2YtbW9udGggbW9udGggZGF5LW9mLXdlZWtgXG4gKiBFdmVudEJyaWRnZSBjcm9uOiBgY3JvbihtaW51dGUgaG91ciBkYXktb2YtbW9udGggbW9udGggZGF5LW9mLXdlZWsgeWVhcilgXG4gKlxuICogVGhlIG5vbi1vYnZpb3VzIGRpZmZlcmVuY2VzIEV2ZW50QnJpZGdlIGltcG9zZXM6XG4gKiAgLSBhIDZ0aCBmaWVsZCAoeWVhciksIHdoaWNoIHdlIGFsd2F5cyBzZXQgdG8gYCpgO1xuICogIC0gZGF5LW9mLW1vbnRoIGFuZCBkYXktb2Ytd2VlayBtYXkgTk9UIGJvdGggYmUgYCpgIOKAlCBleGFjdGx5IG9uZSBtdXN0IGJlIGA/YDtcbiAqICAtIGRheS1vZi13ZWVrIGlzIDHigJM3IHdpdGggMSA9IFN1bmRheSwgd2hlcmVhcyBzdGFuZGFyZCBjcm9uIGlzIDDigJM2IChvciA3KVxuICogICAgd2l0aCAwLzcgPSBTdW5kYXkg4oCUIHNvIG51bWVyaWMgZGF5LW9mLXdlZWsgdmFsdWVzIG11c3QgYmUgcmVtYXBwZWQuXG4gKi9cblxuLyoqIE1pbmltdW0gYWxsb3dlZCBzcGFjaW5nIGJldHdlZW4gZmlyZXMsIGluIG1pbnV0ZXMuICovXG5leHBvcnQgY29uc3QgTUlOX1NDSEVEVUxFX0lOVEVSVkFMX01JTiA9IDE1O1xuXG4vKiogRXhwYW5kIGEgY3JvbiBtaW51dGUgZmllbGQgKHdpbGRjYXJkLCBzdGVwIFwiL25cIiwgcmFuZ2VzIFwiYS1iXCIsIGxpc3RzIFwiYSxiXCIpIHRvIHRoZSBzb3J0ZWQgc2V0IG9mIG1pbnV0ZXMgaXQgZmlyZXMgb24uICovXG5mdW5jdGlvbiBleHBhbmRNaW51dGVGaWVsZChmaWVsZDogc3RyaW5nKTogbnVtYmVyW10ge1xuICBjb25zdCBvdXQgPSBuZXcgU2V0PG51bWJlcj4oKTtcbiAgZm9yIChjb25zdCBwYXJ0IG9mIGZpZWxkLnNwbGl0KCcsJykpIHtcbiAgICBjb25zdCBzbGFzaCA9IHBhcnQuc3BsaXQoJy8nKTtcbiAgICBjb25zdCByYW5nZVBhcnQgPSBzbGFzaFswXSA/PyAnJztcbiAgICBjb25zdCBzdGVwUGFydCA9IHNsYXNoWzFdO1xuICAgIGNvbnN0IHN0ZXAgPSBzdGVwUGFydCAhPT0gdW5kZWZpbmVkID8gcGFyc2VJbnQoc3RlcFBhcnQsIDEwKSA6IDE7XG4gICAgaWYgKHN0ZXBQYXJ0ICE9PSB1bmRlZmluZWQgJiYgKCFOdW1iZXIuaXNJbnRlZ2VyKHN0ZXApIHx8IHN0ZXAgPCAxKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHN0ZXAgaW4gbWludXRlIGZpZWxkOiBcIiR7cGFydH1cImApO1xuICAgIH1cbiAgICBsZXQgbG86IG51bWJlcjtcbiAgICBsZXQgaGk6IG51bWJlcjtcbiAgICBpZiAocmFuZ2VQYXJ0ID09PSAnKicpIHtcbiAgICAgIGxvID0gMDsgaGkgPSA1OTtcbiAgICB9IGVsc2UgaWYgKHJhbmdlUGFydC5pbmNsdWRlcygnLScpKSB7XG4gICAgICBjb25zdCBlbmRzID0gcmFuZ2VQYXJ0LnNwbGl0KCctJyk7XG4gICAgICBsbyA9IHBhcnNlSW50KGVuZHNbMF0gPz8gJycsIDEwKTtcbiAgICAgIGhpID0gcGFyc2VJbnQoZW5kc1sxXSA/PyAnJywgMTApO1xuICAgIH0gZWxzZSB7XG4gICAgICBsbyA9IGhpID0gcGFyc2VJbnQocmFuZ2VQYXJ0LCAxMCk7XG4gICAgfVxuICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihsbykgfHwgIU51bWJlci5pc0ludGVnZXIoaGkpIHx8IGxvIDwgMCB8fCBoaSA+IDU5IHx8IGxvID4gaGkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBtaW51dGUgZmllbGQ6IFwiJHtwYXJ0fVwiYCk7XG4gICAgfVxuICAgIGZvciAobGV0IG0gPSBsbzsgbSA8PSBoaTsgbSArPSBzdGVwKSBvdXQuYWRkKG0pO1xuICB9XG4gIHJldHVybiBbLi4ub3V0XS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG59XG5cbi8qKlxuICogVGhyb3cgaWYgYGZpdmVGaWVsZGAgd291bGQgZmlyZSBtb3JlIG9mdGVuIHRoYW4gZXZlcnkge0BsaW5rIE1JTl9TQ0hFRFVMRV9JTlRFUlZBTF9NSU59XG4gKiBtaW51dGVzLiBDb25zZXJ2YXRpdmU6IHRoZSBzbWFsbGVzdCBjeWNsaWMgZ2FwIGluIHRoZSBtaW51dGUgZmllbGQgaXMgdGhlIHdvcnN0LWNhc2VcbiAqIHNwYWNpbmcgKGl0J3Mgb25seSBldmVyIGxhcmdlciBvbmNlIHRoZSBob3VyL2RheSBmaWVsZHMgcmVzdHJpY3QgdGhpbmdzIGZ1cnRoZXIpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0U2NoZWR1bGVJbnRlcnZhbChmaXZlRmllbGQ6IHN0cmluZyk6IHZvaWQge1xuICBjb25zdCBwYXJ0cyA9IGZpdmVGaWVsZC50cmltKCkuc3BsaXQoL1xccysvKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCAhPT0gNSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgU2NoZWR1bGUgbXVzdCBiZSBhIDUtZmllbGQgY3JvbiAoXCJtaW51dGUgaG91ciBkYXktb2YtbW9udGggbW9udGggZGF5LW9mLXdlZWtcIiksIGdvdDogXCIke2ZpdmVGaWVsZH1cImApO1xuICB9XG4gIGNvbnN0IG1pbnV0ZXMgPSBleHBhbmRNaW51dGVGaWVsZChwYXJ0c1swXSEpO1xuICBpZiAobWludXRlcy5sZW5ndGggPT09IDApIHRocm93IG5ldyBFcnJvcihgTWludXRlIGZpZWxkIG1hdGNoZXMgbm90aGluZzogXCIke3BhcnRzWzBdfVwiYCk7XG4gIC8vIFNtYWxsZXN0IGN5Y2xpYyBnYXAgYWNyb3NzIHRoZSBob3VyIGJvdW5kYXJ5IChlLmcuIHswLDUwfSDihpIgZ2FwcyA1MCBhbmQgMTApLlxuICBsZXQgbWluR2FwID0gNjA7XG4gIGlmIChtaW51dGVzLmxlbmd0aCA+IDEpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1pbnV0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGN1ciA9IG1pbnV0ZXNbaV0hO1xuICAgICAgY29uc3QgbmV4dCA9IG1pbnV0ZXNbKGkgKyAxKSAlIG1pbnV0ZXMubGVuZ3RoXSE7XG4gICAgICBjb25zdCBnYXAgPSAobmV4dCAtIGN1ciArIDYwKSAlIDYwIHx8IDYwO1xuICAgICAgbWluR2FwID0gTWF0aC5taW4obWluR2FwLCBnYXApO1xuICAgIH1cbiAgfVxuICBpZiAobWluR2FwIDwgTUlOX1NDSEVEVUxFX0lOVEVSVkFMX01JTikge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBTY2hlZHVsZSBcIiR7Zml2ZUZpZWxkfVwiIGZpcmVzIGV2ZXJ5ICR7bWluR2FwfSBtaW51dGUocyk7IHRoZSBtaW5pbXVtIGlzICR7TUlOX1NDSEVEVUxFX0lOVEVSVkFMX01JTn0uIGAgK1xuICAgICAgYFVzZSBhIHNwYXJzZXIgc2NoZWR1bGUgKGUuZy4gXCIwIDAgKiAqICpcIiBmb3IgZGFpbHksIFwiKi8xNSAqICogKiAqXCIgZm9yIHRoZSBkZW5zZXN0IGFsbG93ZWQpLmAsXG4gICAgKTtcbiAgfVxufVxuXG4vKiogUmVtYXAgYSBzdGFuZGFyZCBjcm9uIGRheS1vZi13ZWVrIHRva2VuICgw4oCTNywgMC83PVN1bikgdG8gRXZlbnRCcmlkZ2UgKDHigJM3LCAxPVN1bikuIFBhc3NlcyB0aHJvdWdoIG5hbWVzIGFuZCBgKmAvYD9gLiAqL1xuZnVuY3Rpb24gcmVtYXBEYXlPZldlZWsoZmllbGQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChmaWVsZCA9PT0gJyonIHx8IGZpZWxkID09PSAnPycpIHJldHVybiBmaWVsZDtcbiAgLy8gVG9rZW4gbWF5IGNvbnRhaW4gbGlzdHMvcmFuZ2VzL3N0ZXBzIG9mIG51bWJlcnMgYW5kL29yIDMtbGV0dGVyIG5hbWVzLlxuICByZXR1cm4gZmllbGQucmVwbGFjZSgvXFxkKy9nLCAobikgPT4ge1xuICAgIGNvbnN0IHYgPSBwYXJzZUludChuLCAxMCk7XG4gICAgaWYgKHYgPCAwIHx8IHYgPiA3KSB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZGF5LW9mLXdlZWsgdmFsdWU6IFwiJHtufVwiYCk7XG4gICAgcmV0dXJuIFN0cmluZygodiAlIDcpICsgMSk7IC8vIDDihpIxIChTdW4pLCA24oaSNyAoU2F0KSwgN+KGkjEgKFN1bilcbiAgfSk7XG59XG5cbi8qKlxuICogQ29udmVydCBhIHZhbGlkYXRlZCA1LWZpZWxkIGNyb24gZXhwcmVzc2lvbiB0byBhbiBBV1MgRXZlbnRCcmlkZ2UgYGNyb24oLi4uKWBcbiAqIGV4cHJlc3Npb24uIEFsc28gZW5mb3JjZXMgdGhlIDE1LW1pbnV0ZSBndWFyZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvRXZlbnRCcmlkZ2VDcm9uKGZpdmVGaWVsZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgYXNzZXJ0U2NoZWR1bGVJbnRlcnZhbChmaXZlRmllbGQpOyAvLyBhbHNvIHZhbGlkYXRlcyB0aGUgNS1maWVsZCBzaGFwZVxuICBjb25zdCBmID0gZml2ZUZpZWxkLnRyaW0oKS5zcGxpdCgvXFxzKy8pO1xuICBjb25zdCBbbWludXRlLCBob3VyLCBkb21SYXcsIG1vbnRoLCBkb3dSYXddID0gW2ZbMF0hLCBmWzFdISwgZlsyXSEsIGZbM10hLCBmWzRdIV07XG5cbiAgbGV0IGRvbSA9IGRvbVJhdztcbiAgbGV0IGRvdyA9IHJlbWFwRGF5T2ZXZWVrKGRvd1Jhdyk7XG5cbiAgLy8gRXZlbnRCcmlkZ2U6IGV4YWN0bHkgb25lIG9mIGRheS1vZi1tb250aCAvIGRheS1vZi13ZWVrIG11c3QgYmUgYD9gLlxuICBpZiAoZG9tID09PSAnKicgJiYgZG93ID09PSAnKicpIHtcbiAgICBkb3cgPSAnPyc7IC8vIHVucmVzdHJpY3RlZCBib3RoIOKGkiBwaW4gZGF5LW9mLXdlZWsgdG8gP1xuICB9IGVsc2UgaWYgKGRvbSAhPT0gJyonICYmIGRvdyA9PT0gJyonKSB7XG4gICAgZG93ID0gJz8nOyAvLyBzcGVjaWZpYyBkYXktb2YtbW9udGgg4oaSIGRheS1vZi13ZWVrIG11c3QgYmUgP1xuICB9IGVsc2UgaWYgKGRvbSA9PT0gJyonICYmIGRvdyAhPT0gJyonKSB7XG4gICAgZG9tID0gJz8nOyAvLyBzcGVjaWZpYyBkYXktb2Ytd2VlayDihpIgZGF5LW9mLW1vbnRoIG11c3QgYmUgP1xuICB9XG4gIC8vIChib3RoIHNwZWNpZmljIGlzIGxlZnQgYXMtaXM7IEV2ZW50QnJpZGdlIHJlamVjdHMgaXQsIHN1cmZhY2luZyBhIGNsZWFyIGVycm9yKVxuXG4gIHJldHVybiBgY3Jvbigke21pbnV0ZX0gJHtob3VyfSAke2RvbX0gJHttb250aH0gJHtkb3d9ICopYDtcbn1cbiJdfQ==
|
package/package.json
CHANGED
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"typescript": "6.0.3",
|
|
42
42
|
"yaml": "2.9.0",
|
|
43
43
|
"zod": "4.4.3",
|
|
44
|
-
"@pipeline-builder/
|
|
45
|
-
"@pipeline-builder/
|
|
44
|
+
"@pipeline-builder/pipeline-core": "3.4.94",
|
|
45
|
+
"@pipeline-builder/ai-core": "3.4.80"
|
|
46
46
|
},
|
|
47
47
|
"keywords": [
|
|
48
48
|
"ci-cd",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"access": "public",
|
|
98
98
|
"registry": "https://registry.npmjs.org/"
|
|
99
99
|
},
|
|
100
|
-
"version": "3.4.
|
|
100
|
+
"version": "3.4.126",
|
|
101
101
|
"bugs": {
|
|
102
102
|
"url": "https://github.com/mwashburn160/pipeline-builder/issues"
|
|
103
103
|
},
|