truemark-cdk-lib 1.21.0 → 1.21.1-alpha.1768569999

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.
@@ -1,6 +1,7 @@
1
1
  export * from './ecs-service-update';
2
2
  export * from './log-configuration';
3
3
  export * from './otel-configuration';
4
+ export * from './priority-allocator';
4
5
  export * from './standard-fargate-cluster';
5
6
  export * from './standard-fargate-service';
6
7
  export * from './standard-application-fargate-service';
@@ -17,8 +17,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./ecs-service-update"), exports);
18
18
  __exportStar(require("./log-configuration"), exports);
19
19
  __exportStar(require("./otel-configuration"), exports);
20
+ __exportStar(require("./priority-allocator"), exports);
20
21
  __exportStar(require("./standard-fargate-cluster"), exports);
21
22
  __exportStar(require("./standard-fargate-service"), exports);
22
23
  __exportStar(require("./standard-application-fargate-service"), exports);
23
24
  __exportStar(require("./standard-network-fargate-service"), exports);
24
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdURBQXFDO0FBQ3JDLHNEQUFvQztBQUNwQyx1REFBcUM7QUFDckMsNkRBQTJDO0FBQzNDLDZEQUEyQztBQUMzQyx5RUFBdUQ7QUFDdkQscUVBQW1EIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9lY3Mtc2VydmljZS11cGRhdGUnO1xuZXhwb3J0ICogZnJvbSAnLi9sb2ctY29uZmlndXJhdGlvbic7XG5leHBvcnQgKiBmcm9tICcuL290ZWwtY29uZmlndXJhdGlvbic7XG5leHBvcnQgKiBmcm9tICcuL3N0YW5kYXJkLWZhcmdhdGUtY2x1c3Rlcic7XG5leHBvcnQgKiBmcm9tICcuL3N0YW5kYXJkLWZhcmdhdGUtc2VydmljZSc7XG5leHBvcnQgKiBmcm9tICcuL3N0YW5kYXJkLWFwcGxpY2F0aW9uLWZhcmdhdGUtc2VydmljZSc7XG5leHBvcnQgKiBmcm9tICcuL3N0YW5kYXJkLW5ldHdvcmstZmFyZ2F0ZS1zZXJ2aWNlJztcbiJdfQ==
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsdURBQXFDO0FBQ3JDLHNEQUFvQztBQUNwQyx1REFBcUM7QUFDckMsdURBQXFDO0FBQ3JDLDZEQUEyQztBQUMzQyw2REFBMkM7QUFDM0MseUVBQXVEO0FBQ3ZELHFFQUFtRCIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vZWNzLXNlcnZpY2UtdXBkYXRlJztcbmV4cG9ydCAqIGZyb20gJy4vbG9nLWNvbmZpZ3VyYXRpb24nO1xuZXhwb3J0ICogZnJvbSAnLi9vdGVsLWNvbmZpZ3VyYXRpb24nO1xuZXhwb3J0ICogZnJvbSAnLi9wcmlvcml0eS1hbGxvY2F0b3InO1xuZXhwb3J0ICogZnJvbSAnLi9zdGFuZGFyZC1mYXJnYXRlLWNsdXN0ZXInO1xuZXhwb3J0ICogZnJvbSAnLi9zdGFuZGFyZC1mYXJnYXRlLXNlcnZpY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9zdGFuZGFyZC1hcHBsaWNhdGlvbi1mYXJnYXRlLXNlcnZpY2UnO1xuZXhwb3J0ICogZnJvbSAnLi9zdGFuZGFyZC1uZXR3b3JrLWZhcmdhdGUtc2VydmljZSc7XG4iXX0=
@@ -0,0 +1,38 @@
1
+ interface CustomResourceEvent {
2
+ readonly RequestType: 'Create' | 'Update' | 'Delete';
3
+ readonly ResponseURL: string;
4
+ readonly StackId: string;
5
+ readonly RequestId: string;
6
+ readonly ResourceType: string;
7
+ readonly LogicalResourceId: string;
8
+ readonly PhysicalResourceId?: string;
9
+ readonly ResourceProperties: {
10
+ readonly ListenerArn: string;
11
+ readonly ServiceIdentifier: string;
12
+ readonly TableName: string;
13
+ readonly PreferredPriority?: string;
14
+ };
15
+ readonly OldResourceProperties?: {
16
+ readonly ListenerArn: string;
17
+ readonly ServiceIdentifier: string;
18
+ readonly TableName: string;
19
+ readonly PreferredPriority?: string;
20
+ };
21
+ }
22
+ interface CustomResourceResponse {
23
+ Status: 'SUCCESS' | 'FAILED';
24
+ Reason?: string;
25
+ PhysicalResourceId: string;
26
+ StackId: string;
27
+ RequestId: string;
28
+ LogicalResourceId: string;
29
+ NoEcho?: boolean;
30
+ Data?: {
31
+ Priority: string;
32
+ };
33
+ }
34
+ /**
35
+ * Main Lambda handler for the Custom Resource
36
+ */
37
+ export declare function handler(event: CustomResourceEvent): Promise<CustomResourceResponse>;
38
+ export {};
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = handler;
4
+ const client_elastic_load_balancing_v2_1 = require("@aws-sdk/client-elastic-load-balancing-v2");
5
+ const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
6
+ const crypto = require("node:crypto");
7
+ const elbv2Client = new client_elastic_load_balancing_v2_1.ElasticLoadBalancingV2Client({});
8
+ const dynamoClient = new client_dynamodb_1.DynamoDBClient({});
9
+ const MAX_PRIORITY = 50000;
10
+ const MAX_RETRIES = 10;
11
+ /**
12
+ * Creates a deterministic hash of the service identifier
13
+ */
14
+ function hashServiceIdentifier(serviceIdentifier) {
15
+ return crypto.createHash('sha256').update(serviceIdentifier).digest('hex');
16
+ }
17
+ /**
18
+ * Creates a success response
19
+ */
20
+ function success(event, physicalResourceId, priority) {
21
+ return {
22
+ Status: 'SUCCESS',
23
+ PhysicalResourceId: physicalResourceId,
24
+ StackId: event.StackId,
25
+ RequestId: event.RequestId,
26
+ LogicalResourceId: event.LogicalResourceId,
27
+ NoEcho: false,
28
+ Data: {
29
+ Priority: priority.toString(),
30
+ },
31
+ };
32
+ }
33
+ /**
34
+ * Creates a failure response
35
+ */
36
+ function fail(event, physicalResourceId, reason) {
37
+ return {
38
+ Status: 'FAILED',
39
+ Reason: reason,
40
+ PhysicalResourceId: physicalResourceId,
41
+ StackId: event.StackId,
42
+ RequestId: event.RequestId,
43
+ LogicalResourceId: event.LogicalResourceId,
44
+ NoEcho: false,
45
+ };
46
+ }
47
+ /**
48
+ * Extracts valid priority from a rule
49
+ */
50
+ function extractPriorityFromRule(rule) {
51
+ if (!rule.Priority || rule.Priority === 'default') {
52
+ return null;
53
+ }
54
+ const priority = Number.parseInt(rule.Priority, 10);
55
+ return Number.isNaN(priority) ? null : priority;
56
+ }
57
+ /**
58
+ * Formats priority list for logging
59
+ */
60
+ function formatPrioritiesForLog(priorities) {
61
+ const sorted = Array.from(priorities).sort((a, b) => a - b);
62
+ const preview = sorted.slice(0, 10).join(', ');
63
+ return priorities.size > 10 ? `${preview}...` : preview;
64
+ }
65
+ /**
66
+ * Gets all priorities currently in use on the ALB listener
67
+ */
68
+ async function getAlbListenerPriorities(listenerArn) {
69
+ const priorities = new Set();
70
+ try {
71
+ let nextMarker = undefined;
72
+ do {
73
+ const command = new client_elastic_load_balancing_v2_1.DescribeRulesCommand({
74
+ ListenerArn: listenerArn,
75
+ Marker: nextMarker,
76
+ });
77
+ const response = await elbv2Client.send(command);
78
+ if (response.Rules) {
79
+ for (const rule of response.Rules) {
80
+ const priority = extractPriorityFromRule(rule);
81
+ if (priority !== null) {
82
+ priorities.add(priority);
83
+ }
84
+ }
85
+ }
86
+ nextMarker = response.NextMarker;
87
+ } while (nextMarker);
88
+ const formatted = formatPrioritiesForLog(priorities);
89
+ console.log(`Found ${priorities.size} priorities in use on ALB listener: ${formatted}`);
90
+ }
91
+ catch (error) {
92
+ console.error('Error fetching ALB listener priorities:', error);
93
+ throw error;
94
+ }
95
+ return priorities;
96
+ }
97
+ /**
98
+ * Extracts valid priority from a DynamoDB item
99
+ */
100
+ function extractPriorityFromDynamoItem(item) {
101
+ var _a;
102
+ if (!((_a = item.Priority) === null || _a === void 0 ? void 0 : _a.N)) {
103
+ return null;
104
+ }
105
+ const priority = Number.parseInt(item.Priority.N, 10);
106
+ return Number.isNaN(priority) ? null : priority;
107
+ }
108
+ /**
109
+ * Gets all priorities tracked in DynamoDB for this listener
110
+ */
111
+ async function getDynamoDbPriorities(tableName, listenerArn) {
112
+ const priorities = new Set();
113
+ try {
114
+ let lastEvaluatedKey = undefined;
115
+ do {
116
+ const command = new client_dynamodb_1.QueryCommand({
117
+ TableName: tableName,
118
+ KeyConditionExpression: 'ListenerArn = :arn',
119
+ ExpressionAttributeValues: {
120
+ ':arn': { S: listenerArn },
121
+ },
122
+ ExclusiveStartKey: lastEvaluatedKey,
123
+ });
124
+ const response = await dynamoClient.send(command);
125
+ if (response.Items) {
126
+ for (const item of response.Items) {
127
+ const priority = extractPriorityFromDynamoItem(item);
128
+ if (priority !== null) {
129
+ priorities.add(priority);
130
+ }
131
+ }
132
+ }
133
+ lastEvaluatedKey = response.LastEvaluatedKey;
134
+ } while (lastEvaluatedKey);
135
+ console.log(`Found ${priorities.size} priorities tracked in DynamoDB for listener`);
136
+ }
137
+ catch (error) {
138
+ console.error('Error fetching DynamoDB priorities:', error);
139
+ throw error;
140
+ }
141
+ return priorities;
142
+ }
143
+ /**
144
+ * Checks if the service already has an allocated priority (for idempotency)
145
+ */
146
+ async function getExistingAllocation(tableName, listenerArn, serviceIdentifier) {
147
+ var _a, _b;
148
+ try {
149
+ const command = new client_dynamodb_1.QueryCommand({
150
+ TableName: tableName,
151
+ IndexName: 'ServiceIdentifierIndex',
152
+ KeyConditionExpression: 'ServiceIdentifier = :sid AND ListenerArn = :arn',
153
+ ExpressionAttributeValues: {
154
+ ':sid': { S: serviceIdentifier },
155
+ ':arn': { S: listenerArn },
156
+ },
157
+ });
158
+ const response = await dynamoClient.send(command);
159
+ if ((_a = response.Items) === null || _a === void 0 ? void 0 : _a[0]) {
160
+ const item = response.Items[0];
161
+ if ((_b = item.Priority) === null || _b === void 0 ? void 0 : _b.N) {
162
+ const priority = Number.parseInt(item.Priority.N, 10);
163
+ console.log(`Found existing allocation: priority ${priority} for service ${serviceIdentifier}`);
164
+ return priority;
165
+ }
166
+ }
167
+ return null;
168
+ }
169
+ catch (error) {
170
+ console.error('Error checking existing allocation:', error);
171
+ throw error;
172
+ }
173
+ }
174
+ /**
175
+ * Attempts to allocate a specific priority atomically
176
+ */
177
+ async function tryAllocatePriority(tableName, listenerArn, serviceIdentifier, priority) {
178
+ try {
179
+ const now = new Date().toISOString();
180
+ const command = new client_dynamodb_1.PutItemCommand({
181
+ TableName: tableName,
182
+ Item: {
183
+ ListenerArn: { S: listenerArn },
184
+ Priority: { N: priority.toString() },
185
+ ServiceIdentifier: { S: serviceIdentifier },
186
+ AllocatedAt: { S: now },
187
+ Source: { S: 'CDK' },
188
+ },
189
+ ConditionExpression: 'attribute_not_exists(ListenerArn)',
190
+ });
191
+ await dynamoClient.send(command);
192
+ console.log(`Successfully allocated priority ${priority} for service ${serviceIdentifier}`);
193
+ return true;
194
+ }
195
+ catch (error) {
196
+ if (error instanceof client_dynamodb_1.ConditionalCheckFailedException) {
197
+ console.log(`Priority ${priority} already taken (race condition), will try next available`);
198
+ return false;
199
+ }
200
+ console.error('Error allocating priority:', error);
201
+ throw error;
202
+ }
203
+ }
204
+ /**
205
+ * Validates if a priority is within valid range
206
+ */
207
+ function isValidPriorityRange(priority) {
208
+ return priority >= 1 && priority <= MAX_PRIORITY;
209
+ }
210
+ /**
211
+ * Attempts to allocate preferred priority if available
212
+ */
213
+ async function tryPreferredPriority(tableName, listenerArn, serviceIdentifier, preferredPriority, usedPriorities) {
214
+ if (!isValidPriorityRange(preferredPriority)) {
215
+ return null;
216
+ }
217
+ if (usedPriorities.has(preferredPriority)) {
218
+ console.log(`Preferred priority ${preferredPriority} is already in use, finding next available`);
219
+ return null;
220
+ }
221
+ const allocated = await tryAllocatePriority(tableName, listenerArn, serviceIdentifier, preferredPriority);
222
+ return allocated ? preferredPriority : null;
223
+ }
224
+ /**
225
+ * Finds lowest available priority with gap filling
226
+ */
227
+ async function findLowestAvailablePriority(tableName, listenerArn, serviceIdentifier, usedPriorities) {
228
+ let retries = 0;
229
+ for (let priority = 1; priority <= MAX_PRIORITY; priority++) {
230
+ if (usedPriorities.has(priority)) {
231
+ continue;
232
+ }
233
+ const allocated = await tryAllocatePriority(tableName, listenerArn, serviceIdentifier, priority);
234
+ if (allocated) {
235
+ return priority;
236
+ }
237
+ // Race condition: someone else took this priority, try next
238
+ retries++;
239
+ if (retries >= MAX_RETRIES) {
240
+ throw new Error(`Failed to allocate priority after ${MAX_RETRIES} retries due to race conditions`);
241
+ }
242
+ }
243
+ throw new Error(`No available priorities found (all ${MAX_PRIORITY} in use)`);
244
+ }
245
+ /**
246
+ * Finds the lowest available priority and allocates it
247
+ */
248
+ async function allocatePriority(tableName, listenerArn, serviceIdentifier, preferredPriority) {
249
+ // Step 1: Check if service already has an allocation (idempotency)
250
+ const existingPriority = await getExistingAllocation(tableName, listenerArn, serviceIdentifier);
251
+ if (existingPriority !== null) {
252
+ return existingPriority;
253
+ }
254
+ // Step 2: Get all used priorities from ALB
255
+ const albPriorities = await getAlbListenerPriorities(listenerArn);
256
+ // Step 3: Get all tracked priorities from DynamoDB
257
+ const dynamoPriorities = await getDynamoDbPriorities(tableName, listenerArn);
258
+ // Step 4: Merge both sources to get complete picture
259
+ const allUsedPriorities = new Set([...albPriorities, ...dynamoPriorities]);
260
+ console.log(`Total priorities in use (ALB + DynamoDB): ${allUsedPriorities.size}`);
261
+ // Step 5: Try preferred priority first if provided
262
+ if (preferredPriority) {
263
+ const result = await tryPreferredPriority(tableName, listenerArn, serviceIdentifier, preferredPriority, allUsedPriorities);
264
+ if (result !== null) {
265
+ return result;
266
+ }
267
+ }
268
+ // Step 6: Find lowest available priority (gap filling)
269
+ return findLowestAvailablePriority(tableName, listenerArn, serviceIdentifier, allUsedPriorities);
270
+ }
271
+ /**
272
+ * Deletes a priority allocation from DynamoDB
273
+ */
274
+ async function deletePriorityAllocation(tableName, listenerArn, serviceIdentifier) {
275
+ var _a;
276
+ try {
277
+ // Find the priority allocated to this service
278
+ const command = new client_dynamodb_1.QueryCommand({
279
+ TableName: tableName,
280
+ IndexName: 'ServiceIdentifierIndex',
281
+ KeyConditionExpression: 'ServiceIdentifier = :sid AND ListenerArn = :arn',
282
+ ExpressionAttributeValues: {
283
+ ':sid': { S: serviceIdentifier },
284
+ ':arn': { S: listenerArn },
285
+ },
286
+ });
287
+ const response = await dynamoClient.send(command);
288
+ if (!response.Items || response.Items.length === 0) {
289
+ console.log(`No priority found for service ${serviceIdentifier}, nothing to delete`);
290
+ return;
291
+ }
292
+ const item = response.Items[0];
293
+ const priorityValue = (_a = item.Priority) === null || _a === void 0 ? void 0 : _a.N;
294
+ if (!priorityValue) {
295
+ console.error('Priority not found in item:', item);
296
+ return;
297
+ }
298
+ const priority = Number.parseInt(priorityValue, 10);
299
+ // Delete the allocation
300
+ const deleteCommand = new client_dynamodb_1.DeleteItemCommand({
301
+ TableName: tableName,
302
+ Key: {
303
+ ListenerArn: { S: listenerArn },
304
+ Priority: { N: priority.toString() },
305
+ },
306
+ });
307
+ await dynamoClient.send(deleteCommand);
308
+ console.log(`Successfully deleted priority ${priority} for service ${serviceIdentifier}`);
309
+ }
310
+ catch (error) {
311
+ console.error('Error deleting priority allocation:', error);
312
+ throw error;
313
+ }
314
+ }
315
+ /**
316
+ * Main Lambda handler for the Custom Resource
317
+ */
318
+ async function handler(event) {
319
+ console.log('Received event:', JSON.stringify(event, null, 2));
320
+ const listenerArn = event.ResourceProperties.ListenerArn;
321
+ const serviceIdentifier = event.ResourceProperties.ServiceIdentifier;
322
+ const tableName = event.ResourceProperties.TableName;
323
+ const preferredPriority = event.ResourceProperties.PreferredPriority
324
+ ? Number.parseInt(event.ResourceProperties.PreferredPriority, 10)
325
+ : undefined;
326
+ // Physical resource ID is based on listener ARN and service identifier
327
+ const physicalResourceId = hashServiceIdentifier(`${listenerArn}/${serviceIdentifier}`);
328
+ try {
329
+ // Handle Delete operation
330
+ if (event.RequestType === 'Delete') {
331
+ console.log('Handling DELETE request - removing priority allocation');
332
+ await deletePriorityAllocation(tableName, listenerArn, serviceIdentifier);
333
+ // Return success with priority 0 (doesn't matter for delete)
334
+ return success(event, physicalResourceId, 0);
335
+ }
336
+ // Handle Create and Update operations
337
+ console.log(`Handling ${event.RequestType} request - allocating priority`);
338
+ const priority = await allocatePriority(tableName, listenerArn, serviceIdentifier, preferredPriority);
339
+ return success(event, physicalResourceId, priority);
340
+ }
341
+ catch (error) {
342
+ const errorMessage = error instanceof Error ? error.message : String(error);
343
+ console.error('Error in handler:', errorMessage);
344
+ return fail(event, physicalResourceId, errorMessage);
345
+ }
346
+ }
347
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpb3JpdHktYWxsb2NhdG9yLWhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJwcmlvcml0eS1hbGxvY2F0b3ItaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQXFmQSwwQkF5Q0M7QUE5aEJELGdHQUltRDtBQUNuRCw4REFRa0M7QUFDbEMsc0NBQXNDO0FBc0N0QyxNQUFNLFdBQVcsR0FBRyxJQUFJLCtEQUE0QixDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3pELE1BQU0sWUFBWSxHQUFHLElBQUksZ0NBQWMsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUU1QyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUM7QUFDM0IsTUFBTSxXQUFXLEdBQUcsRUFBRSxDQUFDO0FBRXZCOztHQUVHO0FBQ0gsU0FBUyxxQkFBcUIsQ0FBQyxpQkFBeUI7SUFDdEQsT0FBTyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM3RSxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLE9BQU8sQ0FDZCxLQUEwQixFQUMxQixrQkFBMEIsRUFDMUIsUUFBZ0I7SUFFaEIsT0FBTztRQUNMLE1BQU0sRUFBRSxTQUFTO1FBQ2pCLGtCQUFrQixFQUFFLGtCQUFrQjtRQUN0QyxPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU87UUFDdEIsU0FBUyxFQUFFLEtBQUssQ0FBQyxTQUFTO1FBQzFCLGlCQUFpQixFQUFFLEtBQUssQ0FBQyxpQkFBaUI7UUFDMUMsTUFBTSxFQUFFLEtBQUs7UUFDYixJQUFJLEVBQUU7WUFDSixRQUFRLEVBQUUsUUFBUSxDQUFDLFFBQVEsRUFBRTtTQUM5QjtLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLElBQUksQ0FDWCxLQUEwQixFQUMxQixrQkFBMEIsRUFDMUIsTUFBYztJQUVkLE9BQU87UUFDTCxNQUFN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QUFDLENBQUM7UUFDM0UsTUFBTSxRQUFRLEdBQUcsTUFBTSxnQkFBZ0IsQ0FDckMsU0FBUyxFQUNULFdBQVcsRUFDWCxpQkFBaUIsRUFDakIsaUJBQWlCLENBQ2xCLENBQUM7UUFFRixPQUFPLE9BQU8sQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLFlBQVksR0FBRyxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUUsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUNqRCxPQUFPLElBQUksQ0FBQyxLQUFLLEVBQUUsa0JBQWtCLEVBQUUsWUFBWSxDQUFDLENBQUM7SUFDdkQsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBFbGFzdGljTG9hZEJhbGFuY2luZ1YyQ2xpZW50LFxuICBEZXNjcmliZVJ1bGVzQ29tbWFuZCxcbiAgdHlwZSBEZXNjcmliZVJ1bGVzQ29tbWFuZE91dHB1dCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVsYXN0aWMtbG9hZC1iYWxhbmNpbmctdjInO1xuaW1wb3J0IHtcbiAgRHluYW1vREJDbGllbnQsXG4gIFB1dEl0ZW1Db21tYW5kLFxuICBRdWVyeUNvbW1hbmQsXG4gIERlbGV0ZUl0ZW1Db21tYW5kLFxuICBDb25kaXRpb25hbENoZWNrRmFpbGVkRXhjZXB0aW9uLFxuICB0eXBlIFF1ZXJ5Q29tbWFuZE91dHB1dCxcbiAgdHlwZSBBdHRyaWJ1dGVWYWx1ZSxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWR5bmFtb2RiJztcbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdub2RlOmNyeXB0byc7XG5cbi8vIENsb3VkRm9ybWF0aW9uIEN1c3RvbSBSZXNvdXJjZSBldmVudCBpbnRlcmZhY2VcbmludGVyZmFjZSBDdXN0b21SZXNvdXJjZUV2ZW50IHtcbiAgcmVhZG9ubHkgUmVxdWVzdFR5cGU6ICdDcmVhdGUnIHwgJ1VwZGF0ZScgfCAnRGVsZXRlJztcbiAgcmVhZG9ubHkgUmVzcG9uc2VVUkw6IHN0cmluZztcbiAgcmVhZG9ubHkgU3RhY2tJZDogc3RyaW5nO1xuICByZWFkb25seSBSZXF1ZXN0SWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgUmVzb3VyY2VUeXBlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IExvZ2ljYWxSZXNvdXJjZUlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgcmVhZG9ubHkgUmVzb3VyY2VQcm9wZXJ0aWVzOiB7XG4gICAgcmVhZG9ubHkgTGlzdGVuZXJBcm46IHN0cmluZztcbiAgICByZWFkb25seSBTZXJ2aWNlSWRlbnRpZmllcjogc3RyaW5nO1xuICAgIHJlYWRvbmx5IFRhYmxlTmFtZTogc3RyaW5nO1xuICAgIHJlYWRvbmx5IFByZWZlcnJlZFByaW9yaXR5Pzogc3RyaW5nO1xuICB9O1xuICByZWFkb25seSBPbGRSZXNvdXJjZVByb3BlcnRpZXM/OiB7XG4gICAgcmVhZG9ubHkgTGlzdGVuZXJBcm46IHN0cmluZztcbiAgICByZWFkb25seSBTZXJ2aWNlSWRlbnRpZmllcjogc3RyaW5nO1xuICAgIHJlYWRvbmx5IFRhYmxlTmFtZTogc3RyaW5nO1xuICAgIHJlYWRvbmx5IFByZWZlcnJlZFByaW9yaXR5Pzogc3RyaW5nO1xuICB9O1xufVxuXG5pbnRlcmZhY2UgQ3VzdG9tUmVzb3VyY2VSZXNwb25zZSB7XG4gIFN0YXR1czogJ1NVQ0NFU1MnIHwgJ0ZBSUxFRCc7XG4gIFJlYXNvbj86IHN0cmluZztcbiAgUGh5c2ljYWxSZXNvdXJjZUlkOiBzdHJpbmc7XG4gIFN0YWNrSWQ6IHN0cmluZztcbiAgUmVxdWVzdElkOiBzdHJpbmc7XG4gIExvZ2ljYWxSZXNvdXJjZUlkOiBzdHJpbmc7XG4gIE5vRWNobz86IGJvb2xlYW47XG4gIERhdGE/OiB7XG4gICAgUHJpb3JpdHk6IHN0cmluZztcbiAgfTtcbn1cblxuY29uc3QgZWxidjJDbGllbnQgPSBuZXcgRWxhc3RpY0xvYWRCYWxhbmNpbmdWMkNsaWVudCh7fSk7XG5jb25zdCBkeW5hbW9DbGllbnQgPSBuZXcgRHluYW1vREJDbGllbnQoe30pO1xuXG5jb25zdCBNQVhfUFJJT1JJVFkgPSA1MDAwMDtcbmNvbnN0IE1BWF9SRVRSSUVTID0gMTA7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRldGVybWluaXN0aWMgaGFzaCBvZiB0aGUgc2VydmljZSBpZGVudGlmaWVyXG4gKi9cbmZ1bmN0aW9uIGhhc2hTZXJ2aWNlSWRlbnRpZmllcihzZXJ2aWNlSWRlbnRpZmllcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoc2VydmljZUlkZW50aWZpZXIpLmRpZ2VzdCgnaGV4Jyk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHN1Y2Nlc3MgcmVzcG9uc2VcbiAqL1xuZnVuY3Rpb24gc3VjY2VzcyhcbiAgZXZlbnQ6IEN1c3RvbVJlc291cmNlRXZlbnQsXG4gIHBoeXNpY2FsUmVzb3VyY2VJZDogc3RyaW5nLFxuICBwcmlvcml0eTogbnVtYmVyLFxuKTogQ3VzdG9tUmVzb3VyY2VSZXNwb25zZSB7XG4gIHJldHVybiB7XG4gICAgU3RhdHVzOiAnU1VDQ0VTUycsXG4gICAgUGh5c2ljYWxSZXNvdXJjZUlkOiBwaHlzaWNhbFJlc291cmNlSWQsXG4gICAgU3RhY2tJZDogZXZlbnQuU3RhY2tJZCxcbiAgICBSZXF1ZXN0SWQ6IGV2ZW50LlJlcXVlc3RJZCxcbiAgICBMb2dpY2FsUmVzb3VyY2VJZDogZXZlbnQuTG9naWNhbFJlc291cmNlSWQsXG4gICAgTm9FY2hvOiBmYWxzZSxcbiAgICBEYXRhOiB7XG4gICAgICBQcmlvcml0eTogcHJpb3JpdHkudG9TdHJpbmcoKSxcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBmYWlsdXJlIHJlc3BvbnNlXG4gKi9cbmZ1bmN0aW9uIGZhaWwoXG4gIGV2ZW50OiBDdXN0b21SZXNvdXJjZUV2ZW50LFxuICBwaHlzaWNhbFJlc291cmNlSWQ6IHN0cmluZyxcbiAgcmVhc29uOiBzdHJpbmcsXG4pOiBDdXN0b21SZXNvdXJjZVJlc3BvbnNlIHtcbiAgcmV0dXJuIHtcbiAgICBTdGF0dXM6ICdGQUlMRUQnLFxuICAgIFJlYXNvbjogcmVhc29uLFxuICAgIFBoeXNpY2FsUmVzb3VyY2VJZDogcGh5c2ljYWxSZXNvdXJjZUlkLFxuICAgIFN0YWNrSWQ6IGV2ZW50LlN0YWNrSWQsXG4gICAgUmVxdWVzdElkOiBldmVudC5SZXF1ZXN0SWQsXG4gICAgTG9naWNhbFJlc291cmNlSWQ6IGV2ZW50LkxvZ2ljYWxSZXNvdXJjZUlkLFxuICAgIE5vRWNobzogZmFsc2UsXG4gIH07XG59XG5cbi8qKlxuICogRXh0cmFjdHMgdmFsaWQgcHJpb3JpdHkgZnJvbSBhIHJ1bGVcbiAqL1xuZnVuY3Rpb24gZXh0cmFjdFByaW9yaXR5RnJvbVJ1bGUocnVsZToge1ByaW9yaXR5Pzogc3RyaW5nfSk6IG51bWJlciB8IG51bGwge1xuICBpZiAoIXJ1bGUuUHJpb3JpdHkgfHwgcnVsZS5Qcmlvcml0eSA9PT0gJ2RlZmF1bHQnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgcHJpb3JpdHkgPSBOdW1iZXIucGFyc2VJbnQocnVsZS5Qcmlvcml0eSwgMTApO1xuICByZXR1cm4gTnVtYmVyLmlzTmFOKHByaW9yaXR5KSA/IG51bGwgOiBwcmlvcml0eTtcbn1cblxuLyoqXG4gKiBGb3JtYXRzIHByaW9yaXR5IGxpc3QgZm9yIGxvZ2dpbmdcbiAqL1xuZnVuY3Rpb24gZm9ybWF0UHJpb3JpdGllc0ZvckxvZyhwcmlvcml0aWVzOiBTZXQ8bnVtYmVyPik6IHN0cmluZyB7XG4gIGNvbnN0IHNvcnRlZCA9IEFycmF5LmZyb20ocHJpb3JpdGllcykuc29ydCgoYSwgYikgPT4gYSAtIGIpO1xuICBjb25zdCBwcmV2aWV3ID0gc29ydGVkLnNsaWNlKDAsIDEwKS5qb2luKCcsICcpO1xuICByZXR1cm4gcHJpb3JpdGllcy5zaXplID4gMTAgPyBgJHtwcmV2aWV3fS4uLmAgOiBwcmV2aWV3O1xufVxuXG4vKipcbiAqIEdldHMgYWxsIHByaW9yaXRpZXMgY3VycmVudGx5IGluIHVzZSBvbiB0aGUgQUxCIGxpc3RlbmVyXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldEFsYkxpc3RlbmVyUHJpb3JpdGllcyhcbiAgbGlzdGVuZXJBcm46IHN0cmluZyxcbik6IFByb21pc2U8U2V0PG51bWJlcj4+IHtcbiAgY29uc3QgcHJpb3JpdGllcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuXG4gIHRyeSB7XG4gICAgbGV0IG5leHRNYXJrZXI6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICAgIGRvIHtcbiAgICAgIGNvbnN0IGNvbW1hbmQgPSBuZXcgRGVzY3JpYmVSdWxlc0NvbW1hbmQoe1xuICAgICAgICBMaXN0ZW5lckFybjogbGlzdGVuZXJBcm4sXG4gICAgICAgIE1hcmtlcjogbmV4dE1hcmtlcixcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCByZXNwb25zZTogRGVzY3JpYmVSdWxlc0NvbW1hbmRPdXRwdXQgPVxuICAgICAgICBhd2FpdCBlbGJ2MkNsaWVudC5zZW5kKGNvbW1hbmQpO1xuXG4gICAgICBpZiAocmVzcG9uc2UuUnVsZXMpIHtcbiAgICAgICAgZm9yIChjb25zdCBydWxlIG9mIHJlc3BvbnNlLlJ1bGVzKSB7XG4gICAgICAgICAgY29uc3QgcHJpb3JpdHkgPSBleHRyYWN0UHJpb3JpdHlGcm9tUnVsZShydWxlKTtcbiAgICAgICAgICBpZiAocHJpb3JpdHkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHByaW9yaXRpZXMuYWRkKHByaW9yaXR5KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbmV4dE1hcmtlciA9IHJlc3BvbnNlLk5leHRNYXJrZXI7XG4gICAgfSB3aGlsZSAobmV4dE1hcmtlcik7XG5cbiAgICBjb25zdCBmb3JtYXR0ZWQgPSBmb3JtYXRQcmlvcml0aWVzRm9yTG9nKHByaW9yaXRpZXMpO1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYEZvdW5kICR7cHJpb3JpdGllcy5zaXplfSBwcmlvcml0aWVzIGluIHVzZSBvbiBBTEIgbGlzdGVuZXI6ICR7Zm9ybWF0dGVkfWAsXG4gICAgKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdFcnJvciBmZXRjaGluZyBBTEIgbGlzdGVuZXIgcHJpb3JpdGllczonLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cblxuICByZXR1cm4gcHJpb3JpdGllcztcbn1cblxuLyoqXG4gKiBFeHRyYWN0cyB2YWxpZCBwcmlvcml0eSBmcm9tIGEgRHluYW1vREIgaXRlbVxuICovXG5mdW5jdGlvbiBleHRyYWN0UHJpb3JpdHlGcm9tRHluYW1vSXRlbShcbiAgaXRlbTogUmVjb3JkPHN0cmluZywgQXR0cmlidXRlVmFsdWU+LFxuKTogbnVtYmVyIHwgbnVsbCB7XG4gIGlmICghaXRlbS5Qcmlvcml0eT8uTikge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGNvbnN0IHByaW9yaXR5ID0gTnVtYmVyLnBhcnNlSW50KGl0ZW0uUHJpb3JpdHkuTiwgMTApO1xuICByZXR1cm4gTnVtYmVyLmlzTmFOKHByaW9yaXR5KSA/IG51bGwgOiBwcmlvcml0eTtcbn1cblxuLyoqXG4gKiBHZXRzIGFsbCBwcmlvcml0aWVzIHRyYWNrZWQgaW4gRHluYW1vREIgZm9yIHRoaXMgbGlzdGVuZXJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0RHluYW1vRGJQcmlvcml0aWVzKFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgbGlzdGVuZXJBcm46IHN0cmluZyxcbik6IFByb21pc2U8U2V0PG51bWJlcj4+IHtcbiAgY29uc3QgcHJpb3JpdGllcyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuXG4gIHRyeSB7XG4gICAgbGV0IGxhc3RFdmFsdWF0ZWRLZXk6IFJlY29yZDxzdHJpbmcsIEF0dHJpYnV0ZVZhbHVlPiB8IHVuZGVmaW5lZCA9XG4gICAgICB1bmRlZmluZWQ7XG5cbiAgICBkbyB7XG4gICAgICBjb25zdCBjb21tYW5kID0gbmV3IFF1ZXJ5Q29tbWFuZCh7XG4gICAgICAgIFRhYmxlTmFtZTogdGFibGVOYW1lLFxuICAgICAgICBLZXlDb25kaXRpb25FeHByZXNzaW9uOiAnTGlzdGVuZXJBcm4gPSA6YXJuJyxcbiAgICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICc6YXJuJzoge1M6IGxpc3RlbmVyQXJufSxcbiAgICAgICAgfSxcbiAgICAgICAgRXhjbHVzaXZlU3RhcnRLZXk6IGxhc3RFdmFsdWF0ZWRLZXksXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgcmVzcG9uc2U6IFF1ZXJ5Q29tbWFuZE91dHB1dCA9IGF3YWl0IGR5bmFtb0NsaWVudC5zZW5kKGNvbW1hbmQpO1xuXG4gICAgICBpZiAocmVzcG9uc2UuSXRlbXMpIHtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHJlc3BvbnNlLkl0ZW1zKSB7XG4gICAgICAgICAgY29uc3QgcHJpb3JpdHkgPSBleHRyYWN0UHJpb3JpdHlGcm9tRHluYW1vSXRlbShpdGVtKTtcbiAgICAgICAgICBpZiAocHJpb3JpdHkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHByaW9yaXRpZXMuYWRkKHByaW9yaXR5KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgbGFzdEV2YWx1YXRlZEtleSA9IHJlc3BvbnNlLkxhc3RFdmFsdWF0ZWRLZXk7XG4gICAgfSB3aGlsZSAobGFzdEV2YWx1YXRlZEtleSk7XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBGb3VuZCAke3ByaW9yaXRpZXMuc2l6ZX0gcHJpb3JpdGllcyB0cmFja2VkIGluIER5bmFtb0RCIGZvciBsaXN0ZW5lcmAsXG4gICAgKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdFcnJvciBmZXRjaGluZyBEeW5hbW9EQiBwcmlvcml0aWVzOicsIGVycm9yKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxuXG4gIHJldHVybiBwcmlvcml0aWVzO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgc2VydmljZSBhbHJlYWR5IGhhcyBhbiBhbGxvY2F0ZWQgcHJpb3JpdHkgKGZvciBpZGVtcG90ZW5jeSlcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0RXhpc3RpbmdBbGxvY2F0aW9uKFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgbGlzdGVuZXJBcm46IHN0cmluZyxcbiAgc2VydmljZUlkZW50aWZpZXI6IHN0cmluZyxcbik6IFByb21pc2U8bnVtYmVyIHwgbnVsbD4ge1xuICB0cnkge1xuICAgIGNvbnN0IGNvbW1hbmQgPSBuZXcgUXVlcnlDb21tYW5kKHtcbiAgICAgIFRhYmxlTmFtZTogdGFibGVOYW1lLFxuICAgICAgSW5kZXhOYW1lOiAnU2VydmljZUlkZW50aWZpZXJJbmRleCcsXG4gICAgICBLZXlDb25kaXRpb25FeHByZXNzaW9uOiAnU2VydmljZUlkZW50aWZpZXIgPSA6c2lkIEFORCBMaXN0ZW5lckFybiA9IDphcm4nLFxuICAgICAgRXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAnOnNpZCc6IHtTOiBzZXJ2aWNlSWRlbnRpZmllcn0sXG4gICAgICAgICc6YXJuJzoge1M6IGxpc3RlbmVyQXJufSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCByZXNwb25zZTogUXVlcnlDb21tYW5kT3V0cHV0ID0gYXdhaXQgZHluYW1vQ2xpZW50LnNlbmQoY29tbWFuZCk7XG5cbiAgICBpZiAocmVzcG9uc2UuSXRlbXM/LlswXSkge1xuICAgICAgY29uc3QgaXRlbSA9IHJlc3BvbnNlLkl0ZW1zWzBdO1xuICAgICAgaWYgKGl0ZW0uUHJpb3JpdHk/Lk4pIHtcbiAgICAgICAgY29uc3QgcHJpb3JpdHkgPSBOdW1iZXIucGFyc2VJbnQoaXRlbS5Qcmlvcml0eS5OLCAxMCk7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGBGb3VuZCBleGlzdGluZyBhbGxvY2F0aW9uOiBwcmlvcml0eSAke3ByaW9yaXR5fSBmb3Igc2VydmljZSAke3NlcnZpY2VJZGVudGlmaWVyfWAsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBwcmlvcml0eTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBjb25zb2xlLmVycm9yKCdFcnJvciBjaGVja2luZyBleGlzdGluZyBhbGxvY2F0aW9uOicsIGVycm9yKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG4vKipcbiAqIEF0dGVtcHRzIHRvIGFsbG9jYXRlIGEgc3BlY2lmaWMgcHJpb3JpdHkgYXRvbWljYWxseVxuICovXG5hc3luYyBmdW5jdGlvbiB0cnlBbGxvY2F0ZVByaW9yaXR5KFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgbGlzdGVuZXJBcm46IHN0cmluZyxcbiAgc2VydmljZUlkZW50aWZpZXI6IHN0cmluZyxcbiAgcHJpb3JpdHk6IG51bWJlcixcbik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICB0cnkge1xuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcblxuICAgIGNvbnN0IGNvbW1hbmQgPSBuZXcgUHV0SXRlbUNvbW1hbmQoe1xuICAgICAgVGFibGVOYW1lOiB0YWJsZU5hbWUsXG4gICAgICBJdGVtOiB7XG4gICAgICAgIExpc3RlbmVyQXJuOiB7UzogbGlzdGVuZXJBcm59LFxuICAgICAgICBQcmlvcml0eToge046IHByaW9yaXR5LnRvU3RyaW5nKCl9LFxuICAgICAgICBTZXJ2aWNlSWRlbnRpZmllcjoge1M6IHNlcnZpY2VJZGVudGlmaWVyfSxcbiAgICAgICAgQWxsb2NhdGVkQXQ6IHtTOiBub3d9LFxuICAgICAgICBTb3VyY2U6IHtTOiAnQ0RLJ30sXG4gICAgICB9LFxuICAgICAgQ29uZGl0aW9uRXhwcmVzc2lvbjogJ2F0dHJpYnV0ZV9ub3RfZXhpc3RzKExpc3RlbmVyQXJuKScsXG4gICAgfSk7XG5cbiAgICBhd2FpdCBkeW5hbW9DbGllbnQuc2VuZChjb21tYW5kKTtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBTdWNjZXNzZnVsbHkgYWxsb2NhdGVkIHByaW9yaXR5ICR7cHJpb3JpdHl9IGZvciBzZXJ2aWNlICR7c2VydmljZUlkZW50aWZpZXJ9YCxcbiAgICApO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIENvbmRpdGlvbmFsQ2hlY2tGYWlsZWRFeGNlcHRpb24pIHtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBgUHJpb3JpdHkgJHtwcmlvcml0eX0gYWxyZWFkeSB0YWtlbiAocmFjZSBjb25kaXRpb24pLCB3aWxsIHRyeSBuZXh0IGF2YWlsYWJsZWAsXG4gICAgICApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhbGxvY2F0aW5nIHByaW9yaXR5OicsIGVycm9yKTtcbiAgICB0aHJvdyBlcnJvcjtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBpZiBhIHByaW9yaXR5IGlzIHdpdGhpbiB2YWxpZCByYW5nZVxuICovXG5mdW5jdGlvbiBpc1ZhbGlkUHJpb3JpdHlSYW5nZShwcmlvcml0eTogbnVtYmVyKTogYm9vbGVhbiB7XG4gIHJldHVybiBwcmlvcml0eSA+PSAxICYmIHByaW9yaXR5IDw9IE1BWF9QUklPUklUWTtcbn1cblxuLyoqXG4gKiBBdHRlbXB0cyB0byBhbGxvY2F0ZSBwcmVmZXJyZWQgcHJpb3JpdHkgaWYgYXZhaWxhYmxlXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHRyeVByZWZlcnJlZFByaW9yaXR5KFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgbGlzdGVuZXJBcm46IHN0cmluZyxcbiAgc2VydmljZUlkZW50aWZpZXI6IHN0cmluZyxcbiAgcHJlZmVycmVkUHJpb3JpdHk6IG51bWJlcixcbiAgdXNlZFByaW9yaXRpZXM6IFNldDxudW1iZXI+LFxuKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XG4gIGlmICghaXNWYWxpZFByaW9yaXR5UmFuZ2UocHJlZmVycmVkUHJpb3JpdHkpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAodXNlZFByaW9yaXRpZXMuaGFzKHByZWZlcnJlZFByaW9yaXR5KSkge1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYFByZWZlcnJlZCBwcmlvcml0eSAke3ByZWZlcnJlZFByaW9yaXR5fSBpcyBhbHJlYWR5IGluIHVzZSwgZmluZGluZyBuZXh0IGF2YWlsYWJsZWAsXG4gICAgKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGFsbG9jYXRlZCA9IGF3YWl0IHRyeUFsbG9jYXRlUHJpb3JpdHkoXG4gICAgdGFibGVOYW1lLFxuICAgIGxpc3RlbmVyQXJuLFxuICAgIHNlcnZpY2VJZGVudGlmaWVyLFxuICAgIHByZWZlcnJlZFByaW9yaXR5LFxuICApO1xuICByZXR1cm4gYWxsb2NhdGVkID8gcHJlZmVycmVkUHJpb3JpdHkgOiBudWxsO1xufVxuXG4vKipcbiAqIEZpbmRzIGxvd2VzdCBhdmFpbGFibGUgcHJpb3JpdHkgd2l0aCBnYXAgZmlsbGluZ1xuICovXG5hc3luYyBmdW5jdGlvbiBmaW5kTG93ZXN0QXZhaWxhYmxlUHJpb3JpdHkoXG4gIHRhYmxlTmFtZTogc3RyaW5nLFxuICBsaXN0ZW5lckFybjogc3RyaW5nLFxuICBzZXJ2aWNlSWRlbnRpZmllcjogc3RyaW5nLFxuICB1c2VkUHJpb3JpdGllczogU2V0PG51bWJlcj4sXG4pOiBQcm9taXNlPG51bWJlcj4ge1xuICBsZXQgcmV0cmllcyA9IDA7XG5cbiAgZm9yIChsZXQgcHJpb3JpdHkgPSAxOyBwcmlvcml0eSA8PSBNQVhfUFJJT1JJVFk7IHByaW9yaXR5KyspIHtcbiAgICBpZiAodXNlZFByaW9yaXRpZXMuaGFzKHByaW9yaXR5KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgYWxsb2NhdGVkID0gYXdhaXQgdHJ5QWxsb2NhdGVQcmlvcml0eShcbiAgICAgIHRhYmxlTmFtZSxcbiAgICAgIGxpc3RlbmVyQXJuLFxuICAgICAgc2VydmljZUlkZW50aWZpZXIsXG4gICAgICBwcmlvcml0eSxcbiAgICApO1xuXG4gICAgaWYgKGFsbG9jYXRlZCkge1xuICAgICAgcmV0dXJuIHByaW9yaXR5O1xuICAgIH1cblxuICAgIC8vIFJhY2UgY29uZGl0aW9uOiBzb21lb25lIGVsc2UgdG9vayB0aGlzIHByaW9yaXR5LCB0cnkgbmV4dFxuICAgIHJldHJpZXMrKztcbiAgICBpZiAocmV0cmllcyA+PSBNQVhfUkVUUklFUykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgRmFpbGVkIHRvIGFsbG9jYXRlIHByaW9yaXR5IGFmdGVyICR7TUFYX1JFVFJJRVN9IHJldHJpZXMgZHVlIHRvIHJhY2UgY29uZGl0aW9uc2AsXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgTm8gYXZhaWxhYmxlIHByaW9yaXRpZXMgZm91bmQgKGFsbCAke01BWF9QUklPUklUWX0gaW4gdXNlKWApO1xufVxuXG4vKipcbiAqIEZpbmRzIHRoZSBsb3dlc3QgYXZhaWxhYmxlIHByaW9yaXR5IGFuZCBhbGxvY2F0ZXMgaXRcbiAqL1xuYXN5bmMgZnVuY3Rpb24gYWxsb2NhdGVQcmlvcml0eShcbiAgdGFibGVOYW1lOiBzdHJpbmcsXG4gIGxpc3RlbmVyQXJuOiBzdHJpbmcsXG4gIHNlcnZpY2VJZGVudGlmaWVyOiBzdHJpbmcsXG4gIHByZWZlcnJlZFByaW9yaXR5PzogbnVtYmVyLFxuKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgLy8gU3RlcCAxOiBDaGVjayBpZiBzZXJ2aWNlIGFscmVhZHkgaGFzIGFuIGFsbG9jYXRpb24gKGlkZW1wb3RlbmN5KVxuICBjb25zdCBleGlzdGluZ1ByaW9yaXR5ID0gYXdhaXQgZ2V0RXhpc3RpbmdBbGxvY2F0aW9uKFxuICAgIHRhYmxlTmFtZSxcbiAgICBsaXN0ZW5lckFybixcbiAgICBzZXJ2aWNlSWRlbnRpZmllcixcbiAgKTtcbiAgaWYgKGV4aXN0aW5nUHJpb3JpdHkgIT09IG51bGwpIHtcbiAgICByZXR1cm4gZXhpc3RpbmdQcmlvcml0eTtcbiAgfVxuXG4gIC8vIFN0ZXAgMjogR2V0IGFsbCB1c2VkIHByaW9yaXRpZXMgZnJvbSBBTEJcbiAgY29uc3QgYWxiUHJpb3JpdGllcyA9IGF3YWl0IGdldEFsYkxpc3RlbmVyUHJpb3JpdGllcyhsaXN0ZW5lckFybik7XG5cbiAgLy8gU3RlcCAzOiBHZXQgYWxsIHRyYWNrZWQgcHJpb3JpdGllcyBmcm9tIER5bmFtb0RCXG4gIGNvbnN0IGR5bmFtb1ByaW9yaXRpZXMgPSBhd2FpdCBnZXREeW5hbW9EYlByaW9yaXRpZXModGFibGVOYW1lLCBsaXN0ZW5lckFybik7XG5cbiAgLy8gU3RlcCA0OiBNZXJnZSBib3RoIHNvdXJjZXMgdG8gZ2V0IGNvbXBsZXRlIHBpY3R1cmVcbiAgY29uc3QgYWxsVXNlZFByaW9yaXRpZXMgPSBuZXcgU2V0KFsuLi5hbGJQcmlvcml0aWVzLCAuLi5keW5hbW9Qcmlvcml0aWVzXSk7XG5cbiAgY29uc29sZS5sb2coXG4gICAgYFRvdGFsIHByaW9yaXRpZXMgaW4gdXNlIChBTEIgKyBEeW5hbW9EQik6ICR7YWxsVXNlZFByaW9yaXRpZXMuc2l6ZX1gLFxuICApO1xuXG4gIC8vIFN0ZXAgNTogVHJ5IHByZWZlcnJlZCBwcmlvcml0eSBmaXJzdCBpZiBwcm92aWRlZFxuICBpZiAocHJlZmVycmVkUHJpb3JpdHkpIHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0cnlQcmVmZXJyZWRQcmlvcml0eShcbiAgICAgIHRhYmxlTmFtZSxcbiAgICAgIGxpc3RlbmVyQXJuLFxuICAgICAgc2VydmljZUlkZW50aWZpZXIsXG4gICAgICBwcmVmZXJyZWRQcmlvcml0eSxcbiAgICAgIGFsbFVzZWRQcmlvcml0aWVzLFxuICAgICk7XG4gICAgaWYgKHJlc3VsdCAhPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxuICAvLyBTdGVwIDY6IEZpbmQgbG93ZXN0IGF2YWlsYWJsZSBwcmlvcml0eSAoZ2FwIGZpbGxpbmcpXG4gIHJldHVybiBmaW5kTG93ZXN0QXZhaWxhYmxlUHJpb3JpdHkoXG4gICAgdGFibGVOYW1lLFxuICAgIGxpc3RlbmVyQXJuLFxuICAgIHNlcnZpY2VJZGVudGlmaWVyLFxuICAgIGFsbFVzZWRQcmlvcml0aWVzLFxuICApO1xufVxuXG4vKipcbiAqIERlbGV0ZXMgYSBwcmlvcml0eSBhbGxvY2F0aW9uIGZyb20gRHluYW1vREJcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZGVsZXRlUHJpb3JpdHlBbGxvY2F0aW9uKFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgbGlzdGVuZXJBcm46IHN0cmluZyxcbiAgc2VydmljZUlkZW50aWZpZXI6IHN0cmluZyxcbik6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIC8vIEZpbmQgdGhlIHByaW9yaXR5IGFsbG9jYXRlZCB0byB0aGlzIHNlcnZpY2VcbiAgICBjb25zdCBjb21tYW5kID0gbmV3IFF1ZXJ5Q29tbWFuZCh7XG4gICAgICBUYWJsZU5hbWU6IHRhYmxlTmFtZSxcbiAgICAgIEluZGV4TmFtZTogJ1NlcnZpY2VJZGVudGlmaWVySW5kZXgnLFxuICAgICAgS2V5Q29uZGl0aW9uRXhwcmVzc2lvbjogJ1NlcnZpY2VJZGVudGlmaWVyID0gOnNpZCBBTkQgTGlzdGVuZXJBcm4gPSA6YXJuJyxcbiAgICAgIEV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgJzpzaWQnOiB7Uzogc2VydmljZUlkZW50aWZpZXJ9LFxuICAgICAgICAnOmFybic6IHtTOiBsaXN0ZW5lckFybn0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBkeW5hbW9DbGllbnQuc2VuZChjb21tYW5kKTtcblxuICAgIGlmICghcmVzcG9uc2UuSXRlbXMgfHwgcmVzcG9uc2UuSXRlbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYE5vIHByaW9yaXR5IGZvdW5kIGZvciBzZXJ2aWNlICR7c2VydmljZUlkZW50aWZpZXJ9LCBub3RoaW5nIHRvIGRlbGV0ZWAsXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGl0ZW0gPSByZXNwb25zZS5JdGVtc1swXTtcbiAgICBjb25zdCBwcmlvcml0eVZhbHVlID0gaXRlbS5Qcmlvcml0eT8uTjtcbiAgICBpZiAoIXByaW9yaXR5VmFsdWUpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1ByaW9yaXR5IG5vdCBmb3VuZCBpbiBpdGVtOicsIGl0ZW0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHByaW9yaXR5ID0gTnVtYmVyLnBhcnNlSW50KHByaW9yaXR5VmFsdWUsIDEwKTtcblxuICAgIC8vIERlbGV0ZSB0aGUgYWxsb2NhdGlvblxuICAgIGNvbnN0IGRlbGV0ZUNvbW1hbmQgPSBuZXcgRGVsZXRlSXRlbUNvbW1hbmQoe1xuICAgICAgVGFibGVOYW1lOiB0YWJsZU5hbWUsXG4gICAgICBLZXk6IHtcbiAgICAgICAgTGlzdGVuZXJBcm46IHtTOiBsaXN0ZW5lckFybn0sXG4gICAgICAgIFByaW9yaXR5OiB7TjogcHJpb3JpdHkudG9TdHJpbmcoKX0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgYXdhaXQgZHluYW1vQ2xpZW50LnNlbmQoZGVsZXRlQ29tbWFuZCk7XG4gICAgY29uc29sZS5sb2coXG4gICAgICBgU3VjY2Vzc2Z1bGx5IGRlbGV0ZWQgcHJpb3JpdHkgJHtwcmlvcml0eX0gZm9yIHNlcnZpY2UgJHtzZXJ2aWNlSWRlbnRpZmllcn1gLFxuICAgICk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcignRXJyb3IgZGVsZXRpbmcgcHJpb3JpdHkgYWxsb2NhdGlvbjonLCBlcnJvcik7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn1cblxuLyoqXG4gKiBNYWluIExhbWJkYSBoYW5kbGVyIGZvciB0aGUgQ3VzdG9tIFJlc291cmNlXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBoYW5kbGVyKFxuICBldmVudDogQ3VzdG9tUmVzb3VyY2VFdmVudCxcbik6IFByb21pc2U8Q3VzdG9tUmVzb3VyY2VSZXNwb25zZT4ge1xuICBjb25zb2xlLmxvZygnUmVjZWl2ZWQgZXZlbnQ6JywgSlNPTi5zdHJpbmdpZnkoZXZlbnQsIG51bGwsIDIpKTtcblxuICBjb25zdCBsaXN0ZW5lckFybiA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5MaXN0ZW5lckFybjtcbiAgY29uc3Qgc2VydmljZUlkZW50aWZpZXIgPSBldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuU2VydmljZUlkZW50aWZpZXI7XG4gIGNvbnN0IHRhYmxlTmFtZSA9IGV2ZW50LlJlc291cmNlUHJvcGVydGllcy5UYWJsZU5hbWU7XG4gIGNvbnN0IHByZWZlcnJlZFByaW9yaXR5ID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlByZWZlcnJlZFByaW9yaXR5XG4gICAgPyBOdW1iZXIucGFyc2VJbnQoZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzLlByZWZlcnJlZFByaW9yaXR5LCAxMClcbiAgICA6IHVuZGVmaW5lZDtcblxuICAvLyBQaHlzaWNhbCByZXNvdXJjZSBJRCBpcyBiYXNlZCBvbiBsaXN0ZW5lciBBUk4gYW5kIHNlcnZpY2UgaWRlbnRpZmllclxuICBjb25zdCBwaHlzaWNhbFJlc291cmNlSWQgPSBoYXNoU2VydmljZUlkZW50aWZpZXIoXG4gICAgYCR7bGlzdGVuZXJBcm59LyR7c2VydmljZUlkZW50aWZpZXJ9YCxcbiAgKTtcblxuICB0cnkge1xuICAgIC8vIEhhbmRsZSBEZWxldGUgb3BlcmF0aW9uXG4gICAgaWYgKGV2ZW50LlJlcXVlc3RUeXBlID09PSAnRGVsZXRlJykge1xuICAgICAgY29uc29sZS5sb2coJ0hhbmRsaW5nIERFTEVURSByZXF1ZXN0IC0gcmVtb3ZpbmcgcHJpb3JpdHkgYWxsb2NhdGlvbicpO1xuICAgICAgYXdhaXQgZGVsZXRlUHJpb3JpdHlBbGxvY2F0aW9uKHRhYmxlTmFtZSwgbGlzdGVuZXJBcm4sIHNlcnZpY2VJZGVudGlmaWVyKTtcbiAgICAgIC8vIFJldHVybiBzdWNjZXNzIHdpdGggcHJpb3JpdHkgMCAoZG9lc24ndCBtYXR0ZXIgZm9yIGRlbGV0ZSlcbiAgICAgIHJldHVybiBzdWNjZXNzKGV2ZW50LCBwaHlzaWNhbFJlc291cmNlSWQsIDApO1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSBDcmVhdGUgYW5kIFVwZGF0ZSBvcGVyYXRpb25zXG4gICAgY29uc29sZS5sb2coYEhhbmRsaW5nICR7ZXZlbnQuUmVxdWVzdFR5cGV9IHJlcXVlc3QgLSBhbGxvY2F0aW5nIHByaW9yaXR5YCk7XG4gICAgY29uc3QgcHJpb3JpdHkgPSBhd2FpdCBhbGxvY2F0ZVByaW9yaXR5KFxuICAgICAgdGFibGVOYW1lLFxuICAgICAgbGlzdGVuZXJBcm4sXG4gICAgICBzZXJ2aWNlSWRlbnRpZmllcixcbiAgICAgIHByZWZlcnJlZFByaW9yaXR5LFxuICAgICk7XG5cbiAgICByZXR1cm4gc3VjY2VzcyhldmVudCwgcGh5c2ljYWxSZXNvdXJjZUlkLCBwcmlvcml0eSk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpO1xuICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGluIGhhbmRsZXI6JywgZXJyb3JNZXNzYWdlKTtcbiAgICByZXR1cm4gZmFpbChldmVudCwgcGh5c2ljYWxSZXNvdXJjZUlkLCBlcnJvck1lc3NhZ2UpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,84 @@
1
+ import { Construct } from 'constructs';
2
+ import { CustomResource } from 'aws-cdk-lib';
3
+ export interface PriorityAllocatorProps {
4
+ /**
5
+ * The ARN of the ALB listener for which to allocate a priority.
6
+ */
7
+ readonly listenerArn: string;
8
+ /**
9
+ * Optional preferred priority. If available, this priority will be allocated.
10
+ * If not available, the next available priority will be allocated.
11
+ *
12
+ * @default - Next available priority is allocated
13
+ */
14
+ readonly preferredPriority?: number;
15
+ }
16
+ /**
17
+ * Allocates a unique priority for an ALB listener rule using a Lambda-backed Custom Resource.
18
+ *
19
+ * This construct implements a singleton pattern for the Lambda function and DynamoDB table,
20
+ * ensuring that only one instance of each exists per AWS account/region regardless of how
21
+ * many services use priority allocation.
22
+ *
23
+ * The allocation algorithm:
24
+ * 1. Checks if this service already has an allocated priority (idempotent)
25
+ * 2. Queries all priorities currently on the ALB listener (source of truth)
26
+ * 3. Queries priorities tracked in DynamoDB
27
+ * 4. Merges both sources to get complete picture
28
+ * 5. Finds lowest available priority (gap filling)
29
+ * 6. Allocates atomically with DynamoDB conditional write
30
+ * 7. Returns allocated priority to CloudFormation
31
+ *
32
+ * On stack deletion, the priority is released back to the pool for reuse.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const allocator = new PriorityAllocator(this, 'PriorityAllocator', {
37
+ * listenerArn: listener.listenerArn,
38
+ * });
39
+ *
40
+ * // Use the allocated priority
41
+ * listener.addTargetGroups('TargetGroup', {
42
+ * targetGroups: [targetGroup],
43
+ * priority: allocator.priority,
44
+ * });
45
+ * ```
46
+ */
47
+ export declare class PriorityAllocator extends Construct {
48
+ /**
49
+ * The allocated priority for the ALB listener rule.
50
+ */
51
+ readonly priority: number;
52
+ /**
53
+ * The service identifier used for tracking this allocation.
54
+ */
55
+ readonly serviceIdentifier: string;
56
+ /**
57
+ * The Custom Resource that manages the priority allocation.
58
+ */
59
+ readonly resource: CustomResource;
60
+ /**
61
+ * Singleton table name - shared across all priority allocators in the account/region.
62
+ */
63
+ private static readonly TABLE_NAME;
64
+ /**
65
+ * Gets or creates the singleton DynamoDB table for priority tracking.
66
+ * Only one table exists per AWS account/region.
67
+ */
68
+ private static getOrCreateTable;
69
+ /**
70
+ * Gets or creates the singleton Lambda function for priority allocation.
71
+ * Only one Lambda function exists per AWS account/region.
72
+ */
73
+ private static getOrCreateLambda;
74
+ /**
75
+ * Gets or creates the singleton Custom Resource Provider.
76
+ * Only one provider exists per AWS account/region.
77
+ */
78
+ private static getOrCreateProvider;
79
+ /**
80
+ * Generates a deterministic service identifier based on the construct path and listener ARN.
81
+ */
82
+ private generateServiceIdentifier;
83
+ constructor(scope: Construct, id: string, props: PriorityAllocatorProps);
84
+ }
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PriorityAllocator = void 0;
4
+ const constructs_1 = require("constructs");
5
+ const aws_lambda_nodejs_1 = require("aws-cdk-lib/aws-lambda-nodejs");
6
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
7
+ const custom_resources_1 = require("aws-cdk-lib/custom-resources");
8
+ const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
9
+ const path = require("node:path");
10
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
11
+ const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
12
+ const crypto = require("node:crypto");
13
+ /**
14
+ * Allocates a unique priority for an ALB listener rule using a Lambda-backed Custom Resource.
15
+ *
16
+ * This construct implements a singleton pattern for the Lambda function and DynamoDB table,
17
+ * ensuring that only one instance of each exists per AWS account/region regardless of how
18
+ * many services use priority allocation.
19
+ *
20
+ * The allocation algorithm:
21
+ * 1. Checks if this service already has an allocated priority (idempotent)
22
+ * 2. Queries all priorities currently on the ALB listener (source of truth)
23
+ * 3. Queries priorities tracked in DynamoDB
24
+ * 4. Merges both sources to get complete picture
25
+ * 5. Finds lowest available priority (gap filling)
26
+ * 6. Allocates atomically with DynamoDB conditional write
27
+ * 7. Returns allocated priority to CloudFormation
28
+ *
29
+ * On stack deletion, the priority is released back to the pool for reuse.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const allocator = new PriorityAllocator(this, 'PriorityAllocator', {
34
+ * listenerArn: listener.listenerArn,
35
+ * });
36
+ *
37
+ * // Use the allocated priority
38
+ * listener.addTargetGroups('TargetGroup', {
39
+ * targetGroups: [targetGroup],
40
+ * priority: allocator.priority,
41
+ * });
42
+ * ```
43
+ */
44
+ class PriorityAllocator extends constructs_1.Construct {
45
+ /**
46
+ * Gets or creates the singleton DynamoDB table for priority tracking.
47
+ * Only one table exists per AWS account/region.
48
+ */
49
+ static getOrCreateTable(scope) {
50
+ const stack = aws_cdk_lib_1.Stack.of(scope);
51
+ const tableId = 'PriorityAllocatorTable';
52
+ // Try to find existing table in the stack
53
+ const existing = stack.node.tryFindChild(tableId);
54
+ if (existing) {
55
+ return existing;
56
+ }
57
+ // Create new table at stack level (singleton)
58
+ const table = new aws_dynamodb_1.Table(stack, tableId, {
59
+ tableName: PriorityAllocator.TABLE_NAME,
60
+ partitionKey: {
61
+ name: 'ListenerArn',
62
+ type: aws_dynamodb_1.AttributeType.STRING,
63
+ },
64
+ sortKey: {
65
+ name: 'Priority',
66
+ type: aws_dynamodb_1.AttributeType.NUMBER,
67
+ },
68
+ billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST,
69
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN, // Never delete - shared infrastructure
70
+ pointInTimeRecoverySpecification: {
71
+ pointInTimeRecoveryEnabled: true,
72
+ },
73
+ });
74
+ // Add GSI for querying by service identifier
75
+ table.addGlobalSecondaryIndex({
76
+ indexName: 'ServiceIdentifierIndex',
77
+ partitionKey: {
78
+ name: 'ServiceIdentifier',
79
+ type: aws_dynamodb_1.AttributeType.STRING,
80
+ },
81
+ sortKey: {
82
+ name: 'ListenerArn',
83
+ type: aws_dynamodb_1.AttributeType.STRING,
84
+ },
85
+ });
86
+ return table;
87
+ }
88
+ /**
89
+ * Gets or creates the singleton Lambda function for priority allocation.
90
+ * Only one Lambda function exists per AWS account/region.
91
+ */
92
+ static getOrCreateLambda(scope, table) {
93
+ const stack = aws_cdk_lib_1.Stack.of(scope);
94
+ const lambdaId = 'PriorityAllocatorLambda';
95
+ // Try to find existing Lambda in the stack
96
+ const existing = stack.node.tryFindChild(lambdaId);
97
+ if (existing) {
98
+ return existing;
99
+ }
100
+ // Create IAM role for Lambda
101
+ const role = new aws_iam_1.Role(stack, 'PriorityAllocatorLambdaRole', {
102
+ assumedBy: new aws_iam_1.ServicePrincipal('lambda.amazonaws.com'),
103
+ description: 'Role for ALB Priority Allocator Lambda function',
104
+ });
105
+ // CloudWatch Logs permissions
106
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
107
+ effect: aws_iam_1.Effect.ALLOW,
108
+ actions: [
109
+ 'logs:CreateLogGroup',
110
+ 'logs:CreateLogStream',
111
+ 'logs:PutLogEvents',
112
+ ],
113
+ resources: ['*'],
114
+ }));
115
+ // ALB read permissions
116
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
117
+ effect: aws_iam_1.Effect.ALLOW,
118
+ actions: [
119
+ 'elasticloadbalancing:DescribeListeners',
120
+ 'elasticloadbalancing:DescribeRules',
121
+ ],
122
+ resources: ['*'],
123
+ }));
124
+ // DynamoDB permissions
125
+ role.addToPolicy(new aws_iam_1.PolicyStatement({
126
+ effect: aws_iam_1.Effect.ALLOW,
127
+ actions: [
128
+ 'dynamodb:Query',
129
+ 'dynamodb:GetItem',
130
+ 'dynamodb:PutItem',
131
+ 'dynamodb:DeleteItem',
132
+ ],
133
+ resources: [table.tableArn, `${table.tableArn}/index/*`],
134
+ }));
135
+ // Create Lambda function
136
+ return new aws_lambda_nodejs_1.NodejsFunction(stack, lambdaId, {
137
+ role,
138
+ runtime: aws_lambda_1.Runtime.NODEJS_20_X,
139
+ handler: 'handler',
140
+ entry: path.join(__dirname, 'priority-allocator-handler.js'),
141
+ timeout: aws_cdk_lib_1.Duration.seconds(30),
142
+ memorySize: 256,
143
+ description: 'Allocates unique priorities for ALB listener rules',
144
+ functionName: 'priority-allocator-singleton',
145
+ });
146
+ }
147
+ /**
148
+ * Gets or creates the singleton Custom Resource Provider.
149
+ * Only one provider exists per AWS account/region.
150
+ */
151
+ static getOrCreateProvider(scope, lambda) {
152
+ const stack = aws_cdk_lib_1.Stack.of(scope);
153
+ const providerId = 'PriorityAllocatorProvider';
154
+ // Try to find existing provider in the stack
155
+ const existing = stack.node.tryFindChild(providerId);
156
+ if (existing) {
157
+ return existing;
158
+ }
159
+ // Create new provider at stack level (singleton)
160
+ return new custom_resources_1.Provider(stack, providerId, {
161
+ onEventHandler: lambda,
162
+ });
163
+ }
164
+ /**
165
+ * Generates a deterministic service identifier based on the construct path and listener ARN.
166
+ */
167
+ generateServiceIdentifier(listenerArn) {
168
+ const stack = aws_cdk_lib_1.Stack.of(this);
169
+ const region = stack.region;
170
+ const account = stack.account;
171
+ const stackName = stack.stackName;
172
+ const constructPath = this.node.path;
173
+ // Create deterministic hash
174
+ const input = `${account}/${region}/${stackName}/${constructPath}/${listenerArn}`;
175
+ const hash = crypto
176
+ .createHash('sha256')
177
+ .update(input)
178
+ .digest('hex')
179
+ .substring(0, 12);
180
+ // Create human-readable identifier with stack name and hash
181
+ const sanitizedStackName = stackName
182
+ .replaceAll(/[^a-zA-Z0-9-]/g, '-')
183
+ .toLowerCase();
184
+ return `${sanitizedStackName}-${hash}`;
185
+ }
186
+ constructor(scope, id, props) {
187
+ var _a;
188
+ super(scope, id);
189
+ // Get or create singleton resources
190
+ const table = PriorityAllocator.getOrCreateTable(this);
191
+ const lambda = PriorityAllocator.getOrCreateLambda(this, table);
192
+ const provider = PriorityAllocator.getOrCreateProvider(this, lambda);
193
+ // Generate service identifier
194
+ this.serviceIdentifier = this.generateServiceIdentifier(props.listenerArn);
195
+ // Create Custom Resource for this specific service
196
+ this.resource = new aws_cdk_lib_1.CustomResource(this, 'Resource', {
197
+ serviceToken: provider.serviceToken,
198
+ properties: {
199
+ ListenerArn: props.listenerArn,
200
+ ServiceIdentifier: this.serviceIdentifier,
201
+ TableName: PriorityAllocator.TABLE_NAME,
202
+ PreferredPriority: (_a = props.preferredPriority) === null || _a === void 0 ? void 0 : _a.toString(),
203
+ // Add timestamp to ensure update on property changes
204
+ Timestamp: Date.now().toString(),
205
+ },
206
+ });
207
+ // Extract priority from custom resource
208
+ this.priority = aws_cdk_lib_1.Token.asNumber(this.resource.getAtt('Priority'));
209
+ // Add CloudFormation outputs for debugging
210
+ new aws_cdk_lib_1.CfnOutput(this, 'ServiceIdentifier', {
211
+ value: this.serviceIdentifier,
212
+ description: 'Service identifier for priority allocation tracking',
213
+ });
214
+ new aws_cdk_lib_1.CfnOutput(this, 'AllocatedPriority', {
215
+ value: this.priority.toString(),
216
+ description: 'Auto-allocated priority for ALB listener rule',
217
+ });
218
+ }
219
+ }
220
+ exports.PriorityAllocator = PriorityAllocator;
221
+ /**
222
+ * Singleton table name - shared across all priority allocators in the account/region.
223
+ */
224
+ PriorityAllocator.TABLE_NAME = 'alb-listener-priorities';
225
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJpb3JpdHktYWxsb2NhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicHJpb3JpdHktYWxsb2NhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUFxQztBQUNyQyxxRUFBNkQ7QUFDN0QsNkNBT3FCO0FBQ3JCLG1FQUFzRDtBQUN0RCx1REFBK0M7QUFDL0Msa0NBQWtDO0FBQ2xDLGlEQUs2QjtBQUM3QiwyREFBMkU7QUFDM0Usc0NBQXNDO0FBaUJ0Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEJHO0FBQ0gsTUFBYSxpQkFBa0IsU0FBUSxzQkFBUztJQXFCOUM7OztPQUdHO0lBQ0ssTUFBTSxDQUFDLGdCQUFnQixDQUFDLEtBQWdCO1FBQzlDLE1BQU0sS0FBSyxHQUFHLG1CQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlCLE1BQU0sT0FBTyxHQUFHLHdCQUF3QixDQUFDO1FBRXpDLDBDQUEwQztRQUMxQyxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQXNCLENBQUM7UUFDdkUsSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUNiLE9BQU8sUUFBUSxDQUFDO1FBQ2xCLENBQUM7UUFFRCw4Q0FBOEM7UUFDOUMsTUFBTSxLQUFLLEdBQUcsSUFBSSxvQkFBSyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUU7WUFDdEMsU0FBUyxFQUFFLGlCQUFpQixDQUFDLFVBQVU7WUFDdkMsWUFBWSxFQUFFO2dCQUNaLElBQUksRUFBRSxhQUFhO2dCQUNuQixJQUFJLEVBQUUsNEJBQWEsQ0FBQyxNQUFNO2FBQzNCO1lBQ0QsT0FBTyxFQUFFO2dCQUNQLElBQUksRUFBRSxVQUFVO2dCQUNoQixJQUFJLEVBQUUsNEJBQWEsQ0FBQyxNQUFNO2FBQzNCO1lBQ0QsV0FBVyxFQUFFLDBCQUFXLENBQUMsZUFBZTtZQUN4QyxhQUFhLEVBQUUsMkJBQWEsQ0FBQyxNQUFNLEVB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LE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBRWpFLDJDQUEyQztRQUMzQyxJQUFJLHVCQUFTLENBQUMsSUFBSSxFQUFFLG1CQUFtQixFQUFFO1lBQ3ZDLEtBQUssRUFBRSxJQUFJLENBQUMsaUJBQWlCO1lBQzdCLFdBQVcsRUFBRSxxREFBcUQ7U0FDbkUsQ0FBQyxDQUFDO1FBRUgsSUFBSSx1QkFBUyxDQUFDLElBQUksRUFBRSxtQkFBbUIsRUFBRTtZQUN2QyxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUU7WUFDL0IsV0FBVyxFQUFFLCtDQUErQztTQUM3RCxDQUFDLENBQUM7SUFDTCxDQUFDOztBQXpPSCw4Q0EwT0M7QUExTkM7O0dBRUc7QUFDcUIsNEJBQVUsR0FBRyx5QkFBeUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29uc3RydWN0fSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7Tm9kZWpzRnVuY3Rpb259IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtbm9kZWpzJztcbmltcG9ydCB7XG4gIEN1c3RvbVJlc291cmNlLFxuICBEdXJhdGlvbixcbiAgUmVtb3ZhbFBvbGljeSxcbiAgU3RhY2ssXG4gIENmbk91dHB1dCxcbiAgVG9rZW4sXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCB7UHJvdmlkZXJ9IGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0IHtSdW50aW1lfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7XG4gIEVmZmVjdCxcbiAgUG9saWN5U3RhdGVtZW50LFxuICBSb2xlLFxuICBTZXJ2aWNlUHJpbmNpcGFsLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7QXR0cmlidXRlVHlwZSwgQmlsbGluZ01vZGUsIFRhYmxlfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGInO1xuaW1wb3J0ICogYXMgY3J5cHRvIGZyb20gJ25vZGU6Y3J5cHRvJztcblxuZXhwb3J0IGludGVyZmFjZSBQcmlvcml0eUFsbG9jYXRvclByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIEFMQiBsaXN0ZW5lciBmb3Igd2hpY2ggdG8gYWxsb2NhdGUgYSBwcmlvcml0eS5cbiAgICovXG4gIHJlYWRvbmx5IGxpc3RlbmVyQXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIHByZWZlcnJlZCBwcmlvcml0eS4gSWYgYXZhaWxhYmxlLCB0aGlzIHByaW9yaXR5IHdpbGwgYmUgYWxsb2NhdGVkLlxuICAgKiBJZiBub3QgYXZhaWxhYmxlLCB0aGUgbmV4dCBhdmFpbGFibGUgcHJpb3JpdHkgd2lsbCBiZSBhbGxvY2F0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTmV4dCBhdmFpbGFibGUgcHJpb3JpdHkgaXMgYWxsb2NhdGVkXG4gICAqL1xuICByZWFkb25seSBwcmVmZXJyZWRQcmlvcml0eT86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBBbGxvY2F0ZXMgYSB1bmlxdWUgcHJpb3JpdHkgZm9yIGFuIEFMQiBsaXN0ZW5lciBydWxlIHVzaW5nIGEgTGFtYmRhLWJhY2tlZCBDdXN0b20gUmVzb3VyY2UuXG4gKlxuICogVGhpcyBjb25zdHJ1Y3QgaW1wbGVtZW50cyBhIHNpbmdsZXRvbiBwYXR0ZXJuIGZvciB0aGUgTGFtYmRhIGZ1bmN0aW9uIGFuZCBEeW5hbW9EQiB0YWJsZSxcbiAqIGVuc3VyaW5nIHRoYXQgb25seSBvbmUgaW5zdGFuY2Ugb2YgZWFjaCBleGlzdHMgcGVyIEFXUyBhY2NvdW50L3JlZ2lvbiByZWdhcmRsZXNzIG9mIGhvd1xuICogbWFueSBzZXJ2aWNlcyB1c2UgcHJpb3JpdHkgYWxsb2NhdGlvbi5cbiAqXG4gKiBUaGUgYWxsb2NhdGlvbiBhbGdvcml0aG06XG4gKiAxLiBDaGVja3MgaWYgdGhpcyBzZXJ2aWNlIGFscmVhZHkgaGFzIGFuIGFsbG9jYXRlZCBwcmlvcml0eSAoaWRlbXBvdGVudClcbiAqIDIuIFF1ZXJpZXMgYWxsIHByaW9yaXRpZXMgY3VycmVudGx5IG9uIHRoZSBBTEIgbGlzdGVuZXIgKHNvdXJjZSBvZiB0cnV0aClcbiAqIDMuIFF1ZXJpZXMgcHJpb3JpdGllcyB0cmFja2VkIGluIER5bmFtb0RCXG4gKiA0LiBNZXJnZXMgYm90aCBzb3VyY2VzIHRvIGdldCBjb21wbGV0ZSBwaWN0dXJlXG4gKiA1LiBGaW5kcyBsb3dlc3QgYXZhaWxhYmxlIHByaW9yaXR5IChnYXAgZmlsbGluZylcbiAqIDYuIEFsbG9jYXRlcyBhdG9taWNhbGx5IHdpdGggRHluYW1vREIgY29uZGl0aW9uYWwgd3JpdGVcbiAqIDcuIFJldHVybnMgYWxsb2NhdGVkIHByaW9yaXR5IHRvIENsb3VkRm9ybWF0aW9uXG4gKlxuICogT24gc3RhY2sgZGVsZXRpb24sIHRoZSBwcmlvcml0eSBpcyByZWxlYXNlZCBiYWNrIHRvIHRoZSBwb29sIGZvciByZXVzZS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgYWxsb2NhdG9yID0gbmV3IFByaW9yaXR5QWxsb2NhdG9yKHRoaXMsICdQcmlvcml0eUFsbG9jYXRvcicsIHtcbiAqICAgbGlzdGVuZXJBcm46IGxpc3RlbmVyLmxpc3RlbmVyQXJuLFxuICogfSk7XG4gKlxuICogLy8gVXNlIHRoZSBhbGxvY2F0ZWQgcHJpb3JpdHlcbiAqIGxpc3RlbmVyLmFkZFRhcmdldEdyb3VwcygnVGFyZ2V0R3JvdXAnLCB7XG4gKiAgIHRhcmdldEdyb3VwczogW3RhcmdldEdyb3VwXSxcbiAqICAgcHJpb3JpdHk6IGFsbG9jYXRvci5wcmlvcml0eSxcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBQcmlvcml0eUFsbG9jYXRvciBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKlxuICAgKiBUaGUgYWxsb2NhdGVkIHByaW9yaXR5IGZvciB0aGUgQUxCIGxpc3RlbmVyIHJ1bGUuXG4gICAqL1xuICByZWFkb25seSBwcmlvcml0eTogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgc2VydmljZSBpZGVudGlmaWVyIHVzZWQgZm9yIHRyYWNraW5nIHRoaXMgYWxsb2NhdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHNlcnZpY2VJZGVudGlmaWVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBDdXN0b20gUmVzb3VyY2UgdGhhdCBtYW5hZ2VzIHRoZSBwcmlvcml0eSBhbGxvY2F0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2U6IEN1c3RvbVJlc291cmNlO1xuXG4gIC8qKlxuICAgKiBTaW5nbGV0b24gdGFibGUgbmFtZSAtIHNoYXJlZCBhY3Jvc3MgYWxsIHByaW9yaXR5IGFsbG9jYXRvcnMgaW4gdGhlIGFjY291bnQvcmVnaW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgVEFCTEVfTkFNRSA9ICdhbGItbGlzdGVuZXItcHJpb3JpdGllcyc7XG5cbiAgLyoqXG4gICAqIEdldHMgb3IgY3JlYXRlcyB0aGUgc2luZ2xldG9uIER5bmFtb0RCIHRhYmxlIGZvciBwcmlvcml0eSB0cmFja2luZy5cbiAgICogT25seSBvbmUgdGFibGUgZXhpc3RzIHBlciBBV1MgYWNjb3VudC9yZWdpb24uXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBnZXRPckNyZWF0ZVRhYmxlKHNjb3BlOiBDb25zdHJ1Y3QpOiBUYWJsZSB7XG4gICAgY29uc3Qgc3RhY2sgPSBTdGFjay5vZihzY29wZSk7XG4gICAgY29uc3QgdGFibGVJZCA9ICdQcmlvcml0eUFsbG9jYXRvclRhYmxlJztcblxuICAgIC8vIFRyeSB0byBmaW5kIGV4aXN0aW5nIHRhYmxlIGluIHRoZSBzdGFja1xuICAgIGNvbnN0IGV4aXN0aW5nID0gc3RhY2subm9kZS50cnlGaW5kQ2hpbGQodGFibGVJZCkgYXMgVGFibGUgfCB1bmRlZmluZWQ7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gZXhpc3Rpbmc7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIG5ldyB0YWJsZSBhdCBzdGFjayBsZXZlbCAoc2luZ2xldG9uKVxuICAgIGNvbnN0IHRhYmxlID0gbmV3IFRhYmxlKHN0YWNrLCB0YWJsZUlkLCB7XG4gICAgICB0YWJsZU5hbWU6IFByaW9yaXR5QWxsb2NhdG9yLlRBQkxFX05BTUUsXG4gICAgICBwYXJ0aXRpb25LZXk6IHtcbiAgICAgICAgbmFtZTogJ0xpc3RlbmVyQXJuJyxcbiAgICAgICAgdHlwZTogQXR0cmlidXRlVHlwZS5TVFJJTkcsXG4gICAgICB9LFxuICAgICAgc29ydEtleToge1xuICAgICAgICBuYW1lOiAnUHJpb3JpdHknLFxuICAgICAgICB0eXBlOiBBdHRyaWJ1dGVUeXBlLk5VTUJFUixcbiAgICAgIH0sXG4gICAgICBiaWxsaW5nTW9kZTogQmlsbGluZ01vZGUuUEFZX1BFUl9SRVFVRVNULFxuICAgICAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5SRVRBSU4sIC8vIE5ldmVyIGRlbGV0ZSAtIHNoYXJlZCBpbmZyYXN0cnVjdHVyZVxuICAgICAgcG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb246IHtcbiAgICAgICAgcG9pbnRJblRpbWVSZWNvdmVyeUVuYWJsZWQ6IHRydWUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIEdTSSBmb3IgcXVlcnlpbmcgYnkgc2VydmljZSBpZGVudGlmaWVyXG4gICAgdGFibGUuYWRkR2xvYmFsU2Vjb25kYXJ5SW5kZXgoe1xuICAgICAgaW5kZXhOYW1lOiAnU2VydmljZUlkZW50aWZpZXJJbmRleCcsXG4gICAgICBwYXJ0aXRpb25LZXk6IHtcbiAgICAgICAgbmFtZTogJ1NlcnZpY2VJZGVudGlmaWVyJyxcbiAgICAgICAgdHlwZTogQXR0cmlidXRlVHlwZS5TVFJJTkcsXG4gICAgICB9LFxuICAgICAgc29ydEtleToge1xuICAgICAgICBuYW1lOiAnTGlzdGVuZXJBcm4nLFxuICAgICAgICB0eXBlOiBBdHRyaWJ1dGVUeXBlLlNUUklORyxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGFibGU7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBvciBjcmVhdGVzIHRoZSBzaW5nbGV0b24gTGFtYmRhIGZ1bmN0aW9uIGZvciBwcmlvcml0eSBhbGxvY2F0aW9uLlxuICAgKiBPbmx5IG9uZSBMYW1iZGEgZnVuY3Rpb24gZXhpc3RzIHBlciBBV1MgYWNjb3VudC9yZWdpb24uXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBnZXRPckNyZWF0ZUxhbWJkYShcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIHRhYmxlOiBUYWJsZSxcbiAgKTogTm9kZWpzRnVuY3Rpb24ge1xuICAgIGNvbnN0IHN0YWNrID0gU3RhY2sub2Yoc2NvcGUpO1xuICAgIGNvbnN0IGxhbWJkYUlkID0gJ1ByaW9yaXR5QWxsb2NhdG9yTGFtYmRhJztcblxuICAgIC8vIFRyeSB0byBmaW5kIGV4aXN0aW5nIExhbWJkYSBpbiB0aGUgc3RhY2tcbiAgICBjb25zdCBleGlzdGluZyA9IHN0YWNrLm5vZGUudHJ5RmluZENoaWxkKGxhbWJkYUlkKSBhc1xuICAgICAgfCBOb2RlanNGdW5jdGlvblxuICAgICAgfCB1bmRlZmluZWQ7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICByZXR1cm4gZXhpc3Rpbmc7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIElBTSByb2xlIGZvciBMYW1iZGFcbiAgICBjb25zdCByb2xlID0gbmV3IFJvbGUoc3RhY2ssICdQcmlvcml0eUFsbG9jYXRvckxhbWJkYVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdsYW1iZGEuYW1hem9uYXdzLmNvbScpLFxuICAgICAgZGVzY3JpcHRpb246ICdSb2xlIGZvciBBTEIgUHJpb3JpdHkgQWxsb2NhdG9yIExhbWJkYSBmdW5jdGlvbicsXG4gICAgfSk7XG5cbiAgICAvLyBDbG91ZFdhdGNoIExvZ3MgcGVybWlzc2lvbnNcbiAgICByb2xlLmFkZFRvUG9saWN5KFxuICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgJ2xvZ3M6Q3JlYXRlTG9nR3JvdXAnLFxuICAgICAgICAgICdsb2dzOkNyZWF0ZUxvZ1N0cmVhbScsXG4gICAgICAgICAgJ2xvZ3M6UHV0TG9nRXZlbnRzJyxcbiAgICAgICAgXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICAvLyBBTEIgcmVhZCBwZXJtaXNzaW9uc1xuICAgIHJvbGUuYWRkVG9Qb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAnZWxhc3RpY2xvYWRiYWxhbmNpbmc6RGVzY3JpYmVMaXN0ZW5lcnMnLFxuICAgICAgICAgICdlbGFzdGljbG9hZGJhbGFuY2luZzpEZXNjcmliZVJ1bGVzJyxcbiAgICAgICAgXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICAvLyBEeW5hbW9EQiBwZXJtaXNzaW9uc1xuICAgIHJvbGUuYWRkVG9Qb2xpY3koXG4gICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICAnZHluYW1vZGI6UXVlcnknLFxuICAgICAgICAgICdkeW5hbW9kYjpHZXRJdGVtJyxcbiAgICAgICAgICAnZHluYW1vZGI6UHV0SXRlbScsXG4gICAgICAgICAgJ2R5bmFtb2RiOkRlbGV0ZUl0ZW0nLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFt0YWJsZS50YWJsZUFybiwgYCR7dGFibGUudGFibGVBcm59L2luZGV4LypgXSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICAvLyBDcmVhdGUgTGFtYmRhIGZ1bmN0aW9uXG4gICAgcmV0dXJuIG5ldyBOb2RlanNGdW5jdGlvbihzdGFjaywgbGFtYmRhSWQsIHtcbiAgICAgIHJvbGUsXG4gICAgICBydW50aW1lOiBSdW50aW1lLk5PREVKU18yMF9YLFxuICAgICAgaGFuZGxlcjogJ2hhbmRsZXInLFxuICAgICAgZW50cnk6IHBhdGguam9pbihfX2Rpcm5hbWUsICdwcmlvcml0eS1hbGxvY2F0b3ItaGFuZGxlci5qcycpLFxuICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcygzMCksXG4gICAgICBtZW1vcnlTaXplOiAyNTYsXG4gICAgICBkZXNjcmlwdGlvbjogJ0FsbG9jYXRlcyB1bmlxdWUgcHJpb3JpdGllcyBmb3IgQUxCIGxpc3RlbmVyIHJ1bGVzJyxcbiAgICAgIGZ1bmN0aW9uTmFtZTogJ3ByaW9yaXR5LWFsbG9jYXRvci1zaW5nbGV0b24nLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgb3IgY3JlYXRlcyB0aGUgc2luZ2xldG9uIEN1c3RvbSBSZXNvdXJjZSBQcm92aWRlci5cbiAgICogT25seSBvbmUgcHJvdmlkZXIgZXhpc3RzIHBlciBBV1MgYWNjb3VudC9yZWdpb24uXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyBnZXRPckNyZWF0ZVByb3ZpZGVyKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgbGFtYmRhOiBOb2RlanNGdW5jdGlvbixcbiAgKTogUHJvdmlkZXIge1xuICAgIGNvbnN0IHN0YWNrID0gU3RhY2sub2Yoc2NvcGUpO1xuICAgIGNvbnN0IHByb3ZpZGVySWQgPSAnUHJpb3JpdHlBbGxvY2F0b3JQcm92aWRlcic7XG5cbiAgICAvLyBUcnkgdG8gZmluZCBleGlzdGluZyBwcm92aWRlciBpbiB0aGUgc3RhY2tcbiAgICBjb25zdCBleGlzdGluZyA9IHN0YWNrLm5vZGUudHJ5RmluZENoaWxkKHByb3ZpZGVySWQpIGFzXG4gICAgICB8IFByb3ZpZGVyXG4gICAgICB8IHVuZGVmaW5lZDtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIHJldHVybiBleGlzdGluZztcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgbmV3IHByb3ZpZGVyIGF0IHN0YWNrIGxldmVsIChzaW5nbGV0b24pXG4gICAgcmV0dXJuIG5ldyBQcm92aWRlcihzdGFjaywgcHJvdmlkZXJJZCwge1xuICAgICAgb25FdmVudEhhbmRsZXI6IGxhbWJkYSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgYSBkZXRlcm1pbmlzdGljIHNlcnZpY2UgaWRlbnRpZmllciBiYXNlZCBvbiB0aGUgY29uc3RydWN0IHBhdGggYW5kIGxpc3RlbmVyIEFSTi5cbiAgICovXG4gIHByaXZhdGUgZ2VuZXJhdGVTZXJ2aWNlSWRlbnRpZmllcihsaXN0ZW5lckFybjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IHJlZ2lvbiA9IHN0YWNrLnJlZ2lvbjtcbiAgICBjb25zdCBhY2NvdW50ID0gc3RhY2suYWNjb3VudDtcbiAgICBjb25zdCBzdGFja05hbWUgPSBzdGFjay5zdGFja05hbWU7XG4gICAgY29uc3QgY29uc3RydWN0UGF0aCA9IHRoaXMubm9kZS5wYXRoO1xuXG4gICAgLy8gQ3JlYXRlIGRldGVybWluaXN0aWMgaGFzaFxuICAgIGNvbnN0IGlucHV0ID0gYCR7YWNjb3VudH0vJHtyZWdpb259LyR7c3RhY2tOYW1lfS8ke2NvbnN0cnVjdFBhdGh9LyR7bGlzdGVuZXJBcm59YDtcbiAgICBjb25zdCBoYXNoID0gY3J5cHRvXG4gICAgICAuY3JlYXRlSGFzaCgnc2hhMjU2JylcbiAgICAgIC51cGRhdGUoaW5wdXQpXG4gICAgICAuZGlnZXN0KCdoZXgnKVxuICAgICAgLnN1YnN0cmluZygwLCAxMik7XG5cbiAgICAvLyBDcmVhdGUgaHVtYW4tcmVhZGFibGUgaWRlbnRpZmllciB3aXRoIHN0YWNrIG5hbWUgYW5kIGhhc2hcbiAgICBjb25zdCBzYW5pdGl6ZWRTdGFja05hbWUgPSBzdGFja05hbWVcbiAgICAgIC5yZXBsYWNlQWxsKC9bXmEtekEtWjAtOS1dL2csICctJylcbiAgICAgIC50b0xvd2VyQ2FzZSgpO1xuICAgIHJldHVybiBgJHtzYW5pdGl6ZWRTdGFja05hbWV9LSR7aGFzaH1gO1xuICB9XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFByaW9yaXR5QWxsb2NhdG9yUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gR2V0IG9yIGNyZWF0ZSBzaW5nbGV0b24gcmVzb3VyY2VzXG4gICAgY29uc3QgdGFibGUgPSBQcmlvcml0eUFsbG9jYXRvci5nZXRPckNyZWF0ZVRhYmxlKHRoaXMpO1xuICAgIGNvbnN0IGxhbWJkYSA9IFByaW9yaXR5QWxsb2NhdG9yLmdldE9yQ3JlYXRlTGFtYmRhKHRoaXMsIHRhYmxlKTtcbiAgICBjb25zdCBwcm92aWRlciA9IFByaW9yaXR5QWxsb2NhdG9yLmdldE9yQ3JlYXRlUHJvdmlkZXIodGhpcywgbGFtYmRhKTtcblxuICAgIC8vIEdlbmVyYXRlIHNlcnZpY2UgaWRlbnRpZmllclxuICAgIHRoaXMuc2VydmljZUlkZW50aWZpZXIgPSB0aGlzLmdlbmVyYXRlU2VydmljZUlkZW50aWZpZXIocHJvcHMubGlzdGVuZXJBcm4pO1xuXG4gICAgLy8gQ3JlYXRlIEN1c3RvbSBSZXNvdXJjZSBmb3IgdGhpcyBzcGVjaWZpYyBzZXJ2aWNlXG4gICAgdGhpcy5yZXNvdXJjZSA9IG5ldyBDdXN0b21SZXNvdXJjZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgTGlzdGVuZXJBcm46IHByb3BzLmxpc3RlbmVyQXJuLFxuICAgICAgICBTZXJ2aWNlSWRlbnRpZmllcjogdGhpcy5zZXJ2aWNlSWRlbnRpZmllcixcbiAgICAgICAgVGFibGVOYW1lOiBQcmlvcml0eUFsbG9jYXRvci5UQUJMRV9OQU1FLFxuICAgICAgICBQcmVmZXJyZWRQcmlvcml0eTogcHJvcHMucHJlZmVycmVkUHJpb3JpdHk/LnRvU3RyaW5nKCksXG4gICAgICAgIC8vIEFkZCB0aW1lc3RhbXAgdG8gZW5zdXJlIHVwZGF0ZSBvbiBwcm9wZXJ0eSBjaGFuZ2VzXG4gICAgICAgIFRpbWVzdGFtcDogRGF0ZS5ub3coKS50b1N0cmluZygpLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIEV4dHJhY3QgcHJpb3JpdHkgZnJvbSBjdXN0b20gcmVzb3VyY2VcbiAgICB0aGlzLnByaW9yaXR5ID0gVG9rZW4uYXNOdW1iZXIodGhpcy5yZXNvdXJjZS5nZXRBdHQoJ1ByaW9yaXR5JykpO1xuXG4gICAgLy8gQWRkIENsb3VkRm9ybWF0aW9uIG91dHB1dHMgZm9yIGRlYnVnZ2luZ1xuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgJ1NlcnZpY2VJZGVudGlmaWVyJywge1xuICAgICAgdmFsdWU6IHRoaXMuc2VydmljZUlkZW50aWZpZXIsXG4gICAgICBkZXNjcmlwdGlvbjogJ1NlcnZpY2UgaWRlbnRpZmllciBmb3IgcHJpb3JpdHkgYWxsb2NhdGlvbiB0cmFja2luZycsXG4gICAgfSk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsICdBbGxvY2F0ZWRQcmlvcml0eScsIHtcbiAgICAgIHZhbHVlOiB0aGlzLnByaW9yaXR5LnRvU3RyaW5nKCksXG4gICAgICBkZXNjcmlwdGlvbjogJ0F1dG8tYWxsb2NhdGVkIHByaW9yaXR5IGZvciBBTEIgbGlzdGVuZXIgcnVsZScsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -138,8 +138,12 @@ export interface StandardApplicationFargateServiceProps extends StandardFargateS
138
138
  readonly listener?: IApplicationListener;
