@aws-cdk/toolkit-lib 1.30.0 → 1.32.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 (111) hide show
  1. package/build-info.json +2 -2
  2. package/lib/actions/bootstrap/index.d.ts +5 -0
  3. package/lib/actions/bootstrap/index.js +35 -2
  4. package/lib/actions/deploy/index.d.ts +6 -0
  5. package/lib/actions/deploy/index.js +1 -1
  6. package/lib/actions/destroy/index.d.ts +6 -0
  7. package/lib/actions/destroy/index.js +1 -1
  8. package/lib/actions/diff/private/helpers.js +36 -3
  9. package/lib/api/aws-auth/account-cache.js +36 -3
  10. package/lib/api/aws-auth/sdk-provider.js +36 -3
  11. package/lib/api/aws-auth/sdk.d.ts +2 -1
  12. package/lib/api/aws-auth/sdk.js +2 -1
  13. package/lib/api/aws-auth/user-agent.js +35 -2
  14. package/lib/api/aws-auth/util.js +35 -2
  15. package/lib/api/bootstrap/bootstrap-environment.js +35 -2
  16. package/lib/api/bootstrap/bootstrap-props.d.ts +6 -0
  17. package/lib/api/bootstrap/bootstrap-props.js +1 -1
  18. package/lib/api/bootstrap/deploy-bootstrap.js +39 -4
  19. package/lib/api/cloud-assembly/context-store.js +36 -3
  20. package/lib/api/cloud-assembly/environment.js +37 -4
  21. package/lib/api/cloud-assembly/private/context-aware-source.js +35 -2
  22. package/lib/api/cloud-assembly/private/exec.js +35 -2
  23. package/lib/api/cloud-assembly/private/prepare-source.js +39 -6
  24. package/lib/api/cloud-assembly/source-builder.js +37 -4
  25. package/lib/api/cloud-assembly/stack-assembly.js +8 -4
  26. package/lib/api/cloudformation/logical-id-map.js +35 -2
  27. package/lib/api/cloudformation/nested-stack-helpers.js +36 -3
  28. package/lib/api/cloudformation/template-body-parameter.js +42 -6
  29. package/lib/api/deployments/asset-manifest-builder.js +35 -2
  30. package/lib/api/deployments/assets.js +42 -6
  31. package/lib/api/deployments/cfn-api.d.ts +4 -2
  32. package/lib/api/deployments/cfn-api.js +47 -6
  33. package/lib/api/deployments/deploy-stack.d.ts +13 -0
  34. package/lib/api/deployments/deploy-stack.js +29 -9
  35. package/lib/api/deployments/deployment-result.d.ts +7 -1
  36. package/lib/api/deployments/deployment-result.js +1 -1
  37. package/lib/api/deployments/deployments.d.ts +5 -0
  38. package/lib/api/deployments/deployments.js +42 -4
  39. package/lib/api/diagnosing/format-utils.d.ts +29 -0
  40. package/lib/api/diagnosing/format-utils.js +141 -1
  41. package/lib/api/diagnosing/investigate-custom-resource.d.ts +17 -0
  42. package/lib/api/diagnosing/investigate-custom-resource.js +247 -0
  43. package/lib/api/diagnosing/investigate-ecs-service.d.ts +20 -0
  44. package/lib/api/diagnosing/investigate-ecs-service.js +242 -0
  45. package/lib/api/diagnosing/resource-identifiers.d.ts +39 -0
  46. package/lib/api/diagnosing/resource-identifiers.js +90 -0
  47. package/lib/api/diagnosing/resource-investigation.d.ts +2 -30
  48. package/lib/api/diagnosing/resource-investigation.js +9 -289
  49. package/lib/api/diff/diff-formatter.js +11 -8
  50. package/lib/api/drift/drift-formatter.js +20 -17
  51. package/lib/api/garbage-collection/garbage-collector.js +7 -4
  52. package/lib/api/garbage-collection/progress-printer.js +7 -4
  53. package/lib/api/hotswap/hotswap-deployments.js +47 -10
  54. package/lib/api/hotswap/hotswap-template-cache.js +36 -3
  55. package/lib/api/io/private/io-default-messages.js +35 -2
  56. package/lib/api/io/private/message-maker.d.ts +4 -0
  57. package/lib/api/io/private/message-maker.js +3 -1
  58. package/lib/api/io/private/messages.d.ts +5 -0
  59. package/lib/api/io/private/messages.js +55 -2
  60. package/lib/api/io/private/span.js +35 -2
  61. package/lib/api/logs-monitor/logs-monitor.js +40 -4
  62. package/lib/api/network-detector/network-detector.js +37 -4
  63. package/lib/api/notices/cached-data-source.js +35 -2
  64. package/lib/api/notices/filter.js +35 -2
  65. package/lib/api/notices/notices.js +35 -2
  66. package/lib/api/notices/web-data-source.js +35 -2
  67. package/lib/api/refactoring/digest.js +35 -2
  68. package/lib/api/refactoring/stack-definitions.js +40 -4
  69. package/lib/api/resource-import/importer.js +60 -17
  70. package/lib/api/resource-import/migrator.js +42 -6
  71. package/lib/api/rwlock.js +35 -2
  72. package/lib/api/settings.js +38 -5
  73. package/lib/api/source-tracing/private/stack-source-tracing.js +38 -5
  74. package/lib/api/stack-events/resource-errors.d.ts +12 -0
  75. package/lib/api/stack-events/resource-errors.js +2 -1
  76. package/lib/api/stack-events/stack-activity-monitor.d.ts +5 -0
  77. package/lib/api/stack-events/stack-activity-monitor.js +42 -2
  78. package/lib/api/stack-events/stack-event-poller.d.ts +8 -1
  79. package/lib/api/stack-events/stack-event-poller.js +19 -1
  80. package/lib/api/stack-events/stack-progress-monitor.js +35 -2
  81. package/lib/api/toolkit-info.js +7 -4
  82. package/lib/api/tree.js +36 -3
  83. package/lib/api/validate/validate-formatting.js +53 -17
  84. package/lib/api/work-graph/build-destroy-work-graph.js +35 -2
  85. package/lib/api/work-graph/work-graph-builder.js +35 -2
  86. package/lib/context-providers/index.js +35 -2
  87. package/lib/private/activity-printer/current.d.ts +19 -0
  88. package/lib/private/activity-printer/current.js +109 -17
  89. package/lib/private/activity-printer/history.js +50 -14
  90. package/lib/private/tools.js +38 -1
  91. package/lib/toolkit/non-interactive-io-host.js +11 -8
  92. package/lib/toolkit/private/collect-annotation-report.js +35 -2
  93. package/lib/toolkit/private/validation-report.js +36 -3
  94. package/lib/toolkit/toolkit-error.d.ts +20 -0
  95. package/lib/toolkit/toolkit-error.js +30 -2
  96. package/lib/toolkit/toolkit.d.ts +8 -0
  97. package/lib/toolkit/toolkit.js +107 -41
  98. package/lib/toolkit/types.d.ts +22 -0
  99. package/lib/toolkit/types.js +1 -1
  100. package/lib/util/cfn-express.d.ts +24 -0
  101. package/lib/util/cfn-express.js +55 -0
  102. package/lib/util/content-hash.js +35 -2
  103. package/lib/util/directories.js +38 -5
  104. package/lib/util/guess-language.js +36 -3
  105. package/lib/util/index.d.ts +1 -0
  106. package/lib/util/index.js +2 -1
  107. package/lib/util/package-info.js +35 -2
  108. package/lib/util/serialize.js +36 -3
  109. package/lib/util/version-range.js +35 -2
  110. package/lib/util/yaml-cfn.js +36 -3
  111. package/package.json +2 -2
