@chaim-tools/cdk-lib 0.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 (39) hide show
  1. package/README.md +238 -0
  2. package/lib/binders/base-chaim-binder.d.ts +144 -0
  3. package/lib/binders/base-chaim-binder.js +532 -0
  4. package/lib/binders/chaim-dynamodb-binder.d.ts +95 -0
  5. package/lib/binders/chaim-dynamodb-binder.js +292 -0
  6. package/lib/config/chaim-endpoints.d.ts +47 -0
  7. package/lib/config/chaim-endpoints.js +51 -0
  8. package/lib/index.d.ts +15 -0
  9. package/lib/index.js +43 -0
  10. package/lib/lambda-handler/.test-temp/snapshot.json +1 -0
  11. package/lib/lambda-handler/handler.js +513 -0
  12. package/lib/lambda-handler/handler.test.ts +365 -0
  13. package/lib/lambda-handler/package-lock.json +1223 -0
  14. package/lib/lambda-handler/package.json +14 -0
  15. package/lib/services/ingestion-service.d.ts +50 -0
  16. package/lib/services/ingestion-service.js +81 -0
  17. package/lib/services/os-cache-paths.d.ts +52 -0
  18. package/lib/services/os-cache-paths.js +123 -0
  19. package/lib/services/schema-service.d.ts +11 -0
  20. package/lib/services/schema-service.js +67 -0
  21. package/lib/services/snapshot-cleanup.d.ts +78 -0
  22. package/lib/services/snapshot-cleanup.js +220 -0
  23. package/lib/types/base-binder-props.d.ts +32 -0
  24. package/lib/types/base-binder-props.js +17 -0
  25. package/lib/types/credentials.d.ts +57 -0
  26. package/lib/types/credentials.js +83 -0
  27. package/lib/types/data-store-metadata.d.ts +67 -0
  28. package/lib/types/data-store-metadata.js +4 -0
  29. package/lib/types/failure-mode.d.ts +16 -0
  30. package/lib/types/failure-mode.js +21 -0
  31. package/lib/types/ingest-contract.d.ts +110 -0
  32. package/lib/types/ingest-contract.js +12 -0
  33. package/lib/types/snapshot-cache-policy.d.ts +52 -0
  34. package/lib/types/snapshot-cache-policy.js +57 -0
  35. package/lib/types/snapshot-payload.d.ts +245 -0
  36. package/lib/types/snapshot-payload.js +3 -0
  37. package/lib/types/table-binding-config.d.ts +43 -0
  38. package/lib/types/table-binding-config.js +57 -0
  39. package/package.json +67 -0