139
139
  /**
140
140
  * The priority to give the target group on the ALB.
141
+ * If not specified, a unique priority is automatically allocated using
142
+ * the PriorityAllocator, which coordinates with other services across
143
+ * multiple teams and tools (CDK, Terraform, manual) to find the lowest
144
+ * available priority.
141
145
  *
142
- * @default - 1
146
+ * @default - Automatically allocated (recommended for most use cases)
143
147
  */
144
148
  readonly targetGroupPriority?: number;
145
149
  /**
@@ -7,12 +7,13 @@ const aws_elasticloadbalancingv2_1 = require("aws-cdk-lib/aws-elasticloadbalanci
7
7
  const aws_route53_1 = require("aws-cdk-lib/aws-route53");
8
8
  const aws_route53_2 = require("../../aws-route53");
9
9
  const aws_route53_targets_1 = require("aws-cdk-lib/aws-route53-targets");
10
+ const priority_allocator_1 = require("./priority-allocator");
10
11
  /**
11
12
  * Creates an ECS Fargate service and maps it to an Application Load Balancer (ALB).
12
13
  */
13
14
  class StandardApplicationFargateService extends standard_fargate_service_1.StandardFargateService {
14
15
  constructor(scope, id, props) {
15
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
16
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
16
17
  super(scope, id, {
17
18
  ...props,
18
19
  healthCheckGracePeriod: (_a = props.healthCheckGracePeriod) !== null && _a !== void 0 ? _a : aws_cdk_lib_1.Duration.seconds(60),
@@ -87,10 +88,23 @@ class StandardApplicationFargateService extends standard_fargate_service_1.Stand
87
88
  loadBalancerArn: loadBalancer.loadBalancerArn,
88
89
  listenerProtocol: aws_elasticloadbalancingv2_1.ApplicationProtocol.HTTPS,
89
90
  });
91
+ // Determine priority: use explicit value, or allocate automatically
92
+ let priority;
93
+ if (props.targetGroupPriority !== undefined) {
94
+ // Manual priority specified - use it directly
95
+ priority = props.targetGroupPriority;
96
+ }
97
+ else {
98
+ // No priority specified - use automatic allocation
99
+ const allocator = new priority_allocator_1.PriorityAllocator(this, 'PriorityAllocator', {
100
+ listenerArn: listener.listenerArn,
101
+ });
102
+ priority = allocator.priority;
103
+ }
90
104
  listener.addTargetGroups(`${id}TargetGroups`, {
91
105
  targetGroups: [targetGroup],
92
106
  conditions: targetGroupConditions,
93
- priority: (_s = props.targetGroupPriority) !== null && _s !== void 0 ? _s : 1,
107
+ priority,
94
108
  });
95
109
  if (props.domainName !== undefined &&
96
110
  props.domainZone !== undefined &&
@@ -108,4 +122,4 @@ class StandardApplicationFargateService extends standard_fargate_service_1.Stand
108
122
  }
109
123
  }
110
124
  exports.StandardApplicationFargateService = StandardApplicationFargateService;
111
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhbmRhcmQtYXBwbGljYXRpb24tZmFyZ2F0ZS1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RhbmRhcmQtYXBwbGljYXRpb24tZmFyZ2F0ZS1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlFQUdvQztBQUVwQyw2Q0FBcUM7QUFDckMsdUZBVWdEO0FBQ2hELHlEQUEyRTtBQUMzRSxtREFBNkM7QUFDN0MseUVBQW1FO0FBeUtuRTs7R0FFRztBQUNILE1BQWEsaUNBQWtDLFNBQVEsaURBQXNCO0lBTzNFLFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQTZDOztRQUU3QyxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLEdBQUcsS0FBSztZQUNSLHNCQUFzQixFQUNwQixNQUFBLEtBQUssQ0FBQyxzQkFBc0IsbUNBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1NBQ3ZELENBQUMsQ0FBQztRQUVILElBQUksd0JBQXdCLEdBQzFCLE1BQUEsS0FBSyxDQUFDLHdCQUF3QixtQ0FBSSxzQkFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyRCxJQUFJLHdCQUF3QixDQUFDLFNBQVMsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQy9DLHdCQUF3QixHQUFHLFNBQVMsQ0FBQztRQUN2QyxDQUFDO1FBRUQsSUFBSSxvQkFBd0MsQ0FBQztRQUM3QyxJQUFJLHdCQUF3QixLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzNDLG9CQUFvQixHQUFHLE1BQUEsS0FBSyxDQUFDLG9CQUFvQixtQ0FBSSxhQUFhLENBQUM7UUFDckUsQ0FBQztRQUVELElBQUksU0FBUyxHQUNYLE1BQUEsS0FBSyxDQUFDLFNBQVMsbUNBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDMUMsSUFBSSxTQUFTLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUM7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QUssQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQ3BDLHVDQUF1QztZQUN2QyxJQUFJLENBQUMsd0JBQXdCLENBQzNCLDJCQUEyQixFQUMzQixXQUFXLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUNwQyxLQUFLLENBQUMseUJBQXlCLENBQUMsYUFBYSxDQUM5QyxFQUNELEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxTQUFTLENBQzFDLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBakpELDhFQWlKQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIFN0YW5kYXJkRmFyZ2F0ZVNlcnZpY2UsXG4gIFN0YW5kYXJkRmFyZ2F0ZVNlcnZpY2VQcm9wcyxcbn0gZnJvbSAnLi9zdGFuZGFyZC1mYXJnYXRlLXNlcnZpY2UnO1xuaW1wb3J0IHtDb25zdHJ1Y3R9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHtEdXJhdGlvbn0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgQXBwbGljYXRpb25MaXN0ZW5lcixcbiAgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIsXG4gIEFwcGxpY2F0aW9uUHJvdG9jb2wsXG4gIEFwcGxpY2F0aW9uVGFyZ2V0R3JvdXAsXG4gIElBcHBsaWNhdGlvbkxpc3RlbmVyLFxuICBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIsXG4gIElBcHBsaWNhdGlvblRhcmdldEdyb3VwLFxuICBMaXN0ZW5lckNvbmRpdGlvbixcbiAgVGFyZ2V0R3JvdXBMb2FkQmFsYW5jaW5nQWxnb3JpdGhtVHlwZSxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVsYXN0aWNsb2FkYmFsYW5jaW5ndjInO1xuaW1wb3J0IHtBUmVjb3JkLCBJSG9zdGVkWm9uZSwgUmVjb3JkVGFyZ2V0fSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtcm91dGU1Myc7XG5pbXBvcnQge0RvbWFpbk5hbWV9IGZyb20gJy4uLy4uL2F3cy1yb3V0ZTUzJztcbmltcG9ydCB7TG9hZEJhbGFuY2VyVGFyZ2V0fSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtcm91dGU1My10YXJnZXRzJztcbmltcG9ydCB7TWV0cmljT3B0aW9uc30gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2gnO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIFN0YW5kYXJkQXBwbGljYXRpb25GYXJnYXRlU2VydmljZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YW5kYXJkQXBwbGljYXRpb25GYXJnYXRlU2VydmljZVByb3BzIGV4dGVuZHMgU3RhbmRhcmRGYXJnYXRlU2VydmljZVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIGFuIGFwcGxpY2F0aW9uLWJhc2VkIHN0aWNraW5lc3MgY29va2llLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGxiX2FmZmluaXR5XG4gICAqL1xuICByZWFkb25seSBzdGlja2luZXNzQ29va2llTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHN0aWNraW5lc3MgY29va2llIGV4cGlyYXRpb24gcGVyaW9kLiBTZXQgdG8gMCB0byBkaXNhYmxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLmRheXMoMSlcbiAgICovXG4gIHJlYWRvbmx5IHN0aWNraW5lc3NDb29raWVEdXJhdGlvbj86IER1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgdGltZSBwZXJpb2QgZHVyaW5nIHdoaWNoIHRoZSBsb2FkIGJhbGFuY2VyIHNlbmRzIGEgbmV3bHkgcmVnaXN0ZXJlZCB0YXJnZXQgYVxuICAgKiBsaW5lYXJseSBpbmNyZWFzaW5nIHNoYXJlIG9mIHRoZSB0cmFmZmljIHRvIHRoZSB0YXJnZXQgZ3JvdXAuIFNldCB0aGlzIHRvIDBcbiAgICogdG8gZGlzYWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBEdXJhdGlvbi5zZWNvbmRzKDMwKVxuICAgKi9cbiAgcmVhZG9ubHkgc2xvd1N0YXJ0PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBwcm90b2NvbCB1c2VkIGJ5IHRoZSBhcHBsaWNhdGlvbiBpbiB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUFxuICAgKi9cbiAgcmVhZG9ubHkgYXBwbGljYXRpb25Qcm90b2NvbD86IEFwcGxpY2F0aW9uUHJvdG9jb2w7XG5cbiAgLyoqXG4gICAqIFRoZSBhbW91bnQgb2YgdGltZSBmb3IgRWxhc3RpYyBMb2FkIEJhbGFuY2luZyB0byB3YWl0IGJlZm9yZSBkZXJlZ2lzdGVyaW5nIGEgdGFyZ2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLnNlY29uZHMoMTApXG4gICAqL1xuICByZWFkb25seSBkZXJlZ2lzdHJhdGlvbkRlbGF5PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBhcHByb3hpbWF0ZSBudW1iZXIgb2Ygc2Vjb25kcyBiZXR3ZWVuIGhlYWx0aCBjaGVja3MgZm9yIGFuIGluZGl2aWR1YWwgdGFyZ2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLnNlY29uZHMoMTApXG4gICAqL1xuICByZWFkb25seSBoZWFsdGhDaGVja0ludGVydmFsPzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBwZXJpb2Qgb2YgdGltZSwgaW4gc2Vjb25kcywgdGhhdCB0aGUgQW1hem9uIEVDUyBzZXJ2aWNlIHNjaGVkdWxlciBpZ25vcmVzIHVuaGVhbHRoeVxuICAgKiBFbGFzdGljIExvYWQgQmFsYW5jaW5nIHRhcmdldCBoZWFsdGggY2hlY2tzIGFmdGVyIGEgdGFzayBoYXMgZmlyc3Qgc3RhcnRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZWZhdWx0cyB0byA2MCBzZWNvbmRzXG4gICAqL1xuICByZWFkb25seSBoZWFsdGhDaGVja0dyYWNlUGVyaW9kPzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBwaW5nIHBhdGggZGVzdGluYXRpb24gd2hlcmUgRWxhc3RpYyBMb2FkIEJhbGFuY2luZyBzZW5kcyBoZWFsdGggY2hlY2sgcmVxdWVzdHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gL2hlYWx0aFxuICAgKi9cbiAgcmVhZG9ubHkgaGVhbHRoQ2hlY2tQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgYW1vdW50IG9mIHRpbWUsIGluIHNlY29uZHMsIGR1cmluZyB3aGljaCBubyByZXNwb25zZSBmcm9tIGEgdGFyZ2V0IG1lYW5zIGEgZmFpbGVkIGhlYWx0aCBjaGVja1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLnNlY29uZHMoMylcbiAgICovXG4gIHJlYWRvbmx5IGhlYWx0aENoZWNrVGltZW91dD86IER1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGNvbnNlY3V0aXZlIGhlYWx0aCBjaGVja3Mgc3VjY2Vzc2VzIHJlcXVpcmVkIGJlZm9yZSBjb25zaWRlcmluZyBhbiB1bmhlYWx0aHkgdGFyZ2V0IGhlYWx0aHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gMlxuICAgKi9cbiAgcmVhZG9ubHkgaGVhbHRoeVRocmVzaG9sZENvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGNvbnNlY3V0aXZlIGhlYWx0aCBjaGVjayBmYWlsdXJlcyByZXF1aXJlZCBiZWZvcmUgY29uc2lkZXJpbmcgYSB0YXJnZXQgdW5oZWFsdGh5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIDJcbiAgICovXG4gIHJlYWRvbmx5IHVuaGVhbHRoeVRocmVzaG9sZENvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBIVFRQIGNvZGUgdG8gdXNlIHdoZW4gY2hlY2tpbmcgZm9yIGEgc3VjY2Vzc2Z1bCByZXNwb25zZSBmcm9tIGEgdGFyZ2V0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gMjAwLTI5OVxuICAgKi9cbiAgcmVhZG9ubHkgaGVhbHRoeUh0dHBDb2Rlcz86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGxvYWQgYmFsYW5jaW5nIGFsZ29yaXRobSB0byBzZWxlY3QgdGFyZ2V0cyBmb3Igcm91dGluZyByZXF1ZXN0cy5cbiAgICogVG8gc2V0IHRoaXMgdG8gTEVBU1RfT1VUU1RBTkRJTkdfUkVRVUVTVFMsIHN0aWNraW5lc3MgbXVzdCBiZSBkaXNhYmxlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBST1VORF9ST0JJTlxuICAgKi9cbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2luZ0FsZ29yaXRobVR5cGU/OiBUYXJnZXRHcm91cExvYWRCYWxhbmNpbmdBbGdvcml0aG1UeXBlO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIEFMQiByZXF1ZXN0cyB0byB0YXJnZXQgZm9yIHNjYWxpbmcuXG4gICAqIERpc2FibGVkIGJ5IGRlZmF1bHQuXG4gICAqL1xuICByZWFkb25seSBzY2FsZVJlcXVlc3RQZXJUYXJnZXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRhcmdldCByZXNwb25zZSB0aW1lIGZvciBzY2FsaW5nXG4gICAqIERpc2FibGVkIGJ5IGRlZmF1bHRcbiAgICovXG4gIHJlYWRvbmx5IHNjYWxlT25UYXJnZXRSZXNwb25zZVRpbWU/OiB7XG4gICAgLyoqIFRocmVzaG9sZCBpbiBzZWNvbmRzICovXG4gICAgdGhyZXNob2xkOiBudW1iZXI7XG4gICAgbWV0cmljT3B0aW9ucz86IE1ldHJpY09wdGlvbnM7XG4gIH07XG5cbiAgLyoqXG4gICAqIERvbWFpbiBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNlcnZpY2UuXG4gICAqL1xuICByZWFkb25seSBkb21haW5OYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGRvbWFpbiBuYW1lcyB0byBhc3NvY2lhdGUgd2l0aCB0aGlzIHNlcnZpY2UuXG4gICAqL1xuICByZWFkb25seSBkb21haW5OYW1lcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBTZXQgdGhpcyB0byB0cnVlIHRvIHNraXAgdGhlIGNyZWF0aW9uIG9mIHJvdXRlNTMgcmVjb3Jkcy4gQnkgZGVmYXVsdCByZWNvcmRzIHdpbGwgYmUgY3JlYXRlZCBpbiBkb21haW5OYW1lIGFuZCBkb21haW5ab25lIGlzIHByb3ZpZGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICByZWFkb25seSBza2lwQ3JlYXRlUm91dGU1M1JlY29yZHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBQYXRoIHBhdHRlcm4gdG8gbWF0Y2ggb24gdGhlIGxvYWQgYmFsYW5jZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gW1wiLypcIl1cbiAgICovXG4gIHJlYWRvbmx5IHBhdGhQYXR0ZXJuPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIExvYWQgYmFsYW5jZXIgdG8gYXR0YWNoIHRoaXMgc2VydmljZSB0by4gSWYgcGFzc2VkIGFuIEFSTiBvciBuYW1lIGEgbG9va3VwIHdpbGwgYmVcbiAgICogcGVyZm9ybWVkIHRvIGxvY2F0ZSB0aGUgbG9hZCBiYWxhbmNlci5cbiAgICovXG4gIHJlYWRvbmx5IGxvYWRCYWxhbmNlcjogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyIHwgc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbGlzdGVuZXIgdG8gYXR0YWNoIHRoaXMgc2VydmljZSB0by4gSWYgb25lIGlzIG5vdCBwcm92aWRlZCBhbiBIVFRQUyBsaXN0ZW5lciBpcyBvYnRhaW5lZCBmcm9tIGEgbG9va3VwLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUFNcbiAgICovXG4gIHJlYWRvbmx5IGxpc3RlbmVyPzogSUFwcGxpY2F0aW9uTGlzdGVuZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBwcmlvcml0eSB0byBnaXZlIHRoZSB0YXJnZXQgZ3JvdXAgb24gdGhlIEFMQi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSAxXG4gICAqL1xuICByZWFkb25seSB0YXJnZXRHcm91cFByaW9yaXR5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBab25lIG9mIHRoZSBkb21haW4gbmFtZS4gSWYgc2V0LCBhIHJvdXRlNTMgcmVjb3JkIGlzIGNyZWF0ZWQgZm9yIHRoZSBzZXJ2aWNlLlxuICAgKlxuICAgKi9cbiAgcmVhZG9ubHkgZG9tYWluWm9uZT86IElIb3N0ZWRab25lO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYW4gRUNTIEZhcmdhdGUgc2VydmljZSBhbmQgbWFwcyBpdCB0byBhbiBBcHBsaWNhdGlvbiBMb2FkIEJhbGFuY2VyIChBTEIpLlxuICovXG5leHBvcnQgY2xhc3MgU3RhbmRhcmRBcHBsaWNhdGlvbkZhcmdhdGVTZXJ2aWNlIGV4dGVuZHMgU3RhbmRhcmRGYXJnYXRlU2VydmljZSB7XG4gIHJlYWRvbmx5IGxvYWRCYWxhbmNlcjogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyO1xuICByZWFkb25seSBsaXN0ZW5lcjogSUFwcGxpY2F0aW9uTGlzdGVuZXI7XG4gIHJlYWRvbmx5IGRvbWFpbk5hbWU/OiBEb21haW5OYW1lO1xuICByZWFkb25seSByb3V0ZTUzUmVjb3JkPzogQVJlY29yZDtcbiAgcmVhZG9ubHkgdGFyZ2V0R3JvdXA6IElBcHBsaWNhdGlvblRhcmdldEdyb3VwO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwcm9wczogU3RhbmRhcmRBcHBsaWNhdGlvbkZhcmdhdGVTZXJ2aWNlUHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgLi4ucHJvcHMsXG4gICAgICBoZWFsdGhDaGVja0dyYWNlUGVyaW9kOlxuICAgICAgICBwcm9wcy5oZWFsdGhDaGVja0dyYWNlUGVyaW9kID8/IER1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgIH0pO1xuXG4gICAgbGV0IHN0aWNraW5lc3NDb29raWVEdXJhdGlvbjogRHVyYXRpb24gfCB1bmRlZmluZWQgPVxuICAgICAgcHJvcHMuc3RpY2tpbmVzc0Nvb2tpZUR1cmF0aW9uID8/IER1cmF0aW9uLmRheXMoMSk7XG4gICAgaWYgKHN0aWNraW5lc3NDb29raWVEdXJhdGlvbi50b1NlY29uZHMoKSA9PT0gMCkge1xuICAgICAgc3RpY2tpbmVzc0Nvb2tpZUR1cmF0aW9uID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGxldCBzdGlja2luZXNzQ29va2llTmFtZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAgIGlmIChzdGlja2luZXNzQ29va2llRHVyYXRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgc3RpY2tpbmVzc0Nvb2tpZU5hbWUgPSBwcm9wcy5zdGlja2luZXNzQ29va2llTmFtZSA/PyAnbGJfYWZmaW5pdHknO1xuICAgIH1cblxuICAgIGxldCBzbG93U3RhcnQ6IER1cmF0aW9uIHwgdW5kZWZpbmVkID1cbiAgICAgIHByb3BzLnNsb3dTdGFydCA/PyBEdXJhdGlvbi5zZWNvbmRzKDMwKTtcbiAgICBpZiAoc2xvd1N0YXJ0LnRvU2Vjb25kcygpID09PSAwKSB7XG4gICAgICBzbG93U3RhcnQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgY29uc3QgdGFyZ2V0R3JvdXAgPSBuZXcgQXBwbGljYXRpb25UYXJnZXRHcm91cCh0aGlzLCAnVGFyZ2V0R3JvdXAnLCB7XG4gICAgICB0YXJnZXRzOiBbdGhpcy5zZXJ2aWNlXSxcbiAgICAgIHZwYzogcHJvcHMuY2x1c3Rlci52cGMsXG4gICAgICBwb3J0OiB0aGlzLnBvcnQsXG4gICAgICBwcm90b2NvbDogcHJvcHMuYXBwbGljYXRpb25Qcm90b2NvbCA/PyBBcHBsaWNhdGlvblByb3RvY29sLkhUVFAsXG4gICAgICBkZXJlZ2lzdHJhdGlvbkRlbGF5OiBwcm9wcy5kZXJlZ2lzdHJhdGlvbkRlbGF5ID8/IER1cmF0aW9uLnNlY29uZHMoMTApLFxuICAgICAgc2xvd1N0YXJ0LFxuICAgICAgaGVhbHRoQ2hlY2s6IHtcbiAgICAgICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAgICAgaW50ZXJ2YWw6IHByb3BzLmhlYWx0aENoZWNrSW50ZXJ2YWwgPz8gRHVyYXRpb24uc2Vjb25kcygxMCksXG4gICAgICAgIHBhdGg6IHByb3BzLmhlYWx0aENoZWNrUGF0aCA/PyAnL2hlYWx0aCcsXG4gICAgICAgIHRpbWVvdXQ6IHByb3BzLmhlYWx0aENoZWNrVGltZW91dCA/PyBEdXJhdGlvbi5zZWNvbmRzKDMpLFxuICAgICAgICBoZWFsdGh5VGhyZXNob2xkQ291bnQ6IHByb3BzLmhlYWx0aHlUaHJlc2hvbGRDb3VudCA/PyAyLFxuICAgICAgICB1bmhlYWx0aHlUaHJlc2hvbGRDb3VudDogcHJvcHMudW5oZWFsdGh5VGhyZXNob2xkQ291bnQgPz8gMixcbiAgICAgICAgaGVhbHRoeUh0dHBDb2RlczogcHJvcHMuaGVhbHRoeUh0dHBDb2RlcyA/PyAnMjAwLTI5OScsXG4gICAgICB9LFxuICAgICAgc3RpY2tpbmVzc0Nvb2tpZU5hbWUsXG4gICAgICBzdGlja2luZXNzQ29va2llRHVyYXRpb24sXG4gICAgICBsb2FkQmFsYW5jaW5nQWxnb3JpdGhtVHlwZTpcbiAgICAgICAgcHJvcHMubG9hZEJhbGFuY2luZ0FsZ29yaXRobVR5cGUgPz9cbiAgICAgICAgVGFyZ2V0R3JvdXBMb2FkQmFsYW5jaW5nQWxnb3JpdGhtVHlwZS5ST1VORF9ST0JJTixcbiAgICB9KTtcblxuICAgIGlmIChwcm9wcy5zY2FsZVJlcXVlc3RQZXJUYXJnZXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5zY2FsaW5nLnNjYWxlT25SZXF1ZXN0Q291bnQoJ1JlcXVlc3RDb3VudFNjYWxpbmcnLCB7XG4gICAgICAgIHNjYWxlSW5Db29sZG93bjogdGhpcy5zY2FsZUluQ29vbGRvd24sXG4gICAgICAgIHNjYWxlT3V0Q29vbGRvd246IHRoaXMuc2NhbGVPdXRDb29sZG93bixcbiAgICAgICAgdGFyZ2V0R3JvdXAsXG4gICAgICAgIHJlcXVlc3RzUGVyVGFyZ2V0OiBwcm9wcy5zY2FsZVJlcXVlc3RQZXJUYXJnZXQsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCB0YXJnZXRHcm91cENvbmRpdGlvbnM6IExpc3RlbmVyQ29uZGl0aW9uW10gPSBbXTtcbiAgICB0YXJnZXRHcm91cENvbmRpdGlvbnMucHVzaChcbiAgICAgIExpc3RlbmVyQ29uZGl0aW9uLnBhdGhQYXR0ZXJucyhwcm9wcy5wYXRoUGF0dGVybiA/PyBbJy8qJ10pLFxuICAgICk7XG4gICAgaWYgKHByb3BzLmRvbWFpbk5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGFyZ2V0R3JvdXBDb25kaXRpb25zLnB1c2goXG4gICAgICAgIExpc3RlbmVyQ29uZGl0aW9uLmhvc3RIZWFkZXJzKFtcbiAgICAgICAgICBwcm9wcy5kb21haW5OYW1lLFxuICAgICAgICAgIC4uLihwcm9wcy5kb21haW5OYW1lcyA/PyBbXSksXG4gICAgICAgIF0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBsZXQgbG9hZEJhbGFuY2VyOiBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXI7XG4gICAgaWYgKHR5cGVvZiBwcm9wcy5sb2FkQmFsYW5jZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICBpZiAocHJvcHMubG9hZEJhbGFuY2VyLnN0YXJ0c1dpdGgoJ2FybjonKSkge1xuICAgICAgICBsb2FkQmFsYW5jZXIgPSBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlci5mcm9tTG9va3VwKFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgJ0xvYWRCYWxhbmNlcicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgbG9hZEJhbGFuY2VyQXJuOiBwcm9wcy5sb2FkQmFsYW5jZXIsXG4gICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvYWRCYWxhbmNlciA9IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLmZyb21Mb29rdXAoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICAnTG9hZEJhbGFuY2VyJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBsb2FkQmFsYW5jZXJUYWdzOiB7XG4gICAgICAgICAgICAgIE5hbWU6IHByb3BzLmxvYWRCYWxhbmNlcixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbG9hZEJhbGFuY2VyID0gcHJvcHMubG9hZEJhbGFuY2VyO1xuICAgIH1cblxuICAgIGNvbnN0IGxpc3RlbmVyID1cbiAgICAgIHByb3BzLmxpc3RlbmVyID8/XG4gICAgICBBcHBsaWNhdGlvbkxpc3RlbmVyLmZyb21Mb29rdXAodGhpcywgJ0xpc3RlbmVyJywge1xuICAgICAgICBsb2FkQmFsYW5jZXJBcm46IGxvYWRCYWxhbmNlci5sb2FkQmFsYW5jZXJBcm4sXG4gICAgICAgIGxpc3RlbmVyUHJvdG9jb2w6IEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUFMsXG4gICAgICB9KTtcblxuICAgIGxpc3RlbmVyLmFkZFRhcmdldEdyb3VwcyhgJHtpZH1UYXJnZXRHcm91cHNgLCB7XG4gICAgICB0YXJnZXRHcm91cHM6IFt0YXJnZXRHcm91cF0sXG4gICAgICBjb25kaXRpb25zOiB0YXJnZXRHcm91cENvbmRpdGlvbnMsXG4gICAgICBwcmlvcml0eTogcHJvcHMudGFyZ2V0R3JvdXBQcmlvcml0eSA/PyAxLFxuICAgIH0pO1xuXG4gICAgaWYgKFxuICAgICAgcHJvcHMuZG9tYWluTmFtZSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBwcm9wcy5kb21haW5ab25lICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICFwcm9wcy5za2lwQ3JlYXRlUm91dGU1M1JlY29yZHNcbiAgICApIHtcbiAgICAgIHRoaXMuZG9tYWluTmFtZSA9IERvbWFpbk5hbWUuZnJvbUZxZG4ocHJvcHMuZG9tYWluTmFtZSwgcHJvcHMuZG9tYWluWm9uZSk7XG4gICAgICB0aGlzLnJvdXRlNTNSZWNvcmQgPSB0aGlzLmRvbWFpbk5hbWUuY3JlYXRlQVJlY29yZChcbiAgICAgICAgdGhpcyxcbiAgICAgICAgUmVjb3JkVGFyZ2V0LmZyb21BbGlhcyhuZXcgTG9hZEJhbGFuY2VyVGFyZ2V0KGxvYWRCYWxhbmNlcikpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmxvYWRCYWxhbmNlciA9IGxvYWRCYWxhbmNlcjtcbiAgICB0aGlzLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgdGhpcy50YXJnZXRHcm91cCA9IHRhcmdldEdyb3VwO1xuXG4gICAgaWYgKHByb3BzLnNjYWxlT25UYXJnZXRSZXNwb25zZVRpbWUpIHtcbiAgICAgIC8vIEF0dGFjaCBzY2FsaW5nIHBvbGljeSB0byB0aGUgc2VydmljZVxuICAgICAgdGhpcy5zY2FsZVRvVHJhY2tDdXN0b21NZXRyaWMoXG4gICAgICAgICdUYXJnZXRSZXNwb25zZVRpbWVTY2FsaW5nJyxcbiAgICAgICAgdGFyZ2V0R3JvdXAubWV0cmljcy50YXJnZXRSZXNwb25zZVRpbWUoXG4gICAgICAgICAgcHJvcHMuc2NhbGVPblRhcmdldFJlc3BvbnNlVGltZS5tZXRyaWNPcHRpb25zLFxuICAgICAgICApLFxuICAgICAgICBwcm9wcy5zY2FsZU9uVGFyZ2V0UmVzcG9uc2VUaW1lLnRocmVzaG9sZCxcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG4iXX0=
125
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhbmRhcmQtYXBwbGljYXRpb24tZmFyZ2F0ZS1zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RhbmRhcmQtYXBwbGljYXRpb24tZmFyZ2F0ZS1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlFQUdvQztBQUVwQyw2Q0FBcUM7QUFDckMsdUZBVWdEO0FBQ2hELHlEQUEyRTtBQUMzRSxtREFBNkM7QUFDN0MseUVBQW1FO0FBRW5FLDZEQUF1RDtBQTRLdkQ7O0dBRUc7QUFDSCxNQUFhLGlDQUFrQyxTQUFRLGlEQUFzQjtJQU8zRSxZQUNFLEtBQWdCLEVBQ2hCLEVBQVUsRUFDVixLQUE2Qzs7UUFFN0MsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixHQUFHLEtBQUs7WUFDUixzQkFBc0IsRUFDcEIsTUFBQSxLQUFLLENBQUMsc0JBQXNCLG1DQUFJLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztTQUN2RCxDQUFDLENBQUM7UUFFSCxJQUFJLHdCQUF3QixHQUMxQixNQUFBLEtBQUssQ0FBQyx3QkFBd0IsbUNBQUksc0JBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckQsSUFBSSx3QkFBd0IsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUMvQyx3QkFBd0IsR0FBRyxTQUFTLENBQUM7UUFDdkMsQ0FBQztRQUVELElBQUksb0JBQXdDLENBQUM7UUFDN0MsSUFBSSx3QkFBd0IsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMzQyxvQkFBb0IsR0FBRyxNQUFBLEtBQUssQ0FBQyxvQkFBb0IsbUNBQUksYUFBYSxDQUFDO1FBQ3JFLENBQUM7UUFFRCxJQUFJLFNBQVMsR0FDWCxNQUFBLEtBQUssQ0FBQyxTQUFTLG1DQUFJLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzFDLElBQUksU0FBUyxDQUFDLFNBQVMsRUFBRSxLQUFLLENB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QVUsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDMUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FDaEQsSUFBSSxFQUNKLDBCQUFZLENBQUMsU0FBUyxDQUFDLElBQUksd0NBQWtCLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FDN0QsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztRQUNqQyxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztRQUN6QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUUvQixJQUFJLEtBQUssQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQ3BDLHVDQUF1QztZQUN2QyxJQUFJLENBQUMsd0JBQXdCLENBQzNCLDJCQUEyQixFQUMzQixXQUFXLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUNwQyxLQUFLLENBQUMseUJBQXlCLENBQUMsYUFBYSxDQUM5QyxFQUNELEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxTQUFTLENBQzFDLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBOUpELDhFQThKQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIFN0YW5kYXJkRmFyZ2F0ZVNlcnZpY2UsXG4gIFN0YW5kYXJkRmFyZ2F0ZVNlcnZpY2VQcm9wcyxcbn0gZnJvbSAnLi9zdGFuZGFyZC1mYXJnYXRlLXNlcnZpY2UnO1xuaW1wb3J0IHtDb25zdHJ1Y3R9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHtEdXJhdGlvbn0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0IHtcbiAgQXBwbGljYXRpb25MaXN0ZW5lcixcbiAgQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIsXG4gIEFwcGxpY2F0aW9uUHJvdG9jb2wsXG4gIEFwcGxpY2F0aW9uVGFyZ2V0R3JvdXAsXG4gIElBcHBsaWNhdGlvbkxpc3RlbmVyLFxuICBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIsXG4gIElBcHBsaWNhdGlvblRhcmdldEdyb3VwLFxuICBMaXN0ZW5lckNvbmRpdGlvbixcbiAgVGFyZ2V0R3JvdXBMb2FkQmFsYW5jaW5nQWxnb3JpdGhtVHlwZSxcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVsYXN0aWNsb2FkYmFsYW5jaW5ndjInO1xuaW1wb3J0IHtBUmVjb3JkLCBJSG9zdGVkWm9uZSwgUmVjb3JkVGFyZ2V0fSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtcm91dGU1Myc7XG5pbXBvcnQge0RvbWFpbk5hbWV9IGZyb20gJy4uLy4uL2F3cy1yb3V0ZTUzJztcbmltcG9ydCB7TG9hZEJhbGFuY2VyVGFyZ2V0fSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtcm91dGU1My10YXJnZXRzJztcbmltcG9ydCB7TWV0cmljT3B0aW9uc30gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2gnO1xuaW1wb3J0IHtQcmlvcml0eUFsbG9jYXRvcn0gZnJvbSAnLi9wcmlvcml0eS1hbGxvY2F0b3InO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIFN0YW5kYXJkQXBwbGljYXRpb25GYXJnYXRlU2VydmljZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YW5kYXJkQXBwbGljYXRpb25GYXJnYXRlU2VydmljZVByb3BzIGV4dGVuZHMgU3RhbmRhcmRGYXJnYXRlU2VydmljZVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIGFuIGFwcGxpY2F0aW9uLWJhc2VkIHN0aWNraW5lc3MgY29va2llLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGxiX2FmZmluaXR5XG4gICAqL1xuICByZWFkb25seSBzdGlja2luZXNzQ29va2llTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHN0aWNraW5lc3MgY29va2llIGV4cGlyYXRpb24gcGVyaW9kLiBTZXQgdG8gMCB0byBkaXNhYmxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLmRheXMoMSlcbiAgICovXG4gIHJlYWRvbmx5IHN0aWNraW5lc3NDb29raWVEdXJhdGlvbj86IER1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgdGltZSBwZXJpb2QgZHVyaW5nIHdoaWNoIHRoZSBsb2FkIGJhbGFuY2VyIHNlbmRzIGEgbmV3bHkgcmVnaXN0ZXJlZCB0YXJnZXQgYVxuICAgKiBsaW5lYXJseSBpbmNyZWFzaW5nIHNoYXJlIG9mIHRoZSB0cmFmZmljIHRvIHRoZSB0YXJnZXQgZ3JvdXAuIFNldCB0aGlzIHRvIDBcbiAgICogdG8gZGlzYWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBEdXJhdGlvbi5zZWNvbmRzKDMwKVxuICAgKi9cbiAgcmVhZG9ubHkgc2xvd1N0YXJ0PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBwcm90b2NvbCB1c2VkIGJ5IHRoZSBhcHBsaWNhdGlvbiBpbiB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUFxuICAgKi9cbiAgcmVhZG9ubHkgYXBwbGljYXRpb25Qcm90b2NvbD86IEFwcGxpY2F0aW9uUHJvdG9jb2w7XG5cbiAgLyoqXG4gICAqIFRoZSBhbW91bnQgb2YgdGltZSBmb3IgRWxhc3RpYyBMb2FkIEJhbGFuY2luZyB0byB3YWl0IGJlZm9yZSBkZXJlZ2lzdGVyaW5nIGEgdGFyZ2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLnNlY29uZHMoMTApXG4gICAqL1xuICByZWFkb25seSBkZXJlZ2lzdHJhdGlvbkRlbGF5PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBhcHByb3hpbWF0ZSBudW1iZXIgb2Ygc2Vjb25kcyBiZXR3ZWVuIGhlYWx0aCBjaGVja3MgZm9yIGFuIGluZGl2aWR1YWwgdGFyZ2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLnNlY29uZHMoMTApXG4gICAqL1xuICByZWFkb25seSBoZWFsdGhDaGVja0ludGVydmFsPzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBwZXJpb2Qgb2YgdGltZSwgaW4gc2Vjb25kcywgdGhhdCB0aGUgQW1hem9uIEVDUyBzZXJ2aWNlIHNjaGVkdWxlciBpZ25vcmVzIHVuaGVhbHRoeVxuICAgKiBFbGFzdGljIExvYWQgQmFsYW5jaW5nIHRhcmdldCBoZWFsdGggY2hlY2tzIGFmdGVyIGEgdGFzayBoYXMgZmlyc3Qgc3RhcnRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZWZhdWx0cyB0byA2MCBzZWNvbmRzXG4gICAqL1xuICByZWFkb25seSBoZWFsdGhDaGVja0dyYWNlUGVyaW9kPzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBwaW5nIHBhdGggZGVzdGluYXRpb24gd2hlcmUgRWxhc3RpYyBMb2FkIEJhbGFuY2luZyBzZW5kcyBoZWFsdGggY2hlY2sgcmVxdWVzdHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gL2hlYWx0aFxuICAgKi9cbiAgcmVhZG9ubHkgaGVhbHRoQ2hlY2tQYXRoPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgYW1vdW50IG9mIHRpbWUsIGluIHNlY29uZHMsIGR1cmluZyB3aGljaCBubyByZXNwb25zZSBmcm9tIGEgdGFyZ2V0IG1lYW5zIGEgZmFpbGVkIGhlYWx0aCBjaGVja1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIER1cmF0aW9uLnNlY29uZHMoMylcbiAgICovXG4gIHJlYWRvbmx5IGhlYWx0aENoZWNrVGltZW91dD86IER1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGNvbnNlY3V0aXZlIGhlYWx0aCBjaGVja3Mgc3VjY2Vzc2VzIHJlcXVpcmVkIGJlZm9yZSBjb25zaWRlcmluZyBhbiB1bmhlYWx0aHkgdGFyZ2V0IGhlYWx0aHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gMlxuICAgKi9cbiAgcmVhZG9ubHkgaGVhbHRoeVRocmVzaG9sZENvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGNvbnNlY3V0aXZlIGhlYWx0aCBjaGVjayBmYWlsdXJlcyByZXF1aXJlZCBiZWZvcmUgY29uc2lkZXJpbmcgYSB0YXJnZXQgdW5oZWFsdGh5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIDJcbiAgICovXG4gIHJlYWRvbmx5IHVuaGVhbHRoeVRocmVzaG9sZENvdW50PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBIVFRQIGNvZGUgdG8gdXNlIHdoZW4gY2hlY2tpbmcgZm9yIGEgc3VjY2Vzc2Z1bCByZXNwb25zZSBmcm9tIGEgdGFyZ2V0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gMjAwLTI5OVxuICAgKi9cbiAgcmVhZG9ubHkgaGVhbHRoeUh0dHBDb2Rlcz86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGxvYWQgYmFsYW5jaW5nIGFsZ29yaXRobSB0byBzZWxlY3QgdGFyZ2V0cyBmb3Igcm91dGluZyByZXF1ZXN0cy5cbiAgICogVG8gc2V0IHRoaXMgdG8gTEVBU1RfT1VUU1RBTkRJTkdfUkVRVUVTVFMsIHN0aWNraW5lc3MgbXVzdCBiZSBkaXNhYmxlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBST1VORF9ST0JJTlxuICAgKi9cbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2luZ0FsZ29yaXRobVR5cGU/OiBUYXJnZXRHcm91cExvYWRCYWxhbmNpbmdBbGdvcml0aG1UeXBlO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIEFMQiByZXF1ZXN0cyB0byB0YXJnZXQgZm9yIHNjYWxpbmcuXG4gICAqIERpc2FibGVkIGJ5IGRlZmF1bHQuXG4gICAqL1xuICByZWFkb25seSBzY2FsZVJlcXVlc3RQZXJUYXJnZXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRhcmdldCByZXNwb25zZSB0aW1lIGZvciBzY2FsaW5nXG4gICAqIERpc2FibGVkIGJ5IGRlZmF1bHRcbiAgICovXG4gIHJlYWRvbmx5IHNjYWxlT25UYXJnZXRSZXNwb25zZVRpbWU/OiB7XG4gICAgLyoqIFRocmVzaG9sZCBpbiBzZWNvbmRzICovXG4gICAgdGhyZXNob2xkOiBudW1iZXI7XG4gICAgbWV0cmljT3B0aW9ucz86IE1ldHJpY09wdGlvbnM7XG4gIH07XG5cbiAgLyoqXG4gICAqIERvbWFpbiBuYW1lIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHNlcnZpY2UuXG4gICAqL1xuICByZWFkb25seSBkb21haW5OYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGRvbWFpbiBuYW1lcyB0byBhc3NvY2lhdGUgd2l0aCB0aGlzIHNlcnZpY2UuXG4gICAqL1xuICByZWFkb25seSBkb21haW5OYW1lcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBTZXQgdGhpcyB0byB0cnVlIHRvIHNraXAgdGhlIGNyZWF0aW9uIG9mIHJvdXRlNTMgcmVjb3Jkcy4gQnkgZGVmYXVsdCByZWNvcmRzIHdpbGwgYmUgY3JlYXRlZCBpbiBkb21haW5OYW1lIGFuZCBkb21haW5ab25lIGlzIHByb3ZpZGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICByZWFkb25seSBza2lwQ3JlYXRlUm91dGU1M1JlY29yZHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBQYXRoIHBhdHRlcm4gdG8gbWF0Y2ggb24gdGhlIGxvYWQgYmFsYW5jZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gW1wiLypcIl1cbiAgICovXG4gIHJlYWRvbmx5IHBhdGhQYXR0ZXJuPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIExvYWQgYmFsYW5jZXIgdG8gYXR0YWNoIHRoaXMgc2VydmljZSB0by4gSWYgcGFzc2VkIGFuIEFSTiBvciBuYW1lIGEgbG9va3VwIHdpbGwgYmVcbiAgICogcGVyZm9ybWVkIHRvIGxvY2F0ZSB0aGUgbG9hZCBiYWxhbmNlci5cbiAgICovXG4gIHJlYWRvbmx5IGxvYWRCYWxhbmNlcjogSUFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyIHwgc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbGlzdGVuZXIgdG8gYXR0YWNoIHRoaXMgc2VydmljZSB0by4gSWYgb25lIGlzIG5vdCBwcm92aWRlZCBhbiBIVFRQUyBsaXN0ZW5lciBpcyBvYnRhaW5lZCBmcm9tIGEgbG9va3VwLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUFNcbiAgICovXG4gIHJlYWRvbmx5IGxpc3RlbmVyPzogSUFwcGxpY2F0aW9uTGlzdGVuZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBwcmlvcml0eSB0byBnaXZlIHRoZSB0YXJnZXQgZ3JvdXAgb24gdGhlIEFMQi5cbiAgICogSWYgbm90IHNwZWNpZmllZCwgYSB1bmlxdWUgcHJpb3JpdHkgaXMgYXV0b21hdGljYWxseSBhbGxvY2F0ZWQgdXNpbmdcbiAgICogdGhlIFByaW9yaXR5QWxsb2NhdG9yLCB3aGljaCBjb29yZGluYXRlcyB3aXRoIG90aGVyIHNlcnZpY2VzIGFjcm9zc1xuICAgKiBtdWx0aXBsZSB0ZWFtcyBhbmQgdG9vbHMgKENESywgVGVycmFmb3JtLCBtYW51YWwpIHRvIGZpbmQgdGhlIGxvd2VzdFxuICAgKiBhdmFpbGFibGUgcHJpb3JpdHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQXV0b21hdGljYWxseSBhbGxvY2F0ZWQgKHJlY29tbWVuZGVkIGZvciBtb3N0IHVzZSBjYXNlcylcbiAgICovXG4gIHJlYWRvbmx5IHRhcmdldEdyb3VwUHJpb3JpdHk/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFpvbmUgb2YgdGhlIGRvbWFpbiBuYW1lLiBJZiBzZXQsIGEgcm91dGU1MyByZWNvcmQgaXMgY3JlYXRlZCBmb3IgdGhlIHNlcnZpY2UuXG4gICAqXG4gICAqL1xuICByZWFkb25seSBkb21haW5ab25lPzogSUhvc3RlZFpvbmU7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBFQ1MgRmFyZ2F0ZSBzZXJ2aWNlIGFuZCBtYXBzIGl0IHRvIGFuIEFwcGxpY2F0aW9uIExvYWQgQmFsYW5jZXIgKEFMQikuXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGFuZGFyZEFwcGxpY2F0aW9uRmFyZ2F0ZVNlcnZpY2UgZXh0ZW5kcyBTdGFuZGFyZEZhcmdhdGVTZXJ2aWNlIHtcbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2VyOiBJQXBwbGljYXRpb25Mb2FkQmFsYW5jZXI7XG4gIHJlYWRvbmx5IGxpc3RlbmVyOiBJQXBwbGljYXRpb25MaXN0ZW5lcjtcbiAgcmVhZG9ubHkgZG9tYWluTmFtZT86IERvbWFpbk5hbWU7XG4gIHJlYWRvbmx5IHJvdXRlNTNSZWNvcmQ/OiBBUmVjb3JkO1xuICByZWFkb25seSB0YXJnZXRHcm91cDogSUFwcGxpY2F0aW9uVGFyZ2V0R3JvdXA7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBTdGFuZGFyZEFwcGxpY2F0aW9uRmFyZ2F0ZVNlcnZpY2VQcm9wcyxcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICAuLi5wcm9wcyxcbiAgICAgIGhlYWx0aENoZWNrR3JhY2VQZXJpb2Q6XG4gICAgICAgIHByb3BzLmhlYWx0aENoZWNrR3JhY2VQZXJpb2QgPz8gRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgfSk7XG5cbiAgICBsZXQgc3RpY2tpbmVzc0Nvb2tpZUR1cmF0aW9uOiBEdXJhdGlvbiB8IHVuZGVmaW5lZCA9XG4gICAgICBwcm9wcy5zdGlja2luZXNzQ29va2llRHVyYXRpb24gPz8gRHVyYXRpb24uZGF5cygxKTtcbiAgICBpZiAoc3RpY2tpbmVzc0Nvb2tpZUR1cmF0aW9uLnRvU2Vjb25kcygpID09PSAwKSB7XG4gICAgICBzdGlja2luZXNzQ29va2llRHVyYXRpb24gPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgbGV0IHN0aWNraW5lc3NDb29raWVOYW1lOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKHN0aWNraW5lc3NDb29raWVEdXJhdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBzdGlja2luZXNzQ29va2llTmFtZSA9IHByb3BzLnN0aWNraW5lc3NDb29raWVOYW1lID8/ICdsYl9hZmZpbml0eSc7XG4gICAgfVxuXG4gICAgbGV0IHNsb3dTdGFydDogRHVyYXRpb24gfCB1bmRlZmluZWQgPVxuICAgICAgcHJvcHMuc2xvd1N0YXJ0ID8/IER1cmF0aW9uLnNlY29uZHMoMzApO1xuICAgIGlmIChzbG93U3RhcnQudG9TZWNvbmRzKCkgPT09IDApIHtcbiAgICAgIHNsb3dTdGFydCA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCB0YXJnZXRHcm91cCA9IG5ldyBBcHBsaWNhdGlvblRhcmdldEdyb3VwKHRoaXMsICdUYXJnZXRHcm91cCcsIHtcbiAgICAgIHRhcmdldHM6IFt0aGlzLnNlcnZpY2VdLFxuICAgICAgdnBjOiBwcm9wcy5jbHVzdGVyLnZwYyxcbiAgICAgIHBvcnQ6IHRoaXMucG9ydCxcbiAgICAgIHByb3RvY29sOiBwcm9wcy5hcHBsaWNhdGlvblByb3RvY29sID8/IEFwcGxpY2F0aW9uUHJvdG9jb2wuSFRUUCxcbiAgICAgIGRlcmVnaXN0cmF0aW9uRGVsYXk6IHByb3BzLmRlcmVnaXN0cmF0aW9uRGVsYXkgPz8gRHVyYXRpb24uc2Vjb25kcygxMCksXG4gICAgICBzbG93U3RhcnQsXG4gICAgICBoZWFsdGhDaGVjazoge1xuICAgICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgICBpbnRlcnZhbDogcHJvcHMuaGVhbHRoQ2hlY2tJbnRlcnZhbCA/PyBEdXJhdGlvbi5zZWNvbmRzKDEwKSxcbiAgICAgICAgcGF0aDogcHJvcHMuaGVhbHRoQ2hlY2tQYXRoID8/ICcvaGVhbHRoJyxcbiAgICAgICAgdGltZW91dDogcHJvcHMuaGVhbHRoQ2hlY2tUaW1lb3V0ID8/IER1cmF0aW9uLnNlY29uZHMoMyksXG4gICAgICAgIGhlYWx0aHlUaHJlc2hvbGRDb3VudDogcHJvcHMuaGVhbHRoeVRocmVzaG9sZENvdW50ID8/IDIsXG4gICAgICAgIHVuaGVhbHRoeVRocmVzaG9sZENvdW50OiBwcm9wcy51bmhlYWx0aHlUaHJlc2hvbGRDb3VudCA/PyAyLFxuICAgICAgICBoZWFsdGh5SHR0cENvZGVzOiBwcm9wcy5oZWFsdGh5SHR0cENvZGVzID8/ICcyMDAtMjk5JyxcbiAgICAgIH0sXG4gICAgICBzdGlja2luZXNzQ29va2llTmFtZSxcbiAgICAgIHN0aWNraW5lc3NDb29raWVEdXJhdGlvbixcbiAgICAgIGxvYWRCYWxhbmNpbmdBbGdvcml0aG1UeXBlOlxuICAgICAgICBwcm9wcy5sb2FkQmFsYW5jaW5nQWxnb3JpdGhtVHlwZSA/P1xuICAgICAgICBUYXJnZXRHcm91cExvYWRCYWxhbmNpbmdBbGdvcml0aG1UeXBlLlJPVU5EX1JPQklOLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLnNjYWxlUmVxdWVzdFBlclRhcmdldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnNjYWxpbmcuc2NhbGVPblJlcXVlc3RDb3VudCgnUmVxdWVzdENvdW50U2NhbGluZycsIHtcbiAgICAgICAgc2NhbGVJbkNvb2xkb3duOiB0aGlzLnNjYWxlSW5Db29sZG93bixcbiAgICAgICAgc2NhbGVPdXRDb29sZG93bjogdGhpcy5zY2FsZU91dENvb2xkb3duLFxuICAgICAgICB0YXJnZXRHcm91cCxcbiAgICAgICAgcmVxdWVzdHNQZXJUYXJnZXQ6IHByb3BzLnNjYWxlUmVxdWVzdFBlclRhcmdldCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGNvbnN0IHRhcmdldEdyb3VwQ29uZGl0aW9uczogTGlzdGVuZXJDb25kaXRpb25bXSA9IFtdO1xuICAgIHRhcmdldEdyb3VwQ29uZGl0aW9ucy5wdXNoKFxuICAgICAgTGlzdGVuZXJDb25kaXRpb24ucGF0aFBhdHRlcm5zKHByb3BzLnBhdGhQYXR0ZXJuID8/IFsnLyonXSksXG4gICAgKTtcbiAgICBpZiAocHJvcHMuZG9tYWluTmFtZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0YXJnZXRHcm91cENvbmRpdGlvbnMucHVzaChcbiAgICAgICAgTGlzdGVuZXJDb25kaXRpb24uaG9zdEhlYWRlcnMoW1xuICAgICAgICAgIHByb3BzLmRvbWFpbk5hbWUsXG4gICAgICAgICAgLi4uKHByb3BzLmRvbWFpbk5hbWVzID8/IFtdKSxcbiAgICAgICAgXSksXG4gICAgICApO1xuICAgIH1cblxuICAgIGxldCBsb2FkQmFsYW5jZXI6IElBcHBsaWNhdGlvbkxvYWRCYWxhbmNlcjtcbiAgICBpZiAodHlwZW9mIHByb3BzLmxvYWRCYWxhbmNlciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlmIChwcm9wcy5sb2FkQmFsYW5jZXIuc3RhcnRzV2l0aCgnYXJuOicpKSB7XG4gICAgICAgIGxvYWRCYWxhbmNlciA9IEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VyLmZyb21Mb29rdXAoXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgICAnTG9hZEJhbGFuY2VyJyxcbiAgICAgICAgICB7XG4gICAgICAgICAgICBsb2FkQmFsYW5jZXJBcm46IHByb3BzLmxvYWRCYWxhbmNlcixcbiAgICAgICAgICB9LFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9hZEJhbGFuY2VyID0gQXBwbGljYXRpb25Mb2FkQmFsYW5jZXIuZnJvbUxvb2t1cChcbiAgICAgICAgICB0aGlzLFxuICAgICAgICAgICdMb2FkQmFsYW5jZXInLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGxvYWRCYWxhbmNlclRhZ3M6IHtcbiAgICAgICAgICAgICAgTmFtZTogcHJvcHMubG9hZEJhbGFuY2VyLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsb2FkQmFsYW5jZXIgPSBwcm9wcy5sb2FkQmFsYW5jZXI7XG4gICAgfVxuXG4gICAgY29uc3QgbGlzdGVuZXIgPVxuICAgICAgcHJvcHMubGlzdGVuZXIgPz9cbiAgICAgIEFwcGxpY2F0aW9uTGlzdGVuZXIuZnJvbUxvb2t1cCh0aGlzLCAnTGlzdGVuZXInLCB7XG4gICAgICAgIGxvYWRCYWxhbmNlckFybjogbG9hZEJhbGFuY2VyLmxvYWRCYWxhbmNlckFybixcbiAgICAgICAgbGlzdGVuZXJQcm90b2NvbDogQXBwbGljYXRpb25Qcm90b2NvbC5IVFRQUyxcbiAgICAgIH0pO1xuXG4gICAgLy8gRGV0ZXJtaW5lIHByaW9yaXR5OiB1c2UgZXhwbGljaXQgdmFsdWUsIG9yIGFsbG9jYXRlIGF1dG9tYXRpY2FsbHlcbiAgICBsZXQgcHJpb3JpdHk6IG51bWJlcjtcbiAgICBpZiAocHJvcHMudGFyZ2V0R3JvdXBQcmlvcml0eSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBNYW51YWwgcHJpb3JpdHkgc3BlY2lmaWVkIC0gdXNlIGl0IGRpcmVjdGx5XG4gICAgICBwcmlvcml0eSA9IHByb3BzLnRhcmdldEdyb3VwUHJpb3JpdHk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE5vIHByaW9yaXR5IHNwZWNpZmllZCAtIHVzZSBhdXRvbWF0aWMgYWxsb2NhdGlvblxuICAgICAgY29uc3QgYWxsb2NhdG9yID0gbmV3IFByaW9yaXR5QWxsb2NhdG9yKHRoaXMsICdQcmlvcml0eUFsbG9jYXRvcicsIHtcbiAgICAgICAgbGlzdGVuZXJBcm46IGxpc3RlbmVyLmxpc3RlbmVyQXJuLFxuICAgICAgfSk7XG4gICAgICBwcmlvcml0eSA9IGFsbG9jYXRvci5wcmlvcml0eTtcbiAgICB9XG5cbiAgICBsaXN0ZW5lci5hZGRUYXJnZXRHcm91cHMoYCR7aWR9VGFyZ2V0R3JvdXBzYCwge1xuICAgICAgdGFyZ2V0R3JvdXBzOiBbdGFyZ2V0R3JvdXBdLFxuICAgICAgY29uZGl0aW9uczogdGFyZ2V0R3JvdXBDb25kaXRpb25zLFxuICAgICAgcHJpb3JpdHksXG4gICAgfSk7XG5cbiAgICBpZiAoXG4gICAgICBwcm9wcy5kb21haW5OYW1lICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHByb3BzLmRvbWFpblpvbmUgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgIXByb3BzLnNraXBDcmVhdGVSb3V0ZTUzUmVjb3Jkc1xuICAgICkge1xuICAgICAgdGhpcy5kb21haW5OYW1lID0gRG9tYWluTmFtZS5mcm9tRnFkbihwcm9wcy5kb21haW5OYW1lLCBwcm9wcy5kb21haW5ab25lKTtcbiAgICAgIHRoaXMucm91dGU1M1JlY29yZCA9IHRoaXMuZG9tYWluTmFtZS5jcmVhdGVBUmVjb3JkKFxuICAgICAgICB0aGlzLFxuICAgICAgICBSZWNvcmRUYXJnZXQuZnJvbUFsaWFzKG5ldyBMb2FkQmFsYW5jZXJUYXJnZXQobG9hZEJhbGFuY2VyKSksXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMubG9hZEJhbGFuY2VyID0gbG9hZEJhbGFuY2VyO1xuICAgIHRoaXMubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgICB0aGlzLnRhcmdldEdyb3VwID0gdGFyZ2V0R3JvdXA7XG5cbiAgICBpZiAocHJvcHMuc2NhbGVPblRhcmdldFJlc3BvbnNlVGltZSkge1xuICAgICAgLy8gQXR0YWNoIHNjYWxpbmcgcG9saWN5IHRvIHRoZSBzZXJ2aWNlXG4gICAgICB0aGlzLnNjYWxlVG9UcmFja0N1c3RvbU1ldHJpYyhcbiAgICAgICAgJ1RhcmdldFJlc3BvbnNlVGltZVNjYWxpbmcnLFxuICAgICAgICB0YXJnZXRHcm91cC5tZXRyaWNzLnRhcmdldFJlc3BvbnNlVGltZShcbiAgICAgICAgICBwcm9wcy5zY2FsZU9uVGFyZ2V0UmVzcG9uc2VUaW1lLm1ldHJpY09wdGlvbnMsXG4gICAgICAgICksXG4gICAgICAgIHByb3BzLnNjYWxlT25UYXJnZXRSZXNwb25zZVRpbWUudGhyZXNob2xkLFxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "truemark-cdk-lib",
3
3
  "description": "AWS CDK constructs created by TrueMark",
4
- "version": "1.21.0",
4
+ "version": "1.21.1-alpha.1768569999",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "author": "TrueMark Technologies, Inc.",
@@ -22,8 +22,11 @@
22
22
  ],
23
23
  "devDependencies": {
24
24
  "@eslint/js": "^9.39.1",
25
+ "@smithy/types": "^4.9.0",
25
26
  "@types/jest": "^29.5.14",
26
27
  "@types/node": "^22.19.2",
28
+ "aws-sdk-client-mock": "^4.1.0",
29
+ "aws-sdk-client-mock-jest": "^4.1.0",
27
30
  "esbuild": "^0.27.1",
28
31
  "eslint": "^9.39.1",
29
32
  "jest": "^29.7.0",
@@ -33,7 +36,8 @@
33
36
  "typescript": "~5.9.3",
34
37
  "typescript-eslint": "^8.49.0",
35
38
  "@aws-sdk/util-dynamodb": "^3.947.0",
36
- "@aws-sdk/client-dynamodb": "^3.947.0"
39
+ "@aws-sdk/client-dynamodb": "^3.947.0",
40
+ "@aws-sdk/client-elastic-load-balancing-v2": "^3.947.0"
37
41
  },
38
42
  "dependencies": {
39
43
  "@aws-cdk/aws-lambda-go-alpha": "^2.232.1-alpha.0",