@@ -0,0 +1,39 @@
1
+ /** Pure parsers for resource identifiers used during failure diagnosis. */
2
+ /**
3
+ * Parse an ECS service physical resource ID into cluster and service identifiers.
4
+ *
5
+ * The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
6
+ * accept either form for their `cluster` parameter, so this is fine downstream.
7
+ *
8
+ * Recognized formats:
9
+ * - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
10
+ * - Path: `cluster-name/service-name`
11
+ * - Bare service name (uses the default cluster)
12
+ */
13
+ export declare function parseEcsServiceIdentifier(physicalId: string): {
14
+ cluster?: string;
15
+ serviceName?: string;
16
+ };
17
+ /**
18
+ * If a ServiceToken is an `Fn::GetAtt` or `Ref` intrinsic, return the referenced logical ID.
19
+ */
20
+ export declare function serviceTokenReferencedLogicalId(serviceToken: any): string | undefined;
21
+ /**
22
+ * Extract a Lambda function name from a function ARN or a bare name.
23
+ *
24
+ * Returns `undefined` for non-Lambda ARNs (e.g. an SNS-topic ServiceToken).
25
+ */
26
+ export declare function functionNameFromArnOrName(arnOrName: string): string | undefined;
27
+ /**
28
+ * Extract the log stream name out of a cfn-response failure reason
29
+ * ("See the details in CloudWatch Log Stream: <name>").
30
+ */
31
+ export declare function extractLogStreamName(message: string | undefined): string | undefined;
32
+ /**
33
+ * cfn-response defaults the physical ID to the log stream name. Use it only when it looks
34
+ * like a Lambda log stream (`YYYY/MM/DD/...`), so a user-provided physical ID isn't mistaken
35
+ * for one.
36
+ */
37
+ export declare function logStreamNameFromPhysicalId(physicalId: string | undefined): string | undefined;
38
+ export declare function ecsStoppedTasksConsoleUrl(region: string, cluster: string, serviceName: string): string;
39
+ //# sourceMappingURL=resource-identifiers.d.ts.map
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ /** Pure parsers for resource identifiers used during failure diagnosis. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.parseEcsServiceIdentifier = parseEcsServiceIdentifier;
5
+ exports.serviceTokenReferencedLogicalId = serviceTokenReferencedLogicalId;
6
+ exports.functionNameFromArnOrName = functionNameFromArnOrName;
7
+ exports.extractLogStreamName = extractLogStreamName;
8
+ exports.logStreamNameFromPhysicalId = logStreamNameFromPhysicalId;
9
+ exports.ecsStoppedTasksConsoleUrl = ecsStoppedTasksConsoleUrl;
10
+ /**
11
+ * Parse an ECS service physical resource ID into cluster and service identifiers.
12
+ *
13
+ * The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
14
+ * accept either form for their `cluster` parameter, so this is fine downstream.
15
+ *
16
+ * Recognized formats:
17
+ * - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
18
+ * - Path: `cluster-name/service-name`
19
+ * - Bare service name (uses the default cluster)
20
+ */
21
+ function parseEcsServiceIdentifier(physicalId) {
22
+ const arnMatch = physicalId.match(/^arn:[^:]+:ecs:[^:]*:[^:]*:service\/([^/]+)\/([^/]+)$/);
23
+ if (arnMatch) {
24
+ return { cluster: arnMatch[1], serviceName: arnMatch[2] };
25
+ }
26
+ const parts = physicalId.split('/');
27
+ if (parts.length === 2 && parts[0] && parts[1]) {
28
+ return { cluster: parts[0], serviceName: parts[1] };
29
+ }
30
+ if (parts.length === 1 && parts[0]) {
31
+ return { serviceName: parts[0] };
32
+ }
33
+ return {};
34
+ }
35
+ /**
36
+ * If a ServiceToken is an `Fn::GetAtt` or `Ref` intrinsic, return the referenced logical ID.
37
+ */
38
+ function serviceTokenReferencedLogicalId(serviceToken) {
39
+ if (!serviceToken || typeof serviceToken !== 'object') {
40
+ return undefined;
41
+ }
42
+ const getAtt = serviceToken['Fn::GetAtt'];
43
+ // Array form (JSON / CDK output): ["LogicalId", "Arn"].
44
+ if (Array.isArray(getAtt) && typeof getAtt[0] === 'string') {
45
+ return getAtt[0];
46
+ }
47
+ // String short-form (how YAML `!GetAtt LogicalId.Arn` deserializes): "LogicalId.Attr".
48
+ if (typeof getAtt === 'string') {
49
+ return getAtt.split('.')[0] || undefined;
50
+ }
51
+ if (typeof serviceToken.Ref === 'string') {
52
+ return serviceToken.Ref;
53
+ }
54
+ return undefined;
55
+ }
56
+ /**
57
+ * Extract a Lambda function name from a function ARN or a bare name.
58
+ *
59
+ * Returns `undefined` for non-Lambda ARNs (e.g. an SNS-topic ServiceToken).
60
+ */
61
+ function functionNameFromArnOrName(arnOrName) {
62
+ const arnMatch = arnOrName.match(/^arn:[^:]+:lambda:[^:]*:[^:]*:function:([^:]+)/);
63
+ if (arnMatch) {
64
+ return arnMatch[1];
65
+ }
66
+ if (arnOrName.startsWith('arn:')) {
67
+ return undefined;
68
+ }
69
+ return arnOrName || undefined;
70
+ }
71
+ /**
72
+ * Extract the log stream name out of a cfn-response failure reason
73
+ * ("See the details in CloudWatch Log Stream: <name>").
74
+ */
75
+ function extractLogStreamName(message) {
76
+ const match = message?.match(/CloudWatch Log Stream:\s*(\S+)/);
77
+ return match ? match[1] : undefined;
78
+ }
79
+ /**
80
+ * cfn-response defaults the physical ID to the log stream name. Use it only when it looks
81
+ * like a Lambda log stream (`YYYY/MM/DD/...`), so a user-provided physical ID isn't mistaken
82
+ * for one.
83
+ */
84
+ function logStreamNameFromPhysicalId(physicalId) {
85
+ return physicalId && /^\d{4}\/\d{2}\/\d{2}\/.+/.test(physicalId) ? physicalId : undefined;
86
+ }
87
+ function ecsStoppedTasksConsoleUrl(region, cluster, serviceName) {
88
+ return `https://${region}.console.aws.amazon.com/ecs/v2/clusters/${cluster}/services/${serviceName}/tasks?status=STOPPED&region=${region}`;
89
+ }
90
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtaWRlbnRpZmllcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJyZXNvdXJjZS1pZGVudGlmaWVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsMkVBQTJFOztBQWEzRSw4REFlQztBQUtELDBFQWlCQztBQU9ELDhEQVNDO0FBTUQsb0RBR0M7QUFPRCxrRUFFQztBQUVELDhEQUVDO0FBdEZEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxTQUFnQix5QkFBeUIsQ0FBQyxVQUFrQjtJQUMxRCxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7SUFDM0YsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUNiLE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM1RCxDQUFDO0lBRUQsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMvQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQUNELElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDbkMsT0FBTyxFQUFFLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNuQyxDQUFDO0lBRUQsT0FBTyxFQUFFLENBQUM7QUFDWixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQiwrQkFBK0IsQ0FBQyxZQUFpQjtJQUMvRCxJQUFJLENBQUMsWUFBWSxJQUFJLE9BQU8sWUFBWSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3RELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDMUMsd0RBQXdEO0lBQ3hELElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUMzRCxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsdUZBQXVGO0lBQ3ZGLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDL0IsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQztJQUMzQyxDQUFDO0lBQ0QsSUFBSSxPQUFPLFlBQVksQ0FBQyxHQUFHLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDekMsT0FBTyxZQUFZLENBQUMsR0FBRyxDQUFDO0lBQzFCLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQWdCLHlCQUF5QixDQUFDLFNBQWlCO0lBQ3pELE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztJQUNuRixJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQ2IsT0FBTyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckIsQ0FBQztJQUNELElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2pDLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLFNBQVMsSUFBSSxTQUFTLENBQUM7QUFDaEMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLG9CQUFvQixDQUFDLE9BQTJCO0lBQzlELE1BQU0sS0FBSyxHQUFHLE9BQU8sRUFBRSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUMvRCxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDdEMsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQiwyQkFBMkIsQ0FBQyxVQUE4QjtJQUN4RSxPQUFPLFVBQVUsSUFBSSwwQkFBMEIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzVGLENBQUM7QUFFRCxTQUFnQix5QkFBeUIsQ0FBQyxNQUFjLEVBQUUsT0FBZSxFQUFFLFdBQW1CO0lBQzVGLE9BQU8sV0FBVyxNQUFNLDJDQUEyQyxPQUFPLGFBQWEsV0FBVyxnQ0FBZ0MsTUFBTSxFQUFFLENBQUM7QUFDN0ksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKiBQdXJlIHBhcnNlcnMgZm9yIHJlc291cmNlIGlkZW50aWZpZXJzIHVzZWQgZHVyaW5nIGZhaWx1cmUgZGlhZ25vc2lzLiAqL1xuXG4vKipcbiAqIFBhcnNlIGFuIEVDUyBzZXJ2aWNlIHBoeXNpY2FsIHJlc291cmNlIElEIGludG8gY2x1c3RlciBhbmQgc2VydmljZSBpZGVudGlmaWVycy5cbiAqXG4gKiBUaGUgY2x1c3RlciBwb3J0aW9uIGlzIGEgbmFtZSAobm90IGFuIEFSTikg4oCUIGBkZXNjcmliZVNlcnZpY2VzYC9gZGVzY3JpYmVUYXNrc2BcbiAqIGFjY2VwdCBlaXRoZXIgZm9ybSBmb3IgdGhlaXIgYGNsdXN0ZXJgIHBhcmFtZXRlciwgc28gdGhpcyBpcyBmaW5lIGRvd25zdHJlYW0uXG4gKlxuICogUmVjb2duaXplZCBmb3JtYXRzOlxuICogLSBMb25nIEFSTjogYGFybjphd3M6ZWNzOnJlZ2lvbjphY2NvdW50OnNlcnZpY2UvY2x1c3Rlci1uYW1lL3NlcnZpY2UtbmFtZWAgKGN1cnJlbnQgZGVmYXVsdClcbiAqIC0gUGF0aDogYGNsdXN0ZXItbmFtZS9zZXJ2aWNlLW5hbWVgXG4gKiAtIEJhcmUgc2VydmljZSBuYW1lICh1c2VzIHRoZSBkZWZhdWx0IGNsdXN0ZXIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUVjc1NlcnZpY2VJZGVudGlmaWVyKHBoeXNpY2FsSWQ6IHN0cmluZyk6IHsgY2x1c3Rlcj86IHN0cmluZzsgc2VydmljZU5hbWU/OiBzdHJpbmcgfSB7XG4gIGNvbnN0IGFybk1hdGNoID0gcGh5c2ljYWxJZC5tYXRjaCgvXmFybjpbXjpdKzplY3M6W146XSo6W146XSo6c2VydmljZVxcLyhbXi9dKylcXC8oW14vXSspJC8pO1xuICBpZiAoYXJuTWF0Y2gpIHtcbiAgICByZXR1cm4geyBjbHVzdGVyOiBhcm5NYXRjaFsxXSwgc2VydmljZU5hbWU6IGFybk1hdGNoWzJdIH07XG4gIH1cblxuICBjb25zdCBwYXJ0cyA9IHBoeXNpY2FsSWQuc3BsaXQoJy8nKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMiAmJiBwYXJ0c1swXSAmJiBwYXJ0c1sxXSkge1xuICAgIHJldHVybiB7IGNsdXN0ZXI6IHBhcnRzWzBdLCBzZXJ2aWNlTmFtZTogcGFydHNbMV0gfTtcbiAgfVxuICBpZiAocGFydHMubGVuZ3RoID09PSAxICYmIHBhcnRzWzBdKSB7XG4gICAgcmV0dXJuIHsgc2VydmljZU5hbWU6IHBhcnRzWzBdIH07XG4gIH1cblxuICByZXR1cm4ge307XG59XG5cbi8qKlxuICogSWYgYSBTZXJ2aWNlVG9rZW4gaXMgYW4gYEZuOjpHZXRBdHRgIG9yIGBSZWZgIGludHJpbnNpYywgcmV0dXJuIHRoZSByZWZlcmVuY2VkIGxvZ2ljYWwgSUQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXJ2aWNlVG9rZW5SZWZlcmVuY2VkTG9naWNhbElkKHNlcnZpY2VUb2tlbjogYW55KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFzZXJ2aWNlVG9rZW4gfHwgdHlwZW9mIHNlcnZpY2VUb2tlbiAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGNvbnN0IGdldEF0dCA9IHNlcnZpY2VUb2tlblsnRm46OkdldEF0dCddO1xuICAvLyBBcnJheSBmb3JtIChKU09OIC8gQ0RLIG91dHB1dCk6IFtcIkxvZ2ljYWxJZFwiLCBcIkFyblwiXS5cbiAgaWYgKEFycmF5LmlzQXJyYXkoZ2V0QXR0KSAmJiB0eXBlb2YgZ2V0QXR0WzBdID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBnZXRBdHRbMF07XG4gIH1cbiAgLy8gU3RyaW5nIHNob3J0LWZvcm0gKGhvdyBZQU1MIGAhR2V0QXR0IExvZ2ljYWxJZC5Bcm5gIGRlc2VyaWFsaXplcyk6IFwiTG9naWNhbElkLkF0dHJcIi5cbiAgaWYgKHR5cGVvZiBnZXRBdHQgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGdldEF0dC5zcGxpdCgnLicpWzBdIHx8IHVuZGVmaW5lZDtcbiAgfVxuICBpZiAodHlwZW9mIHNlcnZpY2VUb2tlbi5SZWYgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHNlcnZpY2VUb2tlbi5SZWY7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGEgTGFtYmRhIGZ1bmN0aW9uIG5hbWUgZnJvbSBhIGZ1bmN0aW9uIEFSTiBvciBhIGJhcmUgbmFtZS5cbiAqXG4gKiBSZXR1cm5zIGB1bmRlZmluZWRgIGZvciBub24tTGFtYmRhIEFSTnMgKGUuZy4gYW4gU05TLXRvcGljIFNlcnZpY2VUb2tlbikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmdW5jdGlvbk5hbWVGcm9tQXJuT3JOYW1lKGFybk9yTmFtZTogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgYXJuTWF0Y2ggPSBhcm5Pck5hbWUubWF0Y2goL15hcm46W146XSs6bGFtYmRhOlteOl0qOlteOl0qOmZ1bmN0aW9uOihbXjpdKykvKTtcbiAgaWYgKGFybk1hdGNoKSB7XG4gICAgcmV0dXJuIGFybk1hdGNoWzFdO1xuICB9XG4gIGlmIChhcm5Pck5hbWUuc3RhcnRzV2l0aCgnYXJuOicpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gYXJuT3JOYW1lIHx8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBFeHRyYWN0IHRoZSBsb2cgc3RyZWFtIG5hbWUgb3V0IG9mIGEgY2ZuLXJlc3BvbnNlIGZhaWx1cmUgcmVhc29uXG4gKiAoXCJTZWUgdGhlIGRldGFpbHMgaW4gQ2xvdWRXYXRjaCBMb2cgU3RyZWFtOiA8bmFtZT5cIikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBleHRyYWN0TG9nU3RyZWFtTmFtZShtZXNzYWdlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBtYXRjaCA9IG1lc3NhZ2U/Lm1hdGNoKC9DbG91ZFdhdGNoIExvZyBTdHJlYW06XFxzKihcXFMrKS8pO1xuICByZXR1cm4gbWF0Y2ggPyBtYXRjaFsxXSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBjZm4tcmVzcG9uc2UgZGVmYXVsdHMgdGhlIHBoeXNpY2FsIElEIHRvIHRoZSBsb2cgc3RyZWFtIG5hbWUuIFVzZSBpdCBvbmx5IHdoZW4gaXQgbG9va3NcbiAqIGxpa2UgYSBMYW1iZGEgbG9nIHN0cmVhbSAoYFlZWVkvTU0vREQvLi4uYCksIHNvIGEgdXNlci1wcm92aWRlZCBwaHlzaWNhbCBJRCBpc24ndCBtaXN0YWtlblxuICogZm9yIG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvZ1N0cmVhbU5hbWVGcm9tUGh5c2ljYWxJZChwaHlzaWNhbElkOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gcGh5c2ljYWxJZCAmJiAvXlxcZHs0fVxcL1xcZHsyfVxcL1xcZHsyfVxcLy4rLy50ZXN0KHBoeXNpY2FsSWQpID8gcGh5c2ljYWxJZCA6IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGVjc1N0b3BwZWRUYXNrc0NvbnNvbGVVcmwocmVnaW9uOiBzdHJpbmcsIGNsdXN0ZXI6IHN0cmluZywgc2VydmljZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgaHR0cHM6Ly8ke3JlZ2lvbn0uY29uc29sZS5hd3MuYW1hem9uLmNvbS9lY3MvdjIvY2x1c3RlcnMvJHtjbHVzdGVyfS9zZXJ2aWNlcy8ke3NlcnZpY2VOYW1lfS90YXNrcz9zdGF0dXM9U1RPUFBFRCZyZWdpb249JHtyZWdpb259YDtcbn1cbiJdfQ==
@@ -1,21 +1,8 @@
1
+ import { type InvestigateOptions } from './investigate-ecs-service';
1
2
  import type { AdditionalDiagnosticContext } from '../../actions/diagnose';