@@ -0,0 +1,532 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.BaseChaimBinder = void 0;
27
+ const cdk = __importStar(require("aws-cdk-lib"));
28
+ const lambda = __importStar(require("aws-cdk-lib/aws-lambda"));
29
+ const iam = __importStar(require("aws-cdk-lib/aws-iam"));
30
+ const cr = __importStar(require("aws-cdk-lib/custom-resources"));
31
+ const constructs_1 = require("constructs");
32
+ const fs = __importStar(require("fs"));
33
+ const path = __importStar(require("path"));
34
+ const crypto = __importStar(require("crypto"));
35
+ const base_binder_props_1 = require("../types/base-binder-props");
36
+ const schema_service_1 = require("../services/schema-service");
37
+ const snapshot_cache_policy_1 = require("../types/snapshot-cache-policy");
38
+ const chaim_endpoints_1 = require("../config/chaim-endpoints");
39
+ const os_cache_paths_1 = require("../services/os-cache-paths");
40
+ const snapshot_cleanup_1 = require("../services/snapshot-cleanup");
41
+ /**
42
+ * Path to the canonical Lambda handler file.
43
+ * This handler implements the presigned upload flow for Chaim ingestion.
44
+ */
45
+ const LAMBDA_HANDLER_PATH = path.join(__dirname, '..', 'lambda-handler', 'handler.js');
46
+ /**
47
+ * Abstract base class for all Chaim data store binders.
48
+ *
49
+ * Provides shared infrastructure:
50
+ * - Schema loading and validation
51
+ * - Snapshot payload construction
52
+ * - LOCAL snapshot writing during CDK synth (to OS cache)
53
+ * - Lambda-backed custom resource for S3 presigned upload + snapshot-ref
54
+ *
55
+ * Subclasses implement `extractMetadata()` for store-specific metadata extraction
56
+ * and optionally override `getTable()` for DynamoDB-like resources.
57
+ */
58
+ class BaseChaimBinder extends constructs_1.Construct {
59
+ /** Validated schema data */
60
+ schemaData;
61
+ /** Extracted data store metadata */
62
+ dataStoreMetadata;
63
+ /** Generated resource ID ({resourceName}__{entityName}[__N]) */
64
+ resourceId;
65
+ /** Binding configuration */
66
+ config;
67
+ /** Base props (for internal use) */
68
+ baseProps;
69
+ constructor(scope, id, props) {
70
+ super(scope, id);
71
+ this.baseProps = props;
72
+ this.config = props.config;
73
+ // Validate props
74
+ (0, base_binder_props_1.validateBinderProps)(props);
75
+ // Validate consistency with other bindings to same table
76
+ this.validateTableConsistency();
77
+ // Load and validate schema
78
+ this.schemaData = schema_service_1.SchemaService.readSchema(props.schemaPath);
79
+ // Extract data store metadata (implemented by subclass)
80
+ this.dataStoreMetadata = this.extractMetadata();
81
+ // Build stack context
82
+ const stack = cdk.Stack.of(this);
83
+ const stackName = stack.stackName;
84
+ const datastoreType = this.dataStoreMetadata.type;
85
+ // Get resource and entity names
86
+ const resourceName = this.getResourceName();
87
+ const entityName = this.getEntityName();
88
+ // Generate resource ID
89
+ this.resourceId = `${resourceName}__${entityName}`;
90
+ // Normalize values for paths (handle CDK tokens)
91
+ const normalizedAccountId = (0, os_cache_paths_1.normalizeAccountId)(stack.account);
92
+ const normalizedRegion = (0, os_cache_paths_1.normalizeRegion)(stack.region);
93
+ const normalizedResourceName = (0, os_cache_paths_1.normalizeResourceName)(resourceName);
94
+ // Update resource ID with normalized name to avoid special characters
95
+ const normalizedResourceId = `${normalizedResourceName}__${entityName}`;
96
+ // Build LOCAL snapshot payload
97
+ const localSnapshot = this.buildLocalSnapshot({
98
+ accountId: normalizedAccountId,
99
+ region: normalizedRegion,
100
+ stackName,
101
+ datastoreType,
102
+ resourceName: normalizedResourceName,
103
+ resourceId: normalizedResourceId,
104
+ });
105
+ // Apply snapshot cache policy (cleanup if requested)
106
+ this.applySnapshotCachePolicy({
107
+ accountId: normalizedAccountId,
108
+ region: normalizedRegion,
109
+ stackName,
110
+ });
111
+ // Write LOCAL snapshot to OS cache for chaim-cli consumption
112
+ this.writeLocalSnapshotToDisk(localSnapshot);
113
+ // Get or create asset directory
114
+ const assetDir = this.writeSnapshotAsset(localSnapshot, stackName);
115
+ // Deploy Lambda-backed custom resource for ingestion
116
+ this.deployIngestionResources(assetDir);
117
+ }
118
+ /**
119
+ * Validate that all bindings to the same table use the same config.
120
+ *
121
+ * This is a safety check - sharing the same TableBindingConfig object
122
+ * already ensures consistency, but this catches cases where users
123
+ * create separate configs with identical values.
124
+ */
125
+ validateTableConsistency() {
126
+ // Only for DynamoDB binders (has table property)
127
+ const table = this.baseProps.table;
128
+ if (!table) {
129
+ return;
130
+ }
131
+ // Find other binders for the same table
132
+ const stack = cdk.Stack.of(this);
133
+ const otherBinders = stack.node.findAll()
134
+ .filter(node => node instanceof BaseChaimBinder)
135
+ .filter(binder => binder !== this)
136
+ .filter(binder => {
137
+ const otherTable = binder.baseProps.table;
138
+ return otherTable === table;
139
+ })
140
+ .map(binder => binder);
141
+ if (otherBinders.length === 0) {
142
+ return; // First binding for this table
143
+ }
144
+ const firstBinder = otherBinders[0];
145
+ // Check if they're using the exact same config object (recommended)
146
+ if (this.config === firstBinder.config) {
147
+ return; // Perfect - same config object
148
+ }
149
+ // Different config objects - validate they have same values
150
+ if (this.config.appId !== firstBinder.config.appId) {
151
+ throw new Error(`Configuration conflict for table "${table.tableName}".\n\n` +
152
+ `Binder "${firstBinder.node.id}" uses appId: "${firstBinder.config.appId}"\n` +
153
+ `Binder "${this.node.id}" uses appId: "${this.config.appId}"\n\n` +
154
+ `All bindings to the same table MUST use the same appId.\n\n` +
155
+ `RECOMMENDED: Share the same TableBindingConfig object:\n` +
156
+ ` const config = new TableBindingConfig('${firstBinder.config.appId}', credentials);\n` +
157
+ ` new ChaimDynamoDBBinder(this, '${firstBinder.node.id}', { ..., config });\n` +
158
+ ` new ChaimDynamoDBBinder(this, '${this.node.id}', { ..., config });`);
159
+ }
160
+ // Validate credentials match
161
+ const firstCreds = JSON.stringify(firstBinder.config.credentials);
162
+ const thisCreds = JSON.stringify(this.config.credentials);
163
+ if (firstCreds !== thisCreds) {
164
+ throw new Error(`Configuration conflict for table "${table.tableName}".\n\n` +
165
+ `Binder "${firstBinder.node.id}" uses different credentials than "${this.node.id}".\n\n` +
166
+ `All bindings to the same table MUST use the same credentials.\n\n` +
167
+ `RECOMMENDED: Share the same TableBindingConfig object to avoid this error.`);
168
+ }
169
+ // Warn about different failureMode (not an error)
170
+ if (this.config.failureMode !== firstBinder.config.failureMode) {
171
+ console.warn(`Warning: Different failureMode for table "${table.tableName}".\n` +
172
+ ` "${firstBinder.node.id}": ${firstBinder.config.failureMode}\n` +
173
+ ` "${this.node.id}": ${this.config.failureMode}\n` +
174
+ `Consider sharing the same TableBindingConfig object.`);
175
+ }
176
+ }
177
+ /**
178
+ * Override in subclasses to provide the table construct for stable identity.
179
+ * Default returns undefined (will fall back to construct path).
180
+ */
181
+ getTable() {
182
+ return undefined;
183
+ }
184
+ /**
185
+ * Get the resource name for display and filenames.
186
+ * For DynamoDB, this is the user label (not necessarily the physical table name).
187
+ *
188
+ * Subclasses can override this to provide a more meaningful name
189
+ * (e.g., construct node ID instead of physical resource name which may contain tokens).
190
+ */
191
+ getResourceName() {
192
+ const metadata = this.dataStoreMetadata;
193
+ return metadata.tableName || metadata.name || 'resource';
194
+ }
195
+ /**
196
+ * Get the entity name from schema.
197
+ */
198
+ getEntityName() {
199
+ return this.schemaData.entityName;
200
+ }
201
+ /**
202
+ * Read package version from package.json.
203
+ * Used to populate producer metadata in snapshots.
204
+ */
205
+ getPackageVersion() {
206
+ try {
207
+ const packagePath = path.join(__dirname, '..', '..', 'package.json');
208
+ const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
209
+ return packageJson.version || '0.0.0';
210
+ }
211
+ catch (error) {
212
+ console.warn('Failed to read package version:', error);
213
+ return '0.0.0';
214
+ }
215
+ }
216
+ /**
217
+ * Build a LOCAL snapshot payload for CLI consumption.
218
+ * Does not include eventId or contentHash - those are generated at deploy-time.
219
+ */
220
+ buildLocalSnapshot(params) {
221
+ const capturedAt = new Date().toISOString();
222
+ const stack = cdk.Stack.of(this);
223
+ // Build provider identity
224
+ const providerIdentity = {
225
+ cloud: 'aws',
226
+ accountId: params.accountId,
227
+ region: params.region,
228
+ deploymentSystem: 'cloudformation',
229
+ deploymentId: stack.stackId,
230
+ };
231
+ // Build binding identity
232
+ const stableResourceKey = `${params.datastoreType}:path:${params.stackName}/${params.resourceName}`;
233
+ const entityId = `${this.config.appId}:${this.schemaData.entityName}`;
234
+ const bindingId = `${this.config.appId}:${stableResourceKey}:${this.schemaData.entityName}`;
235
+ const identity = {
236
+ appId: this.config.appId,
237
+ entityName: this.schemaData.entityName,
238
+ stableResourceKeyStrategy: 'cdk-construct-path',
239
+ stableResourceKey,
240
+ resourceId: params.resourceId,
241
+ entityId,
242
+ bindingId,
243
+ };
244
+ // Build operation metadata
245
+ const operation = {
246
+ eventId: this.generateUuid(),
247
+ requestType: 'Create',
248
+ failureMode: this.config.failureMode,
249
+ };
250
+ // Build resolution metadata
251
+ const hasTokens = this.detectUnresolvedTokens(this.dataStoreMetadata);
252
+ const resolution = {
253
+ mode: 'LOCAL',
254
+ hasTokens,
255
+ };
256
+ // Build hashes
257
+ const schemaBytes = JSON.stringify(this.schemaData);
258
+ const schemaHash = 'sha256:' + crypto.createHash('sha256').update(schemaBytes).digest('hex');
259
+ const hashes = {
260
+ schemaHash,
261
+ contentHash: '',
262
+ };
263
+ // Build resource metadata
264
+ const resource = this.buildResourceMetadata(params);
265
+ // Build producer metadata
266
+ const producer = {
267
+ component: 'chaim-cdk',
268
+ version: this.getPackageVersion(),
269
+ runtime: process.version,
270
+ };
271
+ return {
272
+ snapshotVersion: chaim_endpoints_1.SNAPSHOT_SCHEMA_VERSION,
273
+ action: 'UPSERT',
274
+ capturedAt,
275
+ providerIdentity,
276
+ identity,
277
+ operation,
278
+ resolution,
279
+ hashes,
280
+ schema: this.schemaData,
281
+ resource,
282
+ producer,
283
+ };
284
+ }
285
+ /**
286
+ * Build resource metadata from dataStore metadata.
287
+ */
288
+ buildResourceMetadata(params) {
289
+ const dynamoMetadata = this.dataStoreMetadata;
290
+ return {
291
+ type: 'dynamodb',
292
+ kind: 'table',
293
+ id: dynamoMetadata.tableArn,
294
+ name: dynamoMetadata.tableName,
295
+ region: params.region,
296
+ partitionKey: dynamoMetadata.partitionKey,
297
+ sortKey: dynamoMetadata.sortKey,
298
+ globalSecondaryIndexes: dynamoMetadata.globalSecondaryIndexes,
299
+ localSecondaryIndexes: dynamoMetadata.localSecondaryIndexes,
300
+ ttlAttribute: dynamoMetadata.ttlAttribute,
301
+ streamEnabled: dynamoMetadata.streamEnabled,
302
+ streamViewType: dynamoMetadata.streamViewType,
303
+ billingMode: dynamoMetadata.billingMode,
304
+ encryptionKeyArn: dynamoMetadata.encryptionKeyArn,
305
+ };
306
+ }
307
+ /**
308
+ * Detect if metadata contains unresolved CDK tokens.
309
+ */
310
+ detectUnresolvedTokens(metadata) {
311
+ const str = JSON.stringify(metadata);
312
+ return str.includes('${Token[');
313
+ }
314
+ /**
315
+ * Generate a UUID v4 for operation tracking.
316
+ */
317
+ generateUuid() {
318
+ return crypto.randomUUID();
319
+ }
320
+ /**
321
+ * Apply snapshot cache policy based on CDK context.
322
+ *
323
+ * Checks the `chaimSnapshotCachePolicy` context value:
324
+ * - NONE (default): No cleanup
325
+ * - PRUNE_STACK: Delete existing stack snapshots before writing new ones
326
+ *
327
+ * This runs once per stack (tracked by static flag) to avoid
328
+ * multiple cleanup attempts when binding multiple entities.
329
+ */
330
+ applySnapshotCachePolicy(params) {
331
+ // Get policy from CDK context (defaults to NONE)
332
+ const policyValue = this.node.tryGetContext(snapshot_cache_policy_1.SNAPSHOT_CACHE_POLICY_CONTEXT_KEY);
333
+ const policy = this.parseSnapshotCachePolicy(policyValue);
334
+ if (policy === snapshot_cache_policy_1.SnapshotCachePolicy.NONE) {
335
+ return; // No cleanup
336
+ }
337
+ // Check if we've already cleaned this stack in this synth
338
+ const stack = cdk.Stack.of(this);
339
+ const cleanupKey = `__chaim_snapshot_cleanup_${params.stackName}`;
340
+ if (stack.node[cleanupKey]) {
341
+ return; // Already cleaned in this synth
342
+ }
343
+ // Mark as cleaned to avoid duplicate cleanup
344
+ stack.node[cleanupKey] = true;
345
+ if (policy === snapshot_cache_policy_1.SnapshotCachePolicy.PRUNE_STACK) {
346
+ const result = (0, snapshot_cleanup_1.pruneStackSnapshots)({
347
+ accountId: params.accountId,
348
+ region: params.region,
349
+ stackName: params.stackName,
350
+ verbose: false, // Don't spam console during synth
351
+ });
352
+ // Only log if verbose mode or errors
353
+ if (result.deletedCount > 0 || result.errors.length > 0) {
354
+ console.log(`[Chaim] Pruned ${result.deletedCount} snapshot(s) for stack: ${params.stackName}`);
355
+ if (result.errors.length > 0) {
356
+ console.warn(`[Chaim] Cleanup warnings:`, result.errors);
357
+ }
358
+ }
359
+ }
360
+ }
361
+ /**
362
+ * Parse snapshot cache policy from context value.
363
+ */
364
+ parseSnapshotCachePolicy(value) {
365
+ if (typeof value !== 'string') {
366
+ return snapshot_cache_policy_1.DEFAULT_SNAPSHOT_CACHE_POLICY;
367
+ }
368
+ const upperValue = value.toUpperCase();
369
+ if (upperValue === 'NONE' || upperValue === 'DISABLED') {
370
+ return snapshot_cache_policy_1.SnapshotCachePolicy.NONE;
371
+ }
372
+ if (upperValue === 'PRUNE_STACK' || upperValue === 'PRUNE') {
373
+ return snapshot_cache_policy_1.SnapshotCachePolicy.PRUNE_STACK;
374
+ }
375
+ console.warn(`[Chaim] Unknown chaimSnapshotCachePolicy: "${value}". ` +
376
+ `Valid values: NONE, PRUNE_STACK. Defaulting to NONE.`);
377
+ return snapshot_cache_policy_1.DEFAULT_SNAPSHOT_CACHE_POLICY;
378
+ }
379
+ /**
380
+ * Extract stack name from stableResourceKey.
381
+ * Format: dynamodb:path:StackName/ResourceName
382
+ */
383
+ extractStackNameFromResourceKey(stableResourceKey) {
384
+ const match = stableResourceKey.match(/path:([^/]+)/);
385
+ return match ? match[1] : 'unknown';
386
+ }
387
+ /**
388
+ * Write LOCAL snapshot to OS cache for chaim-cli consumption.
389
+ * Uses hierarchical path: aws/{accountId}/{region}/{stackName}/{datastoreType}/{resourceId}.json
390
+ *
391
+ * @param snapshot - The snapshot payload to write
392
+ * @returns The path where snapshot was written
393
+ */
394
+ writeLocalSnapshotToDisk(snapshot) {
395
+ const stackName = this.extractStackNameFromResourceKey(snapshot.identity.stableResourceKey);
396
+ const dir = (0, os_cache_paths_1.getSnapshotDir)({
397
+ accountId: snapshot.providerIdentity.accountId,
398
+ region: snapshot.providerIdentity.region,
399
+ stackName,
400
+ datastoreType: snapshot.resource.type,
401
+ });
402
+ (0, os_cache_paths_1.ensureDirExists)(dir);
403
+ const filePath = (0, os_cache_paths_1.getLocalSnapshotPath)({
404
+ accountId: snapshot.providerIdentity.accountId,
405
+ region: snapshot.providerIdentity.region,
406
+ stackName,
407
+ datastoreType: snapshot.resource.type,
408
+ resourceId: snapshot.identity.resourceId,
409
+ });
410
+ fs.writeFileSync(filePath, JSON.stringify(snapshot, null, 2), 'utf-8');
411
+ return filePath;
412
+ }
413
+ /**
414
+ * Find the CDK project root by walking up from current module.
415
+ */
416
+ findCdkProjectRoot() {
417
+ let currentDir = __dirname;
418
+ for (let i = 0; i < 10; i++) {
419
+ const cdkJsonPath = path.join(currentDir, 'cdk.json');
420
+ if (fs.existsSync(cdkJsonPath)) {
421
+ return currentDir;
422
+ }
423
+ const parentDir = path.dirname(currentDir);
424
+ if (parentDir === currentDir) {
425
+ break;
426
+ }
427
+ currentDir = parentDir;
428
+ }
429
+ // Fallback to cwd
430
+ return process.cwd();
431
+ }
432
+ /**
433
+ * Write snapshot and Lambda handler to isolated CDK asset directory for Lambda bundling.
434
+ *
435
+ * Asset directory is per {stackName}/{resourceId} and MUST NOT be shared.
436
+ * The Lambda reads ./snapshot.json from its bundle, NOT from env vars or OS cache.
437
+ *
438
+ * The handler is copied from the canonical handler file (src/lambda-handler/handler.js)
439
+ * rather than being generated inline - this ensures a single source of truth.
440
+ *
441
+ * @returns The asset directory path
442
+ */
443
+ writeSnapshotAsset(snapshot, stackName) {
444
+ const cdkRoot = this.findCdkProjectRoot();
445
+ const assetDir = path.join(cdkRoot, 'cdk.out', 'chaim', 'assets', stackName, this.resourceId);
446
+ (0, os_cache_paths_1.ensureDirExists)(assetDir);
447
+ // Write snapshot.json (OVERWRITE each synth)
448
+ const snapshotPath = path.join(assetDir, 'snapshot.json');
449
+ fs.writeFileSync(snapshotPath, JSON.stringify(snapshot, null, 2), 'utf-8');
450
+ // Copy canonical Lambda handler (OVERWRITE each synth)
451
+ const handlerDestPath = path.join(assetDir, 'index.js');
452
+ fs.copyFileSync(LAMBDA_HANDLER_PATH, handlerDestPath);
453
+ return assetDir;
454
+ }
455
+ /**
456
+ * Deploy Lambda function and custom resource for ingestion.
457
+ */
458
+ deployIngestionResources(assetDir) {
459
+ const handler = this.createIngestionLambda(assetDir);
460
+ this.createCustomResource(handler);
461
+ }
462
+ /**
463
+ * Create Lambda function for ingestion workflow.
464
+ * Lambda reads snapshot from its bundled asset directory.
465
+ */
466
+ createIngestionLambda(assetDir) {
467
+ const handler = new lambda.Function(this, 'IngestionHandler', {
468
+ runtime: lambda.Runtime.NODEJS_20_X,
469
+ handler: 'index.handler',
470
+ code: lambda.Code.fromAsset(assetDir),
471
+ timeout: cdk.Duration.minutes(5),
472
+ environment: this.buildLambdaEnvironment(),
473
+ });
474
+ // Grant CloudWatch Logs permissions
475
+ handler.addToRolePolicy(new iam.PolicyStatement({
476
+ effect: iam.Effect.ALLOW,
477
+ actions: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
478
+ resources: ['*'],
479
+ }));
480
+ // Grant Secrets Manager permissions if using secrets
481
+ const { credentials } = this.config;
482
+ if (credentials.credentialType === 'secretsManager' && credentials.secretName) {
483
+ handler.addToRolePolicy(new iam.PolicyStatement({
484
+ effect: iam.Effect.ALLOW,
485
+ actions: ['secretsmanager:GetSecretValue'],
486
+ resources: [`arn:aws:secretsmanager:*:*:secret:${credentials.secretName}*`],
487
+ }));
488
+ }
489
+ return handler;
490
+ }
491
+ /**
492
+ * Build Lambda environment variables.
493
+ * Note: Snapshot is NOT passed via env - Lambda reads from bundled asset.
494
+ */
495
+ buildLambdaEnvironment() {
496
+ // Allow maintainer override via CDK context, otherwise use default
497
+ const apiBaseUrl = this.node.tryGetContext('chaimApiBaseUrl') ?? chaim_endpoints_1.DEFAULT_CHAIM_API_BASE_URL;
498
+ const { credentials, failureMode } = this.config;
499
+ const env = {
500
+ APP_ID: this.config.appId,
501
+ FAILURE_MODE: failureMode,
502
+ CHAIM_API_BASE_URL: apiBaseUrl,
503
+ CHAIM_MAX_SNAPSHOT_BYTES: String(chaim_endpoints_1.DEFAULT_MAX_SNAPSHOT_BYTES),
504
+ };
505
+ if (credentials.credentialType === 'secretsManager') {
506
+ env.SECRET_NAME = credentials.secretName;
507
+ }
508
+ else {
509
+ env.API_KEY = credentials.apiKey;
510
+ env.API_SECRET = credentials.apiSecret;
511
+ }
512
+ return env;
513
+ }
514
+ /**
515
+ * Create CloudFormation custom resource.
516
+ */
517
+ createCustomResource(handler) {
518
+ const provider = new cr.Provider(this, 'IngestionProvider', {
519
+ onEventHandler: handler,
520
+ });
521
+ // Use resource ID for physical resource ID (stable across deploys)
522
+ new cdk.CustomResource(this, 'IngestionResource', {
523
+ serviceToken: provider.serviceToken,
524
+ properties: {
525
+ ResourceId: this.resourceId,
526
+ // ContentHash is computed at Lambda runtime
527
+ },
528
+ });
529
+ }
530
+ }
531
+ exports.BaseChaimBinder = BaseChaimBinder;
532
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1jaGFpbS1iaW5kZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYmluZGVycy9iYXNlLWNoYWltLWJpbmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlEQUFtQztBQUNuQywrREFBaUQ7QUFDakQseURBQTJDO0FBQzNDLGlFQUFtRDtBQUVuRCwyQ0FBdUM7QUFDdkMsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUM3QiwrQ0FBaUM7QUFHakMsa0VBQWtGO0FBR2xGLCtEQUEyRDtBQUczRCwwRUFJd0M7QUFDeEMsK0RBSW1DO0FBQ25DLCtEQU9vQztBQUNwQyxtRUFBbUU7QUFFbkU7OztHQUdHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFFdkY7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFzQixlQUFnQixTQUFRLHNCQUFTO0lBQ3JELDRCQUE0QjtJQUNaLFVBQVUsQ0FBYTtJQUV2QyxvQ0FBb0M7SUFDcEIsaUJBQWlCLENBQW9CO0lBRXJELGdFQUFnRTtJQUNoRCxVQUFVLENBQVM7SUFFbkMsNEJBQTRCO0lBQ1osTUFBTSxDQUFxQjtJQUUzQyxvQ0FBb0M7SUFDakIsU0FBUyxDQUFrQjtJQUU5QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXNCO1FBQzlELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBRTNCLGlCQUFpQjtRQUNqQixJQUFBLHVDQUFtQixFQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTNCLHlEQUF5RDtRQUN6RCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztR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RixDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUF6a0JELDBDQXlrQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgY3IgZnJvbSAnYXdzLWNkay1saWIvY3VzdG9tLXJlc291cmNlcyc7XG5pbXBvcnQgKiBhcyBkeW5hbW9kYiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGInO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ2NyeXB0byc7XG5cbmltcG9ydCB7IFNjaGVtYURhdGEgfSBmcm9tICdAY2hhaW0tdG9vbHMvY2hhaW0tYnByaW50LXNwZWMnO1xuaW1wb3J0IHsgQmFzZUJpbmRlclByb3BzLCB2YWxpZGF0ZUJpbmRlclByb3BzIH0gZnJvbSAnLi4vdHlwZXMvYmFzZS1iaW5kZXItcHJvcHMnO1xuaW1wb3J0IHsgRGF0YVN0b3JlTWV0YWRhdGEgfSBmcm9tICcuLi90eXBlcy9kYXRhLXN0b3JlLW1ldGFkYXRhJztcbmltcG9ydCB7IExvY2FsU25hcHNob3RQYXlsb2FkIH0gZnJvbSAnLi4vdHlwZXMvc25hcHNob3QtcGF5bG9hZCc7XG5pbXBvcnQgeyBTY2hlbWFTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvc2NoZW1hLXNlcnZpY2UnO1xuaW1wb3J0IHsgRmFpbHVyZU1vZGUgfSBmcm9tICcuLi90eXBlcy9mYWlsdXJlLW1vZGUnO1xuaW1wb3J0IHsgVGFibGVCaW5kaW5nQ29uZmlnIH0gZnJvbSAnLi4vdHlwZXMvdGFibGUtYmluZGluZy1jb25maWcnO1xuaW1wb3J0IHtcbiAgU25hcHNob3RDYWNoZVBvbGljeSxcbiAgREVGQVVMVF9TTkFQU0hPVF9DQUNIRV9QT0xJQ1ksXG4gIFNOQVBTSE9UX0NBQ0hFX1BPTElDWV9DT05URVhUX0tFWSxcbn0gZnJvbSAnLi4vdHlwZXMvc25hcHNob3QtY2FjaGUtcG9saWN5JztcbmltcG9ydCB7XG4gIERFRkFVTFRfQ0hBSU1fQVBJX0JBU0VfVVJMLFxuICBERUZBVUxUX01BWF9TTkFQU0hPVF9CWVRFUyxcbiAgU05BUFNIT1RfU0NIRU1BX1ZFUlNJT04sXG59IGZyb20gJy4uL2NvbmZpZy9jaGFpbS1lbmRwb2ludHMnO1xuaW1wb3J0IHtcbiAgbm9ybWFsaXplQWNjb3VudElkLFxuICBub3JtYWxpemVSZWdpb24sXG4gIG5vcm1hbGl6ZVJlc291cmNlTmFtZSxcbiAgZ2V0U25hcHNob3REaXIsXG4gIGdldExvY2FsU25hcHNob3RQYXRoLFxuICBlbnN1cmVEaXJFeGlzdHMsXG59IGZyb20gJy4uL3NlcnZpY2VzL29zLWNhY2hlLXBhdGhzJztcbmltcG9ydCB7IHBydW5lU3RhY2tTbmFwc2hvdHMgfSBmcm9tICcuLi9zZXJ2aWNlcy9zbmFwc2hvdC1jbGVhbnVwJztcblxuLyoqXG4gKiBQYXRoIHRvIHRoZSBjYW5vbmljYWwgTGFtYmRhIGhhbmRsZXIgZmlsZS5cbiAqIFRoaXMgaGFuZGxlciBpbXBsZW1lbnRzIHRoZSBwcmVzaWduZWQgdXBsb2FkIGZsb3cgZm9yIENoYWltIGluZ2VzdGlvbi5cbiAqL1xuY29uc3QgTEFNQkRBX0hBTkRMRVJfUEFUSCA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICdsYW1iZGEtaGFuZGxlcicsICdoYW5kbGVyLmpzJyk7XG5cbi8qKlxuICogQWJzdHJhY3QgYmFzZSBjbGFzcyBmb3IgYWxsIENoYWltIGRhdGEgc3RvcmUgYmluZGVycy5cbiAqXG4gKiBQcm92aWRlcyBzaGFyZWQgaW5mcmFzdHJ1Y3R1cmU6XG4gKiAtIFNjaGVtYSBsb2FkaW5nIGFuZCB2YWxpZGF0aW9uXG4gKiAtIFNuYXBzaG90IHBheWxvYWQgY29uc3RydWN0aW9uXG4gKiAtIExPQ0FMIHNuYXBzaG90IHdyaXRpbmcgZHVyaW5nIENESyBzeW50aCAodG8gT1MgY2FjaGUpXG4gKiAtIExhbWJkYS1iYWNrZWQgY3VzdG9tIHJlc291cmNlIGZvciBTMyBwcmVzaWduZWQgdXBsb2FkICsgc25hcHNob3QtcmVmXG4gKlxuICogU3ViY2xhc3NlcyBpbXBsZW1lbnQgYGV4dHJhY3RNZXRhZGF0YSgpYCBmb3Igc3RvcmUtc3BlY2lmaWMgbWV0YWRhdGEgZXh0cmFjdGlvblxuICogYW5kIG9wdGlvbmFsbHkgb3ZlcnJpZGUgYGdldFRhYmxlKClgIGZvciBEeW5hbW9EQi1saWtlIHJlc291cmNlcy5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VDaGFpbUJpbmRlciBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKiBWYWxpZGF0ZWQgc2NoZW1hIGRhdGEgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNjaGVtYURhdGE6IFNjaGVtYURhdGE7XG5cbiAgLyoqIEV4dHJhY3RlZCBkYXRhIHN0b3JlIG1ldGFkYXRhICovXG4gIHB1YmxpYyByZWFkb25seSBkYXRhU3RvcmVNZXRhZGF0YTogRGF0YVN0b3JlTWV0YWRhdGE7XG5cbiAgLyoqIEdlbmVyYXRlZCByZXNvdXJjZSBJRCAoe3Jlc291cmNlTmFtZX1fX3tlbnRpdHlOYW1lfVtfX05dKSAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcmVzb3VyY2VJZDogc3RyaW5nO1xuXG4gIC8qKiBCaW5kaW5nIGNvbmZpZ3VyYXRpb24gKi9cbiAgcHVibGljIHJlYWRvbmx5IGNvbmZpZzogVGFibGVCaW5kaW5nQ29uZmlnO1xuXG4gIC8qKiBCYXNlIHByb3BzIChmb3IgaW50ZXJuYWwgdXNlKSAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYmFzZVByb3BzOiBCYXNlQmluZGVyUHJvcHM7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEJhc2VCaW5kZXJQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLmJhc2VQcm9wcyA9IHByb3BzO1xuICAgIHRoaXMuY29uZmlnID0gcHJvcHMuY29uZmlnO1xuXG4gICAgLy8gVmFsaWRhdGUgcHJvcHNcbiAgICB2YWxpZGF0ZUJpbmRlclByb3BzKHByb3BzKTtcblxuICAgIC8vIFZhbGlkYXRlIGNvbnNpc3RlbmN5IHdpdGggb3RoZXIgYmluZGluZ3MgdG8gc2FtZSB0YWJsZVxuICAgIHRoaXMudmFsaWRhdGVUYWJsZUNvbnNpc3RlbmN5KCk7XG5cbiAgICAvLyBMb2FkIGFuZCB2YWxpZGF0ZSBzY2hlbWFcbiAgICB0aGlzLnNjaGVtYURhdGEgPSBTY2hlbWFTZXJ2aWNlLnJlYWRTY2hlbWEocHJvcHMuc2NoZW1hUGF0aCk7XG5cbiAgICAvLyBFeHRyYWN0IGRhdGEgc3RvcmUgbWV0YWRhdGEgKGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzKVxuICAgIHRoaXMuZGF0YVN0b3JlTWV0YWRhdGEgPSB0aGlzLmV4dHJhY3RNZXRhZGF0YSgpO1xuXG4gICAgLy8gQnVpbGQgc3RhY2sgY29udGV4dFxuICAgIGNvbnN0IHN0YWNrID0gY2RrLlN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IHN0YWNrTmFtZSA9IHN0YWNrLnN0YWNrTmFtZTtcbiAgICBjb25zdCBkYXRhc3RvcmVUeXBlID0gdGhpcy5kYXRhU3RvcmVNZXRhZGF0YS50eXBlO1xuXG4gICAgLy8gR2V0IHJlc291cmNlIGFuZCBlbnRpdHkgbmFtZXNcbiAgICBjb25zdCByZXNvdXJjZU5hbWUgPSB0aGlzLmdldFJlc291cmNlTmFtZSgpO1xuICAgIGNvbnN0IGVudGl0eU5hbWUgPSB0aGlzLmdldEVudGl0eU5hbWUoKTtcblxuICAgIC8vIEdlbmVyYXRlIHJlc291cmNlIElEXG4gICAgdGhpcy5yZXNvdXJjZUlkID0gYCR7cmVzb3VyY2VOYW1lfV9fJHtlbnRpdHlOYW1lfWA7XG5cbiAgICAvLyBOb3JtYWxpemUgdmFsdWVzIGZvciBwYXRocyAoaGFuZGxlIENESyB0b2tlbnMpXG4gICAgY29uc3Qgbm9ybWFsaXplZEFjY291bnRJZCA9IG5vcm1hbGl6ZUFjY291bnRJZChzdGFjay5hY2NvdW50KTtcbiAgICBjb25zdCBub3JtYWxpemVkUmVnaW9uID0gbm9ybWFsaXplUmVnaW9uKHN0YWNrLnJlZ2lvbik7XG4gICAgY29uc3Qgbm9ybWFsaXplZFJlc291cmNlTmFtZSA9IG5vcm1hbGl6ZVJlc291cmNlTmFtZShyZXNvdXJjZU5hbWUpO1xuXG4gICAgLy8gVXBkYXRlIHJlc291cmNlIElEIHdpdGggbm9ybWFsaXplZCBuYW1lIHRvIGF2b2lkIHNwZWNpYWwgY2hhcmFjdGVyc1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRSZXNvdXJjZUlkID0gYCR7bm9ybWFsaXplZFJlc291cmNlTmFtZX1fXyR7ZW50aXR5TmFtZX1gO1xuXG4gICAgLy8gQnVpbGQgTE9DQUwgc25hcHNob3QgcGF5bG9hZFxuICAgIGNvbnN0IGxvY2FsU25hcHNob3QgPSB0aGlzLmJ1aWxkTG9jYWxTbmFwc2hvdCh7XG4gICAgICBhY2NvdW50SWQ6IG5vcm1hbGl6ZWRBY2NvdW50SWQsXG4gICAgICByZWdpb246IG5vcm1hbGl6ZWRSZWdpb24sXG4gICAgICBzdGFja05hbWUsXG4gICAgICBkYXRhc3RvcmVUeXBlLFxuICAgICAgcmVzb3VyY2VOYW1lOiBub3JtYWxpemVkUmVzb3VyY2VOYW1lLFxuICAgICAgcmVzb3VyY2VJZDogbm9ybWFsaXplZFJlc291cmNlSWQsXG4gICAgfSk7XG5cbiAgICAvLyBBcHBseSBzbmFwc2hvdCBjYWNoZSBwb2xpY3kgKGNsZWFudXAgaWYgcmVxdWVzdGVkKVxuICAgIHRoaXMuYXBwbHlTbmFwc2hvdENhY2hlUG9saWN5KHtcbiAgICAgIGFjY291bnRJZDogbm9ybWFsaXplZEFjY291bnRJZCxcbiAgICAgIHJlZ2lvbjogbm9ybWFsaXplZFJlZ2lvbixcbiAgICAgIHN0YWNrTmFtZSxcbiAgICB9KTtcblxuICAgIC8vIFdyaXRlIExPQ0FMIHNuYXBzaG90IHRvIE9TIGNhY2hlIGZvciBjaGFpbS1jbGkgY29uc3VtcHRpb25cbiAgICB0aGlzLndyaXRlTG9jYWxTbmFwc2hvdFRvRGlzayhsb2NhbFNuYXBzaG90KTtcblxuICAgIC8vIEdldCBvciBjcmVhdGUgYXNzZXQgZGlyZWN0b3J5XG4gICAgY29uc3QgYXNzZXREaXIgPSB0aGlzLndyaXRlU25hcHNob3RBc3NldChsb2NhbFNuYXBzaG90LCBzdGFja05hbWUpO1xuXG4gICAgLy8gRGVwbG95IExhbWJkYS1iYWNrZWQgY3VzdG9tIHJlc291cmNlIGZvciBpbmdlc3Rpb25cbiAgICB0aGlzLmRlcGxveUluZ2VzdGlvblJlc291cmNlcyhhc3NldERpcik7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCBhbGwgYmluZGluZ3MgdG8gdGhlIHNhbWUgdGFibGUgdXNlIHRoZSBzYW1lIGNvbmZpZy5cbiAgICogXG4gICAqIFRoaXMgaXMgYSBzYWZldHkgY2hlY2sgLSBzaGFyaW5nIHRoZSBzYW1lIFRhYmxlQmluZGluZ0NvbmZpZyBvYmplY3RcbiAgICogYWxyZWFkeSBlbnN1cmVzIGNvbnNpc3RlbmN5LCBidXQgdGhpcyBjYXRjaGVzIGNhc2VzIHdoZXJlIHVzZXJzXG4gICAqIGNyZWF0ZSBzZXBhcmF0ZSBjb25maWdzIHdpdGggaWRlbnRpY2FsIHZhbHVlcy5cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVUYWJsZUNvbnNpc3RlbmN5KCk6IHZvaWQge1xuICAgIC8vIE9ubHkgZm9yIER5bmFtb0RCIGJpbmRlcnMgKGhhcyB0YWJsZSBwcm9wZXJ0eSlcbiAgICBjb25zdCB0YWJsZSA9ICh0aGlzLmJhc2VQcm9wcyBhcyBhbnkpLnRhYmxlO1xuICAgIGlmICghdGFibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBGaW5kIG90aGVyIGJpbmRlcnMgZm9yIHRoZSBzYW1lIHRhYmxlXG4gICAgY29uc3Qgc3RhY2sgPSBjZGsuU3RhY2sub2YodGhpcyk7XG4gICAgY29uc3Qgb3RoZXJCaW5kZXJzID0gc3RhY2subm9kZS5maW5kQWxsKClcbiAgICAgIC5maWx0ZXIobm9kZSA9PiBub2RlIGluc3RhbmNlb2YgQmFzZUNoYWltQmluZGVyKVxuICAgICAgLmZpbHRlcihiaW5kZXIgPT4gYmluZGVyICE9PSB0aGlzKVxuICAgICAgLmZpbHRlcihiaW5kZXIgPT4ge1xuICAgICAgICBjb25zdCBvdGhlclRhYmxlID0gKChiaW5kZXIgYXMgQmFzZUNoYWltQmluZGVyKS5iYXNlUHJvcHMgYXMgYW55KS50YWJsZTtcbiAgICAgICAgcmV0dXJuIG90aGVyVGFibGUgPT09IHRhYmxlO1xuICAgICAgfSlcbiAgICAgIC5tYXAoYmluZGVyID0+IGJpbmRlciBhcyBCYXNlQ2hhaW1CaW5kZXIpO1xuXG4gICAgaWYgKG90aGVyQmluZGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjsgLy8gRmlyc3QgYmluZGluZyBmb3IgdGhpcyB0YWJsZVxuICAgIH1cblxuICAgIGNvbnN0IGZpcnN0QmluZGVyID0gb3RoZXJCaW5kZXJzWzBdO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhleSdyZSB1c2luZyB0aGUgZXhhY3Qgc2FtZSBjb25maWcgb2JqZWN0IChyZWNvbW1lbmRlZClcbiAgICBpZiAodGhpcy5jb25maWcgPT09IGZpcnN0QmluZGVyLmNvbmZpZykge1xuICAgICAgcmV0dXJuOyAvLyBQZXJmZWN0IC0gc2FtZSBjb25maWcgb2JqZWN0XG4gICAgfVxuXG4gICAgLy8gRGlmZmVyZW50IGNvbmZpZyBvYmplY3RzIC0gdmFsaWRhdGUgdGhleSBoYXZlIHNhbWUgdmFsdWVzXG4gICAgaWYgKHRoaXMuY29uZmlnLmFwcElkICE9PSBmaXJzdEJpbmRlci5jb25maWcuYXBwSWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYENvbmZpZ3VyYXRpb24gY29uZmxpY3QgZm9yIHRhYmxlIFwiJHt0YWJsZS50YWJsZU5hbWV9XCIuXFxuXFxuYCArXG4gICAgICAgIGBCaW5kZXIgXCIke2ZpcnN0QmluZGVyLm5vZGUuaWR9XCIgdXNlcyBhcHBJZDogXCIke2ZpcnN0QmluZGVyLmNvbmZpZy5hcHBJZH1cIlxcbmAgK1xuICAgICAgICBgQmluZGVyIFwiJHt0aGlzLm5vZGUuaWR9XCIgdXNlcyBhcHBJZDogXCIke3RoaXMuY29uZmlnLmFwcElkfVwiXFxuXFxuYCArXG4gICAgICAgIGBBbGwgYmluZGluZ3MgdG8gdGhlIHNhbWUgdGFibGUgTVVTVCB1c2UgdGhlIHNhbWUgYXBwSWQuXFxuXFxuYCArXG4gICAgICAgIGBSRUNPTU1FTkRFRDogU2hhcmUgdGhlIHNhbWUgVGFibGVCaW5kaW5nQ29uZmlnIG9iamVjdDpcXG5gICtcbiAgICAgICAgYCAgY29uc3QgY29uZmlnID0gbmV3IFRhYmxlQmluZGluZ0NvbmZpZygnJHtmaXJzdEJpbmRlci5jb25maWcuYXBwSWR9JywgY3JlZGVudGlhbHMpO1xcbmAgK1xuICAgICAgICBgICBuZXcgQ2hhaW1EeW5hbW9EQkJpbmRlcih0aGlzLCAnJHtmaXJzdEJpbmRlci5ub2RlLmlkfScsIHsgLi4uLCBjb25maWcgfSk7XFxuYCArXG4gICAgICAgIGAgIG5ldyBDaGFpbUR5bmFtb0RCQmluZGVyKHRoaXMsICcke3RoaXMubm9kZS5pZH0nLCB7IC4uLiwgY29uZmlnIH0pO2BcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgY3JlZGVudGlhbHMgbWF0Y2hcbiAgICBjb25zdCBmaXJzdENyZWRzID0gSlNPTi5zdHJpbmdpZnkoZmlyc3RCaW5kZXIuY29uZmlnLmNyZWRlbnRpYWxzKTtcbiAgICBjb25zdCB0aGlzQ3JlZHMgPSBKU09OLnN0cmluZ2lmeSh0aGlzLmNvbmZpZy5jcmVkZW50aWFscyk7XG4gICAgXG4gICAgaWYgKGZpcnN0Q3JlZHMgIT09IHRoaXNDcmVkcykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ29uZmlndXJhdGlvbiBjb25mbGljdCBmb3IgdGFibGUgXCIke3RhYmxlLnRhYmxlTmFtZX1cIi5cXG5cXG5gICtcbiAgICAgICAgYEJpbmRlciBcIiR7Zmlyc3RCaW5kZXIubm9kZS5pZH1cIiB1c2VzIGRpZmZlcmVudCBjcmVkZW50aWFscyB0aGFuIFwiJHt0aGlzLm5vZGUuaWR9XCIuXFxuXFxuYCArXG4gICAgICAgIGBBbGwgYmluZGluZ3MgdG8gdGhlIHNhbWUgdGFibGUgTVVTVCB1c2UgdGhlIHNhbWUgY3JlZGVudGlhbHMuXFxuXFxuYCArXG4gICAgICAgIGBSRUNPTU1FTkRFRDogU2hhcmUgdGhlIHNhbWUgVGFibGVCaW5kaW5nQ29uZmlnIG9iamVjdCB0byBhdm9pZCB0aGlzIGVycm9yLmBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gV2FybiBhYm91dCBkaWZmZXJlbnQgZmFpbHVyZU1vZGUgKG5vdCBhbiBlcnJvcilcbiAgICBpZiAodGhpcy5jb25maWcuZmFpbHVyZU1vZGUgIT09IGZpcnN0QmluZGVyLmNvbmZpZy5mYWlsdXJlTW9kZSkge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgV2FybmluZzogRGlmZmVyZW50IGZhaWx1cmVNb2RlIGZvciB0YWJsZSBcIiR7dGFibGUudGFibGVOYW1lfVwiLlxcbmAgK1xuICAgICAgICBgICBcIiR7Zmlyc3RCaW5kZXIubm9kZS5pZH1cIjogJHtmaXJzdEJpbmRlci5jb25maWcuZmFpbHVyZU1vZGV9XFxuYCArXG4gICAgICAgIGAgIFwiJHt0aGlzLm5vZGUuaWR9XCI6ICR7dGhpcy5jb25maWcuZmFpbHVyZU1vZGV9XFxuYCArXG4gICAgICAgIGBDb25zaWRlciBzaGFyaW5nIHRoZSBzYW1lIFRhYmxlQmluZGluZ0NvbmZpZyBvYmplY3QuYFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWJzdHJhY3QgbWV0aG9kIC0gc3ViY2xhc3NlcyBpbXBsZW1lbnQgc3RvcmUtc3BlY2lmaWMgbWV0YWRhdGEgZXh0cmFjdGlvbi5cbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBleHRyYWN0TWV0YWRhdGEoKTogRGF0YVN0b3JlTWV0YWRhdGE7XG5cbiAgLyoqXG4gICAqIE92ZXJyaWRlIGluIHN1YmNsYXNzZXMgdG8gcHJvdmlkZSB0aGUgdGFibGUgY29uc3RydWN0IGZvciBzdGFibGUgaWRlbnRpdHkuXG4gICAqIERlZmF1bHQgcmV0dXJucyB1bmRlZmluZWQgKHdpbGwgZmFsbCBiYWNrIHRvIGNvbnN0cnVjdCBwYXRoKS5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRUYWJsZSgpOiBkeW5hbW9kYi5JVGFibGUgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSByZXNvdXJjZSBuYW1lIGZvciBkaXNwbGF5IGFuZCBmaWxlbmFtZXMuXG4gICAqIEZvciBEeW5hbW9EQiwgdGhpcyBpcyB0aGUgdXNlciBsYWJlbCAobm90IG5lY2Vzc2FyaWx5IHRoZSBwaHlzaWNhbCB0YWJsZSBuYW1lKS5cbiAgICogXG4gICAqIFN1YmNsYXNzZXMgY2FuIG92ZXJyaWRlIHRoaXMgdG8gcHJvdmlkZSBhIG1vcmUgbWVhbmluZ2Z1bCBuYW1lXG4gICAqIChlLmcuLCBjb25zdHJ1Y3Qgbm9kZSBJRCBpbnN0ZWFkIG9mIHBoeXNpY2FsIHJlc291cmNlIG5hbWUgd2hpY2ggbWF5IGNvbnRhaW4gdG9rZW5zKS5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRSZXNvdXJjZU5hbWUoKTogc3RyaW5nIHtcbiAgICBjb25zdCBtZXRhZGF0YSA9IHRoaXMuZGF0YVN0b3JlTWV0YWRhdGEgYXMgYW55O1xuICAgIHJldHVybiBtZXRhZGF0YS50YWJsZU5hbWUgfHwgbWV0YWRhdGEubmFtZSB8fCAncmVzb3VyY2UnO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZW50aXR5IG5hbWUgZnJvbSBzY2hlbWEuXG4gICAqL1xuICBwcml2YXRlIGdldEVudGl0eU5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zY2hlbWFEYXRhLmVudGl0eU5hbWU7XG4gIH1cblxuICAvKipcbiAgICogUmVhZCBwYWNrYWdlIHZlcnNpb24gZnJvbSBwYWNrYWdlLmpzb24uXG4gICAqIFVzZWQgdG8gcG9wdWxhdGUgcHJvZHVjZXIgbWV0YWRhdGEgaW4gc25hcHNob3RzLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRQYWNrYWdlVmVyc2lvbigpOiBzdHJpbmcge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYWNrYWdlUGF0aCA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICcuLicsICdwYWNrYWdlLmpzb24nKTtcbiAgICAgIGNvbnN0IHBhY2thZ2VKc29uID0gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMocGFja2FnZVBhdGgsICd1dGYtOCcpKTtcbiAgICAgIHJldHVybiBwYWNrYWdlSnNvbi52ZXJzaW9uIHx8ICcwLjAuMCc7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUud2FybignRmFpbGVkIHRvIHJlYWQgcGFja2FnZSB2ZXJzaW9uOicsIGVycm9yKTtcbiAgICAgIHJldHVybiAnMC4wLjAnO1xuICAgIH1cbiAgfVxuXG5cblxuICAvKipcbiAgICogQnVpbGQgYSBMT0NBTCBzbmFwc2hvdCBwYXlsb2FkIGZvciBDTEkgY29uc3VtcHRpb24uXG4gICAqIERvZXMgbm90IGluY2x1ZGUgZXZlbnRJZCBvciBjb250ZW50SGFzaCAtIHRob3NlIGFyZSBnZW5lcmF0ZWQgYXQgZGVwbG95LXRpbWUuXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkTG9jYWxTbmFwc2hvdChwYXJhbXM6IHtcbiAgICBhY2NvdW50SWQ6IHN0cmluZztcbiAgICByZWdpb246IHN0cmluZztcbiAgICBzdGFja05hbWU6IHN0cmluZztcbiAgICBkYXRhc3RvcmVUeXBlOiBzdHJpbmc7XG4gICAgcmVzb3VyY2VOYW1lOiBzdHJpbmc7XG4gICAgcmVzb3VyY2VJZDogc3RyaW5nO1xuICB9KTogTG9jYWxTbmFwc2hvdFBheWxvYWQge1xuICAgIGNvbnN0IGNhcHR1cmVkQXQgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gICAgY29uc3Qgc3RhY2sgPSBjZGsuU3RhY2sub2YodGhpcyk7XG5cbiAgICAvLyBCdWlsZCBwcm92aWRlciBpZGVudGl0eVxuICAgIGNvbnN0IHByb3ZpZGVySWRlbnRpdHkgPSB7XG4gICAgICBjbG91ZDogJ2F3cycgYXMgY29uc3QsXG4gICAgICBhY2NvdW50SWQ6IHBhcmFtcy5hY2NvdW50SWQsXG4gICAgICByZWdpb246IHBhcmFtcy5yZWdpb24sXG4gICAgICBkZXBsb3ltZW50U3lzdGVtOiAnY2xvdWRmb3JtYXRpb24nIGFzIGNvbnN0LFxuICAgICAgZGVwbG95bWVudElkOiBzdGFjay5zdGFja0lkLFxuICAgIH07XG5cbiAgICAvLyBCdWlsZCBiaW5kaW5nIGlkZW50aXR5XG4gICAgY29uc3Qgc3RhYmxlUmVzb3VyY2VLZXkgPSBgJHtwYXJhbXMuZGF0YXN0b3JlVHlwZX06cGF0aDoke3BhcmFtcy5zdGFja05hbWV9LyR7cGFyYW1zLnJlc291cmNlTmFtZX1gO1xuICAgIGNvbnN0IGVudGl0eUlkID0gYCR7dGhpcy5jb25maWcuYXBwSWR9OiR7dGhpcy5zY2hlbWFEYXRhLmVudGl0eU5hbWV9YDtcbiAgICBjb25zdCBiaW5kaW5nSWQgPSBgJHt0aGlzLmNvbmZpZy5hcHBJZH06JHtzdGFibGVSZXNvdXJjZUtleX06JHt0aGlzLnNjaGVtYURhdGEuZW50aXR5TmFtZX1gO1xuXG4gICAgY29uc3QgaWRlbnRpdHkgPSB7XG4gICAgICBhcHBJZDogdGhpcy5jb25maWcuYXBwSWQsXG4gICAgICBlbnRpdHlOYW1lOiB0aGlzLnNjaGVtYURhdGEuZW50aXR5TmFtZSxcbiAgICAgIHN0YWJsZVJlc291cmNlS2V5U3RyYXRlZ3k6ICdjZGstY29uc3RydWN0LXBhdGgnIGFzIGNvbnN0LFxuICAgICAgc3RhYmxlUmVzb3VyY2VLZXksXG4gICAgICByZXNvdXJjZUlkOiBwYXJhbXMucmVzb3VyY2VJZCxcbiAgICAgIGVudGl0eUlkLFxuICAgICAgYmluZGluZ0lkLFxuICAgIH07XG5cbiAgICAvLyBCdWlsZCBvcGVyYXRpb24gbWV0YWRhdGFcbiAgICBjb25zdCBvcGVyYXRpb24gPSB7XG4gICAgICBldmVudElkOiB0aGlzLmdlbmVyYXRlVXVpZCgpLFxuICAgICAgcmVxdWVzdFR5cGU6ICdDcmVhdGUnIGFzIGNvbnN0LFxuICAgICAgZmFpbHVyZU1vZGU6IHRoaXMuY29uZmlnLmZhaWx1cmVNb2RlLFxuICAgIH07XG5cbiAgICAvLyBCdWlsZCByZXNvbHV0aW9uIG1ldGFkYXRhXG4gICAgY29uc3QgaGFzVG9rZW5zID0gdGhpcy5kZXRlY3RVbnJlc29sdmVkVG9rZW5zKHRoaXMuZGF0YVN0b3JlTWV0YWRhdGEpO1xuICAgIGNvbnN0IHJlc29sdXRpb24gPSB7XG4gICAgICBtb2RlOiAnTE9DQUwnIGFzIGNvbnN0LFxuICAgICAgaGFzVG9rZW5zLFxuICAgIH07XG5cbiAgICAvLyBCdWlsZCBoYXNoZXNcbiAgICBjb25zdCBzY2hlbWFCeXRlcyA9IEpTT04uc3RyaW5naWZ5KHRoaXMuc2NoZW1hRGF0YSk7XG4gICAgY29uc3Qgc2NoZW1hSGFzaCA9ICdzaGEyNTY6JyArIGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoc2NoZW1hQnl0ZXMpLmRpZ2VzdCgnaGV4Jyk7XG4gICAgY29uc3QgaGFzaGVzID0ge1xuICAgICAgc2NoZW1hSGFzaCxcbiAgICAgIGNvbnRlbnRIYXNoOiAnJyxcbiAgICB9O1xuXG4gICAgLy8gQnVpbGQgcmVzb3VyY2UgbWV0YWRhdGFcbiAgICBjb25zdCByZXNvdXJjZSA9IHRoaXMuYnVpbGRSZXNvdXJjZU1ldGFkYXRhKHBhcmFtcyk7XG5cbiAgICAvLyBCdWlsZCBwcm9kdWNlciBtZXRhZGF0YVxuICAgIGNvbnN0IHByb2R1Y2VyID0ge1xuICAgICAgY29tcG9uZW50OiAnY2hhaW0tY2RrJyBhcyBjb25zdCxcbiAgICAgIHZlcnNpb246IHRoaXMuZ2V0UGFja2FnZVZlcnNpb24oKSxcbiAgICAgIHJ1bnRpbWU6IHByb2Nlc3MudmVyc2lvbixcbiAgICB9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHNuYXBzaG90VmVyc2lvbjogU05BUFNIT1RfU0NIRU1BX1ZFUlNJT04sXG4gICAgICBhY3Rpb246ICdVUFNFUlQnLFxuICAgICAgY2FwdHVyZWRBdCxcbiAgICAgIHByb3ZpZGVySWRlbnRpdHksXG4gICAgICBpZGVudGl0eSxcbiAgICAgIG9wZXJhdGlvbixcbiAgICAgIHJlc29sdXRpb24sXG4gICAgICBoYXNoZXMsXG4gICAgICBzY2hlbWE6IHRoaXMuc2NoZW1hRGF0YSxcbiAgICAgIHJlc291cmNlLFxuICAgICAgcHJvZHVjZXIsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCByZXNvdXJjZSBtZXRhZGF0YSBmcm9tIGRhdGFTdG9yZSBtZXRhZGF0YS5cbiAgICovXG4gIHByaXZhdGUgYnVpbGRSZXNvdXJjZU1ldGFkYXRhKHBhcmFtczogYW55KTogYW55IHtcbiAgICBjb25zdCBkeW5hbW9NZXRhZGF0YSA9IHRoaXMuZGF0YVN0b3JlTWV0YWRhdGEgYXMgYW55O1xuICAgIFxuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAnZHluYW1vZGInLFxuICAgICAga2luZDogJ3RhYmxlJyxcbiAgICAgIGlkOiBkeW5hbW9NZXRhZGF0YS50YWJsZUFybixcbiAgICAgIG5hbWU6IGR5bmFtb01ldGFkYXRhLnRhYmxlTmFtZSxcbiAgICAgIHJlZ2lvbjogcGFyYW1zLnJlZ2lvbixcbiAgICAgIHBhcnRpdGlvbktleTogZHluYW1vTWV0YWRhdGEucGFydGl0aW9uS2V5LFxuICAgICAgc29ydEtleTogZHluYW1vTWV0YWRhdGEuc29ydEtleSxcbiAgICAgIGdsb2JhbFNlY29uZGFyeUluZGV4ZXM6IGR5bmFtb01ldGFkYXRhLmdsb2JhbFNlY29uZGFyeUluZGV4ZXMsXG4gICAgICBsb2NhbFNlY29uZGFyeUluZGV4ZXM6IGR5bmFtb01ldGFkYXRhLmxvY2FsU2Vjb25kYXJ5SW5kZXhlcyxcbiAgICAgIHR0bEF0dHJpYnV0ZTogZHluYW1vTWV0YWRhdGEudHRsQXR0cmlidXRlLFxuICAgICAgc3RyZWFtRW5hYmxlZDogZHluYW1vTWV0YWRhdGEuc3RyZWFtRW5hYmxlZCxcbiAgICAgIHN0cmVhbVZpZXdUeXBlOiBkeW5hbW9NZXRhZGF0YS5zdHJlYW1WaWV3VHlwZSxcbiAgICAgIGJpbGxpbmdNb2RlOiBkeW5hbW9NZXRhZGF0YS5iaWxsaW5nTW9kZSxcbiAgICAgIGVuY3J5cHRpb25LZXlBcm46IGR5bmFtb01ldGFkYXRhLmVuY3J5cHRpb25LZXlBcm4sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlY3QgaWYgbWV0YWRhdGEgY29udGFpbnMgdW5yZXNvbHZlZCBDREsgdG9rZW5zLlxuICAgKi9cbiAgcHJpdmF0ZSBkZXRlY3RVbnJlc29sdmVkVG9rZW5zKG1ldGFkYXRhOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBzdHIgPSBKU09OLnN0cmluZ2lmeShtZXRhZGF0YSk7XG4gICAgcmV0dXJuIHN0ci5pbmNsdWRlcygnJHtUb2tlblsnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBhIFVVSUQgdjQgZm9yIG9wZXJhdGlvbiB0cmFja2luZy5cbiAgICovXG4gIHByaXZhdGUgZ2VuZXJhdGVVdWlkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNyeXB0by5yYW5kb21VVUlEKCk7XG4gIH1cblxuICAvKipcbiAgICogQXBwbHkgc25hcHNob3QgY2FjaGUgcG9saWN5IGJhc2VkIG9uIENESyBjb250ZXh0LlxuICAgKiBcbiAgICogQ2hlY2tzIHRoZSBgY2hhaW1TbmFwc2hvdENhY2hlUG9saWN5YCBjb250ZXh0IHZhbHVlOlxuICAgKiAtIE5PTkUgKGRlZmF1bHQpOiBObyBjbGVhbnVwXG4gICAqIC0gUFJVTkVfU1RBQ0s6IERlbGV0ZSBleGlzdGluZyBzdGFjayBzbmFwc2hvdHMgYmVmb3JlIHdyaXRpbmcgbmV3IG9uZXNcbiAgICogXG4gICAqIFRoaXMgcnVucyBvbmNlIHBlciBzdGFjayAodHJhY2tlZCBieSBzdGF0aWMgZmxhZykgdG8gYXZvaWRcbiAgICogbXVsdGlwbGUgY2xlYW51cCBhdHRlbXB0cyB3aGVuIGJpbmRpbmcgbXVsdGlwbGUgZW50aXRpZXMuXG4gICAqL1xuICBwcml2YXRlIGFwcGx5U25hcHNob3RDYWNoZVBvbGljeShwYXJhbXM6IHtcbiAgICBhY2NvdW50SWQ6IHN0cmluZztcbiAgICByZWdpb246IHN0cmluZztcbiAgICBzdGFja05hbWU6IHN0cmluZztcbiAgfSk6IHZvaWQge1xuICAgIC8vIEdldCBwb2xpY3kgZnJvbSBDREsgY29udGV4dCAoZGVmYXVsdHMgdG8gTk9ORSlcbiAgICBjb25zdCBwb2xpY3lWYWx1ZSA9IHRoaXMubm9kZS50cnlHZXRDb250ZXh0KFNOQVBTSE9UX0NBQ0hFX1BPTElDWV9DT05URVhUX0tFWSk7XG4gICAgY29uc3QgcG9saWN5ID0gdGhpcy5wYXJzZVNuYXBzaG90Q2FjaGVQb2xpY3kocG9saWN5VmFsdWUpO1xuXG4gICAgaWYgKHBvbGljeSA9PT0gU25hcHNob3RDYWNoZVBvbGljeS5OT05FKSB7XG4gICAgICByZXR1cm47IC8vIE5vIGNsZWFudXBcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB3ZSd2ZSBhbHJlYWR5IGNsZWFuZWQgdGhpcyBzdGFjayBpbiB0aGlzIHN5bnRoXG4gICAgY29uc3Qgc3RhY2sgPSBjZGsuU3RhY2sub2YodGhpcyk7XG4gICAgY29uc3QgY2xlYW51cEtleSA9IGBfX2NoYWltX3NuYXBzaG90X2NsZWFudXBfJHtwYXJhbXMuc3RhY2tOYW1lfWA7XG4gICAgXG4gICAgaWYgKChzdGFjay5ub2RlIGFzIGFueSlbY2xlYW51cEtleV0pIHtcbiAgICAgIHJldHVybjsgLy8gQWxyZWFkeSBjbGVhbmVkIGluIHRoaXMgc3ludGhcbiAgICB9XG5cbiAgICAvLyBNYXJrIGFzIGNsZWFuZWQgdG8gYXZvaWQgZHVwbGljYXRlIGNsZWFudXBcbiAgICAoc3RhY2subm9kZSBhcyBhbnkpW2NsZWFudXBLZXldID0gdHJ1ZTtcblxuICAgIGlmIChwb2xpY3kgPT09IFNuYXBzaG90Q2FjaGVQb2xpY3kuUFJVTkVfU1RBQ0spIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHBydW5lU3RhY2tTbmFwc2hvdHMoe1xuICAgICAgICBhY2NvdW50SWQ6IHBhcmFtcy5hY2NvdW50SWQsXG4gICAgICAgIHJlZ2lvbjogcGFyYW1zLnJlZ2lvbixcbiAgICAgICAgc3RhY2tOYW1lOiBwYXJhbXMuc3RhY2tOYW1lLFxuICAgICAgICB2ZXJib3NlOiBmYWxzZSwgLy8gRG9uJ3Qgc3BhbSBjb25zb2xlIGR1cmluZyBzeW50aFxuICAgICAgfSk7XG5cbiAgICAgIC8vIE9ubHkgbG9nIGlmIHZlcmJvc2UgbW9kZSBvciBlcnJvcnNcbiAgICAgIGlmIChyZXN1bHQuZGVsZXRlZENvdW50ID4gMCB8fCByZXN1bHQuZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coYFtDaGFpbV0gUHJ1bmVkICR7cmVzdWx0LmRlbGV0ZWRDb3VudH0gc25hcHNob3QocykgZm9yIHN0YWNrOiAke3BhcmFtcy5zdGFja05hbWV9YCk7XG4gICAgICAgIFxuICAgICAgICBpZiAocmVzdWx0LmVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKGBbQ2hhaW1dIENsZWFudXAgd2FybmluZ3M6YCwgcmVzdWx0LmVycm9ycyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2Ugc25hcHNob3QgY2FjaGUgcG9saWN5IGZyb20gY29udGV4dCB2YWx1ZS5cbiAgICovXG4gIHByaXZhdGUgcGFyc2VTbmFwc2hvdENhY2hlUG9saWN5KHZhbHVlOiB1bmtub3duKTogU25hcHNob3RDYWNoZVBvbGljeSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBERUZBVUxUX1NOQVBTSE9UX0NBQ0hFX1BPTElDWTtcbiAgICB9XG5cbiAgICBjb25zdCB1cHBlclZhbHVlID0gdmFsdWUudG9VcHBlckNhc2UoKTtcbiAgICBcbiAgICBpZiAodXBwZXJWYWx1ZSA9PT0gJ05PTkUnIHx8IHVwcGVyVmFsdWUgPT09ICdESVNBQkxFRCcpIHtcbiAgICAgIHJldHVybiBTbmFwc2hvdENhY2hlUG9saWN5Lk5PTkU7XG4gICAgfVxuICAgIFxuICAgIGlmICh1cHBlclZhbHVlID09PSAnUFJVTkVfU1RBQ0snIHx8IHVwcGVyVmFsdWUgPT09ICdQUlVORScpIHtcbiAgICAgIHJldHVybiBTbmFwc2hvdENhY2hlUG9saWN5LlBSVU5FX1NUQUNLO1xuICAgIH1cblxuICAgIGNvbnNvbGUud2FybihcbiAgICAgIGBbQ2hhaW1dIFVua25vd24gY2hhaW1TbmFwc2hvdENhY2hlUG9saWN5OiBcIiR7dmFsdWV9XCIuIGAgK1xuICAgICAgYFZhbGlkIHZhbHVlczogTk9ORSwgUFJVTkVfU1RBQ0suIERlZmF1bHRpbmcgdG8gTk9ORS5gXG4gICAgKTtcbiAgICBcbiAgICByZXR1cm4gREVGQVVMVF9TTkFQU0hPVF9DQUNIRV9QT0xJQ1k7XG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdCBzdGFjayBuYW1lIGZyb20gc3RhYmxlUmVzb3VyY2VLZXkuXG4gICAqIEZvcm1hdDogZHluYW1vZGI6cGF0aDpTdGFja05hbWUvUmVzb3VyY2VOYW1lXG4gICAqL1xuICBwcml2YXRlIGV4dHJhY3RTdGFja05hbWVGcm9tUmVzb3VyY2VLZXkoc3RhYmxlUmVzb3VyY2VLZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgbWF0Y2ggPSBzdGFibGVSZXNvdXJjZUtleS5tYXRjaCgvcGF0aDooW14vXSspLyk7XG4gICAgcmV0dXJuIG1hdGNoID8gbWF0Y2hbMV0gOiAndW5rbm93bic7XG4gIH1cblxuICAvKipcbiAgICogV3JpdGUgTE9DQUwgc25hcHNob3QgdG8gT1MgY2FjaGUgZm9yIGNoYWltLWNsaSBjb25zdW1wdGlvbi5cbiAgICogVXNlcyBoaWVyYXJjaGljYWwgcGF0aDogYXdzL3thY2NvdW50SWR9L3tyZWdpb259L3tzdGFja05hbWV9L3tkYXRhc3RvcmVUeXBlfS97cmVzb3VyY2VJZH0uanNvblxuICAgKiBcbiAgICogQHBhcmFtIHNuYXBzaG90IC0gVGhlIHNuYXBzaG90IHBheWxvYWQgdG8gd3JpdGVcbiAgICogQHJldHVybnMgVGhlIHBhdGggd2hlcmUgc25hcHNob3Qgd2FzIHdyaXR0ZW5cbiAgICovXG4gIHByaXZhdGUgd3JpdGVMb2NhbFNuYXBzaG90VG9EaXNrKHNuYXBzaG90OiBMb2NhbFNuYXBzaG90UGF5bG9hZCk6IHN0cmluZyB7XG4gICAgY29uc3Qgc3RhY2tOYW1lID0gdGhpcy5leHRyYWN0U3RhY2tOYW1lRnJvbVJlc291cmNlS2V5KHNuYXBzaG90LmlkZW50aXR5LnN0YWJsZVJlc291cmNlS2V5KTtcbiAgICBcbiAgICBjb25zdCBkaXIgPSBnZXRTbmFwc2hvdERpcih7XG4gICAgICBhY2NvdW50SWQ6IHNuYXBzaG90LnByb3ZpZGVySWRlbnRpdHkuYWNjb3VudElkLFxuICAgICAgcmVnaW9uOiBzbmFwc2hvdC5wcm92aWRlcklkZW50aXR5LnJlZ2lvbixcbiAgICAgIHN0YWNrTmFtZSxcbiAgICAgIGRhdGFzdG9yZVR5cGU6IHNuYXBzaG90LnJlc291cmNlLnR5cGUsXG4gICAgfSk7XG4gICAgXG4gICAgZW5zdXJlRGlyRXhpc3RzKGRpcik7XG4gICAgXG4gICAgY29uc3QgZmlsZVBhdGggPSBnZXRMb2NhbFNuYXBzaG90UGF0aCh7XG4gICAgICBhY2NvdW50SWQ6IHNuYXBzaG90LnByb3ZpZGVySWRlbnRpdHkuYWNjb3VudElkLFxuICAgICAgcmVnaW9uOiBzbmFwc2hvdC5wcm92aWRlcklkZW50aXR5LnJlZ2lvbixcbiAgICAgIHN0YWNrTmFtZSxcbiAgICAgIGRhdGFzdG9yZVR5cGU6IHNuYXBzaG90LnJlc291cmNlLnR5cGUsXG4gICAgICByZXNvdXJjZUlkOiBzbmFwc2hvdC5pZGVudGl0eS5yZXNvdXJjZUlkLFxuICAgIH0pO1xuICAgIFxuICAgIGZzLndyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIEpTT04uc3RyaW5naWZ5KHNuYXBzaG90LCBudWxsLCAyKSwgJ3V0Zi04Jyk7XG4gICAgXG4gICAgcmV0dXJuIGZpbGVQYXRoO1xuICB9XG5cblxuICAvKipcbiAgICogRmluZCB0aGUgQ0RLIHByb2plY3Qgcm9vdCBieSB3YWxraW5nIHVwIGZyb20gY3VycmVudCBtb2R1bGUuXG4gICAqL1xuICBwcml2YXRlIGZpbmRDZGtQcm9qZWN0Um9vdCgpOiBzdHJpbmcge1xuICAgIGxldCBjdXJyZW50RGlyID0gX19kaXJuYW1lO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTA7IGkrKykge1xuICAgICAgY29uc3QgY2RrSnNvblBhdGggPSBwYXRoLmpvaW4oY3VycmVudERpciwgJ2Nkay5qc29uJyk7XG4gICAgICBpZiAoZnMuZXhpc3RzU3luYyhjZGtKc29uUGF0aCkpIHtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnREaXI7XG4gICAgICB9XG4gICAgICBjb25zdCBwYXJlbnREaXIgPSBwYXRoLmRpcm5hbWUoY3VycmVudERpcik7XG4gICAgICBpZiAocGFyZW50RGlyID09PSBjdXJyZW50RGlyKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY3VycmVudERpciA9IHBhcmVudERpcjtcbiAgICB9XG4gICAgLy8gRmFsbGJhY2sgdG8gY3dkXG4gICAgcmV0dXJuIHByb2Nlc3MuY3dkKCk7XG4gIH1cblxuICAvKipcbiAgICogV3JpdGUgc25hcHNob3QgYW5kIExhbWJkYSBoYW5kbGVyIHRvIGlzb2xhdGVkIENESyBhc3NldCBkaXJlY3RvcnkgZm9yIExhbWJkYSBidW5kbGluZy5cbiAgICogXG4gICAqIEFzc2V0IGRpcmVjdG9yeSBpcyBwZXIge3N0YWNrTmFtZX0ve3Jlc291cmNlSWR9IGFuZCBNVVNUIE5PVCBiZSBzaGFyZWQuXG4gICAqIFRoZSBMYW1iZGEgcmVhZHMgLi9zbmFwc2hvdC5qc29uIGZyb20gaXRzIGJ1bmRsZSwgTk9UIGZyb20gZW52IHZhcnMgb3IgT1MgY2FjaGUuXG4gICAqIFxuICAgKiBUaGUgaGFuZGxlciBpcyBjb3BpZWQgZnJvbSB0aGUgY2Fub25pY2FsIGhhbmRsZXIgZmlsZSAoc3JjL2xhbWJkYS1oYW5kbGVyL2hhbmRsZXIuanMpXG4gICAqIHJhdGhlciB0aGFuIGJlaW5nIGdlbmVyYXRlZCBpbmxpbmUgLSB0aGlzIGVuc3VyZXMgYSBzaW5nbGUgc291cmNlIG9mIHRydXRoLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgYXNzZXQgZGlyZWN0b3J5IHBhdGhcbiAgICovXG4gIHByaXZhdGUgd3JpdGVTbmFwc2hvdEFzc2V0KHNuYXBzaG90OiBMb2NhbFNuYXBzaG90UGF5bG9hZCwgc3RhY2tOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGNka1Jvb3QgPSB0aGlzLmZpbmRDZGtQcm9qZWN0Um9vdCgpO1xuICAgIGNvbnN0IGFzc2V0RGlyID0gcGF0aC5qb2luKGNka1Jvb3QsICdjZGsub3V0JywgJ2NoYWltJywgJ2Fzc2V0cycsIHN0YWNrTmFtZSwgdGhpcy5yZXNvdXJjZUlkKTtcbiAgICBlbnN1cmVEaXJFeGlzdHMoYXNzZXREaXIpO1xuXG4gICAgLy8gV3JpdGUgc25hcHNob3QuanNvbiAoT1ZFUldSSVRFIGVhY2ggc3ludGgpXG4gICAgY29uc3Qgc25hcHNob3RQYXRoID0gcGF0aC5qb2luKGFzc2V0RGlyLCAnc25hcHNob3QuanNvbicpO1xuICAgIGZzLndyaXRlRmlsZVN5bmMoc25hcHNob3RQYXRoLCBKU09OLnN0cmluZ2lmeShzbmFwc2hvdCwgbnVsbCwgMiksICd1dGYtOCcpO1xuXG4gICAgLy8gQ29weSBjYW5vbmljYWwgTGFtYmRhIGhhbmRsZXIgKE9WRVJXUklURSBlYWNoIHN5bnRoKVxuICAgIGNvbnN0IGhhbmRsZXJEZXN0UGF0aCA9IHBhdGguam9pbihhc3NldERpciwgJ2luZGV4LmpzJyk7XG4gICAgZnMuY29weUZpbGVTeW5jKExBTUJEQV9IQU5ETEVSX1BBVEgsIGhhbmRsZXJEZXN0UGF0aCk7XG5cbiAgICByZXR1cm4gYXNzZXREaXI7XG4gIH1cblxuICAvKipcbiAgICogRGVwbG95IExhbWJkYSBmdW5jdGlvbiBhbmQgY3VzdG9tIHJlc291cmNlIGZvciBpbmdlc3Rpb24uXG4gICAqL1xuICBwcml2YXRlIGRlcGxveUluZ2VzdGlvblJlc291cmNlcyhhc3NldERpcjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgaGFuZGxlciA9IHRoaXMuY3JlYXRlSW5nZXN0aW9uTGFtYmRhKGFzc2V0RGlyKTtcbiAgICB0aGlzLmNyZWF0ZUN1c3RvbVJlc291cmNlKGhhbmRsZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBMYW1iZGEgZnVuY3Rpb24gZm9yIGluZ2VzdGlvbiB3b3JrZmxvdy5cbiAgICogTGFtYmRhIHJlYWRzIHNuYXBzaG90IGZyb20gaXRzIGJ1bmRsZWQgYXNzZXQgZGlyZWN0b3J5LlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVJbmdlc3Rpb25MYW1iZGEoYXNzZXREaXI6IHN0cmluZyk6IGxhbWJkYS5GdW5jdGlvbiB7XG4gICAgY29uc3QgaGFuZGxlciA9IG5ldyBsYW1iZGEuRnVuY3Rpb24odGhpcywgJ0luZ2VzdGlvbkhhbmRsZXInLCB7XG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjBfWCxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChhc3NldERpciksXG4gICAgICB0aW1lb3V0OiBjZGsuRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGVudmlyb25tZW50OiB0aGlzLmJ1aWxkTGFtYmRhRW52aXJvbm1lbnQoKSxcbiAgICB9KTtcblxuICAgIC8vIEdyYW50IENsb3VkV2F0Y2ggTG9ncyBwZXJtaXNzaW9uc1xuICAgIGhhbmRsZXIuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFsnbG9nczpDcmVhdGVMb2dHcm91cCcsICdsb2dzOkNyZWF0ZUxvZ1N0cmVhbScsICdsb2dzOlB1dExvZ0V2ZW50cyddLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gR3JhbnQgU2VjcmV0cyBNYW5hZ2VyIHBlcm1pc3Npb25zIGlmIHVzaW5nIHNlY3JldHNcbiAgICBjb25zdCB7IGNyZWRlbnRpYWxzIH0gPSB0aGlzLmNvbmZpZztcbiAgICBpZiAoY3JlZGVudGlhbHMuY3JlZGVudGlhbFR5cGUgPT09ICdzZWNyZXRzTWFuYWdlcicgJiYgY3JlZGVudGlhbHMuc2VjcmV0TmFtZSkge1xuICAgICAgaGFuZGxlci5hZGRUb1JvbGVQb2xpY3koXG4gICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgICAgYWN0aW9uczogWydzZWNyZXRzbWFuYWdlcjpHZXRTZWNyZXRWYWx1ZSddLFxuICAgICAgICAgIHJlc291cmNlczogW2Bhcm46YXdzOnNlY3JldHNtYW5hZ2VyOio6KjpzZWNyZXQ6JHtjcmVkZW50aWFscy5zZWNyZXROYW1lfSpgXSxcbiAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhhbmRsZXI7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgTGFtYmRhIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICogTm90ZTogU25hcHNob3QgaXMgTk9UIHBhc3NlZCB2aWEgZW52IC0gTGFtYmRhIHJlYWRzIGZyb20gYnVuZGxlZCBhc3NldC5cbiAgICovXG4gIHByaXZhdGUgYnVpbGRMYW1iZGFFbnZpcm9ubWVudCgpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICAvLyBBbGxvdyBtYWludGFpbmVyIG92ZXJyaWRlIHZpYSBDREsgY29udGV4dCwgb3RoZXJ3aXNlIHVzZSBkZWZhdWx0XG4gICAgY29uc3QgYXBpQmFzZVVybCA9IHRoaXMubm9kZS50cnlHZXRDb250ZXh0KCdjaGFpbUFwaUJhc2VVcmwnKSA/PyBERUZBVUxUX0NIQUlNX0FQSV9CQVNFX1VSTDtcbiAgICBjb25zdCB7IGNyZWRlbnRpYWxzLCBmYWlsdXJlTW9kZSB9ID0gdGhpcy5jb25maWc7XG5cbiAgICBjb25zdCBlbnY6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICBBUFBfSUQ6IHRoaXMuY29uZmlnLmFwcElkLFxuICAgICAgRkFJTFVSRV9NT0RFOiBmYWlsdXJlTW9kZSxcbiAgICAgIENIQUlNX0FQSV9CQVNFX1VSTDogYXBpQmFzZVVybCxcbiAgICAgIENIQUlNX01BWF9TTkFQU0hPVF9CWVRFUzogU3RyaW5nKERFRkFVTFRfTUFYX1NOQVBTSE9UX0JZVEVTKSxcbiAgICB9O1xuXG4gICAgaWYgKGNyZWRlbnRpYWxzLmNyZWRlbnRpYWxUeXBlID09PSAnc2VjcmV0c01hbmFnZXInKSB7XG4gICAgICBlbnYuU0VDUkVUX05BTUUgPSBjcmVkZW50aWFscy5zZWNyZXROYW1lITtcbiAgICB9IGVsc2Uge1xuICAgICAgZW52LkFQSV9LRVkgPSBjcmVkZW50aWFscy5hcGlLZXkhO1xuICAgICAgZW52LkFQSV9TRUNSRVQgPSBjcmVkZW50aWFscy5hcGlTZWNyZXQhO1xuICAgIH1cblxuICAgIHJldHVybiBlbnY7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIENsb3VkRm9ybWF0aW9uIGN1c3RvbSByZXNvdXJjZS5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQ3VzdG9tUmVzb3VyY2UoaGFuZGxlcjogbGFtYmRhLkZ1bmN0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgcHJvdmlkZXIgPSBuZXcgY3IuUHJvdmlkZXIodGhpcywgJ0luZ2VzdGlvblByb3ZpZGVyJywge1xuICAgICAgb25FdmVudEhhbmRsZXI6IGhhbmRsZXIsXG4gICAgfSk7XG5cbiAgICAvLyBVc2UgcmVzb3VyY2UgSUQgZm9yIHBoeXNpY2FsIHJlc291cmNlIElEIChzdGFibGUgYWNyb3NzIGRlcGxveXMpXG4gICAgbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCAnSW5nZXN0aW9uUmVzb3VyY2UnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgUmVzb3VyY2VJZDogdGhpcy5yZXNvdXJjZUlkLFxuICAgICAgICAvLyBDb250ZW50SGFzaCBpcyBjb21wdXRlZCBhdCBMYW1iZGEgcnVudGltZVxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuIl19