serverless-spy 0.0.33 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.jsii +9 -9
- package/common/publishSpyEvent.ts +269 -0
- package/dist/releasetag.txt +1 -1
- package/extension/interceptor.ts +27 -13
- package/functions/onConnect.ts +2 -1
- package/functions/onDisconnect.ts +2 -1
- package/functions/sendMessage.ts +3 -268
- package/lib/common/publishSpyEvent.d.ts +4 -0
- package/lib/common/publishSpyEvent.js +211 -0
- package/lib/common/publishSpyEvent.mjs +205 -0
- package/lib/extension/dist/layer/nodejs/node_modules/interceptor.js +13888 -13
- package/lib/extension/dist/layer/nodejs/node_modules/interceptor.js.map +4 -4
- package/lib/listener/{SpyListener.d.ts → ServerlessSpyListener.d.ts} +12 -12
- package/lib/listener/ServerlessSpyListener.js +3 -0
- package/lib/listener/ServerlessSpyListener.mjs +2 -0
- package/lib/listener/ServerlessSpyListenerParams.d.ts +5 -0
- package/lib/listener/ServerlessSpyListenerParams.js +3 -0
- package/lib/listener/ServerlessSpyListenerParams.mjs +2 -0
- package/lib/listener/SpyHandlers.ts.d.ts +1 -1
- package/lib/listener/SpyHandlers.ts.js +1 -1
- package/lib/listener/SpyHandlers.ts.mjs +1 -1
- package/lib/listener/WaitForParams.d.ts +5 -0
- package/lib/listener/WaitForParams.js +3 -0
- package/lib/listener/WaitForParams.mjs +2 -0
- package/lib/listener/WsListener.d.ts +38 -0
- package/lib/listener/WsListener.js +185 -0
- package/lib/listener/WsListener.mjs +181 -0
- package/lib/listener/createServerlessSpyListener.d.ts +2 -13
- package/lib/listener/createServerlessSpyListener.js +5 -163
- package/lib/listener/createServerlessSpyListener.mjs +5 -163
- package/lib/listener/index.d.ts +1 -1
- package/lib/listener/index.js +2 -2
- package/lib/listener/index.mjs +2 -2
- package/lib/src/ServerlessSpy.d.ts +17 -8
- package/lib/src/ServerlessSpy.js +108 -67
- package/lib/src/ServerlessSpy.mjs +105 -64
- package/lib/src/common/envVariableNames.d.ts +19 -0
- package/lib/src/common/envVariableNames.js +26 -0
- package/lib/src/common/envVariableNames.mjs +23 -0
- package/listener/{SpyListener.ts → ServerlessSpyListener.ts} +12 -13
- package/listener/ServerlessSpyListenerParams.ts +6 -0
- package/listener/SpyHandlers.ts.ts +1 -1
- package/listener/WaitForParams.ts +6 -0
- package/listener/WsListener.ts +273 -0
- package/listener/createServerlessSpyListener.ts +5 -265
- package/listener/index.ts +1 -1
- package/package.json +1 -1
- package/lib/listener/SpyListener.js +0 -3
- package/lib/listener/SpyListener.mjs +0 -2
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { ApiGatewayManagementApi, PostToConnectionCommand, } from '@aws-sdk/client-apigatewaymanagementapi';
|
|
2
|
+
import { DeleteItemCommand, DynamoDBClient, ScanCommand, } from '@aws-sdk/client-dynamodb';
|
|
3
|
+
import { unmarshall } from '@aws-sdk/util-dynamodb';
|
|
4
|
+
import { envVariableNames } from '../src/common/envVariableNames';
|
|
5
|
+
const ddb = new DynamoDBClient({
|
|
6
|
+
region: process.env.AWS_REGION,
|
|
7
|
+
});
|
|
8
|
+
const apigwManagementApi = new ApiGatewayManagementApi({
|
|
9
|
+
apiVersion: '2018-11-29',
|
|
10
|
+
endpoint: process.env[envVariableNames.SSPY_WS_ENDPOINT],
|
|
11
|
+
});
|
|
12
|
+
let connections;
|
|
13
|
+
export async function publishSpyEvent(event) {
|
|
14
|
+
console.log('EVENT', JSON.stringify(event));
|
|
15
|
+
const mapping = JSON.parse(process.env[envVariableNames.SSPY_INFRA_MAPPING]);
|
|
16
|
+
console.log('mapping', JSON.stringify(mapping));
|
|
17
|
+
let connectionData;
|
|
18
|
+
const scanParams = new ScanCommand({
|
|
19
|
+
TableName: process.env[envVariableNames.SSPY_WS_TABLE_NAME],
|
|
20
|
+
ProjectionExpression: 'connectionId',
|
|
21
|
+
});
|
|
22
|
+
connectionData = await ddb.send(scanParams);
|
|
23
|
+
connections = connectionData.Items;
|
|
24
|
+
console.log(`connections at ${new Date().toISOString()}`, JSON.stringify(connections));
|
|
25
|
+
const postDataPromises = [];
|
|
26
|
+
if (event?.Records && event.Records[0]?.Sns) {
|
|
27
|
+
console.log('*** SNS ***');
|
|
28
|
+
const eventSns = event;
|
|
29
|
+
for (const record of eventSns.Records) {
|
|
30
|
+
const subscriptionArn = record.EventSubscriptionArn;
|
|
31
|
+
let serviceKey;
|
|
32
|
+
if (mapping[subscriptionArn]) {
|
|
33
|
+
// subscription event that could contain filter based on existing subscription
|
|
34
|
+
serviceKey = mapping[subscriptionArn];
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// catch all subscription
|
|
38
|
+
const topicArn = record.Sns.TopicArn;
|
|
39
|
+
serviceKey = mapping[topicArn];
|
|
40
|
+
}
|
|
41
|
+
let message;
|
|
42
|
+
try {
|
|
43
|
+
message = JSON.parse(record.Sns.Message);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
message = record.Sns.Message;
|
|
47
|
+
}
|
|
48
|
+
const spyEventType = getSpyEventType(serviceKey);
|
|
49
|
+
const data = {
|
|
50
|
+
spyEventType,
|
|
51
|
+
message,
|
|
52
|
+
subject: record.Sns.Subject,
|
|
53
|
+
timestamp: record.Sns.Timestamp,
|
|
54
|
+
topicArn: record.Sns.TopicArn,
|
|
55
|
+
messageId: record.Sns.MessageId,
|
|
56
|
+
messageAttributes: record.Sns.MessageAttributes,
|
|
57
|
+
};
|
|
58
|
+
const fluentEvent = {
|
|
59
|
+
data,
|
|
60
|
+
serviceKey,
|
|
61
|
+
};
|
|
62
|
+
postDataPromises.push(postData(fluentEvent));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else if (event?.Records && event.Records[0]?.eventSource === 'aws:sqs') {
|
|
66
|
+
console.log('*** SQS ***');
|
|
67
|
+
const eventSqs = event;
|
|
68
|
+
for (const record of eventSqs.Records) {
|
|
69
|
+
const subscriptionArn = record.eventSourceARN;
|
|
70
|
+
const serviceKey = mapping[subscriptionArn];
|
|
71
|
+
let body;
|
|
72
|
+
try {
|
|
73
|
+
body = JSON.parse(record.body);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
body = record.body;
|
|
77
|
+
}
|
|
78
|
+
const data = {
|
|
79
|
+
spyEventType: 'Sqs',
|
|
80
|
+
body,
|
|
81
|
+
messageAttributes: record.messageAttributes,
|
|
82
|
+
};
|
|
83
|
+
const fluentEvent = {
|
|
84
|
+
data,
|
|
85
|
+
serviceKey,
|
|
86
|
+
};
|
|
87
|
+
postDataPromises.push(postData(fluentEvent));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else if (event?.Records && event.Records[0]?.s3) {
|
|
91
|
+
console.log('*** S3 ***');
|
|
92
|
+
const eventS3 = event;
|
|
93
|
+
for (const record of eventS3.Records) {
|
|
94
|
+
const bucketArn = record.s3.bucket.arn;
|
|
95
|
+
const data = {
|
|
96
|
+
spyEventType: 'S3',
|
|
97
|
+
eventName: record.eventName,
|
|
98
|
+
eventTime: record.eventTime,
|
|
99
|
+
bucket: record.s3.bucket.name,
|
|
100
|
+
key: record.s3.object.key,
|
|
101
|
+
};
|
|
102
|
+
const fluentEvent = {
|
|
103
|
+
data,
|
|
104
|
+
serviceKey: mapping[bucketArn],
|
|
105
|
+
};
|
|
106
|
+
postDataPromises.push(postData(fluentEvent));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (event.Records && event.Records[0]?.dynamodb) {
|
|
110
|
+
console.log('*** DYNAMODB ***');
|
|
111
|
+
const eventDynamoDB = event;
|
|
112
|
+
for (const record of eventDynamoDB.Records) {
|
|
113
|
+
let arn = record.eventSourceARN;
|
|
114
|
+
arn = arn.substring(0, arn.indexOf('/stream/'));
|
|
115
|
+
const data = {
|
|
116
|
+
spyEventType: 'DynamoDB',
|
|
117
|
+
eventName: record.eventName,
|
|
118
|
+
newImage: unmarshall(record.dynamodb?.NewImage),
|
|
119
|
+
keys: unmarshall(record.dynamodb?.Keys),
|
|
120
|
+
oldImage: record.dynamodb?.OldImage
|
|
121
|
+
? unmarshall(record.dynamodb?.OldImage)
|
|
122
|
+
: undefined,
|
|
123
|
+
};
|
|
124
|
+
const fluentEvent = {
|
|
125
|
+
data,
|
|
126
|
+
serviceKey: mapping[arn],
|
|
127
|
+
};
|
|
128
|
+
postDataPromises.push(postData(fluentEvent));
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
else if (event.detail &&
|
|
132
|
+
event['detail-type'] &&
|
|
133
|
+
event.version &&
|
|
134
|
+
event.source) {
|
|
135
|
+
console.log('*** EventBridge ***');
|
|
136
|
+
const eventEb = event;
|
|
137
|
+
const serviceKey = mapping.eventBridge; // the is new lambda for each subscription
|
|
138
|
+
const spyEventType = getSpyEventType(serviceKey);
|
|
139
|
+
const message = eventEb.detail;
|
|
140
|
+
const data = {
|
|
141
|
+
spyEventType,
|
|
142
|
+
detail: message,
|
|
143
|
+
detailType: eventEb['detail-type'],
|
|
144
|
+
source: eventEb.source,
|
|
145
|
+
time: eventEb.time,
|
|
146
|
+
account: eventEb.account,
|
|
147
|
+
};
|
|
148
|
+
const fluentEvent = {
|
|
149
|
+
data,
|
|
150
|
+
serviceKey,
|
|
151
|
+
};
|
|
152
|
+
postDataPromises.push(postData(fluentEvent));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
console.log('*** OTHER ***');
|
|
156
|
+
const fluentEvent = event;
|
|
157
|
+
postDataPromises.push(postData(fluentEvent));
|
|
158
|
+
}
|
|
159
|
+
await Promise.all(postDataPromises);
|
|
160
|
+
}
|
|
161
|
+
export async function postData(spyMessage) {
|
|
162
|
+
// const postData = JSON.parse(event.body!).data;
|
|
163
|
+
console.log('postData', JSON.stringify(spyMessage));
|
|
164
|
+
if (!connections) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const postCalls = connections.map(async ({ connectionId }) => {
|
|
168
|
+
console.log(`Sending message to: ${connectionId.S}`);
|
|
169
|
+
try {
|
|
170
|
+
const postToConnectionCommand = new PostToConnectionCommand({
|
|
171
|
+
ConnectionId: connectionId.S,
|
|
172
|
+
Data: JSON.stringify({
|
|
173
|
+
timestamp: new Date().toISOString(),
|
|
174
|
+
serviceKey: spyMessage.serviceKey,
|
|
175
|
+
data: spyMessage.data,
|
|
176
|
+
}),
|
|
177
|
+
});
|
|
178
|
+
await apigwManagementApi.send(postToConnectionCommand);
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
console.error(`Fails sending message to: ${connectionId.S}`, e);
|
|
182
|
+
console.error(`Status code: ${e.statusCode}`);
|
|
183
|
+
if (e.$metadata.httpStatusCode === 410) {
|
|
184
|
+
console.log(`Found stale connection, deleting ${connectionId}`);
|
|
185
|
+
const deleteParams = new DeleteItemCommand({
|
|
186
|
+
TableName: process.env[envVariableNames.SSPY_WS_TABLE_NAME],
|
|
187
|
+
Key: { connectionId },
|
|
188
|
+
});
|
|
189
|
+
await ddb.send(deleteParams);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
throw e;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
await Promise.all(postCalls);
|
|
197
|
+
console.log('Send message finish');
|
|
198
|
+
}
|
|
199
|
+
export function getSpyEventType(serviceKey) {
|
|
200
|
+
if (!serviceKey) {
|
|
201
|
+
throw new Error('Missing serviceKey');
|
|
202
|
+
}
|
|
203
|
+
return serviceKey.substring(0, serviceKey.indexOf('#'));
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGlzaFNweUV2ZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vY29tbW9uL3B1Ymxpc2hTcHlFdmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLHVCQUF1QixHQUN4QixNQUFNLHlDQUF5QyxDQUFDO0FBQ2pELE9BQU8sRUFFTCxpQkFBaUIsRUFDakIsY0FBYyxFQUNkLFdBQVcsR0FDWixNQUFNLDBCQUEwQixDQUFDO0FBRWxDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQVFwRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQVVsRSxNQUFNLEdBQUcsR0FBRyxJQUFJLGNBQWMsQ0FBQztJQUM3QixNQUFNLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVO0NBQy9CLENBQUMsQ0FBQztBQUVILE1BQU0sa0JBQWtCLEdBQUcsSUFBSSx1QkFBdUIsQ0FBQztJQUNyRCxVQUFVLEVBQUUsWUFBWTtJQUN4QixRQUFRLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxnQkFBZ0IsQ0FBRTtDQUMxRCxDQUFDLENBQUM7QUFFSCxJQUFJLFdBQXlELENBQUM7QUFFOUQsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsS0FBVTtJQUM5QyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFFNUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixDQUFFLENBQUMsQ0FBQztJQUM5RSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFFaEQsSUFBSSxjQUFjLENBQUM7SUFF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LENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQzlCO2lCQUFNO2dCQUNMLE1BQU0sQ0FBQyxDQUFDO2FBQ1Q7U0FDRjtJQUNILENBQUMsQ0FBQyxDQUFDO0lBRUgsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdCLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLENBQUMsQ0FBQztBQUNyQyxDQUFDO0FBRUQsTUFBTSxVQUFVLGVBQWUsQ0FBQyxVQUFrQjtJQUNoRCxJQUFJLENBQUMsVUFBVSxFQUFFO1FBQ2YsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO0tBQ3ZDO0lBRUQsT0FBTyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFDMUQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFwaUdhdGV3YXlNYW5hZ2VtZW50QXBpLFxuICBQb3N0VG9Db25uZWN0aW9uQ29tbWFuZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWFwaWdhdGV3YXltYW5hZ2VtZW50YXBpJztcbmltcG9ydCB7XG4gIEF0dHJpYnV0ZVZhbHVlLFxuICBEZWxldGVJdGVtQ29tbWFuZCxcbiAgRHluYW1vREJDbGllbnQsXG4gIFNjYW5Db21tYW5kLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtZHluYW1vZGInO1xuXG5pbXBvcnQgeyB1bm1hcnNoYWxsIH0gZnJvbSAnQGF3cy1zZGsvdXRpbC1keW5hbW9kYic7XG5pbXBvcnQge1xuICBEeW5hbW9EQlN0cmVhbUV2ZW50LFxuICBTM0V2ZW50LFxuICBTTlNFdmVudCxcbiAgRXZlbnRCcmlkZ2VFdmVudCxcbiAgU1FTRXZlbnQsXG59IGZyb20gJ2F3cy1sYW1iZGEnO1xuaW1wb3J0IHsgZW52VmFyaWFibGVOYW1lcyB9IGZyb20gJy4uL3NyYy9jb21tb24vZW52VmFyaWFibGVOYW1lcyc7XG5pbXBvcnQgeyBEeW5hbW9EQlNweUV2ZW50IH0gZnJvbSAnLi9zcHlFdmVudHMvRHluYW1vREJTcHlFdmVudCc7XG5pbXBvcnQgeyBFdmVudEJyaWRnZVJ1bGVTcHlFdmVudCB9IGZyb20gJy4vc3B5RXZlbnRzL0V2ZW50QnJpZGdlUnVsZVNweUV2ZW50JztcbmltcG9ydCB7IEV2ZW50QnJpZGdlU3B5RXZlbnQgfSBmcm9tICcuL3NweUV2ZW50cy9FdmVudEJyaWRnZVNweUV2ZW50JztcbmltcG9ydCB7IFMzU3B5RXZlbnQgfSBmcm9tICcuL3NweUV2ZW50cy9TM1NweUV2ZW50JztcbmltcG9ydCB7IFNuc1N1YnNjcmlwdGlvblNweUV2ZW50IH0gZnJvbSAnLi9zcHlFdmVudHMvU25zU3Vic2NyaXB0aW9uU3B5RXZlbnQnO1xuaW1wb3J0IHsgU25zVG9waWNTcHlFdmVudCB9IGZyb20gJy4vc3B5RXZlbnRzL1Nuc1RvcGljU3B5RXZlbnQnO1xuaW1wb3J0IHsgU3B5TWVzc2FnZSB9IGZyb20gJy4vc3B5RXZlbnRzL1NweU1lc3NhZ2UnO1xuaW1wb3J0IHsgU3FzU3B5RXZlbnQgfSBmcm9tICcuL3NweUV2ZW50cy9TcXNTcHlFdmVudCc7XG5cbmNvbnN0IGRkYiA9IG5ldyBEeW5hbW9EQkNsaWVudCh7XG4gIHJlZ2lvbjogcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTixcbn0pO1xuXG5jb25zdCBhcGlnd01hbmFnZW1lbnRBcGkgPSBuZXcgQXBpR2F0ZXdheU1hbmFnZW1lbnRBcGkoe1xuICBhcGlWZXJzaW9uOiAnMjAxOC0xMS0yOScsXG4gIGVuZHBvaW50OiBwcm9jZXNzLmVudltlbnZWYXJpYWJsZU5hbWVzLlNTUFlfV1NfRU5EUE9JTlRdISxcbn0pO1xuXG5sZXQgY29ubmVjdGlvbnM6IFJlY29yZDxzdHJpbmcsIEF0dHJpYnV0ZVZhbHVlPltdIHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHVibGlzaFNweUV2ZW50KGV2ZW50OiBhbnkpIHtcbiAgY29uc29sZS5sb2coJ0VWRU5UJywgSlNPTi5zdHJpbmdpZnkoZXZlbnQpKTtcblxuICBjb25zdCBtYXBwaW5nID0gSlNPTi5wYXJzZShwcm9jZXNzLmVudltlbnZWYXJpYWJsZU5hbWVzLlNTUFlfSU5GUkFfTUFQUElOR10hKTtcbiAgY29uc29sZS5sb2coJ21hcHBpbmcnLCBKU09OLnN0cmluZ2lmeShtYXBwaW5nKSk7XG5cbiAgbGV0IGNvbm5lY3Rpb25EYXRhO1xuXG4gIGNvbnN0IHNjYW5QYXJhbXMgPSBuZXcgU2NhbkNvbW1hbmQoe1xuICAgIFRhYmxlTmFtZTogcHJvY2Vzcy5lbnZbZW52VmFyaWFibGVOYW1lcy5TU1BZX1dTX1RBQkxFX05BTUVdIGFzIHN0cmluZyxcbiAgICBQcm9qZWN0aW9uRXhwcmVzc2lvbjogJ2Nvbm5lY3Rpb25JZCcsXG4gIH0pO1xuXG4gIGNvbm5lY3Rpb25EYXRhID0gYXdhaXQgZGRiLnNlbmQoc2NhblBhcmFtcyk7XG5cbiAgY29ubmVjdGlvbnMgPSBjb25uZWN0aW9uRGF0YS5JdGVtcztcblxuICBjb25zb2xlLmxvZyhcbiAgICBgY29ubmVjdGlvbnMgYXQgJHtuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCl9YCxcbiAgICBKU09OLnN0cmluZ2lmeShjb25uZWN0aW9ucylcbiAgKTtcblxuICBjb25zdCBwb3N0RGF0YVByb21pc2VzOiBQcm9taXNlPGFueT5bXSA9IFtdO1xuXG4gIGlmIChldmVudD8uUmVjb3JkcyAmJiBldmVudC5SZWNvcmRzWzBdPy5TbnMpIHtcbiAgICBjb25zb2xlLmxvZygnKioqIFNOUyAqKionKTtcbiAgICBjb25zdCBldmVudFNucyA9IGV2ZW50IGFzIFNOU0V2ZW50O1xuICAgIGZvciAoY29uc3QgcmVjb3JkIG9mIGV2ZW50U25zLlJlY29yZHMpIHtcbiAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbkFybiA9IHJlY29yZC5FdmVudFN1YnNjcmlwdGlvbkFybjtcblxuICAgICAgbGV0IHNlcnZpY2VLZXk6IHN0cmluZztcbiAgICAgIGlmIChtYXBwaW5nW3N1YnNjcmlwdGlvbkFybl0pIHtcbiAgICAgICAgLy8gc3Vic2NyaXB0aW9uIGV2ZW50IHRoYXQgY291bGQgY29udGFpbiBmaWx0ZXIgYmFzZWQgb24gZXhpc3Rpbmcgc3Vic2NyaXB0aW9uXG4gICAgICAgIHNlcnZpY2VLZXkgPSBtYXBwaW5nW3N1YnNjcmlwdGlvbkFybl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBjYXRjaCBhbGwgc3Vic2NyaXB0aW9uXG4gICAgICAgIGNvbnN0IHRvcGljQXJuID0gcmVjb3JkLlNucy5Ub3BpY0FybjtcbiAgICAgICAgc2VydmljZUtleSA9IG1hcHBpbmdbdG9waWNBcm5dO1xuICAgICAgfVxuXG4gICAgICBsZXQgbWVzc2FnZTogc3RyaW5nO1xuXG4gICAgICB0cnkge1xuICAgICAgICBtZXNzYWdlID0gSlNPTi5wYXJzZShyZWNvcmQuU25zLk1lc3NhZ2UpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIG1lc3NhZ2UgPSByZWNvcmQuU25zLk1lc3NhZ2U7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHNweUV2ZW50VHlwZSA9IGdldFNweUV2ZW50VHlwZShzZXJ2aWNlS2V5KSBhc1xuICAgICAgICB8ICdGdW5jdGlvblNuc1RvcGljJ1xuICAgICAgICB8ICdGdW5jdGlvblNuc1N1YnNjcmlwdGlvbic7XG5cbiAgICAgIGNvbnN0IGRhdGE6IFNuc1RvcGljU3B5RXZlbnQgfCBTbnNTdWJzY3JpcHRpb25TcHlFdmVudCA9IHtcbiAgICAgICAgc3B5RXZlbnRUeXBlLFxuICAgICAgICBtZXNzYWdlLFxuICAgICAgICBzdWJqZWN0OiByZWNvcmQuU25zLlN1YmplY3QsXG4gICAgICAgIHRpbWVzdGFtcDogcmVjb3JkLlNucy5UaW1lc3RhbXAsXG4gICAgICAgIHRvcGljQXJuOiByZWNvcmQuU25zLlRvcGljQXJuLFxuICAgICAgICBtZXNzYWdlSWQ6IHJlY29yZC5TbnMuTWVzc2FnZUlkLFxuICAgICAgICBtZXNzYWdlQXR0cmlidXRlczogcmVjb3JkLlNucy5NZXNzYWdlQXR0cmlidXRlcyxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGZsdWVudEV2ZW50OiBPbWl0PFNweU1lc3NhZ2UsICd0aW1lc3RhbXAnPiA9IHtcbiAgICAgICAgZGF0YSxcbiAgICAgICAgc2VydmljZUtleSxcbiAgICAgIH07XG4gICAgICBwb3N0RGF0YVByb21pc2VzLnB1c2gocG9zdERhdGEoZmx1ZW50RXZlbnQpKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoZXZlbnQ/LlJlY29yZHMgJiYgZXZlbnQuUmVjb3Jkc1swXT8uZXZlbnRTb3VyY2UgPT09ICdhd3M6c3FzJykge1xuICAgIGNvbnNvbGUubG9nKCcqKiogU1FTICoqKicpO1xuICAgIGNvbnN0IGV2ZW50U3FzID0gZXZlbnQgYXMgU1FTRXZlbnQ7XG4gICAgZm9yIChjb25zdCByZWNvcmQgb2YgZXZlbnRTcXMuUmVjb3Jkcykge1xuICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uQXJuID0gcmVjb3JkLmV2ZW50U291cmNlQVJOO1xuXG4gICAgICBjb25zdCBzZXJ2aWNlS2V5ID0gbWFwcGluZ1tzdWJzY3JpcHRpb25Bcm5dO1xuICAgICAgbGV0IGJvZHk6IHN0cmluZztcblxuICAgICAgdHJ5IHtcbiAgICAgICAgYm9keSA9IEpTT04ucGFyc2UocmVjb3JkLmJvZHkpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIGJvZHkgPSByZWNvcmQuYm9keTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YTogU3FzU3B5RXZlbnQgPSB7XG4gICAgICAgIHNweUV2ZW50VHlwZTogJ1NxcycsXG4gICAgICAgIGJvZHksXG4gICAgICAgIG1lc3NhZ2VBdHRyaWJ1dGVzOiByZWNvcmQubWVzc2FnZUF0dHJpYnV0ZXMsXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBmbHVlbnRFdmVudDogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4gPSB7XG4gICAgICAgIGRhdGEsXG4gICAgICAgIHNlcnZpY2VLZXksXG4gICAgICB9O1xuICAgICAgcG9zdERhdGFQcm9taXNlcy5wdXNoKHBvc3REYXRhKGZsdWVudEV2ZW50KSk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGV2ZW50Py5SZWNvcmRzICYmIGV2ZW50LlJlY29yZHNbMF0/LnMzKSB7XG4gICAgY29uc29sZS5sb2coJyoqKiBTMyAqKionKTtcbiAgICBjb25zdCBldmVudFMzID0gZXZlbnQgYXMgUzNFdmVudDtcbiAgICBmb3IgKGNvbnN0IHJlY29yZCBvZiBldmVudFMzLlJlY29yZHMpIHtcbiAgICAgIGNvbnN0IGJ1Y2tldEFybiA9IHJlY29yZC5zMy5idWNrZXQuYXJuO1xuXG4gICAgICBjb25zdCBkYXRhOiBTM1NweUV2ZW50ID0ge1xuICAgICAgICBzcHlFdmVudFR5cGU6ICdTMycsXG4gICAgICAgIGV2ZW50TmFtZTogcmVjb3JkLmV2ZW50TmFtZSxcbiAgICAgICAgZXZlbnRUaW1lOiByZWNvcmQuZXZlbnRUaW1lLFxuICAgICAgICBidWNrZXQ6IHJlY29yZC5zMy5idWNrZXQubmFtZSxcbiAgICAgICAga2V5OiByZWNvcmQuczMub2JqZWN0LmtleSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGZsdWVudEV2ZW50OiBPbWl0PFNweU1lc3NhZ2UsICd0aW1lc3RhbXAnPiA9IHtcbiAgICAgICAgZGF0YSxcbiAgICAgICAgc2VydmljZUtleTogbWFwcGluZ1tidWNrZXRBcm5dLFxuICAgICAgfTtcbiAgICAgIHBvc3REYXRhUHJvbWlzZXMucHVzaChwb3N0RGF0YShmbHVlbnRFdmVudCkpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChldmVudC5SZWNvcmRzICYmIGV2ZW50LlJlY29yZHNbMF0/LmR5bmFtb2RiKSB7XG4gICAgY29uc29sZS5sb2coJyoqKiBEWU5BTU9EQiAqKionKTtcbiAgICBjb25zdCBldmVudER5bmFtb0RCID0gZXZlbnQgYXMgRHluYW1vREJTdHJlYW1FdmVudDtcbiAgICBmb3IgKGNvbnN0IHJlY29yZCBvZiBldmVudER5bmFtb0RCLlJlY29yZHMpIHtcbiAgICAgIGxldCBhcm4gPSByZWNvcmQuZXZlbnRTb3VyY2VBUk4hO1xuICAgICAgYXJuID0gYXJuLnN1YnN0cmluZygwLCBhcm4uaW5kZXhPZignL3N0cmVhbS8nKSk7XG5cbiAgICAgIGNvbnN0IGRhdGE6IER5bmFtb0RCU3B5RXZlbnQgPSB7XG4gICAgICAgIHNweUV2ZW50VHlwZTogJ0R5bmFtb0RCJyxcbiAgICAgICAgZXZlbnROYW1lOiByZWNvcmQuZXZlbnROYW1lLFxuICAgICAgICBuZXdJbWFnZTogdW5tYXJzaGFsbChyZWNvcmQuZHluYW1vZGI/Lk5ld0ltYWdlIGFzIGFueSksXG4gICAgICAgIGtleXM6IHVubWFyc2hhbGwocmVjb3JkLmR5bmFtb2RiPy5LZXlzIGFzIGFueSksXG4gICAgICAgIG9sZEltYWdlOiByZWNvcmQuZHluYW1vZGI/Lk9sZEltYWdlXG4gICAgICAgICAgPyB1bm1hcnNoYWxsKHJlY29yZC5keW5hbW9kYj8uT2xkSW1hZ2UgYXMgYW55KVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgfTtcblxuICAgICAgY29uc3QgZmx1ZW50RXZlbnQ6IE9taXQ8U3B5TWVzc2FnZSwgJ3RpbWVzdGFtcCc+ID0ge1xuICAgICAgICBkYXRhLFxuICAgICAgICBzZXJ2aWNlS2V5OiBtYXBwaW5nW2Fybl0sXG4gICAgICB9O1xuICAgICAgcG9zdERhdGFQcm9taXNlcy5wdXNoKHBvc3REYXRhKGZsdWVudEV2ZW50KSk7XG4gICAgfVxuICB9IGVsc2UgaWYgKFxuICAgIGV2ZW50LmRldGFpbCAmJlxuICAgIGV2ZW50WydkZXRhaWwtdHlwZSddICYmXG4gICAgZXZlbnQudmVyc2lvbiAmJlxuICAgIGV2ZW50LnNvdXJjZVxuICApIHtcbiAgICBjb25zb2xlLmxvZygnKioqIEV2ZW50QnJpZGdlICoqKicpO1xuICAgIGNvbnN0IGV2ZW50RWIgPSBldmVudCBhcyBFdmVudEJyaWRnZUV2ZW50PGFueSwgYW55PjtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBtYXBwaW5nLmV2ZW50QnJpZGdlOyAvLyB0aGUgaXMgbmV3IGxhbWJkYSBmb3IgZWFjaCBzdWJzY3JpcHRpb25cblxuICAgIGNvbnN0IHNweUV2ZW50VHlwZSA9IGdldFNweUV2ZW50VHlwZShzZXJ2aWNlS2V5KSBhc1xuICAgICAgfCAnRXZlbnRCcmlkZ2UnXG4gICAgICB8ICdFdmVudEJyaWRnZVJ1bGUnO1xuXG4gICAgY29uc3QgbWVzc2FnZSA9IGV2ZW50RWIuZGV0YWlsO1xuXG4gICAgY29uc3QgZGF0YTogRXZlbnRCcmlkZ2VTcHlFdmVudCB8IEV2ZW50QnJpZGdlUnVsZVNweUV2ZW50ID0ge1xuICAgICAgc3B5RXZlbnRUeXBlLFxuICAgICAgZGV0YWlsOiBtZXNzYWdlLFxuICAgICAgZGV0YWlsVHlwZTogZXZlbnRFYlsnZGV0YWlsLXR5cGUnXSxcbiAgICAgIHNvdXJjZTogZXZlbnRFYi5zb3VyY2UsXG4gICAgICB0aW1lOiBldmVudEViLnRpbWUsXG4gICAgICBhY2NvdW50OiBldmVudEViLmFjY291bnQsXG4gICAgfTtcblxuICAgIGNvbnN0IGZsdWVudEV2ZW50OiBPbWl0PFNweU1lc3NhZ2UsICd0aW1lc3RhbXAnPiA9IHtcbiAgICAgIGRhdGEsXG4gICAgICBzZXJ2aWNlS2V5LFxuICAgIH07XG4gICAgcG9zdERhdGFQcm9taXNlcy5wdXNoKHBvc3REYXRhKGZsdWVudEV2ZW50KSk7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5sb2coJyoqKiBPVEhFUiAqKionKTtcbiAgICBjb25zdCBmbHVlbnRFdmVudDogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4gPSBldmVudDtcbiAgICBwb3N0RGF0YVByb21pc2VzLnB1c2gocG9zdERhdGEoZmx1ZW50RXZlbnQpKTtcbiAgfVxuXG4gIGF3YWl0IFByb21pc2UuYWxsKHBvc3REYXRhUHJvbWlzZXMpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcG9zdERhdGEoc3B5TWVzc2FnZTogT21pdDxTcHlNZXNzYWdlLCAndGltZXN0YW1wJz4pIHtcbiAgLy8gY29uc3QgcG9zdERhdGEgPSBKU09OLnBhcnNlKGV2ZW50LmJvZHkhKS5kYXRhO1xuICBjb25zb2xlLmxvZygncG9zdERhdGEnLCBKU09OLnN0cmluZ2lmeShzcHlNZXNzYWdlKSk7XG5cbiAgaWYgKCFjb25uZWN0aW9ucykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHBvc3RDYWxscyA9IGNvbm5lY3Rpb25zLm1hcChhc3luYyAoeyBjb25uZWN0aW9uSWQgfSkgPT4ge1xuICAgIGNvbnNvbGUubG9nKGBTZW5kaW5nIG1lc3NhZ2UgdG86ICR7Y29ubmVjdGlvbklkLlN9YCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcG9zdFRvQ29ubmVjdGlvbkNvbW1hbmQgPSBuZXcgUG9zdFRvQ29ubmVjdGlvbkNvbW1hbmQoe1xuICAgICAgICBDb25uZWN0aW9uSWQ6IGNvbm5lY3Rpb25JZC5TLFxuICAgICAgICBEYXRhOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICAgc2VydmljZUtleTogc3B5TWVzc2FnZS5zZXJ2aWNlS2V5LFxuICAgICAgICAgIGRhdGE6IHNweU1lc3NhZ2UuZGF0YSxcbiAgICAgICAgfSkgYXMgYW55LFxuICAgICAgfSk7XG5cbiAgICAgIGF3YWl0IGFwaWd3TWFuYWdlbWVudEFwaS5zZW5kKHBvc3RUb0Nvbm5lY3Rpb25Db21tYW5kKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGBGYWlscyBzZW5kaW5nIG1lc3NhZ2UgdG86ICR7Y29ubmVjdGlvbklkLlN9YCwgZSk7XG4gICAgICBjb25zb2xlLmVycm9yKGBTdGF0dXMgY29kZTogJHsoZSBhcyBhbnkpLnN0YXR1c0NvZGV9YCk7XG4gICAgICBpZiAoKGUgYXMgYW55KS4kbWV0YWRhdGEuaHR0cFN0YXR1c0NvZGUgPT09IDQxMCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgRm91bmQgc3RhbGUgY29ubmVjdGlvbiwgZGVsZXRpbmcgJHtjb25uZWN0aW9uSWR9YCk7XG5cbiAgICAgICAgY29uc3QgZGVsZXRlUGFyYW1zID0gbmV3IERlbGV0ZUl0ZW1Db21tYW5kKHtcbiAgICAgICAgICBUYWJsZU5hbWU6IHByb2Nlc3MuZW52W2VudlZhcmlhYmxlTmFtZXMuU1NQWV9XU19UQUJMRV9OQU1FXSxcbiAgICAgICAgICBLZXk6IHsgY29ubmVjdGlvbklkIH0sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGF3YWl0IGRkYi5zZW5kKGRlbGV0ZVBhcmFtcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG5cbiAgYXdhaXQgUHJvbWlzZS5hbGwocG9zdENhbGxzKTtcbiAgY29uc29sZS5sb2coJ1NlbmQgbWVzc2FnZSBmaW5pc2gnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNweUV2ZW50VHlwZShzZXJ2aWNlS2V5OiBzdHJpbmcpIHtcbiAgaWYgKCFzZXJ2aWNlS2V5KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHNlcnZpY2VLZXknKTtcbiAgfVxuXG4gIHJldHVybiBzZXJ2aWNlS2V5LnN1YnN0cmluZygwLCBzZXJ2aWNlS2V5LmluZGV4T2YoJyMnKSk7XG59XG4iXX0=
|