2
3
  import type { SDK } from '../aws-auth/sdk';
3
4
  import type { ResourceError } from '../stack-events/resource-errors';
4
- /**
5
- * Options that influence how a resource is investigated.
6
- */
7
- export interface InvestigateOptions {
8
- /**
9
- * Whether CloudFormation rollback is enabled for this deployment.
10
- *
11
- * When rollback is enabled, a failed resource is torn down before we can
12
- * inspect its runtime state, so we may suggest re-running with `--no-rollback`
13
- * to retain that detail.
14
- *
15
- * @default true
16
- */
17
- readonly rollbackEnabled?: boolean;
18
- }
5
+ export type { InvestigateOptions };
19
6
  /**
20
7
  * Investigate a failed resource using AWS service APIs to gather additional root cause context.
21
8
  *
@@ -23,19 +10,4 @@ export interface InvestigateOptions {
23
10
  * investigation is not possible or yields no results for this resource type.
24
11
  */
25
12
  export declare function investigateResource(err: ResourceError, sdk: SDK, debug: (msg: string) => Promise<void>, options?: InvestigateOptions): Promise<AdditionalDiagnosticContext[]>;
26
- /**
27
- * Parse an ECS service physical resource ID into cluster and service identifiers.
28
- *
29
- * The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
30
- * accept either form for their `cluster` parameter, so this is fine downstream.
31
- *
32
- * Recognized formats:
33
- * - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
34
- * - Path: `cluster-name/service-name`
35
- * - Bare service name (uses the default cluster)
36
- */
37
- export declare function parseEcsServiceIdentifier(physicalId: string): {
38
- cluster?: string;
39
- serviceName?: string;
40
- };
41
13
  //# sourceMappingURL=resource-investigation.d.ts.map
@@ -1,14 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.investigateResource = investigateResource;
4
- exports.parseEcsServiceIdentifier = parseEcsServiceIdentifier;
5
- /**
6
- * Maximum number of log lines included per CloudWatch Logs context block.
7
- *
8
- * The formatter renders the messages array verbatim, so this is the
9
- * single user-visible cap.
10
- */
11
- const MAX_LOG_LINES = 50;
4
+ const investigate_custom_resource_1 = require("./investigate-custom-resource");
5
+ const investigate_ecs_service_1 = require("./investigate-ecs-service");
12
6
  /**
13
7
  * Investigate a failed resource using AWS service APIs to gather additional root cause context.
14
8
  *
@@ -16,287 +10,13 @@ const MAX_LOG_LINES = 50;
16
10
  * investigation is not possible or yields no results for this resource type.
17
11
  */
18
12
  async function investigateResource(err, sdk, debug, options = {}) {
19
- switch (err.resourceType) {
20
- case 'AWS::ECS::Service':
21
- return investigateEcsService(err, sdk, debug, options);
22
- default:
23
- return [];
24
- }
25
- }
26
- async function investigateEcsService(err, sdk, debug, options) {
27
- const physicalId = err.physicalId;
28
- if (!physicalId) {
29
- await debug('ECS investigation: no physical ID available');
30
- return [];
31
- }
32
- const { cluster, serviceName } = parseEcsServiceIdentifier(physicalId);
33
- if (!serviceName) {
34
- await debug(`ECS investigation: could not parse service identifier from "${physicalId}"`);
35
- return [];
36
- }
37
- const region = sdk.currentRegion;
38
- const ecs = sdk.ecs();
39
- const cwl = sdk.cloudWatchLogs();
40
- const service = await describeService(ecs, cluster, serviceName, debug);
41
- if (!service) {
42
- // The service is gone. The most common reason is that CloudFormation rolled the
43
- // deployment back and deleted it, taking the task/runtime detail with it. If rollback
44
- // was enabled, point the user at the flag that would have retained that detail.
45
- if (options.rollbackEnabled) {
46
- return [{
47
- source: 'ECS Service',
48
- messages: [
49
- 'The service and its tasks were removed during rollback, so container-level failure detail is unavailable.',
50
- 'Re-run the deployment with `--no-rollback` to retain the failed tasks and see why they stopped.',
51
- ],
52
- }];
53
- }
54
- return [];
55
- }
56
- const results = [];
57
- const stoppedTaskResult = await getStoppedTaskReasons(ecs, cluster, serviceName, region, service, debug);
58
- if (stoppedTaskResult.context) {
59
- results.push(stoppedTaskResult.context);
60
- }
61
- const taskDefinitionArn = service.taskDefinition;
62
- if (!taskDefinitionArn) {
63
- return results;
64
- }
65
- const taskDefInfo = await getTaskDefinitionInfo(ecs, taskDefinitionArn, debug);
66
- if (!taskDefInfo) {
67
- return results;
68
- }
69
- const logConfigs = taskDefInfo.logConfigs;
70
- if (logConfigs.length === 0) {
71
- results.push({
72
- source: 'CloudWatch Logs',
73
- messages: [
74
- 'No CloudWatch Logs configuration found. Enable logging to see container output on failure.',
75
- 'Example:',
76
- ' taskDefinition.addContainer("app", {',
77
- ' // ...',
78
- ' logging: ecs.LogDrivers.awsLogs({ streamPrefix: "my-service" }),',
79
- ' });',
80
- ],
81
- });
82
- return results;
13
+ const resourceType = err.resourceType ?? '';
14
+ if (resourceType === 'AWS::ECS::Service') {
15
+ return (0, investigate_ecs_service_1.investigateEcsService)(err, sdk, debug, options);
83
16
  }
84
- // `logConfigs` has one entry per container in the task definition that uses the awslogs
85
- // driver a handful at most — so this fan-out is bounded by the task shape and needs no
86
- // explicit concurrency limit.
87
- // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
88
- const logResults = await Promise.all(logConfigs.map(cfg => fetchRecentLogs(cwl, cfg, region, stoppedTaskResult.taskIds, debug)));
89
- const logContexts = logResults.filter((c) => c !== undefined);
90
- results.push(...logContexts);
91
- if (logContexts.length === 0) {
92
- results.push({
93
- source: 'CloudWatch Logs',
94
- messages: ['No CloudWatch Logs found.'],
95
- });
96
- }
97
- return results;
98
- }
99
- /**
100
- * Parse an ECS service physical resource ID into cluster and service identifiers.
101
- *
102
- * The cluster portion is a name (not an ARN) — `describeServices`/`describeTasks`
103
- * accept either form for their `cluster` parameter, so this is fine downstream.
104
- *
105
- * Recognized formats:
106
- * - Long ARN: `arn:aws:ecs:region:account:service/cluster-name/service-name` (current default)
107
- * - Path: `cluster-name/service-name`
108
- * - Bare service name (uses the default cluster)
109
- */
110
- function parseEcsServiceIdentifier(physicalId) {
111
- const arnMatch = physicalId.match(/^arn:[^:]+:ecs:[^:]*:[^:]*:service\/([^/]+)\/([^/]+)$/);
112
- if (arnMatch) {
113
- return { cluster: arnMatch[1], serviceName: arnMatch[2] };
114
- }
115
- const parts = physicalId.split('/');
116
- if (parts.length === 2 && parts[0] && parts[1]) {
117
- return { cluster: parts[0], serviceName: parts[1] };
118
- }
119
- if (parts.length === 1 && parts[0]) {
120
- return { serviceName: parts[0] };
121
- }
122
- return {};
123
- }
124
- async function describeService(ecs, cluster, serviceName, debug) {
125
- try {
126
- const resp = await ecs.describeServices({ cluster, services: [serviceName] });
127
- const service = resp.services?.[0];
128
- if (!service) {
129
- await debug(`ECS investigation: service "${serviceName}" not found`);
130
- }
131
- return service;
17
+ if (resourceType === 'AWS::CloudFormation::CustomResource' || resourceType.startsWith('Custom::')) {
18
+ return (0, investigate_custom_resource_1.investigateCustomResource)(err, sdk, debug);
132
19
  }
133
- catch (e) {
134
- await debug(`ECS investigation: failed to describe service: ${e.message}`);
135
- return undefined;
136
- }
137
- }
138
- async function getStoppedTaskReasons(ecs, cluster, serviceName, region, service, debug) {
139
- try {
140
- // Ask ECS for the service's stopped tasks. The IDs we need live in "has started 1 tasks: (task <id>)" events
141
- const taskIds = await listStoppedTaskIds(ecs, cluster, serviceName, debug);
142
- const messages = [];
143
- if (taskIds.length > 0) {
144
- // Show details from the most recently stopped task only.
145
- const tasksResp = await ecs.describeTasks({ cluster, tasks: [taskIds[0]] });
146
- const task = tasksResp.tasks?.[0];
147
- if (task) {
148
- if (task.stoppedReason) {
149
- messages.push(`Task stopped: ${task.stoppedReason}`);
150
- }
151
- for (const container of task.containers ?? []) {
152
- if (container.reason) {
153
- messages.push(`Container "${container.name}": ${container.reason}`);
154
- }
155
- if (container.exitCode != null && container.exitCode !== 0) {
156
- messages.push(`Container "${container.name}" exited with code ${container.exitCode}`);
157
- }
158
- }
159
- }
160
- if (messages.length > 0 && taskIds.length > 1) {
161
- messages.push(`(${taskIds.length - 1} other failed task(s) not shown)`);
162
- }
163
- }
164
- // Fall back to the most relevant service event if we couldn't get a task-level reason
165
- // (e.g. tasks already aged out, or no stopped tasks retained).
166
- if (messages.length === 0) {
167
- const failureEvent = (service.events ?? [])
168
- .find(e => e.message?.includes('stopped') || e.message?.includes('failed') || e.message?.includes('unhealthy'));
169
- if (failureEvent?.message) {
170
- messages.push(failureEvent.message);
171
- }
172
- }
173
- if (messages.length === 0) {
174
- return { taskIds };
175
- }
176
- return {
177
- context: {
178
- source: 'ECS Stopped Tasks',
179
- messages,
180
- link: ecsStoppedTasksConsoleUrl(region, cluster ?? 'default', serviceName),
181
- linkLabel: 'Tasks',
182
- },
183
- taskIds,
184
- };
185
- }
186
- catch (e) {
187
- await debug(`ECS investigation: failed to get stopped task reasons: ${e.message}`);
188
- return { taskIds: [] };
189
- }
190
- }
191
- /**
192
- * Maximum number of stopped task IDs to consider. We only render detail for the most
193
- * recent one, but keep a few so we can report how many others failed.
194
- */
195
- const MAX_STOPPED_TASKS = 3;
196
- /**
197
- * List the bare task IDs of the service's stopped tasks, newest first.
198
- *
199
- * Prefers scoping by service name; if that yields nothing (some ECS API versions only
200
- * apply the service filter to running tasks), falls back to listing the cluster's stopped
201
- * tasks. Returns an empty array if none are retained (e.g. they aged out, or rollback
202
- * already drained the cluster).
203
- */
204
- async function listStoppedTaskIds(ecs, cluster, serviceName, debug) {
205
- const toIds = (arns) => (arns ?? []).map(arn => arn.split('/').pop()).filter((id) => !!id);
206
- let arns;
207
- try {
208
- const byService = await ecs.listTasks({ cluster, serviceName, desiredStatus: 'STOPPED' });
209
- arns = byService.taskArns;
210
- if (!arns || arns.length === 0) {
211
- const byCluster = await ecs.listTasks({ cluster, desiredStatus: 'STOPPED' });
212
- arns = byCluster.taskArns;
213
- }
214
- }
215
- catch (e) {
216
- await debug(`ECS investigation: failed to list stopped tasks: ${e.message}`);
217
- return [];
218
- }
219
- return toIds(arns).slice(0, MAX_STOPPED_TASKS);
220
- }
221
- async function getTaskDefinitionInfo(ecs, taskDefinitionArn, debug) {
222
- try {
223
- const resp = await ecs.describeTaskDefinition({ taskDefinition: taskDefinitionArn });
224
- const containers = resp.taskDefinition?.containerDefinitions ?? [];
225
- const logConfigs = [];
226
- for (const container of containers) {
227
- const logConfig = container.logConfiguration;
228
- if (logConfig?.logDriver === 'awslogs') {
229
- const logGroup = logConfig.options?.['awslogs-group'];
230
- if (logGroup) {
231
- logConfigs.push({
232
- logGroup,
233
- streamPrefix: logConfig.options?.['awslogs-stream-prefix'],
234
- containerName: container.name,
235
- });
236
- }
237
- }
238
- }
239
- return { logConfigs };
240
- }
241
- catch (e) {
242
- await debug(`ECS investigation: failed to describe task definition: ${e.message}`);
243
- return undefined;
244
- }
245
- }
246
- async function fetchRecentLogs(cwl, logConfig, region, taskIds, debug) {
247
- try {
248
- // Target the most recently failed task's log stream for the most relevant output
249
- const lastTaskId = taskIds[0];
250
- const targetStream = (logConfig.streamPrefix && logConfig.containerName && lastTaskId)
251
- ? `${logConfig.streamPrefix}/${logConfig.containerName}/${lastTaskId}`
252
- : undefined;
253
- const resp = await cwl.filterLogEvents({
254
- logGroupName: logConfig.logGroup,
255
- startTime: Date.now() - 30 * 60 * 1000,
256
- limit: 1000,
257
- ...(targetStream
258
- ? { logStreamNames: [targetStream] }
259
- : logConfig.streamPrefix ? { logStreamNamePrefix: logConfig.streamPrefix } : {}),
260
- });
261
- const events = resp.events ?? [];
262
- if (events.length === 0) {
263
- await debug(`ECS investigation: no recent log events in ${logConfig.logGroup}${targetStream ? ` (targeted stream: ${targetStream})` : ''}`);
264
- return undefined;
265
- }
266
- // Keep the most recent lines (newer output is more useful for diagnosis).
267
- // This is the only truncation point — the formatter renders these verbatim.
268
- const allMessages = events
269
- .map(e => e.message?.trimEnd())
270
- .filter((m) => m != null);
271
- const messages = allMessages.slice(-MAX_LOG_LINES);
272
- const omitted = allMessages.length - messages.length;
273
- if (omitted > 0) {
274
- messages.unshift(`... (${omitted} earlier lines omitted)`);
275
- }
276
- if (taskIds.length > 1) {
277
- messages.push(`(showing logs from last failed task; ${taskIds.length - 1} other failed task(s) available in console)`);
278
- }
279
- const source = logConfig.containerName
280
- ? `CloudWatch Logs: ${logConfig.logGroup} (container: ${logConfig.containerName})`
281
- : `CloudWatch Logs: ${logConfig.logGroup}`;
282
- return {
283
- source,
284
- messages,
285
- link: cloudWatchLogsConsoleUrl(region, logConfig.logGroup),
286
- linkLabel: 'Logs',
287
- };
288
- }
289
- catch (e) {
290
- await debug(`ECS investigation: failed to fetch logs from ${logConfig.logGroup}: ${e.message}`);
291
- return undefined;
292
- }
293
- }
294
- // CloudWatch console uses double-URI-encoding with '$' replacing '%' for the log group in the fragment.
295
- function cloudWatchLogsConsoleUrl(region, logGroup) {
296
- const encodedLogGroup = encodeURIComponent(encodeURIComponent(logGroup)).replace(/%/g, '$');
297
- return `https://${region}.console.aws.amazon.com/cloudwatch/home?region=${region}#logsV2:log-groups/log-group/${encodedLogGroup}`;
298
- }
299
- function ecsStoppedTasksConsoleUrl(region, cluster, serviceName) {
300
- return `https://${region}.console.aws.amazon.com/ecs/v2/clusters/${cluster}/services/${serviceName}/tasks?status=STOPPED&region=${region}`;
20
+ return [];
301
21
  }
302
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtaW52ZXN0aWdhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc291cmNlLWludmVzdGlnYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFrQ0Esa0RBWUM7QUF3R0QsOERBZUM7QUFqS0Q7Ozs7O0dBS0c7QUFDSCxNQUFNLGFBQWEsR0FBRyxFQUFFLENBQUM7QUFrQnpCOzs7OztHQUtHO0FBQ0ksS0FBSyxVQUFVLG1CQUFtQixDQUN2QyxHQUFrQixFQUNsQixHQUFRLEVBQ1IsS0FBcUMsRUFDckMsVUFBOEIsRUFBRTtJQUVoQyxRQUFRLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN6QixLQUFLLG1CQUFtQjtZQUN0QixPQUFPLHFCQUFxQixDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pEO1lBQ0UsT0FBTyxFQUFFLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUVELEtBQUssVUFBVSxxQkFBcUIsQ0FDbEMsR0FBa0IsRUFDbEIsR0FBUSxFQUNSLEtBQXFDLEVBQ3JDLE9BQTJCO0lBRTNCLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUM7SUFDbEMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLE1BQU0sS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7UUFDM0QsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsR0FBRyx5QkFBeUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN2RSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDakIsTUFBTSxLQUFLLENBQUMsK0RBQStELFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDMUYsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQztJQUNqQyxNQUFNLEdBQUcsR0FB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Q0FBQyxvQkFBb0IsU0FBUyxDQUFDLFFBQVEsZ0JBQWdCLFNBQVMsQ0FBQyxhQUFhLEdBQUc7WUFDbEYsQ0FBQyxDQUFDLG9CQUFvQixTQUFTLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFN0MsT0FBTztZQUNMLE1BQU07WUFDTixRQUFRO1lBQ1IsSUFBSSxFQUFFLHdCQUF3QixDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsUUFBUSxDQUFDO1lBQzFELFNBQVMsRUFBRSxNQUFNO1NBQ2xCLENBQUM7SUFDSixDQUFDO0lBQUMsT0FBTyxDQUFNLEVBQUUsQ0FBQztRQUNoQixNQUFNLEtBQUssQ0FBQyxnREFBZ0QsU0FBUyxDQUFDLFFBQVEsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNoRyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0FBQ0gsQ0FBQztBQUVELHdHQUF3RztBQUN4RyxTQUFTLHdCQUF3QixDQUFDLE1BQWMsRUFBRSxRQUFnQjtJQUNoRSxNQUFNLGVBQWUsR0FBRyxrQkFBa0IsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDNUYsT0FBTyxXQUFXLE1BQU0sa0RBQWtELE1BQU0sZ0NBQWdDLGVBQWUsRUFBRSxDQUFDO0FBQ3BJLENBQUM7QUFFRCxTQUFTLHlCQUF5QixDQUFDLE1BQWMsRUFBRSxPQUFlLEVBQUUsV0FBbUI7SUFDckYsT0FBTyxXQUFXLE1BQU0sMkNBQTJDLE9BQU8sYUFBYSxXQUFXLGdDQUFnQyxNQUFNLEVBQUUsQ0FBQztBQUM3SSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHQgfSBmcm9tICcuLi8uLi9hY3Rpb25zL2RpYWdub3NlJztcbmltcG9ydCB0eXBlIHsgSUNsb3VkV2F0Y2hMb2dzQ2xpZW50LCBJRUNTQ2xpZW50LCBTREsgfSBmcm9tICcuLi9hd3MtYXV0aC9zZGsnO1xuaW1wb3J0IHR5cGUgeyBSZXNvdXJjZUVycm9yIH0gZnJvbSAnLi4vc3RhY2stZXZlbnRzL3Jlc291cmNlLWVycm9ycyc7XG5cbi8qKlxuICogTWF4aW11bSBudW1iZXIgb2YgbG9nIGxpbmVzIGluY2x1ZGVkIHBlciBDbG91ZFdhdGNoIExvZ3MgY29udGV4dCBibG9jay5cbiAqXG4gKiBUaGUgZm9ybWF0dGVyIHJlbmRlcnMgdGhlIG1lc3NhZ2VzIGFycmF5IHZlcmJhdGltLCBzbyB0aGlzIGlzIHRoZVxuICogc2luZ2xlIHVzZXItdmlzaWJsZSBjYXAuXG4gKi9cbmNvbnN0IE1BWF9MT0dfTElORVMgPSA1MDtcblxuLyoqXG4gKiBPcHRpb25zIHRoYXQgaW5mbHVlbmNlIGhvdyBhIHJlc291cmNlIGlzIGludmVzdGlnYXRlZC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbnZlc3RpZ2F0ZU9wdGlvbnMge1xuICAvKipcbiAgICogV2hldGhlciBDbG91ZEZvcm1hdGlvbiByb2xsYmFjayBpcyBlbmFibGVkIGZvciB0aGlzIGRlcGxveW1lbnQuXG4gICAqXG4gICAqIFdoZW4gcm9sbGJhY2sgaXMgZW5hYmxlZCwgYSBmYWlsZWQgcmVzb3VyY2UgaXMgdG9ybiBkb3duIGJlZm9yZSB3ZSBjYW5cbiAgICogaW5zcGVjdCBpdHMgcnVudGltZSBzdGF0ZSwgc28gd2UgbWF5IHN1Z2dlc3QgcmUtcnVubmluZyB3aXRoIGAtLW5vLXJvbGxiYWNrYFxuICAgKiB0byByZXRhaW4gdGhhdCBkZXRhaWwuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHJvbGxiYWNrRW5hYmxlZD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogSW52ZXN0aWdhdGUgYSBmYWlsZWQgcmVzb3VyY2UgdXNpbmcgQVdTIHNlcnZpY2UgQVBJcyB0byBnYXRoZXIgYWRkaXRpb25hbCByb290IGNhdXNlIGNvbnRleHQuXG4gKlxuICogUmV0dXJucyBhZGRpdGlvbmFsIGRpYWdub3N0aWMgY29udGV4dCAoZS5nLiBsb2cgbGluZXMpIG9yIGFuIGVtcHR5IGFycmF5IGlmXG4gKiBpbnZlc3RpZ2F0aW9uIGlzIG5vdCBwb3NzaWJsZSBvciB5aWVsZHMgbm8gcmVzdWx0cyBmb3IgdGhpcyByZXNvdXJjZSB0eXBlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gaW52ZXN0aWdhdGVSZXNvdXJjZShcbiAgZXJyOiBSZXNvdXJjZUVycm9yLFxuICBzZGs6IFNESyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbiAgb3B0aW9uczogSW52ZXN0aWdhdGVPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPEFkZGl0aW9uYWxEaWFnbm9zdGljQ29udGV4dFtdPiB7XG4gIHN3aXRjaCAoZXJyLnJlc291cmNlVHlwZSkge1xuICAgIGNhc2UgJ0FXUzo6RUNTOjpTZXJ2aWNlJzpcbiAgICAgIHJldHVybiBpbnZlc3RpZ2F0ZUVjc1NlcnZpY2UoZXJyLCBzZGssIGRlYnVnLCBvcHRpb25zKTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIFtdO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGludmVzdGlnYXRlRWNzU2VydmljZShcbiAgZXJyOiBSZXNvdXJjZUVycm9yLFxuICBzZGs6IFNESyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbiAgb3B0aW9uczogSW52ZXN0aWdhdGVPcHRpb25zLFxuKTogUHJvbWlzZTxBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHRbXT4ge1xuICBjb25zdCBwaHlzaWNhbElkID0gZXJyLnBoeXNpY2FsSWQ7XG4gIGlmICghcGh5c2ljYWxJZCkge1xuICAgIGF3YWl0IGRlYnVnKCdFQ1MgaW52ZXN0aWdhdGlvbjogbm8gcGh5c2ljYWwgSUQgYXZhaWxhYmxlJyk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgeyBjbHVzdGVyLCBzZXJ2aWNlTmFtZSB9ID0gcGFyc2VFY3NTZXJ2aWNlSWRlbnRpZmllcihwaHlzaWNhbElkKTtcbiAgaWYgKCFzZXJ2aWNlTmFtZSkge1xuICAgIGF3YWl0IGRlYnVnKGBFQ1MgaW52ZXN0aWdhdGlvbjogY291bGQgbm90IHBhcnNlIHNlcnZpY2UgaWRlbnRpZmllciBmcm9tIFwiJHtwaHlzaWNhbElkfVwiYCk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgcmVnaW9uID0gc2RrLmN1cnJlbnRSZWdpb247XG4gIGNvbnN0IGVjcyA9IHNkay5lY3MoKTtcbiAgY29uc3QgY3dsID0gc2RrLmNsb3VkV2F0Y2hMb2dzKCk7XG5cbiAgY29uc3Qgc2VydmljZSA9IGF3YWl0IGRlc2NyaWJlU2VydmljZShlY3MsIGNsdXN0ZXIsIHNlcnZpY2VOYW1lLCBkZWJ1Zyk7XG4gIGlmICghc2VydmljZSkge1xuICAgIC8vIFRoZSBzZXJ2aWNlIGlzIGdvbmUuIFRoZSBtb3N0IGNvbW1vbiByZWFzb24gaXMgdGhhdCBDbG91ZEZvcm1hdGlvbiByb2xsZWQgdGhlXG4gICAgLy8gZGVwbG95bWVudCBiYWNrIGFuZCBkZWxldGVkIGl0LCB0YWtpbmcgdGhlIHRhc2svcnVudGltZSBkZXRhaWwgd2l0aCBpdC4gSWYgcm9sbGJhY2tcbiAgICAvLyB3YXMgZW5hYmxlZCwgcG9pbnQgdGhlIHVzZXIgYXQgdGhlIGZsYWcgdGhhdCB3b3VsZCBoYXZlIHJldGFpbmVkIHRoYXQgZGV0YWlsLlxuICAgIGlmIChvcHRpb25zLnJvbGxiYWNrRW5hYmxlZCkge1xuICAgICAgcmV0dXJuIFt7XG4gICAgICAgIHNvdXJjZTogJ0VDUyBTZXJ2aWNlJyxcbiAgICAgICAgbWVzc2FnZXM6IFtcbiAgICAgICAgICAnVGhlIHNlcnZpY2UgYW5kIGl0cyB0YXNrcyB3ZXJlIHJlbW92ZWQgZHVyaW5nIHJvbGxiYWNrLCBzbyBjb250YWluZXItbGV2ZWwgZmFpbHVyZSBkZXRhaWwgaXMgdW5hdmFpbGFibGUuJyxcbiAgICAgICAgICAnUmUtcnVuIHRoZSBkZXBsb3ltZW50IHdpdGggYC0tbm8tcm9sbGJhY2tgIHRvIHJldGFpbiB0aGUgZmFpbGVkIHRhc2tzIGFuZCBzZWUgd2h5IHRoZXkgc3RvcHBlZC4nLFxuICAgICAgICBdLFxuICAgICAgfV07XG4gICAgfVxuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIGNvbnN0IHJlc3VsdHM6IEFkZGl0aW9uYWxEaWFnbm9zdGljQ29udGV4dFtdID0gW107XG5cbiAgY29uc3Qgc3RvcHBlZFRhc2tSZXN1bHQgPSBhd2FpdCBnZXRTdG9wcGVkVGFza1JlYXNvbnMoZWNzLCBjbHVzdGVyLCBzZXJ2aWNlTmFtZSwgcmVnaW9uLCBzZXJ2aWNlLCBkZWJ1Zyk7XG4gIGlmIChzdG9wcGVkVGFza1Jlc3VsdC5jb250ZXh0KSB7XG4gICAgcmVzdWx0cy5wdXNoKHN0b3BwZWRUYXNrUmVzdWx0LmNvbnRleHQpO1xuICB9XG5cbiAgY29uc3QgdGFza0RlZmluaXRpb25Bcm4gPSBzZXJ2aWNlLnRhc2tEZWZpbml0aW9uO1xuICBpZiAoIXRhc2tEZWZpbml0aW9uQXJuKSB7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cblxuICBjb25zdCB0YXNrRGVmSW5mbyA9IGF3YWl0IGdldFRhc2tEZWZpbml0aW9uSW5mbyhlY3MsIHRhc2tEZWZpbml0aW9uQXJuLCBkZWJ1Zyk7XG4gIGlmICghdGFza0RlZkluZm8pIHtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIGNvbnN0IGxvZ0NvbmZpZ3MgPSB0YXNrRGVmSW5mby5sb2dDb25maWdzO1xuXG4gIGlmIChsb2dDb25maWdzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICBzb3VyY2U6ICdDbG91ZFdhdGNoIExvZ3MnLFxuICAgICAgbWVzc2FnZXM6IFtcbiAgICAgICAgJ05vIENsb3VkV2F0Y2ggTG9ncyBjb25maWd1cmF0aW9uIGZvdW5kLiBFbmFibGUgbG9nZ2luZyB0byBzZWUgY29udGFpbmVyIG91dHB1dCBvbiBmYWlsdXJlLicsXG4gICAgICAgICdFeGFtcGxlOicsXG4gICAgICAgICcgIHRhc2tEZWZpbml0aW9uLmFkZENvbnRhaW5lcihcImFwcFwiLCB7JyxcbiAgICAgICAgJyAgICAvLyAuLi4nLFxuICAgICAgICAnICAgIGxvZ2dpbmc6IGVjcy5Mb2dEcml2ZXJzLmF3c0xvZ3MoeyBzdHJlYW1QcmVmaXg6IFwibXktc2VydmljZVwiIH0pLCcsXG4gICAgICAgICcgIH0pOycsXG4gICAgICBdLFxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9XG5cbiAgLy8gYGxvZ0NvbmZpZ3NgIGhhcyBvbmUgZW50cnkgcGVyIGNvbnRhaW5lciBpbiB0aGUgdGFzayBkZWZpbml0aW9uIHRoYXQgdXNlcyB0aGUgYXdzbG9nc1xuICAvLyBkcml2ZXIg4oCUIGEgaGFuZGZ1bCBhdCBtb3N0IOKAlCBzbyB0aGlzIGZhbi1vdXQgaXMgYm91bmRlZCBieSB0aGUgdGFzayBzaGFwZSBhbmQgbmVlZHMgbm9cbiAgLy8gZXhwbGljaXQgY29uY3VycmVuY3kgbGltaXQuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAY2RrbGFicy9wcm9taXNlYWxsLW5vLXVuYm91bmRlZC1wYXJhbGxlbGlzbVxuICBjb25zdCBsb2dSZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwobG9nQ29uZmlncy5tYXAoY2ZnID0+IGZldGNoUmVjZW50TG9ncyhjd2wsIGNmZywgcmVnaW9uLCBzdG9wcGVkVGFza1Jlc3VsdC50YXNrSWRzLCBkZWJ1ZykpKTtcbiAgY29uc3QgbG9nQ29udGV4dHMgPSBsb2dSZXN1bHRzLmZpbHRlcigoYyk6IGMgaXMgQWRkaXRpb25hbERpYWdub3N0aWNDb250ZXh0ID0+IGMgIT09IHVuZGVmaW5lZCk7XG5cbiAgcmVzdWx0cy5wdXNoKC4uLmxvZ0NvbnRleHRzKTtcbiAgaWYgKGxvZ0NvbnRleHRzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJlc3VsdHMucHVzaCh7XG4gICAgICBzb3VyY2U6ICdDbG91ZFdhdGNoIExvZ3MnLFxuICAgICAgbWVzc2FnZXM6IFsnTm8gQ2xvdWRXYXRjaCBMb2dzIGZvdW5kLiddLFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdHM7XG59XG5cbi8qKlxuICogUGFyc2UgYW4gRUNTIHNlcnZpY2UgcGh5c2ljYWwgcmVzb3VyY2UgSUQgaW50byBjbHVzdGVyIGFuZCBzZXJ2aWNlIGlkZW50aWZpZXJzLlxuICpcbiAqIFRoZSBjbHVzdGVyIHBvcnRpb24gaXMgYSBuYW1lIChub3QgYW4gQVJOKSDigJQgYGRlc2NyaWJlU2VydmljZXNgL2BkZXNjcmliZVRhc2tzYFxuICogYWNjZXB0IGVpdGhlciBmb3JtIGZvciB0aGVpciBgY2x1c3RlcmAgcGFyYW1ldGVyLCBzbyB0aGlzIGlzIGZpbmUgZG93bnN0cmVhbS5cbiAqXG4gKiBSZWNvZ25pemVkIGZvcm1hdHM6XG4gKiAtIExvbmcgQVJOOiBgYXJuOmF3czplY3M6cmVnaW9uOmFjY291bnQ6c2VydmljZS9jbHVzdGVyLW5hbWUvc2VydmljZS1uYW1lYCAoY3VycmVudCBkZWZhdWx0KVxuICogLSBQYXRoOiBgY2x1c3Rlci1uYW1lL3NlcnZpY2UtbmFtZWBcbiAqIC0gQmFyZSBzZXJ2aWNlIG5hbWUgKHVzZXMgdGhlIGRlZmF1bHQgY2x1c3RlcilcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlRWNzU2VydmljZUlkZW50aWZpZXIocGh5c2ljYWxJZDogc3RyaW5nKTogeyBjbHVzdGVyPzogc3RyaW5nOyBzZXJ2aWNlTmFtZT86IHN0cmluZyB9IHtcbiAgY29uc3QgYXJuTWF0Y2ggPSBwaHlzaWNhbElkLm1hdGNoKC9eYXJuOlteOl0rOmVjczpbXjpdKjpbXjpdKjpzZXJ2aWNlXFwvKFteL10rKVxcLyhbXi9dKykkLyk7XG4gIGlmIChhcm5NYXRjaCkge1xuICAgIHJldHVybiB7IGNsdXN0ZXI6IGFybk1hdGNoWzFdLCBzZXJ2aWNlTmFtZTogYXJuTWF0Y2hbMl0gfTtcbiAgfVxuXG4gIGNvbnN0IHBhcnRzID0gcGh5c2ljYWxJZC5zcGxpdCgnLycpO1xuICBpZiAocGFydHMubGVuZ3RoID09PSAyICYmIHBhcnRzWzBdICYmIHBhcnRzWzFdKSB7XG4gICAgcmV0dXJuIHsgY2x1c3RlcjogcGFydHNbMF0sIHNlcnZpY2VOYW1lOiBwYXJ0c1sxXSB9O1xuICB9XG4gIGlmIChwYXJ0cy5sZW5ndGggPT09IDEgJiYgcGFydHNbMF0pIHtcbiAgICByZXR1cm4geyBzZXJ2aWNlTmFtZTogcGFydHNbMF0gfTtcbiAgfVxuXG4gIHJldHVybiB7fTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZGVzY3JpYmVTZXJ2aWNlKFxuICBlY3M6IElFQ1NDbGllbnQsXG4gIGNsdXN0ZXI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgc2VydmljZU5hbWU6IHN0cmluZyxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbikge1xuICB0cnkge1xuICAgIGNvbnN0IHJlc3AgPSBhd2FpdCBlY3MuZGVzY3JpYmVTZXJ2aWNlcyh7IGNsdXN0ZXIsIHNlcnZpY2VzOiBbc2VydmljZU5hbWVdIH0pO1xuICAgIGNvbnN0IHNlcnZpY2UgPSByZXNwLnNlcnZpY2VzPy5bMF07XG4gICAgaWYgKCFzZXJ2aWNlKSB7XG4gICAgICBhd2FpdCBkZWJ1ZyhgRUNTIGludmVzdGlnYXRpb246IHNlcnZpY2UgXCIke3NlcnZpY2VOYW1lfVwiIG5vdCBmb3VuZGApO1xuICAgIH1cbiAgICByZXR1cm4gc2VydmljZTtcbiAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgYXdhaXQgZGVidWcoYEVDUyBpbnZlc3RpZ2F0aW9uOiBmYWlsZWQgdG8gZGVzY3JpYmUgc2VydmljZTogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgU3RvcHBlZFRhc2tSZXN1bHQge1xuICBjb250ZXh0PzogQWRkaXRpb25hbERpYWdub3N0aWNDb250ZXh0O1xuICB0YXNrSWRzOiBzdHJpbmdbXTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0U3RvcHBlZFRhc2tSZWFzb25zKFxuICBlY3M6IElFQ1NDbGllbnQsXG4gIGNsdXN0ZXI6IHN0cmluZyB8IHVuZGVmaW5lZCxcbiAgc2VydmljZU5hbWU6IHN0cmluZyxcbiAgcmVnaW9uOiBzdHJpbmcsXG4gIHNlcnZpY2U6IHsgZXZlbnRzPzogQXJyYXk8eyBtZXNzYWdlPzogc3RyaW5nIH0+OyBba2V5OiBzdHJpbmddOiBhbnkgfSxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8U3RvcHBlZFRhc2tSZXN1bHQ+IHtcbiAgdHJ5IHtcbiAgICAvLyBBc2sgRUNTIGZvciB0aGUgc2VydmljZSdzIHN0b3BwZWQgdGFza3MuIFRoZSBJRHMgd2UgbmVlZCBsaXZlIGluIFwiaGFzIHN0YXJ0ZWQgMSB0YXNrczogKHRhc2sgPGlkPilcIiBldmVudHNcbiAgICBjb25zdCB0YXNrSWRzID0gYXdhaXQgbGlzdFN0b3BwZWRUYXNrSWRzKGVjcywgY2x1c3Rlciwgc2VydmljZU5hbWUsIGRlYnVnKTtcblxuICAgIGNvbnN0IG1lc3NhZ2VzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKHRhc2tJZHMubGVuZ3RoID4gMCkge1xuICAgICAgLy8gU2hvdyBkZXRhaWxzIGZyb20gdGhlIG1vc3QgcmVjZW50bHkgc3RvcHBlZCB0YXNrIG9ubHkuXG4gICAgICBjb25zdCB0YXNrc1Jlc3AgPSBhd2FpdCBlY3MuZGVzY3JpYmVUYXNrcyh7IGNsdXN0ZXIsIHRhc2tzOiBbdGFza0lkc1swXV0gfSk7XG4gICAgICBjb25zdCB0YXNrID0gdGFza3NSZXNwLnRhc2tzPy5bMF07XG4gICAgICBpZiAodGFzaykge1xuICAgICAgICBpZiAodGFzay5zdG9wcGVkUmVhc29uKSB7XG4gICAgICAgICAgbWVzc2FnZXMucHVzaChgVGFzayBzdG9wcGVkOiAke3Rhc2suc3RvcHBlZFJlYXNvbn1gKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGNvbnN0IGNvbnRhaW5lciBvZiB0YXNrLmNvbnRhaW5lcnMgPz8gW10pIHtcbiAgICAgICAgICBpZiAoY29udGFpbmVyLnJlYXNvbikge1xuICAgICAgICAgICAgbWVzc2FnZXMucHVzaChgQ29udGFpbmVyIFwiJHtjb250YWluZXIubmFtZX1cIjogJHtjb250YWluZXIucmVhc29ufWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoY29udGFpbmVyLmV4aXRDb2RlICE9IG51bGwgJiYgY29udGFpbmVyLmV4aXRDb2RlICE9PSAwKSB7XG4gICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGBDb250YWluZXIgXCIke2NvbnRhaW5lci5uYW1lfVwiIGV4aXRlZCB3aXRoIGNvZGUgJHtjb250YWluZXIuZXhpdENvZGV9YCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAobWVzc2FnZXMubGVuZ3RoID4gMCAmJiB0YXNrSWRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgbWVzc2FnZXMucHVzaChgKCR7dGFza0lkcy5sZW5ndGggLSAxfSBvdGhlciBmYWlsZWQgdGFzayhzKSBub3Qgc2hvd24pYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRmFsbCBiYWNrIHRvIHRoZSBtb3N0IHJlbGV2YW50IHNlcnZpY2UgZXZlbnQgaWYgd2UgY291bGRuJ3QgZ2V0IGEgdGFzay1sZXZlbCByZWFzb25cbiAgICAvLyAoZS5nLiB0YXNrcyBhbHJlYWR5IGFnZWQgb3V0LCBvciBubyBzdG9wcGVkIHRhc2tzIHJldGFpbmVkKS5cbiAgICBpZiAobWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zdCBmYWlsdXJlRXZlbnQgPSAoc2VydmljZS5ldmVudHMgPz8gW10pXG4gICAgICAgIC5maW5kKGUgPT4gZS5tZXNzYWdlPy5pbmNsdWRlcygnc3RvcHBlZCcpIHx8IGUubWVzc2FnZT8uaW5jbHVkZXMoJ2ZhaWxlZCcpIHx8IGUubWVzc2FnZT8uaW5jbHVkZXMoJ3VuaGVhbHRoeScpKTtcbiAgICAgIGlmIChmYWlsdXJlRXZlbnQ/Lm1lc3NhZ2UpIHtcbiAgICAgICAgbWVzc2FnZXMucHVzaChmYWlsdXJlRXZlbnQubWVzc2FnZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHsgdGFza0lkcyB9O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBjb250ZXh0OiB7XG4gICAgICAgIHNvdXJjZTogJ0VDUyBTdG9wcGVkIFRhc2tzJyxcbiAgICAgICAgbWVzc2FnZXMsXG4gICAgICAgIGxpbms6IGVjc1N0b3BwZWRUYXNrc0NvbnNvbGVVcmwocmVnaW9uLCBjbHVzdGVyID8/ICdkZWZhdWx0Jywgc2VydmljZU5hbWUpLFxuICAgICAgICBsaW5rTGFiZWw6ICdUYXNrcycsXG4gICAgICB9LFxuICAgICAgdGFza0lkcyxcbiAgICB9O1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICBhd2FpdCBkZWJ1ZyhgRUNTIGludmVzdGlnYXRpb246IGZhaWxlZCB0byBnZXQgc3RvcHBlZCB0YXNrIHJlYXNvbnM6ICR7ZS5tZXNzYWdlfWApO1xuICAgIHJldHVybiB7IHRhc2tJZHM6IFtdIH07XG4gIH1cbn1cblxuLyoqXG4gKiBNYXhpbXVtIG51bWJlciBvZiBzdG9wcGVkIHRhc2sgSURzIHRvIGNvbnNpZGVyLiBXZSBvbmx5IHJlbmRlciBkZXRhaWwgZm9yIHRoZSBtb3N0XG4gKiByZWNlbnQgb25lLCBidXQga2VlcCBhIGZldyBzbyB3ZSBjYW4gcmVwb3J0IGhvdyBtYW55IG90aGVycyBmYWlsZWQuXG4gKi9cbmNvbnN0IE1BWF9TVE9QUEVEX1RBU0tTID0gMztcblxuLyoqXG4gKiBMaXN0IHRoZSBiYXJlIHRhc2sgSURzIG9mIHRoZSBzZXJ2aWNlJ3Mgc3RvcHBlZCB0YXNrcywgbmV3ZXN0IGZpcnN0LlxuICpcbiAqIFByZWZlcnMgc2NvcGluZyBieSBzZXJ2aWNlIG5hbWU7IGlmIHRoYXQgeWllbGRzIG5vdGhpbmcgKHNvbWUgRUNTIEFQSSB2ZXJzaW9ucyBvbmx5XG4gKiBhcHBseSB0aGUgc2VydmljZSBmaWx0ZXIgdG8gcnVubmluZyB0YXNrcyksIGZhbGxzIGJhY2sgdG8gbGlzdGluZyB0aGUgY2x1c3RlcidzIHN0b3BwZWRcbiAqIHRhc2tzLiBSZXR1cm5zIGFuIGVtcHR5IGFycmF5IGlmIG5vbmUgYXJlIHJldGFpbmVkIChlLmcuIHRoZXkgYWdlZCBvdXQsIG9yIHJvbGxiYWNrXG4gKiBhbHJlYWR5IGRyYWluZWQgdGhlIGNsdXN0ZXIpLlxuICovXG5hc3luYyBmdW5jdGlvbiBsaXN0U3RvcHBlZFRhc2tJZHMoXG4gIGVjczogSUVDU0NsaWVudCxcbiAgY2x1c3Rlcjogc3RyaW5nIHwgdW5kZWZpbmVkLFxuICBzZXJ2aWNlTmFtZTogc3RyaW5nLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCB0b0lkcyA9IChhcm5zOiBzdHJpbmdbXSB8IHVuZGVmaW5lZCkgPT4gKGFybnMgPz8gW10pLm1hcChhcm4gPT4gYXJuLnNwbGl0KCcvJykucG9wKCkpLmZpbHRlcigoaWQpOiBpZCBpcyBzdHJpbmcgPT4gISFpZCk7XG5cbiAgbGV0IGFybnM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkO1xuICB0cnkge1xuICAgIGNvbnN0IGJ5U2VydmljZSA9IGF3YWl0IGVjcy5saXN0VGFza3MoeyBjbHVzdGVyLCBzZXJ2aWNlTmFtZSwgZGVzaXJlZFN0YXR1czogJ1NUT1BQRUQnIH0pO1xuICAgIGFybnMgPSBieVNlcnZpY2UudGFza0FybnM7XG4gICAgaWYgKCFhcm5zIHx8IGFybnMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zdCBieUNsdXN0ZXIgPSBhd2FpdCBlY3MubGlzdFRhc2tzKHsgY2x1c3RlciwgZGVzaXJlZFN0YXR1czogJ1NUT1BQRUQnIH0pO1xuICAgICAgYXJucyA9IGJ5Q2x1c3Rlci50YXNrQXJucztcbiAgICB9XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIGF3YWl0IGRlYnVnKGBFQ1MgaW52ZXN0aWdhdGlvbjogZmFpbGVkIHRvIGxpc3Qgc3RvcHBlZCB0YXNrczogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcmV0dXJuIHRvSWRzKGFybnMpLnNsaWNlKDAsIE1BWF9TVE9QUEVEX1RBU0tTKTtcbn1cblxuaW50ZXJmYWNlIEF3c0xvZ3NDb25maWcge1xuICBsb2dHcm91cDogc3RyaW5nO1xuICBzdHJlYW1QcmVmaXg/OiBzdHJpbmc7XG4gIGNvbnRhaW5lck5hbWU/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBUYXNrRGVmaW5pdGlvbkluZm8ge1xuICBsb2dDb25maWdzOiBBd3NMb2dzQ29uZmlnW107XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFRhc2tEZWZpbml0aW9uSW5mbyhcbiAgZWNzOiBJRUNTQ2xpZW50LFxuICB0YXNrRGVmaW5pdGlvbkFybjogc3RyaW5nLFxuICBkZWJ1ZzogKG1zZzogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+LFxuKTogUHJvbWlzZTxUYXNrRGVmaW5pdGlvbkluZm8gfCB1bmRlZmluZWQ+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXNwID0gYXdhaXQgZWNzLmRlc2NyaWJlVGFza0RlZmluaXRpb24oeyB0YXNrRGVmaW5pdGlvbjogdGFza0RlZmluaXRpb25Bcm4gfSk7XG4gICAgY29uc3QgY29udGFpbmVycyA9IHJlc3AudGFza0RlZmluaXRpb24/LmNvbnRhaW5lckRlZmluaXRpb25zID8/IFtdO1xuICAgIGNvbnN0IGxvZ0NvbmZpZ3M6IEF3c0xvZ3NDb25maWdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgY29udGFpbmVyIG9mIGNvbnRhaW5lcnMpIHtcbiAgICAgIGNvbnN0IGxvZ0NvbmZpZyA9IGNvbnRhaW5lci5sb2dDb25maWd1cmF0aW9uO1xuICAgICAgaWYgKGxvZ0NvbmZpZz8ubG9nRHJpdmVyID09PSAnYXdzbG9ncycpIHtcbiAgICAgICAgY29uc3QgbG9nR3JvdXAgPSBsb2dDb25maWcub3B0aW9ucz8uWydhd3Nsb2dzLWdyb3VwJ107XG4gICAgICAgIGlmIChsb2dHcm91cCkge1xuICAgICAgICAgIGxvZ0NvbmZpZ3MucHVzaCh7XG4gICAgICAgICAgICBsb2dHcm91cCxcbiAgICAgICAgICAgIHN0cmVhbVByZWZpeDogbG9nQ29uZmlnLm9wdGlvbnM/LlsnYXdzbG9ncy1zdHJlYW0tcHJlZml4J10sXG4gICAgICAgICAgICBjb250YWluZXJOYW1lOiBjb250YWluZXIubmFtZSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4geyBsb2dDb25maWdzIH07XG4gIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgIGF3YWl0IGRlYnVnKGBFQ1MgaW52ZXN0aWdhdGlvbjogZmFpbGVkIHRvIGRlc2NyaWJlIHRhc2sgZGVmaW5pdGlvbjogJHtlLm1lc3NhZ2V9YCk7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBmZXRjaFJlY2VudExvZ3MoXG4gIGN3bDogSUNsb3VkV2F0Y2hMb2dzQ2xpZW50LFxuICBsb2dDb25maWc6IEF3c0xvZ3NDb25maWcsXG4gIHJlZ2lvbjogc3RyaW5nLFxuICB0YXNrSWRzOiBzdHJpbmdbXSxcbiAgZGVidWc6IChtc2c6IHN0cmluZykgPT4gUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8QWRkaXRpb25hbERpYWdub3N0aWNDb250ZXh0IHwgdW5kZWZpbmVkPiB7XG4gIHRyeSB7XG4gICAgLy8gVGFyZ2V0IHRoZSBtb3N0IHJlY2VudGx5IGZhaWxlZCB0YXNrJ3MgbG9nIHN0cmVhbSBmb3IgdGhlIG1vc3QgcmVsZXZhbnQgb3V0cHV0XG4gICAgY29uc3QgbGFzdFRhc2tJZCA9IHRhc2tJZHNbMF07XG4gICAgY29uc3QgdGFyZ2V0U3RyZWFtID0gKGxvZ0NvbmZpZy5zdHJlYW1QcmVmaXggJiYgbG9nQ29uZmlnLmNvbnRhaW5lck5hbWUgJiYgbGFzdFRhc2tJZClcbiAgICAgID8gYCR7bG9nQ29uZmlnLnN0cmVhbVByZWZpeH0vJHtsb2dDb25maWcuY29udGFpbmVyTmFtZX0vJHtsYXN0VGFza0lkfWBcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgcmVzcCA9IGF3YWl0IGN3bC5maWx0ZXJMb2dFdmVudHMoe1xuICAgICAgbG9nR3JvdXBOYW1lOiBsb2dDb25maWcubG9nR3JvdXAsXG4gICAgICBzdGFydFRpbWU6IERhdGUubm93KCkgLSAzMCAqIDYwICogMTAwMCxcbiAgICAgIGxpbWl0OiAxMDAwLFxuICAgICAgLi4uKHRhcmdldFN0cmVhbVxuICAgICAgICA/IHsgbG9nU3RyZWFtTmFtZXM6IFt0YXJnZXRTdHJlYW1dIH1cbiAgICAgICAgOiBsb2dDb25maWcuc3RyZWFtUHJlZml4ID8geyBsb2dTdHJlYW1OYW1lUHJlZml4OiBsb2dDb25maWcuc3RyZWFtUHJlZml4IH0gOiB7fSksXG4gICAgfSk7XG5cbiAgICBjb25zdCBldmVudHMgPSByZXNwLmV2ZW50cyA/PyBbXTtcbiAgICBpZiAoZXZlbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgYXdhaXQgZGVidWcoYEVDUyBpbnZlc3RpZ2F0aW9uOiBubyByZWNlbnQgbG9nIGV2ZW50cyBpbiAke2xvZ0NvbmZpZy5sb2dHcm91cH0ke3RhcmdldFN0cmVhbSA/IGAgKHRhcmdldGVkIHN0cmVhbTogJHt0YXJnZXRTdHJlYW19KWAgOiAnJ31gKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLy8gS2VlcCB0aGUgbW9zdCByZWNlbnQgbGluZXMgKG5ld2VyIG91dHB1dCBpcyBtb3JlIHVzZWZ1bCBmb3IgZGlhZ25vc2lzKS5cbiAgICAvLyBUaGlzIGlzIHRoZSBvbmx5IHRydW5jYXRpb24gcG9pbnQg4oCUIHRoZSBmb3JtYXR0ZXIgcmVuZGVycyB0aGVzZSB2ZXJiYXRpbS5cbiAgICBjb25zdCBhbGxNZXNzYWdlcyA9IGV2ZW50c1xuICAgICAgLm1hcChlID0+IGUubWVzc2FnZT8udHJpbUVuZCgpKVxuICAgICAgLmZpbHRlcigobSk6IG0gaXMgc3RyaW5nID0+IG0gIT0gbnVsbCk7XG4gICAgY29uc3QgbWVzc2FnZXM6IHN0cmluZ1tdID0gYWxsTWVzc2FnZXMuc2xpY2UoLU1BWF9MT0dfTElORVMpO1xuICAgIGNvbnN0IG9taXR0ZWQgPSBhbGxNZXNzYWdlcy5sZW5ndGggLSBtZXNzYWdlcy5sZW5ndGg7XG4gICAgaWYgKG9taXR0ZWQgPiAwKSB7XG4gICAgICBtZXNzYWdlcy51bnNoaWZ0KGAuLi4gKCR7b21pdHRlZH0gZWFybGllciBsaW5lcyBvbWl0dGVkKWApO1xuICAgIH1cblxuICAgIGlmICh0YXNrSWRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIG1lc3NhZ2VzLnB1c2goYChzaG93aW5nIGxvZ3MgZnJvbSBsYXN0IGZhaWxlZCB0YXNrOyAke3Rhc2tJZHMubGVuZ3RoIC0gMX0gb3RoZXIgZmFpbGVkIHRhc2socykgYXZhaWxhYmxlIGluIGNvbnNvbGUpYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgc291cmNlID0gbG9nQ29uZmlnLmNvbnRhaW5lck5hbWVcbiAgICAgID8gYENsb3VkV2F0Y2ggTG9nczogJHtsb2dDb25maWcubG9nR3JvdXB9IChjb250YWluZXI6ICR7bG9nQ29uZmlnLmNvbnRhaW5lck5hbWV9KWBcbiAgICAgIDogYENsb3VkV2F0Y2ggTG9nczogJHtsb2dDb25maWcubG9nR3JvdXB9YDtcblxuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2UsXG4gICAgICBtZXNzYWdlcyxcbiAgICAgIGxpbms6IGNsb3VkV2F0Y2hMb2dzQ29uc29sZVVybChyZWdpb24sIGxvZ0NvbmZpZy5sb2dHcm91cCksXG4gICAgICBsaW5rTGFiZWw6ICdMb2dzJyxcbiAgICB9O1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICBhd2FpdCBkZWJ1ZyhgRUNTIGludmVzdGlnYXRpb246IGZhaWxlZCB0byBmZXRjaCBsb2dzIGZyb20gJHtsb2dDb25maWcubG9nR3JvdXB9OiAke2UubWVzc2FnZX1gKTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8vIENsb3VkV2F0Y2ggY29uc29sZSB1c2VzIGRvdWJsZS1VUkktZW5jb2Rpbmcgd2l0aCAnJCcgcmVwbGFjaW5nICclJyBmb3IgdGhlIGxvZyBncm91cCBpbiB0aGUgZnJhZ21lbnQuXG5mdW5jdGlvbiBjbG91ZFdhdGNoTG9nc0NvbnNvbGVVcmwocmVnaW9uOiBzdHJpbmcsIGxvZ0dyb3VwOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBlbmNvZGVkTG9nR3JvdXAgPSBlbmNvZGVVUklDb21wb25lbnQoZW5jb2RlVVJJQ29tcG9uZW50KGxvZ0dyb3VwKSkucmVwbGFjZSgvJS9nLCAnJCcpO1xuICByZXR1cm4gYGh0dHBzOi8vJHtyZWdpb259LmNvbnNvbGUuYXdzLmFtYXpvbi5jb20vY2xvdWR3YXRjaC9ob21lP3JlZ2lvbj0ke3JlZ2lvbn0jbG9nc1YyOmxvZy1ncm91cHMvbG9nLWdyb3VwLyR7ZW5jb2RlZExvZ0dyb3VwfWA7XG59XG5cbmZ1bmN0aW9uIGVjc1N0b3BwZWRUYXNrc0NvbnNvbGVVcmwocmVnaW9uOiBzdHJpbmcsIGNsdXN0ZXI6IHN0cmluZywgc2VydmljZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgaHR0cHM6Ly8ke3JlZ2lvbn0uY29uc29sZS5hd3MuYW1hem9uLmNvbS9lY3MvdjIvY2x1c3RlcnMvJHtjbHVzdGVyfS9zZXJ2aWNlcy8ke3NlcnZpY2VOYW1lfS90YXNrcz9zdGF0dXM9U1RPUFBFRCZyZWdpb249JHtyZWdpb259YDtcbn1cbiJdfQ==
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtaW52ZXN0aWdhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc291cmNlLWludmVzdGlnYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFjQSxrREFjQztBQTVCRCwrRUFBMEU7QUFDMUUsdUVBQTJGO0FBTzNGOzs7OztHQUtHO0FBQ0ksS0FBSyxVQUFVLG1CQUFtQixDQUN2QyxHQUFrQixFQUNsQixHQUFRLEVBQ1IsS0FBcUMsRUFDckMsVUFBOEIsRUFBRTtJQUVoQyxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQztJQUM1QyxJQUFJLFlBQVksS0FBSyxtQkFBbUIsRUFBRSxDQUFDO1FBQ3pDLE9BQU8sSUFBQSwrQ0FBcUIsRUFBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsSUFBSSxZQUFZLEtBQUsscUNBQXFDLElBQUksWUFBWSxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1FBQ2xHLE9BQU8sSUFBQSx1REFBeUIsRUFBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpbnZlc3RpZ2F0ZUN1c3RvbVJlc291cmNlIH0gZnJvbSAnLi9pbnZlc3RpZ2F0ZS1jdXN0b20tcmVzb3VyY2UnO1xuaW1wb3J0IHsgaW52ZXN0aWdhdGVFY3NTZXJ2aWNlLCB0eXBlIEludmVzdGlnYXRlT3B0aW9ucyB9IGZyb20gJy4vaW52ZXN0aWdhdGUtZWNzLXNlcnZpY2UnO1xuaW1wb3J0IHR5cGUgeyBBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHQgfSBmcm9tICcuLi8uLi9hY3Rpb25zL2RpYWdub3NlJztcbmltcG9ydCB0eXBlIHsgU0RLIH0gZnJvbSAnLi4vYXdzLWF1dGgvc2RrJztcbmltcG9ydCB0eXBlIHsgUmVzb3VyY2VFcnJvciB9IGZyb20gJy4uL3N0YWNrLWV2ZW50cy9yZXNvdXJjZS1lcnJvcnMnO1xuXG5leHBvcnQgdHlwZSB7IEludmVzdGlnYXRlT3B0aW9ucyB9O1xuXG4vKipcbiAqIEludmVzdGlnYXRlIGEgZmFpbGVkIHJlc291cmNlIHVzaW5nIEFXUyBzZXJ2aWNlIEFQSXMgdG8gZ2F0aGVyIGFkZGl0aW9uYWwgcm9vdCBjYXVzZSBjb250ZXh0LlxuICpcbiAqIFJldHVybnMgYWRkaXRpb25hbCBkaWFnbm9zdGljIGNvbnRleHQgKGUuZy4gbG9nIGxpbmVzKSBvciBhbiBlbXB0eSBhcnJheSBpZlxuICogaW52ZXN0aWdhdGlvbiBpcyBub3QgcG9zc2libGUgb3IgeWllbGRzIG5vIHJlc3VsdHMgZm9yIHRoaXMgcmVzb3VyY2UgdHlwZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGludmVzdGlnYXRlUmVzb3VyY2UoXG4gIGVycjogUmVzb3VyY2VFcnJvcixcbiAgc2RrOiBTREssXG4gIGRlYnVnOiAobXNnOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD4sXG4gIG9wdGlvbnM6IEludmVzdGlnYXRlT3B0aW9ucyA9IHt9LFxuKTogUHJvbWlzZTxBZGRpdGlvbmFsRGlhZ25vc3RpY0NvbnRleHRbXT4ge1xuICBjb25zdCByZXNvdXJjZVR5cGUgPSBlcnIucmVzb3VyY2VUeXBlID8/ICcnO1xuICBpZiAocmVzb3VyY2VUeXBlID09PSAnQVdTOjpFQ1M6OlNlcnZpY2UnKSB7XG4gICAgcmV0dXJuIGludmVzdGlnYXRlRWNzU2VydmljZShlcnIsIHNkaywgZGVidWcsIG9wdGlvbnMpO1xuICB9XG4gIGlmIChyZXNvdXJjZVR5cGUgPT09ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpDdXN0b21SZXNvdXJjZScgfHwgcmVzb3VyY2VUeXBlLnN0YXJ0c1dpdGgoJ0N1c3RvbTo6JykpIHtcbiAgICByZXR1cm4gaW52ZXN0aWdhdGVDdXN0b21SZXNvdXJjZShlcnIsIHNkaywgZGVidWcpO1xuICB9XG4gIHJldHVybiBbXTtcbn1cbiJdfQ==