@discordeno/gateway 19.0.0-next.85ea2d9 → 19.0.0-next.87f62d2

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.
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./manager.cjs"), exports);
6
+ _export_star(require("./Shard.cjs"), exports);
7
+ _export_star(require("./types.cjs"), exports);
8
+ function _export_star(from, to) {
9
+ Object.keys(from).forEach(function(k) {
10
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
11
+ Object.defineProperty(to, k, {
12
+ enumerable: true,
13
+ get: function() {
14
+ return from[k];
15
+ }
16
+ });
17
+ }
18
+ });
19
+ return from;
20
+ }
21
+
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL21hbmFnZXIuanMnXG5leHBvcnQgKiBmcm9tICcuL1NoYXJkLmpzJ1xuZXhwb3J0ICogZnJvbSAnLi90eXBlcy5qcydcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O3FCQUFjO3FCQUNBO3FCQUNBIn0=
@@ -0,0 +1,463 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "createGatewayManager", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return createGatewayManager;
9
+ }
10
+ });
11
+ const _types = require("@discordeno/types");
12
+ const _utils = require("@discordeno/utils");
13
+ const _Shard = /*#__PURE__*/ _interop_require_default(require("./Shard.cjs"));
14
+ const _types1 = require("./types.cjs");
15
+ function _interop_require_default(obj) {
16
+ return obj && obj.__esModule ? obj : {
17
+ default: obj
18
+ };
19
+ }
20
+ function createGatewayManager(options) {
21
+ const connectionOptions = options.connection ?? {
22
+ url: 'wss://gateway.discord.gg',
23
+ shards: 1,
24
+ sessionStartLimit: {
25
+ maxConcurrency: 1,
26
+ remaining: 1000,
27
+ total: 1000,
28
+ resetAfter: 1000 * 60 * 60 * 24
29
+ }
30
+ };
31
+ const gateway = {
32
+ events: options.events ?? {},
33
+ compress: options.compress ?? false,
34
+ intents: options.intents ?? 0,
35
+ properties: {
36
+ os: options.properties?.os ?? process.platform,
37
+ browser: options.properties?.browser ?? 'Discordeno',
38
+ device: options.properties?.device ?? 'Discordeno'
39
+ },
40
+ token: options.token,
41
+ url: options.url ?? connectionOptions.url ?? 'wss://gateway.discord.gg',
42
+ version: options.version ?? 10,
43
+ connection: connectionOptions,
44
+ totalShards: options.totalShards ?? connectionOptions.shards ?? 1,
45
+ lastShardId: options.lastShardId ?? (options.totalShards ? options.totalShards - 1 : connectionOptions ? connectionOptions.shards - 1 : 0),
46
+ firstShardId: options.firstShardId ?? 0,
47
+ totalWorkers: options.totalWorkers ?? 4,
48
+ shardsPerWorker: options.shardsPerWorker ?? 25,
49
+ spawnShardDelay: options.spawnShardDelay ?? 5300,
50
+ preferSnakeCase: options.preferSnakeCase ?? false,
51
+ shards: new Map(),
52
+ buckets: new Map(),
53
+ cache: {
54
+ requestMembers: {
55
+ enabled: options.cache?.requestMembers?.enabled ?? false,
56
+ pending: new _utils.Collection()
57
+ }
58
+ },
59
+ logger: options.logger ?? _utils.logger,
60
+ resharding: {
61
+ enabled: true,
62
+ shardsFullPercentage: 80,
63
+ checkInterval: 28800000,
64
+ shards: new _utils.Collection(),
65
+ pendingShards: new _utils.Collection(),
66
+ async getSessionInfo () {
67
+ throw new Error('[Resharding] was enabled but no getSessionInfo handler was provided. Please set a handler like: gateway.resharding.getSessionInfo = async () => { // insert code here to fetch getSessionInfo from rest process. }');
68
+ },
69
+ async checkIfReshardingIsNeeded () {
70
+ _utils.logger.warn(`[Resharding] Checking if resharding is needed.`);
71
+ // Resharding is disabled.
72
+ if (!gateway.resharding.enabled) return {
73
+ needed: false
74
+ };
75
+ _utils.logger.warn(`[Resharding] Resharding is enabled.`);
76
+ const sessionInfo = await gateway.resharding.getSessionInfo();
77
+ _utils.logger.warn(`[Resharding] Session info retrieved.`);
78
+ // Don't have enough identify limits to try resharding
79
+ if (sessionInfo.sessionStartLimit.remaining < sessionInfo.shards) return {
80
+ needed: false,
81
+ info: sessionInfo
82
+ };
83
+ _utils.logger.warn(`[Resharding] Able to reshard, checking whether necessary now.`);
84
+ // 2500 is the max amount of guilds a single shard can handle
85
+ // 1000 is the amount of guilds discord uses to determine how many shards to recommend.
86
+ // This algo helps check if your bot has grown enough to reshard.
87
+ const percentage = 2500 * sessionInfo.shards / (gateway.totalShards * 1000) * 100;
88
+ // Less than necessary% being used so do nothing
89
+ if (percentage < gateway.resharding.shardsFullPercentage) return {
90
+ needed: false,
91
+ info: sessionInfo
92
+ };
93
+ _utils.logger.warn(`[Resharding] Resharding is needed.`);
94
+ return {
95
+ needed: true,
96
+ info: sessionInfo
97
+ };
98
+ },
99
+ async reshard (info) {
100
+ _utils.logger.warn(`[Resharding] Starting the reshard process. Previous total shards. ${gateway.totalShards}`);
101
+ // Set values on gateway
102
+ gateway.totalShards = info.shards;
103
+ // Handles preparing mid sized bots for LBS
104
+ gateway.totalShards = gateway.calculateTotalShards();
105
+ // Set first shard id if provided in info
106
+ if (typeof info.firstShardId === 'number') gateway.firstShardId = info.firstShardId;
107
+ // Set last shard id if provided in info
108
+ if (typeof info.lastShardId === 'number') gateway.lastShardId = info.lastShardId;
109
+ _utils.logger.warn(`[Resharding] Starting the reshard process. New Total Shards. ${gateway.totalShards}`);
110
+ // Resetting buckets
111
+ gateway.buckets.clear();
112
+ // Refilling buckets with new values
113
+ gateway.prepareBuckets();
114
+ // SPREAD THIS OUT TO DIFFERENT WORKERS TO BEGIN STARTING UP
115
+ gateway.buckets.forEach(async (bucket, bucketId)=>{
116
+ for (const worker of bucket.workers){
117
+ for (const shardId of worker.queue){
118
+ await gateway.resharding.tellWorkerToPrepare(worker.id, shardId, bucketId);
119
+ }
120
+ }
121
+ });
122
+ },
123
+ async tellWorkerToPrepare (workerId, shardId, bucketId) {
124
+ _utils.logger.warn(`[Resharding] Telling worker to prepare. Worker: ${workerId} | Shard: ${shardId} | Bucket: ${bucketId}`);
125
+ const shard = new _Shard.default({
126
+ id: shardId,
127
+ connection: {
128
+ compress: gateway.compress,
129
+ intents: gateway.intents,
130
+ properties: gateway.properties,
131
+ token: gateway.token,
132
+ totalShards: gateway.totalShards,
133
+ url: gateway.url,
134
+ version: gateway.version
135
+ },
136
+ // Ignore events until we are ready
137
+ events: {
138
+ async message (_shard, payload) {
139
+ if (payload.t === 'READY') {
140
+ await gateway.resharding.updateGuildsShardId(payload.d.guilds.map((g)=>g.id), shardId);
141
+ }
142
+ }
143
+ },
144
+ requestIdentify: async ()=>{
145
+ await gateway.identify(shardId);
146
+ },
147
+ shardIsReady: async ()=>{
148
+ _utils.logger.debug(`[Shard] Shard #${shardId} is ready`);
149
+ await (0, _utils.delay)(gateway.spawnShardDelay);
150
+ _utils.logger.debug(`[Shard] Resolving shard identify request`);
151
+ gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency).identifyRequests.shift()?.();
152
+ }
153
+ });
154
+ if (gateway.preferSnakeCase) {
155
+ shard.forwardToBot = async (payload)=>{
156
+ shard.events?.message?.(shard, payload);
157
+ };
158
+ }
159
+ gateway.resharding.shards.set(shardId, shard);
160
+ const bucket = gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency);
161
+ if (!bucket) return;
162
+ return await new Promise((resolve)=>{
163
+ // Mark that we are making an identify request so another is not made.
164
+ bucket.identifyRequests.push(resolve);
165
+ _utils.logger.debug(`[Gateway] identifying shard #(${shardId}).`);
166
+ // This will trigger identify and when READY is received it will resolve the above request.
167
+ shard?.identify().then(async ()=>{
168
+ // Tell the manager that this shard is online
169
+ return await gateway.resharding.shardIsPending(shard);
170
+ });
171
+ });
172
+ },
173
+ async updateGuildsShardId (guildIds, shardId) {
174
+ _utils.logger.debug(`[Resharding] Updating the following guild ids shard to #${shardId}: ${guildIds.join(', ')}. Override this function to update your cache if you need to.`);
175
+ },
176
+ async shardIsPending (shard) {
177
+ // Save this in pending at the moment, until all shards are online
178
+ gateway.resharding.pendingShards.set(shard.id, shard);
179
+ _utils.logger.warn(`[Resharding] Shard #${shard.id} is now pending`);
180
+ // Check if all shards are now online.
181
+ if (gateway.lastShardId - gateway.firstShardId + 1 > gateway.resharding.pendingShards.size) return;
182
+ _utils.logger.warn(`[Resharding] All shards are now online.`);
183
+ // New shards start processing events
184
+ for (const shard of gateway.resharding.pendingShards.values()){
185
+ for(const event in options.events){
186
+ // @ts-expect-error fixing this seems complex and doesnt seem worth it, feel free to fix if you wish
187
+ shard.events[event] = options.events[event];
188
+ }
189
+ }
190
+ // Old shards stop processing events
191
+ for (const shard of gateway.shards.values()){
192
+ const oldHandler = shard.events.message;
193
+ // Change with spread operator to not affect new shards, as changing anything on shard.events will directly change options.events, which changes new shards' events
194
+ shard.events = {
195
+ ...shard.events,
196
+ message: async function(_, message) {
197
+ // Member checks need to continue but others can stop
198
+ if (message.t !== 'GUILD_MEMBERS_CHUNK') return;
199
+ // Process only the chunking events
200
+ oldHandler?.(shard, message);
201
+ }
202
+ };
203
+ }
204
+ _utils.logger.warn(`[Resharding] Shutting down old shards.`);
205
+ // Close old shards
206
+ await gateway.shutdown(_types1.ShardSocketCloseCodes.Resharded, 'Resharded!', false);
207
+ _utils.logger.warn(`[Resharding] Completed.`);
208
+ // Replace old shards
209
+ gateway.shards = gateway.resharding.shards;
210
+ }
211
+ },
212
+ calculateTotalShards () {
213
+ // Bots under 100k servers do not have access to LBS.
214
+ if (gateway.totalShards < 100) {
215
+ gateway.logger.debug(`[Gateway] Calculating total shards: ${gateway.totalShards}`);
216
+ return gateway.totalShards;
217
+ }
218
+ gateway.logger.debug(`[Gateway] Calculating total shards`, gateway.totalShards, gateway.connection.sessionStartLimit.maxConcurrency);
219
+ // Calculate a multiple of `maxConcurrency` which can be used to connect to the gateway.
220
+ return Math.ceil(gateway.totalShards / // If `maxConcurrency` is 1, we can safely use 16 to get `totalShards` to be in a multiple of 16 so that we can prepare bots with 100k servers for LBS.
221
+ (gateway.connection.sessionStartLimit.maxConcurrency === 1 ? 16 : gateway.connection.sessionStartLimit.maxConcurrency)) * (gateway.connection.sessionStartLimit.maxConcurrency === 1 ? 16 : gateway.connection.sessionStartLimit.maxConcurrency);
222
+ },
223
+ calculateWorkerId (shardId) {
224
+ const workerId = Math.min(shardId % gateway.shardsPerWorker, gateway.totalWorkers - 1);
225
+ gateway.logger.debug(`[Gateway] Calculating workerId: Shard: ${shardId} -> Worker: ${workerId} -> Per Worker: ${gateway.shardsPerWorker} -> Total: ${gateway.totalWorkers}`);
226
+ return workerId;
227
+ },
228
+ prepareBuckets () {
229
+ for(let i = 0; i < gateway.connection.sessionStartLimit.maxConcurrency; ++i){
230
+ gateway.logger.debug(`[Gateway] Preparing buckets for concurrency: ${i}`);
231
+ gateway.buckets.set(i, {
232
+ workers: [],
233
+ identifyRequests: []
234
+ });
235
+ }
236
+ // ORGANIZE ALL SHARDS INTO THEIR OWN BUCKETS
237
+ for(let shardId = gateway.firstShardId; shardId <= gateway.lastShardId; ++shardId){
238
+ gateway.logger.debug(`[Gateway] Preparing buckets for shard: ${shardId}`);
239
+ if (shardId >= gateway.totalShards) {
240
+ throw new Error(`Shard (id: ${shardId}) is bigger or equal to the used amount of used shards which is ${gateway.totalShards}`);
241
+ }
242
+ const bucketId = shardId % gateway.connection.sessionStartLimit.maxConcurrency;
243
+ const bucket = gateway.buckets.get(bucketId);
244
+ if (!bucket) {
245
+ throw new Error(`Shard (id: ${shardId}) got assigned to an illegal bucket id: ${bucketId}, expected a bucket id between 0 and ${gateway.connection.sessionStartLimit.maxConcurrency - 1}`);
246
+ }
247
+ // FIND A QUEUE IN THIS BUCKET THAT HAS SPACE
248
+ // const worker = bucket.workers.find((w) => w.queue.length < gateway.shardsPerWorker);
249
+ const workerId = gateway.calculateWorkerId(shardId);
250
+ const worker = bucket.workers.find((w)=>w.id === workerId);
251
+ if (worker) {
252
+ // IF THE QUEUE HAS SPACE JUST ADD IT TO THIS QUEUE
253
+ worker.queue.push(shardId);
254
+ } else {
255
+ bucket.workers.push({
256
+ id: workerId,
257
+ queue: [
258
+ shardId
259
+ ]
260
+ });
261
+ }
262
+ }
263
+ for (const bucket of gateway.buckets.values()){
264
+ for (const worker of bucket.workers.values()){
265
+ worker.queue = worker.queue.sort((a, b)=>a - b);
266
+ }
267
+ }
268
+ },
269
+ async spawnShards () {
270
+ // PREPARES ALL SHARDS IN SPECIFIC BUCKETS
271
+ gateway.prepareBuckets();
272
+ // Prefer concurrency of forEach instead of forof
273
+ await Promise.all([
274
+ ...gateway.buckets.entries()
275
+ ].map(async ([bucketId, bucket])=>{
276
+ for (const worker of bucket.workers){
277
+ for (const shardId of worker.queue){
278
+ await gateway.tellWorkerToIdentify(worker.id, shardId, bucketId);
279
+ }
280
+ }
281
+ }));
282
+ // Check and reshard automatically if auto resharding is enabled.
283
+ if (gateway.resharding.enabled && gateway.resharding.checkInterval !== -1) {
284
+ gateway.resharding.checkIntervalId = setInterval(async ()=>{
285
+ const reshardingInfo = await gateway.resharding.checkIfReshardingIsNeeded();
286
+ if (reshardingInfo.needed && reshardingInfo.info) await gateway.resharding.reshard(reshardingInfo.info);
287
+ }, gateway.resharding.checkInterval);
288
+ }
289
+ },
290
+ async shutdown (code, reason, clearReshardingInterval = true) {
291
+ gateway.shards.forEach((shard)=>shard.close(code, reason));
292
+ if (clearReshardingInterval && gateway.resharding.checkIntervalId) clearInterval(gateway.resharding.checkIntervalId);
293
+ await (0, _utils.delay)(5000);
294
+ },
295
+ async sendPayload (shardId, payload) {
296
+ const shard = gateway.shards.get(shardId);
297
+ if (!shard) {
298
+ throw new Error(`Shard (id: ${shardId} not found`);
299
+ }
300
+ await shard.send(payload);
301
+ },
302
+ async tellWorkerToIdentify (workerId, shardId, bucketId) {
303
+ gateway.logger.debug(`[Gateway] tell worker to identify (${workerId}, ${shardId}, ${bucketId})`);
304
+ await gateway.identify(shardId);
305
+ },
306
+ async identify (shardId) {
307
+ let shard = this.shards.get(shardId);
308
+ gateway.logger.debug(`[Gateway] identifying ${shard ? 'existing' : 'new'} shard (${shardId})`);
309
+ if (!shard) {
310
+ shard = new _Shard.default({
311
+ id: shardId,
312
+ connection: {
313
+ compress: this.compress,
314
+ intents: this.intents,
315
+ properties: this.properties,
316
+ token: this.token,
317
+ totalShards: this.totalShards,
318
+ url: this.url,
319
+ version: this.version
320
+ },
321
+ events: options.events ?? {},
322
+ logger: this.logger,
323
+ requestIdentify: async ()=>{
324
+ await gateway.identify(shardId);
325
+ },
326
+ shardIsReady: async ()=>{
327
+ gateway.logger.debug(`[Shard] Shard #${shardId} is ready`);
328
+ await (0, _utils.delay)(gateway.spawnShardDelay);
329
+ gateway.logger.debug(`[Shard] Resolving shard identify request`);
330
+ gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency).identifyRequests.shift()?.();
331
+ }
332
+ });
333
+ if (this.preferSnakeCase) {
334
+ shard.forwardToBot = async (payload)=>{
335
+ shard.events.message?.(shard, payload);
336
+ };
337
+ }
338
+ this.shards.set(shardId, shard);
339
+ }
340
+ const bucket = gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency);
341
+ if (!bucket) return;
342
+ return await new Promise((resolve)=>{
343
+ // Mark that we are making an identify request so another is not made.
344
+ bucket.identifyRequests.push(resolve);
345
+ gateway.logger.debug(`[Gateway] identifying shard #(${shardId}).`);
346
+ // This will trigger identify and when READY is received it will resolve the above request.
347
+ shard?.identify();
348
+ });
349
+ },
350
+ async kill (shardId) {
351
+ const shard = this.shards.get(shardId);
352
+ if (!shard) {
353
+ return gateway.logger.debug(`[Gateway] kill shard but not found (${shardId})`);
354
+ }
355
+ gateway.logger.debug(`[Gateway] kill shard (${shardId})`);
356
+ this.shards.delete(shardId);
357
+ await shard.shutdown();
358
+ },
359
+ async requestIdentify (_shardId) {
360
+ gateway.logger.debug(`[Gateway] requesting identify`);
361
+ // const bucket = gateway.buckets.get(shardId % gateway.connection.sessionStartLimit.maxConcurrency)
362
+ // if (!bucket) return
363
+ // return await new Promise((resolve) => {
364
+ // bucket.identifyRequests.push(resolve)
365
+ // })
366
+ },
367
+ // Helpers methods below this
368
+ calculateShardId (guildId, totalShards) {
369
+ // If none is provided, use the total shards number from gateway object.
370
+ if (!totalShards) totalShards = gateway.totalShards;
371
+ // If it is only 1 shard, it will always be shard id 0
372
+ if (totalShards === 1) {
373
+ gateway.logger.debug(`[Gateway] calculateShardId (1 shard)`);
374
+ return 0;
375
+ }
376
+ gateway.logger.debug(`[Gateway] calculateShardId (guildId: ${guildId}, totalShards: ${totalShards})`);
377
+ return Number((BigInt(guildId) >> 22n) % BigInt(totalShards));
378
+ },
379
+ async joinVoiceChannel (guildId, channelId, options) {
380
+ const shardId = gateway.calculateShardId(guildId);
381
+ gateway.logger.debug(`[Gateway] joinVoiceChannel guildId: ${guildId} channelId: ${channelId}`);
382
+ await gateway.sendPayload(shardId, {
383
+ op: _types.GatewayOpcodes.VoiceStateUpdate,
384
+ d: {
385
+ guild_id: guildId.toString(),
386
+ channel_id: channelId.toString(),
387
+ self_mute: options?.selfMute ?? false,
388
+ self_deaf: options?.selfDeaf ?? true
389
+ }
390
+ });
391
+ },
392
+ async editBotStatus (data) {
393
+ gateway.logger.debug(`[Gateway] editBotStatus data: ${JSON.stringify(data)}`);
394
+ await Promise.all([
395
+ ...gateway.shards.values()
396
+ ].map(async (shard)=>{
397
+ gateway.editShardStatus(shard.id, data);
398
+ }));
399
+ },
400
+ async editShardStatus (shardId, data) {
401
+ gateway.logger.debug(`[Gateway] editShardStatus shardId: ${shardId} -> data: ${JSON.stringify(data)}`);
402
+ await gateway.sendPayload(shardId, {
403
+ op: _types.GatewayOpcodes.PresenceUpdate,
404
+ d: {
405
+ since: null,
406
+ afk: false,
407
+ activities: data.activities,
408
+ status: data.status
409
+ }
410
+ });
411
+ },
412
+ async requestMembers (guildId, options) {
413
+ const shardId = gateway.calculateShardId(guildId);
414
+ if (gateway.intents && (!options?.limit || options.limit > 1) && !(gateway.intents & _types.GatewayIntents.GuildMembers)) throw new Error('Cannot fetch more then 1 member without the GUILD_MEMBERS intent');
415
+ gateway.logger.debug(`[Gateway] requestMembers guildId: ${guildId} -> data: ${JSON.stringify(options)}`);
416
+ if (options?.userIds?.length) {
417
+ gateway.logger.debug(`[Gateway] requestMembers guildId: ${guildId} -> setting user limit based on userIds length: ${options.userIds.length}`);
418
+ options.limit = options.userIds.length;
419
+ }
420
+ const members = !gateway.cache.requestMembers.enabled || !options?.nonce ? [] : new Promise((resolve, reject)=>{
421
+ // Should never happen.
422
+ if (!gateway.cache.requestMembers.enabled || !options?.nonce) {
423
+ reject(new Error("Can't request the members without the nonce or with the feature disabled."));
424
+ return;
425
+ }
426
+ gateway.cache.requestMembers.pending.set(options.nonce, {
427
+ nonce: options.nonce,
428
+ resolve,
429
+ members: []
430
+ });
431
+ });
432
+ await gateway.sendPayload(shardId, {
433
+ op: _types.GatewayOpcodes.RequestGuildMembers,
434
+ d: {
435
+ guild_id: guildId.toString(),
436
+ // If a query is provided use it, OR if a limit is NOT provided use ""
437
+ query: options?.query ?? (options?.limit ? undefined : ''),
438
+ limit: options?.limit ?? 0,
439
+ presences: options?.presences ?? false,
440
+ user_ids: options?.userIds?.map((id)=>id.toString()),
441
+ nonce: options?.nonce
442
+ }
443
+ });
444
+ return await members;
445
+ },
446
+ async leaveVoiceChannel (guildId) {
447
+ const shardId = gateway.calculateShardId(guildId);
448
+ gateway.logger.debug(`[Gateway] leaveVoiceChannel guildId: ${guildId} Shard ${shardId}`);
449
+ await gateway.sendPayload(shardId, {
450
+ op: _types.GatewayOpcodes.VoiceStateUpdate,
451
+ d: {
452
+ guild_id: guildId.toString(),
453
+ channel_id: null,
454
+ self_mute: false,
455
+ self_deaf: false
456
+ }
457
+ });
458
+ }
459
+ };
460
+ return gateway;
461
+ }
462
+
463
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tYW5hZ2VyLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIHR5cGUgQXRMZWFzdE9uZSxcbiAgdHlwZSBCaWdTdHJpbmcsXG4gIHR5cGUgQ2FtZWxpemUsXG4gIHR5cGUgRGlzY29yZEdldEdhdGV3YXlCb3QsXG4gIHR5cGUgRGlzY29yZE1lbWJlcldpdGhVc2VyLFxuICB0eXBlIERpc2NvcmRSZWFkeSxcbiAgR2F0ZXdheUludGVudHMsXG4gIEdhdGV3YXlPcGNvZGVzLFxuICB0eXBlIFJlcXVlc3RHdWlsZE1lbWJlcnMsXG59IGZyb20gJ0BkaXNjb3JkZW5vL3R5cGVzJ1xuaW1wb3J0IHsgQ29sbGVjdGlvbiwgZGVsYXksIGxvZ2dlciB9IGZyb20gJ0BkaXNjb3JkZW5vL3V0aWxzJ1xuaW1wb3J0IFNoYXJkIGZyb20gJy4vU2hhcmQuanMnXG5pbXBvcnQgeyB0eXBlIFNoYXJkRXZlbnRzLCBTaGFyZFNvY2tldENsb3NlQ29kZXMsIHR5cGUgU2hhcmRTb2NrZXRSZXF1ZXN0LCB0eXBlIFN0YXR1c1VwZGF0ZSwgdHlwZSBVcGRhdGVWb2ljZVN0YXRlIH0gZnJvbSAnLi90eXBlcy5qcydcblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUdhdGV3YXlNYW5hZ2VyKG9wdGlvbnM6IENyZWF0ZUdhdGV3YXlNYW5hZ2VyT3B0aW9ucyk6IEdhdGV3YXlNYW5hZ2VyIHtcbiAgY29uc3QgY29ubmVjdGlvbk9wdGlvbnMgPSBvcHRpb25zLmNvbm5lY3Rpb24gPz8ge1xuICAgIHVybDogJ3dzczovL2dhdGV3YXkuZGlzY29yZC5nZycsXG4gICAgc2hhcmRzOiAxLFxuICAgIHNlc3Npb25TdGFydExpbWl0OiB7XG4gICAgICBtYXhDb25jdXJyZW5jeTogMSxcbiAgICAgIHJlbWFpbmluZzogMTAwMCxcbiAgICAgIHRvdGFsOiAxMDAwLFxuICAgICAgcmVzZXRBZnRlcjogMTAwMCAqIDYwICogNjAgKiAyNCxcbiAgICB9LFxuICB9XG5cbiAgY29uc3QgZ2F0ZXdheTogR2F0ZXdheU1hbmFnZXIgPSB7XG4gICAgZXZlbnRzOiBvcHRpb25zLmV2ZW50cyA/PyB7fSxcbiAgICBjb21wcmVzczogb3B0aW9ucy5jb21wcmVzcyA/PyBmYWxzZSxcbiAgICBpbnRlbnRzOiBvcHRpb25zLmludGVudHMgPz8gMCxcbiAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICBvczogb3B0aW9ucy5wcm9wZXJ0aWVzPy5vcyA/PyBwcm9jZXNzLnBsYXRmb3JtLFxuICAgICAgYnJvd3Nlcjogb3B0aW9ucy5wcm9wZXJ0aWVzPy5icm93c2VyID8/ICdEaXNjb3JkZW5vJyxcbiAgICAgIGRldmljZTogb3B0aW9ucy5wcm9wZXJ0aWVzPy5kZXZpY2UgPz8gJ0Rpc2NvcmRlbm8nLFxuICAgIH0sXG4gICAgdG9rZW46IG9wdGlvbnMudG9rZW4sXG4gICAgdXJsOiBvcHRpb25zLnVybCA/PyBjb25uZWN0aW9uT3B0aW9ucy51cmwgPz8gJ3dzczovL2dhdGV3YXkuZGlzY29yZC5nZycsXG4gICAgdmVyc2lvbjogb3B0aW9ucy52ZXJzaW9uID8/IDEwLFxuICAgIGNvbm5lY3Rpb246IGNvbm5lY3Rpb25PcHRpb25zLFxuICAgIHRvdGFsU2hhcmRzOiBvcHRpb25zLnRvdGFsU2hhcmRzID8/IGNvbm5lY3Rpb25PcHRpb25zLnNoYXJkcyA/PyAxLFxuICAgIGxhc3RTaGFyZElkOiBvcHRpb25zLmxhc3RTaGFyZElkID8/IChvcHRpb25zLnRvdGFsU2hhcmRzID8gb3B0aW9ucy50b3RhbFNoYXJkcyAtIDEgOiBjb25uZWN0aW9uT3B0aW9ucyA/IGNvbm5lY3Rpb25PcHRpb25zLnNoYXJkcyAtIDEgOiAwKSxcbiAgICBmaXJzdFNoYXJkSWQ6IG9wdGlvbnMuZmlyc3RTaGFyZElkID8/IDAsXG4gICAgdG90YWxXb3JrZXJzOiBvcHRpb25zLnRvdGFsV29ya2VycyA/PyA0LFxuICAgIHNoYXJkc1Blcldvcmtlcjogb3B0aW9ucy5zaGFyZHNQZXJXb3JrZXIgPz8gMjUsXG4gICAgc3Bhd25TaGFyZERlbGF5OiBvcHRpb25zLnNwYXduU2hhcmREZWxheSA/PyA1MzAwLFxuICAgIHByZWZlclNuYWtlQ2FzZTogb3B0aW9ucy5wcmVmZXJTbmFrZUNhc2UgPz8gZmFsc2UsXG4gICAgc2hhcmRzOiBuZXcgTWFwKCksXG4gICAgYnVja2V0czogbmV3IE1hcCgpLFxuICAgIGNhY2hlOiB7XG4gICAgICByZXF1ZXN0TWVtYmVyczoge1xuICAgICAgICBlbmFibGVkOiBvcHRpb25zLmNhY2hlPy5yZXF1ZXN0TWVtYmVycz8uZW5hYmxlZCA/PyBmYWxzZSxcbiAgICAgICAgcGVuZGluZzogbmV3IENvbGxlY3Rpb24oKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBsb2dnZXI6IG9wdGlvbnMubG9nZ2VyID8/IGxvZ2dlcixcbiAgICByZXNoYXJkaW5nOiB7XG4gICAgICBlbmFibGVkOiB0cnVlLFxuICAgICAgc2hhcmRzRnVsbFBlcmNlbnRhZ2U6IDgwLFxuICAgICAgY2hlY2tJbnRlcnZhbDogMjg4MDAwMDAsXG4gICAgICBzaGFyZHM6IG5ldyBDb2xsZWN0aW9uKCksXG4gICAgICBwZW5kaW5nU2hhcmRzOiBuZXcgQ29sbGVjdGlvbigpLFxuICAgICAgYXN5bmMgZ2V0U2Vzc2lvbkluZm8oKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAnW1Jlc2hhcmRpbmddIHdhcyBlbmFibGVkIGJ1dCBubyBnZXRTZXNzaW9uSW5mbyBoYW5kbGVyIHdhcyBwcm92aWRlZC4gUGxlYXNlIHNldCBhIGhhbmRsZXIgbGlrZTogZ2F0ZXdheS5yZXNoYXJkaW5nLmdldFNlc3Npb25JbmZvID0gYXN5bmMgKCkgPT4geyAvLyBpbnNlcnQgY29kZSBoZXJlIHRvIGZldGNoIGdldFNlc3Npb25JbmZvIGZyb20gcmVzdCBwcm9jZXNzLiB9JyxcbiAgICAgICAgKVxuICAgICAgfSxcbiAgICAgIGFzeW5jIGNoZWNrSWZSZXNoYXJkaW5nSXNOZWVkZWQoKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbUmVzaGFyZGluZ10gQ2hlY2tpbmcgaWYgcmVzaGFyZGluZyBpcyBuZWVkZWQuYClcbiAgICAgICAgLy8gUmVzaGFyZGluZyBpcyBkaXNhYmxlZC5cbiAgICAgICAgaWYgKCFnYXRld2F5LnJlc2hhcmRpbmcuZW5hYmxlZCkgcmV0dXJuIHsgbmVlZGVkOiBmYWxzZSB9XG4gICAgICAgIGxvZ2dlci53YXJuKGBbUmVzaGFyZGluZ10gUmVzaGFyZGluZyBpcyBlbmFibGVkLmApXG5cbiAgICAgICAgY29uc3Qgc2Vzc2lvbkluZm8gPSBhd2FpdCBnYXRld2F5LnJlc2hhcmRpbmcuZ2V0U2Vzc2lvbkluZm8oKVxuICAgICAgICBsb2dnZXIud2FybihgW1Jlc2hhcmRpbmddIFNlc3Npb24gaW5mbyByZXRyaWV2ZWQuYClcbiAgICAgICAgLy8gRG9uJ3QgaGF2ZSBlbm91Z2ggaWRlbnRpZnkgbGltaXRzIHRvIHRyeSByZXNoYXJkaW5nXG4gICAgICAgIGlmIChzZXNzaW9uSW5mby5zZXNzaW9uU3RhcnRMaW1pdC5yZW1haW5pbmcgPCBzZXNzaW9uSW5mby5zaGFyZHMpIHJldHVybiB7IG5lZWRlZDogZmFsc2UsIGluZm86IHNlc3Npb25JbmZvIH1cbiAgICAgICAgbG9nZ2VyLndhcm4oYFtSZXNoYXJkaW5nXSBBYmxlIHRvIHJlc2hhcmQsIGNoZWNraW5nIHdoZXRoZXIgbmVjZXNzYXJ5IG5vdy5gKVxuXG4gICAgICAgIC8vIDI1MDAgaXMgdGhlIG1heCBhbW91bnQgb2YgZ3VpbGRzIGEgc2luZ2xlIHNoYXJkIGNhbiBoYW5kbGVcbiAgICAgICAgLy8gMTAwMCBpcyB0aGUgYW1vdW50IG9mIGd1aWxkcyBkaXNjb3JkIHVzZXMgdG8gZGV0ZXJtaW5lIGhvdyBtYW55IHNoYXJkcyB0byByZWNvbW1lbmQuXG4gICAgICAgIC8vIFRoaXMgYWxnbyBoZWxwcyBjaGVjayBpZiB5b3VyIGJvdCBoYXMgZ3Jvd24gZW5vdWdoIHRvIHJlc2hhcmQuXG4gICAgICAgIGNvbnN0IHBlcmNlbnRhZ2UgPSAoKDI1MDAgKiBzZXNzaW9uSW5mby5zaGFyZHMpIC8gKGdhdGV3YXkudG90YWxTaGFyZHMgKiAxMDAwKSkgKiAxMDBcbiAgICAgICAgLy8gTGVzcyB0aGFuIG5lY2Vzc2FyeSUgYmVpbmcgdXNlZCBzbyBkbyBub3RoaW5nXG4gICAgICAgIGlmIChwZXJjZW50YWdlIDwgZ2F0ZXdheS5yZXNoYXJkaW5nLnNoYXJkc0Z1bGxQZXJjZW50YWdlKSByZXR1cm4geyBuZWVkZWQ6IGZhbHNlLCBpbmZvOiBzZXNzaW9uSW5mbyB9XG4gICAgICAgIGxvZ2dlci53YXJuKGBbUmVzaGFyZGluZ10gUmVzaGFyZGluZyBpcyBuZWVkZWQuYClcblxuICAgICAgICByZXR1cm4geyBuZWVkZWQ6IHRydWUsIGluZm86IHNlc3Npb25JbmZvIH1cbiAgICAgIH0sXG4gICAgICBhc3luYyByZXNoYXJkKGluZm8pIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oYFtSZXNoYXJkaW5nXSBTdGFydGluZyB0aGUgcmVzaGFyZCBwcm9jZXNzLiBQcmV2aW91cyB0b3RhbCBzaGFyZHMuICR7Z2F0ZXdheS50b3RhbFNoYXJkc31gKVxuICAgICAgICAvLyBTZXQgdmFsdWVzIG9uIGdhdGV3YXlcbiAgICAgICAgZ2F0ZXdheS50b3RhbFNoYXJkcyA9IGluZm8uc2hhcmRzXG4gICAgICAgIC8vIEhhbmRsZXMgcHJlcGFyaW5nIG1pZCBzaXplZCBib3RzIGZvciBMQlNcbiAgICAgICAgZ2F0ZXdheS50b3RhbFNoYXJkcyA9IGdhdGV3YXkuY2FsY3VsYXRlVG90YWxTaGFyZHMoKVxuICAgICAgICAvLyBTZXQgZmlyc3Qgc2hhcmQgaWQgaWYgcHJvdmlkZWQgaW4gaW5mb1xuICAgICAgICBpZiAodHlwZW9mIGluZm8uZmlyc3RTaGFyZElkID09PSAnbnVtYmVyJykgZ2F0ZXdheS5maXJzdFNoYXJkSWQgPSBpbmZvLmZpcnN0U2hhcmRJZFxuICAgICAgICAvLyBTZXQgbGFzdCBzaGFyZCBpZCBpZiBwcm92aWRlZCBpbiBpbmZvXG4gICAgICAgIGlmICh0eXBlb2YgaW5mby5sYXN0U2hhcmRJZCA9PT0gJ251bWJlcicpIGdhdGV3YXkubGFzdFNoYXJkSWQgPSBpbmZvLmxhc3RTaGFyZElkXG4gICAgICAgIGxvZ2dlci53YXJuKGBbUmVzaGFyZGluZ10gU3RhcnRpbmcgdGhlIHJlc2hhcmQgcHJvY2Vzcy4gTmV3IFRvdGFsIFNoYXJkcy4gJHtnYXRld2F5LnRvdGFsU2hhcmRzfWApXG5cbiAgICAgICAgLy8gUmVzZXR0aW5nIGJ1Y2tldHNcbiAgICAgICAgZ2F0ZXdheS5idWNrZXRzLmNsZWFyKClcbiAgICAgICAgLy8gUmVmaWxsaW5nIGJ1Y2tldHMgd2l0aCBuZXcgdmFsdWVzXG4gICAgICAgIGdhdGV3YXkucHJlcGFyZUJ1Y2tldHMoKVxuXG4gICAgICAgIC8vIFNQUkVBRCBUSElTIE9VVCBUTyBESUZGRVJFTlQgV09SS0VSUyBUTyBCRUdJTiBTVEFSVElORyBVUFxuICAgICAgICBnYXRld2F5LmJ1Y2tldHMuZm9yRWFjaChhc3luYyAoYnVja2V0LCBidWNrZXRJZCkgPT4ge1xuICAgICAgICAgIGZvciAoY29uc3Qgd29ya2VyIG9mIGJ1Y2tldC53b3JrZXJzKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHNoYXJkSWQgb2Ygd29ya2VyLnF1ZXVlKSB7XG4gICAgICAgICAgICAgIGF3YWl0IGdhdGV3YXkucmVzaGFyZGluZy50ZWxsV29ya2VyVG9QcmVwYXJlKHdvcmtlci5pZCwgc2hhcmRJZCwgYnVja2V0SWQpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgfSxcbiAgICAgIGFzeW5jIHRlbGxXb3JrZXJUb1ByZXBhcmUod29ya2VySWQsIHNoYXJkSWQsIGJ1Y2tldElkKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbUmVzaGFyZGluZ10gVGVsbGluZyB3b3JrZXIgdG8gcHJlcGFyZS4gV29ya2VyOiAke3dvcmtlcklkfSB8IFNoYXJkOiAke3NoYXJkSWR9IHwgQnVja2V0OiAke2J1Y2tldElkfWApXG4gICAgICAgIGNvbnN0IHNoYXJkID0gbmV3IFNoYXJkKHtcbiAgICAgICAgICBpZDogc2hhcmRJZCxcbiAgICAgICAgICBjb25uZWN0aW9uOiB7XG4gICAgICAgICAgICBjb21wcmVzczogZ2F0ZXdheS5jb21wcmVzcyxcbiAgICAgICAgICAgIGludGVudHM6IGdhdGV3YXkuaW50ZW50cyxcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IGdhdGV3YXkucHJvcGVydGllcyxcbiAgICAgICAgICAgIHRva2VuOiBnYXRld2F5LnRva2VuLFxuICAgICAgICAgICAgdG90YWxTaGFyZHM6IGdhdGV3YXkudG90YWxTaGFyZHMsXG4gICAgICAgICAgICB1cmw6IGdhdGV3YXkudXJsLFxuICAgICAgICAgICAgdmVyc2lvbjogZ2F0ZXdheS52ZXJzaW9uLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLy8gSWdub3JlIGV2ZW50cyB1bnRpbCB3ZSBhcmUgcmVhZHlcbiAgICAgICAgICBldmVudHM6IHtcbiAgICAgICAgICAgIGFzeW5jIG1lc3NhZ2UoX3NoYXJkLCBwYXlsb2FkKSB7XG4gICAgICAgICAgICAgIGlmIChwYXlsb2FkLnQgPT09ICdSRUFEWScpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCBnYXRld2F5LnJlc2hhcmRpbmcudXBkYXRlR3VpbGRzU2hhcmRJZChcbiAgICAgICAgICAgICAgICAgIChwYXlsb2FkLmQgYXMgRGlzY29yZFJlYWR5KS5ndWlsZHMubWFwKChnKSA9PiBnLmlkKSxcbiAgICAgICAgICAgICAgICAgIHNoYXJkSWQsXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVxdWVzdElkZW50aWZ5OiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBhd2FpdCBnYXRld2F5LmlkZW50aWZ5KHNoYXJkSWQpXG4gICAgICAgICAgfSxcbiAgICAgICAgICBzaGFyZElzUmVhZHk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgW1NoYXJkXSBTaGFyZCAjJHtzaGFyZElkfSBpcyByZWFkeWApXG4gICAgICAgICAgICBhd2FpdCBkZWxheShnYXRld2F5LnNwYXduU2hhcmREZWxheSlcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgW1NoYXJkXSBSZXNvbHZpbmcgc2hhcmQgaWRlbnRpZnkgcmVxdWVzdGApXG4gICAgICAgICAgICBnYXRld2F5LmJ1Y2tldHMuZ2V0KHNoYXJkSWQgJSBnYXRld2F5LmNvbm5lY3Rpb24uc2Vzc2lvblN0YXJ0TGltaXQubWF4Q29uY3VycmVuY3kpIS5pZGVudGlmeVJlcXVlc3RzLnNoaWZ0KCk/LigpXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcblxuICAgICAgICBpZiAoZ2F0ZXdheS5wcmVmZXJTbmFrZUNhc2UpIHtcbiAgICAgICAgICBzaGFyZC5mb3J3YXJkVG9Cb3QgPSBhc3luYyAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgc2hhcmQuZXZlbnRzPy5tZXNzYWdlPy4oc2hhcmQsIHBheWxvYWQpXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZ2F0ZXdheS5yZXNoYXJkaW5nLnNoYXJkcy5zZXQoc2hhcmRJZCwgc2hhcmQpXG5cbiAgICAgICAgY29uc3QgYnVja2V0ID0gZ2F0ZXdheS5idWNrZXRzLmdldChzaGFyZElkICUgZ2F0ZXdheS5jb25uZWN0aW9uLnNlc3Npb25TdGFydExpbWl0Lm1heENvbmN1cnJlbmN5KVxuICAgICAgICBpZiAoIWJ1Y2tldCkgcmV0dXJuXG5cbiAgICAgICAgcmV0dXJuIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgLy8gTWFyayB0aGF0IHdlIGFyZSBtYWtpbmcgYW4gaWRlbnRpZnkgcmVxdWVzdCBzbyBhbm90aGVyIGlzIG5vdCBtYWRlLlxuICAgICAgICAgIGJ1Y2tldC5pZGVudGlmeVJlcXVlc3RzLnB1c2gocmVzb2x2ZSlcbiAgICAgICAgICBsb2dnZXIuZGVidWcoYFtHYXRld2F5XSBpZGVudGlmeWluZyBzaGFyZCAjKCR7c2hhcmRJZH0pLmApXG4gICAgICAgICAgLy8gVGhpcyB3aWxsIHRyaWdnZXIgaWRlbnRpZnkgYW5kIHdoZW4gUkVBRFkgaXMgcmVjZWl2ZWQgaXQgd2lsbCByZXNvbHZlIHRoZSBhYm92ZSByZXF1ZXN0LlxuICAgICAgICAgIHNoYXJkPy5pZGVudGlmeSgpLnRoZW4oYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgLy8gVGVsbCB0aGUgbWFuYWdlciB0aGF0IHRoaXMgc2hhcmQgaXMgb25saW5lXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgZ2F0ZXdheS5yZXNoYXJkaW5nLnNoYXJkSXNQZW5kaW5nKHNoYXJkKVxuICAgICAgICAgIH0pXG4gICAgICAgIH0pXG4gICAgICB9LFxuICAgICAgYXN5bmMgdXBkYXRlR3VpbGRzU2hhcmRJZChndWlsZElkcywgc2hhcmRJZCkge1xuICAgICAgICBsb2dnZXIuZGVidWcoXG4gICAgICAgICAgYFtSZXNoYXJkaW5nXSBVcGRhdGluZyB0aGUgZm9sbG93aW5nIGd1aWxkIGlkcyBzaGFyZCB0byAjJHtzaGFyZElkfTogJHtndWlsZElkcy5qb2luKCcsICcpfS4gT3ZlcnJpZGUgdGhpcyBmdW5jdGlvbiB0byB1cGRhdGUgeW91ciBjYWNoZSBpZiB5b3UgbmVlZCB0by5gLFxuICAgICAgICApXG4gICAgICB9LFxuICAgICAgYXN5bmMgc2hhcmRJc1BlbmRpbmcoc2hhcmQpIHtcbiAgICAgICAgLy8gU2F2ZSB0aGlzIGluIHBlbmRpbmcgYXQgdGhlIG1vbWVudCwgdW50aWwgYWxsIHNoYXJkcyBhcmUgb25saW5lXG4gICAgICAgIGdhdGV3YXkucmVzaGFyZGluZy5wZW5kaW5nU2hhcmRzLnNldChzaGFyZC5pZCwgc2hhcmQpXG4gICAgICAgIGxvZ2dlci53YXJuKGBbUmVzaGFyZGluZ10gU2hhcmQgIyR7c2hhcmQuaWR9IGlzIG5vdyBwZW5kaW5nYClcbiAgICAgICAgLy8gQ2hlY2sgaWYgYWxsIHNoYXJkcyBhcmUgbm93IG9ubGluZS5cbiAgICAgICAgaWYgKGdhdGV3YXkubGFzdFNoYXJkSWQgLSBnYXRld2F5LmZpcnN0U2hhcmRJZCArIDEgPiBnYXRld2F5LnJlc2hhcmRpbmcucGVuZGluZ1NoYXJkcy5zaXplKSByZXR1cm5cbiAgICAgICAgbG9nZ2VyLndhcm4oYFtSZXNoYXJkaW5nXSBBbGwgc2hhcmRzIGFyZSBub3cgb25saW5lLmApXG5cbiAgICAgICAgLy8gTmV3IHNoYXJkcyBzdGFydCBwcm9jZXNzaW5nIGV2ZW50c1xuICAgICAgICBmb3IgKGNvbnN0IHNoYXJkIG9mIGdhdGV3YXkucmVzaGFyZGluZy5wZW5kaW5nU2hhcmRzLnZhbHVlcygpKSB7XG4gICAgICAgICAgZm9yIChjb25zdCBldmVudCBpbiBvcHRpb25zLmV2ZW50cykge1xuICAgICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBmaXhpbmcgdGhpcyBzZWVtcyBjb21wbGV4IGFuZCBkb2VzbnQgc2VlbSB3b3J0aCBpdCwgZmVlbCBmcmVlIHRvIGZpeCBpZiB5b3Ugd2lzaFxuICAgICAgICAgICAgc2hhcmQuZXZlbnRzW2V2ZW50XSA9IG9wdGlvbnMuZXZlbnRzW2V2ZW50XVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9sZCBzaGFyZHMgc3RvcCBwcm9jZXNzaW5nIGV2ZW50c1xuICAgICAgICBmb3IgKGNvbnN0IHNoYXJkIG9mIGdhdGV3YXkuc2hhcmRzLnZhbHVlcygpKSB7XG4gICAgICAgICAgY29uc3Qgb2xkSGFuZGxlciA9IHNoYXJkLmV2ZW50cy5tZXNzYWdlXG5cbiAgICAgICAgICAvLyBDaGFuZ2Ugd2l0aCBzcHJlYWQgb3BlcmF0b3IgdG8gbm90IGFmZmVjdCBuZXcgc2hhcmRzLCBhcyBjaGFuZ2luZyBhbnl0aGluZyBvbiBzaGFyZC5ldmVudHMgd2lsbCBkaXJlY3RseSBjaGFuZ2Ugb3B0aW9ucy5ldmVudHMsIHdoaWNoIGNoYW5nZXMgbmV3IHNoYXJkcycgZXZlbnRzXG4gICAgICAgICAgc2hhcmQuZXZlbnRzID0ge1xuICAgICAgICAgICAgLi4uc2hhcmQuZXZlbnRzLFxuICAgICAgICAgICAgbWVzc2FnZTogYXN5bmMgZnVuY3Rpb24gKF8sIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgLy8gTWVtYmVyIGNoZWNrcyBuZWVkIHRvIGNvbnRpbnVlIGJ1dCBvdGhlcnMgY2FuIHN0b3BcbiAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UudCAhPT0gJ0dVSUxEX01FTUJFUlNfQ0hVTksnKSByZXR1cm5cbiAgICAgICAgICAgICAgLy8gUHJvY2VzcyBvbmx5IHRoZSBjaHVua2luZyBldmVudHNcbiAgICAgICAgICAgICAgb2xkSGFuZGxlcj8uKHNoYXJkLCBtZXNzYWdlKVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsb2dnZXIud2FybihgW1Jlc2hhcmRpbmddIFNodXR0aW5nIGRvd24gb2xkIHNoYXJkcy5gKVxuICAgICAgICAvLyBDbG9zZSBvbGQgc2hhcmRzXG4gICAgICAgIGF3YWl0IGdhdGV3YXkuc2h1dGRvd24oU2hhcmRTb2NrZXRDbG9zZUNvZGVzLlJlc2hhcmRlZCwgJ1Jlc2hhcmRlZCEnLCBmYWxzZSlcbiAgICAgICAgbG9nZ2VyLndhcm4oYFtSZXNoYXJkaW5nXSBDb21wbGV0ZWQuYClcblxuICAgICAgICAvLyBSZXBsYWNlIG9sZCBzaGFyZHNcbiAgICAgICAgZ2F0ZXdheS5zaGFyZHMgPSBnYXRld2F5LnJlc2hhcmRpbmcuc2hhcmRzXG4gICAgICB9LFxuICAgIH0sXG5cbiAgICBjYWxjdWxhdGVUb3RhbFNoYXJkcygpIHtcbiAgICAgIC8vIEJvdHMgdW5kZXIgMTAwayBzZXJ2ZXJzIGRvIG5vdCBoYXZlIGFjY2VzcyB0byBMQlMuXG4gICAgICBpZiAoZ2F0ZXdheS50b3RhbFNoYXJkcyA8IDEwMCkge1xuICAgICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW0dhdGV3YXldIENhbGN1bGF0aW5nIHRvdGFsIHNoYXJkczogJHtnYXRld2F5LnRvdGFsU2hhcmRzfWApXG4gICAgICAgIHJldHVybiBnYXRld2F5LnRvdGFsU2hhcmRzXG4gICAgICB9XG5cbiAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gQ2FsY3VsYXRpbmcgdG90YWwgc2hhcmRzYCwgZ2F0ZXdheS50b3RhbFNoYXJkcywgZ2F0ZXdheS5jb25uZWN0aW9uLnNlc3Npb25TdGFydExpbWl0Lm1heENvbmN1cnJlbmN5KVxuICAgICAgLy8gQ2FsY3VsYXRlIGEgbXVsdGlwbGUgb2YgYG1heENvbmN1cnJlbmN5YCB3aGljaCBjYW4gYmUgdXNlZCB0byBjb25uZWN0IHRvIHRoZSBnYXRld2F5LlxuICAgICAgcmV0dXJuIChcbiAgICAgICAgTWF0aC5jZWlsKFxuICAgICAgICAgIGdhdGV3YXkudG90YWxTaGFyZHMgL1xuICAgICAgICAgICAgLy8gSWYgYG1heENvbmN1cnJlbmN5YCBpcyAxLCB3ZSBjYW4gc2FmZWx5IHVzZSAxNiB0byBnZXQgYHRvdGFsU2hhcmRzYCB0byBiZSBpbiBhIG11bHRpcGxlIG9mIDE2IHNvIHRoYXQgd2UgY2FuIHByZXBhcmUgYm90cyB3aXRoIDEwMGsgc2VydmVycyBmb3IgTEJTLlxuICAgICAgICAgICAgKGdhdGV3YXkuY29ubmVjdGlvbi5zZXNzaW9uU3RhcnRMaW1pdC5tYXhDb25jdXJyZW5jeSA9PT0gMSA/IDE2IDogZ2F0ZXdheS5jb25uZWN0aW9uLnNlc3Npb25TdGFydExpbWl0Lm1heENvbmN1cnJlbmN5KSxcbiAgICAgICAgKSAqIChnYXRld2F5LmNvbm5lY3Rpb24uc2Vzc2lvblN0YXJ0TGltaXQubWF4Q29uY3VycmVuY3kgPT09IDEgPyAxNiA6IGdhdGV3YXkuY29ubmVjdGlvbi5zZXNzaW9uU3RhcnRMaW1pdC5tYXhDb25jdXJyZW5jeSlcbiAgICAgIClcbiAgICB9LFxuICAgIGNhbGN1bGF0ZVdvcmtlcklkKHNoYXJkSWQpIHtcbiAgICAgIGNvbnN0IHdvcmtlcklkID0gTWF0aC5taW4oc2hhcmRJZCAlIGdhdGV3YXkuc2hhcmRzUGVyV29ya2VyLCBnYXRld2F5LnRvdGFsV29ya2VycyAtIDEpXG4gICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhcbiAgICAgICAgYFtHYXRld2F5XSBDYWxjdWxhdGluZyB3b3JrZXJJZDogU2hhcmQ6ICR7c2hhcmRJZH0gLT4gV29ya2VyOiAke3dvcmtlcklkfSAtPiBQZXIgV29ya2VyOiAke2dhdGV3YXkuc2hhcmRzUGVyV29ya2VyfSAtPiBUb3RhbDogJHtnYXRld2F5LnRvdGFsV29ya2Vyc31gLFxuICAgICAgKVxuICAgICAgcmV0dXJuIHdvcmtlcklkXG4gICAgfSxcbiAgICBwcmVwYXJlQnVja2V0cygpIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZ2F0ZXdheS5jb25uZWN0aW9uLnNlc3Npb25TdGFydExpbWl0Lm1heENvbmN1cnJlbmN5OyArK2kpIHtcbiAgICAgICAgZ2F0ZXdheS5sb2dnZXIuZGVidWcoYFtHYXRld2F5XSBQcmVwYXJpbmcgYnVja2V0cyBmb3IgY29uY3VycmVuY3k6ICR7aX1gKVxuICAgICAgICBnYXRld2F5LmJ1Y2tldHMuc2V0KGksIHtcbiAgICAgICAgICB3b3JrZXJzOiBbXSxcbiAgICAgICAgICBpZGVudGlmeVJlcXVlc3RzOiBbXSxcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgLy8gT1JHQU5JWkUgQUxMIFNIQVJEUyBJTlRPIFRIRUlSIE9XTiBCVUNLRVRTXG4gICAgICBmb3IgKGxldCBzaGFyZElkID0gZ2F0ZXdheS5maXJzdFNoYXJkSWQ7IHNoYXJkSWQgPD0gZ2F0ZXdheS5sYXN0U2hhcmRJZDsgKytzaGFyZElkKSB7XG4gICAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gUHJlcGFyaW5nIGJ1Y2tldHMgZm9yIHNoYXJkOiAke3NoYXJkSWR9YClcbiAgICAgICAgaWYgKHNoYXJkSWQgPj0gZ2F0ZXdheS50b3RhbFNoYXJkcykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU2hhcmQgKGlkOiAke3NoYXJkSWR9KSBpcyBiaWdnZXIgb3IgZXF1YWwgdG8gdGhlIHVzZWQgYW1vdW50IG9mIHVzZWQgc2hhcmRzIHdoaWNoIGlzICR7Z2F0ZXdheS50b3RhbFNoYXJkc31gKVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgYnVja2V0SWQgPSBzaGFyZElkICUgZ2F0ZXdheS5jb25uZWN0aW9uLnNlc3Npb25TdGFydExpbWl0Lm1heENvbmN1cnJlbmN5XG4gICAgICAgIGNvbnN0IGJ1Y2tldCA9IGdhdGV3YXkuYnVja2V0cy5nZXQoYnVja2V0SWQpXG4gICAgICAgIGlmICghYnVja2V0KSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFNoYXJkIChpZDogJHtzaGFyZElkfSkgZ290IGFzc2lnbmVkIHRvIGFuIGlsbGVnYWwgYnVja2V0IGlkOiAke2J1Y2tldElkfSwgZXhwZWN0ZWQgYSBidWNrZXQgaWQgYmV0d2VlbiAwIGFuZCAke1xuICAgICAgICAgICAgICBnYXRld2F5LmNvbm5lY3Rpb24uc2Vzc2lvblN0YXJ0TGltaXQubWF4Q29uY3VycmVuY3kgLSAxXG4gICAgICAgICAgICB9YCxcbiAgICAgICAgICApXG4gICAgICAgIH1cblxuICAgICAgICAvLyBGSU5EIEEgUVVFVUUgSU4gVEhJUyBCVUNLRVQgVEhBVCBIQVMgU1BBQ0VcbiAgICAgICAgLy8gY29uc3Qgd29ya2VyID0gYnVja2V0LndvcmtlcnMuZmluZCgodykgPT4gdy5xdWV1ZS5sZW5ndGggPCBnYXRld2F5LnNoYXJkc1Blcldvcmtlcik7XG4gICAgICAgIGNvbnN0IHdvcmtlcklkID0gZ2F0ZXdheS5jYWxjdWxhdGVXb3JrZXJJZChzaGFyZElkKVxuICAgICAgICBjb25zdCB3b3JrZXIgPSBidWNrZXQud29ya2Vycy5maW5kKCh3KSA9PiB3LmlkID09PSB3b3JrZXJJZClcbiAgICAgICAgaWYgKHdvcmtlcikge1xuICAgICAgICAgIC8vIElGIFRIRSBRVUVVRSBIQVMgU1BBQ0UgSlVTVCBBREQgSVQgVE8gVEhJUyBRVUVVRVxuICAgICAgICAgIHdvcmtlci5xdWV1ZS5wdXNoKHNoYXJkSWQpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnVja2V0LndvcmtlcnMucHVzaCh7IGlkOiB3b3JrZXJJZCwgcXVldWU6IFtzaGFyZElkXSB9KVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgYnVja2V0IG9mIGdhdGV3YXkuYnVja2V0cy52YWx1ZXMoKSkge1xuICAgICAgICBmb3IgKGNvbnN0IHdvcmtlciBvZiBidWNrZXQud29ya2Vycy52YWx1ZXMoKSkge1xuICAgICAgICAgIHdvcmtlci5xdWV1ZSA9IHdvcmtlci5xdWV1ZS5zb3J0KChhLCBiKSA9PiBhIC0gYilcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgYXN5bmMgc3Bhd25TaGFyZHMoKSB7XG4gICAgICAvLyBQUkVQQVJFUyBBTEwgU0hBUkRTIElOIFNQRUNJRklDIEJVQ0tFVFNcbiAgICAgIGdhdGV3YXkucHJlcGFyZUJ1Y2tldHMoKVxuXG4gICAgICAvLyBQcmVmZXIgY29uY3VycmVuY3kgb2YgZm9yRWFjaCBpbnN0ZWFkIG9mIGZvcm9mXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgWy4uLmdhdGV3YXkuYnVja2V0cy5lbnRyaWVzKCldLm1hcChhc3luYyAoW2J1Y2tldElkLCBidWNrZXRdKSA9PiB7XG4gICAgICAgICAgZm9yIChjb25zdCB3b3JrZXIgb2YgYnVja2V0LndvcmtlcnMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3Qgc2hhcmRJZCBvZiB3b3JrZXIucXVldWUpIHtcbiAgICAgICAgICAgICAgYXdhaXQgZ2F0ZXdheS50ZWxsV29ya2VyVG9JZGVudGlmeSh3b3JrZXIuaWQsIHNoYXJkSWQsIGJ1Y2tldElkKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICApXG5cbiAgICAgIC8vIENoZWNrIGFuZCByZXNoYXJkIGF1dG9tYXRpY2FsbHkgaWYgYXV0byByZXNoYXJkaW5nIGlzIGVuYWJsZWQuXG4gICAgICBpZiAoZ2F0ZXdheS5yZXNoYXJkaW5nLmVuYWJsZWQgJiYgZ2F0ZXdheS5yZXNoYXJkaW5nLmNoZWNrSW50ZXJ2YWwgIT09IC0xKSB7XG4gICAgICAgIGdhdGV3YXkucmVzaGFyZGluZy5jaGVja0ludGVydmFsSWQgPSBzZXRJbnRlcnZhbChhc3luYyAoKSA9PiB7XG4gICAgICAgICAgY29uc3QgcmVzaGFyZGluZ0luZm8gPSBhd2FpdCBnYXRld2F5LnJlc2hhcmRpbmcuY2hlY2tJZlJlc2hhcmRpbmdJc05lZWRlZCgpXG5cbiAgICAgICAgICBpZiAocmVzaGFyZGluZ0luZm8ubmVlZGVkICYmIHJlc2hhcmRpbmdJbmZvLmluZm8pIGF3YWl0IGdhdGV3YXkucmVzaGFyZGluZy5yZXNoYXJkKHJlc2hhcmRpbmdJbmZvLmluZm8pXG4gICAgICAgIH0sIGdhdGV3YXkucmVzaGFyZGluZy5jaGVja0ludGVydmFsKVxuICAgICAgfVxuICAgIH0sXG4gICAgYXN5bmMgc2h1dGRvd24oY29kZSwgcmVhc29uLCBjbGVhclJlc2hhcmRpbmdJbnRlcnZhbCA9IHRydWUpIHtcbiAgICAgIGdhdGV3YXkuc2hhcmRzLmZvckVhY2goKHNoYXJkKSA9PiBzaGFyZC5jbG9zZShjb2RlLCByZWFzb24pKVxuXG4gICAgICBpZiAoY2xlYXJSZXNoYXJkaW5nSW50ZXJ2YWwgJiYgZ2F0ZXdheS5yZXNoYXJkaW5nLmNoZWNrSW50ZXJ2YWxJZCkgY2xlYXJJbnRlcnZhbChnYXRld2F5LnJlc2hhcmRpbmcuY2hlY2tJbnRlcnZhbElkKVxuXG4gICAgICBhd2FpdCBkZWxheSg1MDAwKVxuICAgIH0sXG4gICAgYXN5bmMgc2VuZFBheWxvYWQoc2hhcmRJZCwgcGF5bG9hZCkge1xuICAgICAgY29uc3Qgc2hhcmQgPSBnYXRld2F5LnNoYXJkcy5nZXQoc2hhcmRJZClcblxuICAgICAgaWYgKCFzaGFyZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFNoYXJkIChpZDogJHtzaGFyZElkfSBub3QgZm91bmRgKVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBzaGFyZC5zZW5kKHBheWxvYWQpXG4gICAgfSxcbiAgICBhc3luYyB0ZWxsV29ya2VyVG9JZGVudGlmeSh3b3JrZXJJZCwgc2hhcmRJZCwgYnVja2V0SWQpIHtcbiAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gdGVsbCB3b3JrZXIgdG8gaWRlbnRpZnkgKCR7d29ya2VySWR9LCAke3NoYXJkSWR9LCAke2J1Y2tldElkfSlgKVxuICAgICAgYXdhaXQgZ2F0ZXdheS5pZGVudGlmeShzaGFyZElkKVxuICAgIH0sXG4gICAgYXN5bmMgaWRlbnRpZnkoc2hhcmRJZDogbnVtYmVyKSB7XG4gICAgICBsZXQgc2hhcmQgPSB0aGlzLnNoYXJkcy5nZXQoc2hhcmRJZClcbiAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gaWRlbnRpZnlpbmcgJHtzaGFyZCA/ICdleGlzdGluZycgOiAnbmV3J30gc2hhcmQgKCR7c2hhcmRJZH0pYClcblxuICAgICAgaWYgKCFzaGFyZCkge1xuICAgICAgICBzaGFyZCA9IG5ldyBTaGFyZCh7XG4gICAgICAgICAgaWQ6IHNoYXJkSWQsXG4gICAgICAgICAgY29ubmVjdGlvbjoge1xuICAgICAgICAgICAgY29tcHJlc3M6IHRoaXMuY29tcHJlc3MsXG4gICAgICAgICAgICBpbnRlbnRzOiB0aGlzLmludGVudHMsXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiB0aGlzLnByb3BlcnRpZXMsXG4gICAgICAgICAgICB0b2tlbjogdGhpcy50b2tlbixcbiAgICAgICAgICAgIHRvdGFsU2hhcmRzOiB0aGlzLnRvdGFsU2hhcmRzLFxuICAgICAgICAgICAgdXJsOiB0aGlzLnVybCxcbiAgICAgICAgICAgIHZlcnNpb246IHRoaXMudmVyc2lvbixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGV2ZW50czogb3B0aW9ucy5ldmVudHMgPz8ge30sXG4gICAgICAgICAgbG9nZ2VyOiB0aGlzLmxvZ2dlcixcbiAgICAgICAgICByZXF1ZXN0SWRlbnRpZnk6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGF3YWl0IGdhdGV3YXkuaWRlbnRpZnkoc2hhcmRJZClcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNoYXJkSXNSZWFkeTogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgZ2F0ZXdheS5sb2dnZXIuZGVidWcoYFtTaGFyZF0gU2hhcmQgIyR7c2hhcmRJZH0gaXMgcmVhZHlgKVxuICAgICAgICAgICAgYXdhaXQgZGVsYXkoZ2F0ZXdheS5zcGF3blNoYXJkRGVsYXkpXG4gICAgICAgICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW1NoYXJkXSBSZXNvbHZpbmcgc2hhcmQgaWRlbnRpZnkgcmVxdWVzdGApXG4gICAgICAgICAgICBnYXRld2F5LmJ1Y2tldHMuZ2V0KHNoYXJkSWQgJSBnYXRld2F5LmNvbm5lY3Rpb24uc2Vzc2lvblN0YXJ0TGltaXQubWF4Q29uY3VycmVuY3kpIS5pZGVudGlmeVJlcXVlc3RzLnNoaWZ0KCk/LigpXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcblxuICAgICAgICBpZiAodGhpcy5wcmVmZXJTbmFrZUNhc2UpIHtcbiAgICAgICAgICBzaGFyZC5mb3J3YXJkVG9Cb3QgPSBhc3luYyAocGF5bG9hZCkgPT4ge1xuICAgICAgICAgICAgc2hhcmQhLmV2ZW50cy5tZXNzYWdlPy4oc2hhcmQhLCBwYXlsb2FkKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2hhcmRzLnNldChzaGFyZElkLCBzaGFyZClcbiAgICAgIH1cblxuICAgICAgY29uc3QgYnVja2V0ID0gZ2F0ZXdheS5idWNrZXRzLmdldChzaGFyZElkICUgZ2F0ZXdheS5jb25uZWN0aW9uLnNlc3Npb25TdGFydExpbWl0Lm1heENvbmN1cnJlbmN5KVxuICAgICAgaWYgKCFidWNrZXQpIHJldHVyblxuXG4gICAgICByZXR1cm4gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgLy8gTWFyayB0aGF0IHdlIGFyZSBtYWtpbmcgYW4gaWRlbnRpZnkgcmVxdWVzdCBzbyBhbm90aGVyIGlzIG5vdCBtYWRlLlxuICAgICAgICBidWNrZXQuaWRlbnRpZnlSZXF1ZXN0cy5wdXNoKHJlc29sdmUpXG4gICAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gaWRlbnRpZnlpbmcgc2hhcmQgIygke3NoYXJkSWR9KS5gKVxuICAgICAgICAvLyBUaGlzIHdpbGwgdHJpZ2dlciBpZGVudGlmeSBhbmQgd2hlbiBSRUFEWSBpcyByZWNlaXZlZCBpdCB3aWxsIHJlc29sdmUgdGhlIGFib3ZlIHJlcXVlc3QuXG4gICAgICAgIHNoYXJkPy5pZGVudGlmeSgpXG4gICAgICB9KVxuICAgIH0sXG4gICAgYXN5bmMga2lsbChzaGFyZElkOiBudW1iZXIpIHtcbiAgICAgIGNvbnN0IHNoYXJkID0gdGhpcy5zaGFyZHMuZ2V0KHNoYXJkSWQpXG4gICAgICBpZiAoIXNoYXJkKSB7XG4gICAgICAgIHJldHVybiBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW0dhdGV3YXldIGtpbGwgc2hhcmQgYnV0IG5vdCBmb3VuZCAoJHtzaGFyZElkfSlgKVxuICAgICAgfVxuXG4gICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW0dhdGV3YXldIGtpbGwgc2hhcmQgKCR7c2hhcmRJZH0pYClcbiAgICAgIHRoaXMuc2hhcmRzLmRlbGV0ZShzaGFyZElkKVxuICAgICAgYXdhaXQgc2hhcmQuc2h1dGRvd24oKVxuICAgIH0sXG4gICAgYXN5bmMgcmVxdWVzdElkZW50aWZ5KF9zaGFyZElkOiBudW1iZXIpIHtcbiAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gcmVxdWVzdGluZyBpZGVudGlmeWApXG4gICAgICAvLyBjb25zdCBidWNrZXQgPSBnYXRld2F5LmJ1Y2tldHMuZ2V0KHNoYXJkSWQgJSBnYXRld2F5LmNvbm5lY3Rpb24uc2Vzc2lvblN0YXJ0TGltaXQubWF4Q29uY3VycmVuY3kpXG4gICAgICAvLyBpZiAoIWJ1Y2tldCkgcmV0dXJuXG5cbiAgICAgIC8vIHJldHVybiBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgICAgLy8gICBidWNrZXQuaWRlbnRpZnlSZXF1ZXN0cy5wdXNoKHJlc29sdmUpXG4gICAgICAvLyB9KVxuICAgIH0sXG5cbiAgICAvLyBIZWxwZXJzIG1ldGhvZHMgYmVsb3cgdGhpc1xuXG4gICAgY2FsY3VsYXRlU2hhcmRJZChndWlsZElkLCB0b3RhbFNoYXJkcykge1xuICAgICAgLy8gSWYgbm9uZSBpcyBwcm92aWRlZCwgdXNlIHRoZSB0b3RhbCBzaGFyZHMgbnVtYmVyIGZyb20gZ2F0ZXdheSBvYmplY3QuXG4gICAgICBpZiAoIXRvdGFsU2hhcmRzKSB0b3RhbFNoYXJkcyA9IGdhdGV3YXkudG90YWxTaGFyZHNcbiAgICAgIC8vIElmIGl0IGlzIG9ubHkgMSBzaGFyZCwgaXQgd2lsbCBhbHdheXMgYmUgc2hhcmQgaWQgMFxuICAgICAgaWYgKHRvdGFsU2hhcmRzID09PSAxKSB7XG4gICAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gY2FsY3VsYXRlU2hhcmRJZCAoMSBzaGFyZClgKVxuICAgICAgICByZXR1cm4gMFxuICAgICAgfVxuXG4gICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW0dhdGV3YXldIGNhbGN1bGF0ZVNoYXJkSWQgKGd1aWxkSWQ6ICR7Z3VpbGRJZH0sIHRvdGFsU2hhcmRzOiAke3RvdGFsU2hhcmRzfSlgKVxuICAgICAgcmV0dXJuIE51bWJlcigoQmlnSW50KGd1aWxkSWQpID4+IDIybikgJSBCaWdJbnQodG90YWxTaGFyZHMpKVxuICAgIH0sXG5cbiAgICBhc3luYyBqb2luVm9pY2VDaGFubmVsKGd1aWxkSWQsIGNoYW5uZWxJZCwgb3B0aW9ucykge1xuICAgICAgY29uc3Qgc2hhcmRJZCA9IGdhdGV3YXkuY2FsY3VsYXRlU2hhcmRJZChndWlsZElkKVxuXG4gICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW0dhdGV3YXldIGpvaW5Wb2ljZUNoYW5uZWwgZ3VpbGRJZDogJHtndWlsZElkfSBjaGFubmVsSWQ6ICR7Y2hhbm5lbElkfWApXG5cbiAgICAgIGF3YWl0IGdhdGV3YXkuc2VuZFBheWxvYWQoc2hhcmRJZCwge1xuICAgICAgICBvcDogR2F0ZXdheU9wY29kZXMuVm9pY2VTdGF0ZVVwZGF0ZSxcbiAgICAgICAgZDoge1xuICAgICAgICAgIGd1aWxkX2lkOiBndWlsZElkLnRvU3RyaW5nKCksXG4gICAgICAgICAgY2hhbm5lbF9pZDogY2hhbm5lbElkLnRvU3RyaW5nKCksXG4gICAgICAgICAgc2VsZl9tdXRlOiBvcHRpb25zPy5zZWxmTXV0ZSA/PyBmYWxzZSxcbiAgICAgICAgICBzZWxmX2RlYWY6IG9wdGlvbnM/LnNlbGZEZWFmID8/IHRydWUsXG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgIH0sXG5cbiAgICBhc3luYyBlZGl0Qm90U3RhdHVzKGRhdGEpIHtcbiAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gZWRpdEJvdFN0YXR1cyBkYXRhOiAke0pTT04uc3RyaW5naWZ5KGRhdGEpfWApXG5cbiAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgICBbLi4uZ2F0ZXdheS5zaGFyZHMudmFsdWVzKCldLm1hcChhc3luYyAoc2hhcmQpID0+IHtcbiAgICAgICAgICBnYXRld2F5LmVkaXRTaGFyZFN0YXR1cyhzaGFyZC5pZCwgZGF0YSlcbiAgICAgICAgfSksXG4gICAgICApXG4gICAgfSxcblxuICAgIGFzeW5jIGVkaXRTaGFyZFN0YXR1cyhzaGFyZElkLCBkYXRhKSB7XG4gICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW0dhdGV3YXldIGVkaXRTaGFyZFN0YXR1cyBzaGFyZElkOiAke3NoYXJkSWR9IC0+IGRhdGE6ICR7SlNPTi5zdHJpbmdpZnkoZGF0YSl9YClcblxuICAgICAgYXdhaXQgZ2F0ZXdheS5zZW5kUGF5bG9hZChzaGFyZElkLCB7XG4gICAgICAgIG9wOiBHYXRld2F5T3Bjb2Rlcy5QcmVzZW5jZVVwZGF0ZSxcbiAgICAgICAgZDoge1xuICAgICAgICAgIHNpbmNlOiBudWxsLFxuICAgICAgICAgIGFmazogZmFsc2UsXG4gICAgICAgICAgYWN0aXZpdGllczogZGF0YS5hY3Rpdml0aWVzLFxuICAgICAgICAgIHN0YXR1czogZGF0YS5zdGF0dXMsXG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgIH0sXG5cbiAgICBhc3luYyByZXF1ZXN0TWVtYmVycyhndWlsZElkLCBvcHRpb25zKSB7XG4gICAgICBjb25zdCBzaGFyZElkID0gZ2F0ZXdheS5jYWxjdWxhdGVTaGFyZElkKGd1aWxkSWQpXG5cbiAgICAgIGlmIChnYXRld2F5LmludGVudHMgJiYgKCFvcHRpb25zPy5saW1pdCB8fCBvcHRpb25zLmxpbWl0ID4gMSkgJiYgIShnYXRld2F5LmludGVudHMgJiBHYXRld2F5SW50ZW50cy5HdWlsZE1lbWJlcnMpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmZXRjaCBtb3JlIHRoZW4gMSBtZW1iZXIgd2l0aG91dCB0aGUgR1VJTERfTUVNQkVSUyBpbnRlbnQnKVxuXG4gICAgICBnYXRld2F5LmxvZ2dlci5kZWJ1ZyhgW0dhdGV3YXldIHJlcXVlc3RNZW1iZXJzIGd1aWxkSWQ6ICR7Z3VpbGRJZH0gLT4gZGF0YTogJHtKU09OLnN0cmluZ2lmeShvcHRpb25zKX1gKVxuXG4gICAgICBpZiAob3B0aW9ucz8udXNlcklkcz8ubGVuZ3RoKSB7XG4gICAgICAgIGdhdGV3YXkubG9nZ2VyLmRlYnVnKGBbR2F0ZXdheV0gcmVxdWVzdE1lbWJlcnMgZ3VpbGRJZDogJHtndWlsZElkfSAtPiBzZXR0aW5nIHVzZXIgbGltaXQgYmFzZWQgb24gdXNlcklkcyBsZW5ndGg6ICR7b3B0aW9ucy51c2VySWRzLmxlbmd0aH1gKVxuXG4gICAgICAgIG9wdGlvbnMubGltaXQgPSBvcHRpb25zLnVzZXJJZHMubGVuZ3RoXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1lbWJlcnMgPVxuICAgICAgICAhZ2F0ZXdheS5jYWNoZS5yZXF1ZXN0TWVtYmVycy5lbmFibGVkIHx8ICFvcHRpb25zPy5ub25jZVxuICAgICAgICAgID8gW11cbiAgICAgICAgICA6IG5ldyBQcm9taXNlPENhbWVsaXplPERpc2NvcmRNZW1iZXJXaXRoVXNlcltdPj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAvLyBTaG91bGQgbmV2ZXIgaGFwcGVuLlxuICAgICAgICAgICAgICBpZiAoIWdhdGV3YXkuY2FjaGUucmVxdWVzdE1lbWJlcnMuZW5hYmxlZCB8fCAhb3B0aW9ucz8ubm9uY2UpIHtcbiAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKFwiQ2FuJ3QgcmVxdWVzdCB0aGUgbWVtYmVycyB3aXRob3V0IHRoZSBub25jZSBvciB3aXRoIHRoZSBmZWF0dXJlIGRpc2FibGVkLlwiKSlcbiAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGdhdGV3YXkuY2FjaGUucmVxdWVzdE1lbWJlcnMucGVuZGluZy5zZXQob3B0aW9ucy5ub25jZSwge1xuICAgICAgICAgICAgICAgIG5vbmNlOiBvcHRpb25zLm5vbmNlLFxuICAgICAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICAgICAgbWVtYmVyczogW10sXG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9KVxuXG4gICAgICBhd2FpdCBnYXRld2F5LnNlbmRQYXlsb2FkKHNoYXJkSWQsIHtcbiAgICAgICAgb3A6IEdhdGV3YXlPcGNvZGVzLlJlcXVlc3RHdWlsZE1lbWJlcnMsXG4gICAgICAgIGQ6IHtcbiAgICAgICAgICBndWlsZF9pZDogZ3VpbGRJZC50b1N0cmluZygpLFxuICAgICAgICAgIC8vIElmIGEgcXVlcnkgaXMgcHJvdmlkZWQgdXNlIGl0LCBPUiBpZiBhIGxpbWl0IGlzIE5PVCBwcm92aWRlZCB1c2UgXCJcIlxuICAgICAgICAgIHF1ZXJ5OiBvcHRpb25zPy5xdWVyeSA/PyAob3B0aW9ucz8ubGltaXQgPyB1bmRlZmluZWQgOiAnJyksXG4gICAgICAgICAgbGltaXQ6IG9wdGlvbnM/LmxpbWl0ID8/IDAsXG4gICAgICAgICAgcHJlc2VuY2VzOiBvcHRpb25zPy5wcmVzZW5jZXMgPz8gZmFsc2UsXG4gICAgICAgICAgdXNlcl9pZHM6IG9wdGlvbnM/LnVzZXJJZHM/Lm1hcCgoaWQpID0+IGlkLnRvU3RyaW5nKCkpLFxuICAgICAgICAgIG5vbmNlOiBvcHRpb25zPy5ub25jZSxcbiAgICAgICAgfSxcbiAgICAgIH0pXG5cbiAgICAgIHJldHVybiBhd2FpdCBtZW1iZXJzXG4gICAgfSxcblxuICAgIGFzeW5jIGxlYXZlVm9pY2VDaGFubmVsKGd1aWxkSWQpIHtcbiAgICAgIGNvbnN0IHNoYXJkSWQgPSBnYXRld2F5LmNhbGN1bGF0ZVNoYXJkSWQoZ3VpbGRJZClcblxuICAgICAgZ2F0ZXdheS5sb2dnZXIuZGVidWcoYFtHYXRld2F5XSBsZWF2ZVZvaWNlQ2hhbm5lbCBndWlsZElkOiAke2d1aWxkSWR9IFNoYXJkICR7c2hhcmRJZH1gKVxuXG4gICAgICBhd2FpdCBnYXRld2F5LnNlbmRQYXlsb2FkKHNoYXJkSWQsIHtcbiAgICAgICAgb3A6IEdhdGV3YXlPcGNvZGVzLlZvaWNlU3RhdGVVcGRhdGUsXG4gICAgICAgIGQ6IHtcbiAgICAgICAgICBndWlsZF9pZDogZ3VpbGRJZC50b1N0cmluZygpLFxuICAgICAgICAgIGNoYW5uZWxfaWQ6IG51bGwsXG4gICAgICAgICAgc2VsZl9tdXRlOiBmYWxzZSxcbiAgICAgICAgICBzZWxmX2RlYWY6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgfSlcbiAgICB9LFxuICB9XG5cbiAgcmV0dXJuIGdhdGV3YXlcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVHYXRld2F5TWFuYWdlck9wdGlvbnMge1xuICAvKipcbiAgICogSWQgb2YgdGhlIGZpcnN0IFNoYXJkIHdoaWNoIHNob3VsZCBnZXQgY29udHJvbGxlZCBieSB0aGlzIG1hbmFnZXIuXG4gICAqIEBkZWZhdWx0IDBcbiAgICovXG4gIGZpcnN0U2hhcmRJZD86IG51bWJlclxuICAvKipcbiAgICogSWQgb2YgdGhlIGxhc3QgU2hhcmQgd2hpY2ggc2hvdWxkIGdldCBjb250cm9sbGVkIGJ5IHRoaXMgbWFuYWdlci5cbiAgICogQGRlZmF1bHQgMFxuICAgKi9cbiAgbGFzdFNoYXJkSWQ/OiBudW1iZXJcbiAgLyoqXG4gICAqIERlbGF5IGluIG1pbGxpc2Vjb25kcyB0byB3YWl0IGJlZm9yZSBzcGF3bmluZyBuZXh0IHNoYXJkLiBPUFRJTUFMIElTIEFCT1ZFIDUxMDAuIFlPVSBET04nVCBXQU5UIFRPIEhJVCBUSEUgUkFURSBMSU1JVCEhIVxuICAgKiBAZGVmYXVsdCA1MzAwXG4gICAqL1xuICBzcGF3blNoYXJkRGVsYXk/OiBudW1iZXJcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gc2VuZCB0aGUgZGlzY29yZCBwYWNrZXRzIGluIHNuYWtlIGNhc2UgZm9ybS5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHByZWZlclNuYWtlQ2FzZT86IGJvb2xlYW5cbiAgLyoqXG4gICAqIFRvdGFsIGFtb3VudCBvZiBzaGFyZHMgeW91ciBib3QgdXNlcy4gVXNlZnVsIGZvciB6ZXJvLWRvd250aW1lIHVwZGF0ZXMgb3IgcmVzaGFyZGluZy5cbiAgICogQGRlZmF1bHQgMVxuICAgKi9cbiAgdG90YWxTaGFyZHM/OiBudW1iZXJcbiAgLyoqXG4gICAqIFRoZSBhbW91bnQgb2Ygc2hhcmRzIHRvIGxvYWQgcGVyIHdvcmtlci5cbiAgICogQGRlZmF1bHQgMjVcbiAgICovXG4gIHNoYXJkc1Blcldvcmtlcj86IG51bWJlclxuICAvKipcbiAgICogVGhlIHRvdGFsIGFtb3VudCBvZiB3b3JrZXJzIHRvIHVzZSBmb3IgeW91ciBib3QuXG4gICAqIEBkZWZhdWx0IDRcbiAgICovXG4gIHRvdGFsV29ya2Vycz86IG51bWJlclxuICAvKiogSW1wb3J0YW50IGRhdGEgd2hpY2ggaXMgdXNlZCBieSB0aGUgbWFuYWdlciB0byBjb25uZWN0IHNoYXJkcyB0byB0aGUgZ2F0ZXdheS4gKi9cbiAgY29ubmVjdGlvbj86IENhbWVsaXplPERpc2NvcmRHZXRHYXRld2F5Qm90PlxuICAvKiogV2hldGhlciBpbmNvbWluZyBwYXlsb2FkcyBhcmUgY29tcHJlc3NlZCB1c2luZyB6bGliLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgY29tcHJlc3M/OiBib29sZWFuXG4gIC8qKiBUaGUgY2FsY3VsYXRlZCBpbnRlbnQgdmFsdWUgb2YgdGhlIGV2ZW50cyB3aGljaCB0aGUgc2hhcmQgc2hvdWxkIHJlY2VpdmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDBcbiAgICovXG4gIGludGVudHM/OiBudW1iZXJcbiAgLyoqIElkZW50aWZ5IHByb3BlcnRpZXMgdG8gdXNlICovXG4gIHByb3BlcnRpZXM/OiB7XG4gICAgLyoqIE9wZXJhdGluZyBzeXN0ZW0gdGhlIHNoYXJkIHJ1bnMgb24uXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCBcImRhcndpblwiIHwgXCJsaW51eFwiIHwgXCJ3aW5kb3dzXCJcbiAgICAgKi9cbiAgICBvczogc3RyaW5nXG4gICAgLyoqIFRoZSBcImJyb3dzZXJcIiB3aGVyZSB0aGlzIHNoYXJkIGlzIHJ1bm5pbmcgb24uXG4gICAgICpcbiAgICAgKiBAZGVmYXVsdCBcIkRpc2NvcmRlbm9cIlxuICAgICAqL1xuICAgIGJyb3dzZXI6IHN0cmluZ1xuICAgIC8qKiBUaGUgZGV2aWNlIG9uIHdoaWNoIHRoZSBzaGFyZCBpcyBydW5uaW5nLlxuICAgICAqXG4gICAgICogQGRlZmF1bHQgXCJEaXNjb3JkZW5vXCJcbiAgICAgKi9cbiAgICBkZXZpY2U6IHN0cmluZ1xuICB9XG4gIC8qKiBCb3QgdG9rZW4gd2hpY2ggaXMgdXNlZCB0byBjb25uZWN0IHRvIERpc2NvcmQgKi9cbiAgdG9rZW46IHN0cmluZ1xuICAvKiogVGhlIFVSTCBvZiB0aGUgZ2F0ZXdheSB3aGljaCBzaG91bGQgYmUgY29ubmVjdGVkIHRvLlxuICAgKlxuICAgKiBAZGVmYXVsdCBcIndzczovL2dhdGV3YXkuZGlzY29yZC5nZ1wiXG4gICAqL1xuICB1cmw/OiBzdHJpbmdcbiAgLyoqIFRoZSBnYXRld2F5IHZlcnNpb24gd2hpY2ggc2hvdWxkIGJlIHVzZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDEwXG4gICAqL1xuICB2ZXJzaW9uPzogbnVtYmVyXG4gIC8qKiBUaGUgZXZlbnRzIGhhbmRsZXJzICovXG4gIGV2ZW50cz86IFNoYXJkRXZlbnRzXG4gIC8qKiBUaGlzIG1hbmFnZXJzIGNhY2hlIHJlbGF0ZWQgc2V0dGluZ3MuICovXG4gIGNhY2hlPzoge1xuICAgIHJlcXVlc3RNZW1iZXJzPzoge1xuICAgICAgLyoqXG4gICAgICAgKiBXaGV0aGVyIG9yIG5vdCByZXF1ZXN0IG1lbWJlciByZXF1ZXN0cyBzaG91bGQgYmUgY2FjaGVkLlxuICAgICAgICogQGRlZmF1bHQgZmFsc2VcbiAgICAgICAqL1xuICAgICAgZW5hYmxlZD86IGJvb2xlYW5cbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIFRoZSBsb2dnZXIgdGhhdCB0aGUgZ2F0ZXdheSBtYW5hZ2VyIHdpbGwgdXNlXG4gICAqIEBkZWZhdWx0IGxvZ2dlciAvLyBUaGUgbG9nZ2VyIGV4cG9ydGVkIGJ5IGBAZGlzY29yZGVuby91dGlsc2BcbiAgICovXG4gIGxvZ2dlcj86IFBpY2s8dHlwZW9mIGxvZ2dlciwgJ2RlYnVnJyB8ICdpbmZvJyB8ICd3YXJuJyB8ICdlcnJvcicgfCAnZmF0YWwnPlxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdhdGV3YXlNYW5hZ2VyIGV4dGVuZHMgUmVxdWlyZWQ8Q3JlYXRlR2F0ZXdheU1hbmFnZXJPcHRpb25zPiB7XG4gIC8qKiBUaGUgbWF4IGNvbmN1cnJlbmN5IGJ1Y2tldHMuIFRob3NlIHdpbGwgYmUgY3JlYXRlZCB3aGVuIHRoZSBgc3Bhd25TaGFyZHNgICh3aGljaCBjYWxscyBgcHJlcGFyZUJ1Y2tldHNgIHVuZGVyIHRoZSBob29kKSBmdW5jdGlvbiBnZXRzIGNhbGxlZC4gKi9cbiAgYnVja2V0czogTWFwPFxuICAgIG51bWJlcixcbiAgICB7XG4gICAgICB3b3JrZXJzOiBBcnJheTx7IGlkOiBudW1iZXI7IHF1ZXVlOiBudW1iZXJbXSB9PlxuICAgICAgLyoqIFJlcXVlc3RzIHRvIGlkZW50aWZ5IHNoYXJkcyBhcmUgbWFkZSBiYXNlZCBvbiB3aGV0aGVyIGl0IGlzIGF2YWlsYWJsZSB0byBiZSBtYWRlLiAqL1xuICAgICAgaWRlbnRpZnlSZXF1ZXN0czogQXJyYXk8KHZhbHVlOiB2b2lkIHwgUHJvbWlzZUxpa2U8dm9pZD4pID0+IHZvaWQ+XG4gICAgfVxuICA+XG4gIC8qKiBUaGUgc2hhcmRzIHRoYXQgYXJlIGNyZWF0ZWQuICovXG4gIHNoYXJkczogTWFwPG51bWJlciwgU2hhcmQ+XG4gIC8qKiBUaGUgbG9nZ2VyIGZvciB0aGUgZ2F0ZXdheSBtYW5hZ2VyICovXG4gIGxvZ2dlcjogUGljazx0eXBlb2YgbG9nZ2VyLCAnZGVidWcnIHwgJ2luZm8nIHwgJ3dhcm4nIHwgJ2Vycm9yJyB8ICdmYXRhbCc+XG4gIC8qKiBFdmVyeXRoaW5nIHJlbGF0ZWQgdG8gcmVzaGFyZGluZy4gKi9cbiAgcmVzaGFyZGluZzoge1xuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgb3Igbm90IGF1dG9tYXRlZCByZXNoYXJkaW5nIHNob3VsZCBiZSBlbmFibGVkLlxuICAgICAqIEBkZWZhdWx0IHRydWVcbiAgICAgKi9cbiAgICBlbmFibGVkOiBib29sZWFuXG4gICAgLyoqXG4gICAgICogVGhlICUgb2YgaG93IGZ1bGwgYSBzaGFyZCBpcyB3aGVuIHJlc2hhcmRpbmcgc2hvdWxkIGJlIHRyaWdnZXJlZC5cbiAgICAgKiBAZGVmYXVsdCA4MCBhcyBpbiA4MCVcbiAgICAgKi9cbiAgICBzaGFyZHNGdWxsUGVyY2VudGFnZTogbnVtYmVyXG4gICAgLyoqXG4gICAgICogVGhlIGludGVydmFsIGluIG1pbGxpc2Vjb25kcywgb2YgaG93IG9mdGVuIHRvIGNoZWNrIHdoZXRoZXIgcmVzaGFyZGluZyBpcyBuZWVkZWQgYW5kIHJlc2hhcmQgYXV0b21hdGljYWxseS4gU2V0IHRvIC0xIHRvIGRpc2FibGUgYXV0byByZXNoYXJkaW5nLlxuICAgICAqIEBkZWZhdWx0IDI4ODAwMDAwICg4IGhvdXJzKVxuICAgICAqL1xuICAgIGNoZWNrSW50ZXJ2YWw6IG51bWJlclxuICAgIC8qKlxuICAgICAqIFRoZSBpbnRlcnZhbCBpZCBvZiB0aGUgY2hlY2sgaW50ZXJ2YWwuIFRoaXMgaXMgdXNlZCB0byBjbGVhciB0aGUgaW50ZXJ2YWwgd2hlbiB0aGUgbWFuYWdlciBpcyBzaHV0ZG93bi5cbiAgICAgKi9cbiAgICBjaGVja0ludGVydmFsSWQ/OiBOb2RlSlMuVGltZW91dCB8IHVuZGVmaW5lZFxuICAgIC8qKiBIb2xkcyB0aGUgc2hhcmRzIHRoYXQgcmVzaGFyZGluZyBoYXMgY3JlYXRlZC4gT25jZSByZXNoYXJkaW5nIGlzIGRvbmUsIHRoaXMgcmVwbGFjZXMgdGhlIGdhdGV3YXkuc2hhcmRzICovXG4gICAgc2hhcmRzOiBDb2xsZWN0aW9uPG51bWJlciwgU2hhcmQ+XG4gICAgLyoqIEhvbGRzIHRoZSBwZW5kaW5nIHNoYXJkcyB0aGF0IGhhdmUgYmVlbiBjcmVhdGVkIGFuZCBhcmUgcGVuZGluZyBhbGwgc2hhcmRzIGZpbmlzaCBsb2FkaW5nLiAqL1xuICAgIHBlbmRpbmdTaGFyZHM6IENvbGxlY3Rpb248bnVtYmVyLCBTaGFyZD5cbiAgICAvKiogSGFuZGxlciB0byBnZXQgc2hhcmQgY291bnQgYW5kIG90aGVyIHNlc3Npb24gaW5mby4gKi9cbiAgICBnZXRTZXNzaW9uSW5mbzogKCkgPT4gUHJvbWlzZTxDYW1lbGl6ZTxEaXNjb3JkR2V0R2F0ZXdheUJvdD4+XG4gICAgLyoqIEhhbmRsZXIgdG8gZWRpdCB0aGUgc2hhcmQgaWQgb24gYW55IGNhY2hlZCBndWlsZHMuICovXG4gICAgdXBkYXRlR3VpbGRzU2hhcmRJZDogKGd1aWxkSWRzOiBzdHJpbmdbXSwgc2hhcmRJZDogbnVtYmVyKSA9PiBQcm9taXNlPHZvaWQ+XG4gICAgLyoqIEhhbmRsZXIgdG8gY2hlY2sgaWYgcmVzaGFyZGluZyBpcyBuZWNlc3NhcnkuICovXG4gICAgY2hlY2tJZlJlc2hhcmRpbmdJc05lZWRlZDogKCkgPT4gUHJvbWlzZTx7IG5lZWRlZDogYm9vbGVhbjsgaW5mbz86IENhbWVsaXplPERpc2NvcmRHZXRHYXRld2F5Qm90PiB9PlxuICAgIC8qKiBIYW5kbGVyIHRvIGJlZ2luIHJlc2hhcmRpbmcuICovXG4gICAgcmVzaGFyZDogKGluZm86IENhbWVsaXplPERpc2NvcmRHZXRHYXRld2F5Qm90PiAmIHsgZmlyc3RTaGFyZElkPzogbnVtYmVyOyBsYXN0U2hhcmRJZD86IG51bWJlciB9KSA9PiBQcm9taXNlPHZvaWQ+XG4gICAgLyoqIEhhbmRsZXIgdG8gY29tbXVuaWNhdGUgdG8gYSB3b3JrZXIgdGhhdCBhIHNoYXJkIG5lZWRzIHRvIGJlIGNyZWF0ZWQuICovXG4gICAgdGVsbFdvcmtlclRvUHJlcGFyZTogKHdvcmtlcklkOiBudW1iZXIsIHNoYXJkSWQ6IG51bWJlciwgYnVja2V0SWQ6IG51bWJlcikgPT4gUHJvbWlzZTx2b2lkPlxuICAgIC8qKiBIYW5kbGVyIHRvIGFsZXJ0IHRoZSBnYXRld2F5IHRoYXQgYSBzaGFyZChyZXNoYXJkZWQpIGlzIG9ubGluZS4gSXQgc2hvdWxkIG5vdyB3YWl0IGZvciBhbGwgc2hhcmRzIHRvIGJlIHBlbmRpbmcgYmVmb3JlIHNodXR0aW5nIG9mZiBvbGQgc2hhcmRzLiAqL1xuICAgIHNoYXJkSXNQZW5kaW5nOiAoc2hhcmQ6IFNoYXJkKSA9PiBQcm9taXNlPHZvaWQ+XG4gIH1cbiAgLyoqIERldGVybWluZSBtYXggbnVtYmVyIG9mIHNoYXJkcyB0byB1c2UgYmFzZWQgdXBvbiB0aGUgbWF4IGNvbmN1cnJlbmN5LiAqL1xuICBjYWxjdWxhdGVUb3RhbFNoYXJkczogKCkgPT4gbnVtYmVyXG4gIC8qKiBEZXRlcm1pbmUgdGhlIGlkIG9mIHRoZSB3b3JrZXIgd2hpY2ggaXMgaGFuZGxpbmcgYSBzaGFyZC4gKi9cbiAgY2FsY3VsYXRlV29ya2VySWQ6IChzaGFyZElkOiBudW1iZXIpID0+IG51bWJlclxuICAvKiogUHJlcGFyZXMgYWxsIHRoZSBidWNrZXRzIHRoYXQgYXJlIGF2YWlsYWJsZSBmb3IgaWRlbnRpZnlpbmcgdGhlIHNoYXJkcy4gKi9cbiAgcHJlcGFyZUJ1Y2tldHM6ICgpID0+IHZvaWRcbiAgLyoqIFN0YXJ0IGlkZW50aWZ5aW5nIGFsbCB0aGUgc2hhcmRzLiAqL1xuICBzcGF3blNoYXJkczogKCkgPT4gUHJvbWlzZTx2b2lkPlxuICAvKiogU2h1dGRvd24gYWxsIHNoYXJkcy4gKi9cbiAgc2h1dGRvd246IChjb2RlOiBudW1iZXIsIHJlYXNvbjogc3RyaW5nLCBjbGVhclJlc2hhcmRpbmdJbnRlcnZhbD86IGJvb2xlYW4pID0+IFByb21pc2U8dm9pZD5cbiAgc2VuZFBheWxvYWQ6IChzaGFyZElkOiBudW1iZXIsIHBheWxvYWQ6IFNoYXJkU29ja2V0UmVxdWVzdCkgPT4gUHJvbWlzZTx2b2lkPlxuICAvKiogQWxsb3dzIHVzZXJzIHRvIGhvb2sgaW4gYW5kIGNoYW5nZSB0byBjb21tdW5pY2F0ZSB0byBkaWZmZXJlbnQgd29ya2VycyBhY3Jvc3MgZGlmZmVyZW50IHNlcnZlcnMgb3IgYW55dGhpbmcgdGhleSBsaWtlLiBGb3IgZXhhbXBsZSB1c2luZyByZWRpcyBwdWJzdWIgdG8gdGFsayB0byBvdGhlciBzZXJ2ZXJzLiAqL1xuICB0ZWxsV29ya2VyVG9JZGVudGlmeTogKHdvcmtlcklkOiBudW1iZXIsIHNoYXJkSWQ6IG51bWJlciwgYnVja2V0SWQ6IG51bWJlcikgPT4gUHJvbWlzZTx2b2lkPlxuICAvKiogVGVsbCB0aGUgbWFuYWdlciB0byBpZGVudGlmeSBhIFNoYXJkLiBJZiB0aGlzIFNoYXJkIGlzIG5vdCBhbHJlYWR5IG1hbmFnZWQgdGhpcyB3aWxsIGFsc28gYWRkIHRoZSBTaGFyZCB0byB0aGUgbWFuYWdlci4gKi9cbiAgaWRlbnRpZnk6IChzaGFyZElkOiBudW1iZXIpID0+IFByb21pc2U8dm9pZD5cbiAgLyoqIEtpbGwgYSBzaGFyZC4gQ2xvc2UgYSBzaGFyZHMgY29ubmVjdGlvbiB0byBEaXNjb3JkJ3MgZ2F0ZXdheSAoaWYgYW55KSBhbmQgcmVtb3ZlIGl0IGZyb20gdGhlIG1hbmFnZXIuICovXG4gIGtpbGw6IChzaGFyZElkOiBudW1iZXIpID0+IFByb21pc2U8dm9pZD5cbiAgLyoqIFRoaXMgZnVuY3Rpb24gbWFrZXMgc3VyZSB0aGF0IHRoZSBidWNrZXQgaXMgYWxsb3dlZCB0byBtYWtlIHRoZSBuZXh0IGlkZW50aWZ5IHJlcXVlc3QuICovXG4gIHJlcXVlc3RJZGVudGlmeTogKHNoYXJkSWQ6IG51bWJlcikgPT4gUHJvbWlzZTx2b2lkPlxuICAvKiogQ2FsY3VsYXRlcyB0aGUgbnVtYmVyIG9mIHNoYXJkcyBiYXNlZCBvbiB0aGUgZ3VpbGQgaWQgYW5kIHRvdGFsIHNoYXJkcy4gKi9cbiAgY2FsY3VsYXRlU2hhcmRJZDogKGd1aWxkSWQ6IEJpZ1N0cmluZywgdG90YWxTaGFyZHM/OiBudW1iZXIpID0+IG51bWJlclxuICAvKipcbiAgICogQ29ubmVjdHMgdGhlIGJvdCB1c2VyIHRvIGEgdm9pY2Ugb3Igc3RhZ2UgY2hhbm5lbC5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBzZW5kcyB0aGUgX1VwZGF0ZSBWb2ljZSBTdGF0ZV8gZ2F0ZXdheSBjb21tYW5kIG92ZXIgdGhlIGdhdGV3YXkgYmVoaW5kIHRoZSBzY2VuZXMuXG4gICAqXG4gICAqIEBwYXJhbSBndWlsZElkIC0gVGhlIElEIG9mIHRoZSBndWlsZCB0aGUgdm9pY2UgY2hhbm5lbCB0byBsZWF2ZSBpcyBpbi5cbiAgICogQHBhcmFtIGNoYW5uZWxJZCAtIFRoZSBJRCBvZiB0aGUgY2hhbm5lbCB5b3Ugd2FudCB0byBqb2luLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBSZXF1aXJlcyB0aGUgYENPTk5FQ1RgIHBlcm1pc3Npb24uXG4gICAqXG4gICAqIEZpcmVzIGEgX1ZvaWNlIFN0YXRlIFVwZGF0ZV8gZ2F0ZXdheSBldmVudC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kaXNjb3JkLmNvbS9kZXZlbG9wZXJzL2RvY3MvdG9waWNzL2dhdGV3YXkjdXBkYXRlLXZvaWNlLXN0YXRlfVxuICAgKi9cbiAgam9pblZvaWNlQ2hhbm5lbDogKGd1aWxkSWQ6IEJpZ1N0cmluZywgY2hhbm5lbElkOiBCaWdTdHJpbmcsIG9wdGlvbnM/OiBBdExlYXN0T25lPE9taXQ8VXBkYXRlVm9pY2VTdGF0ZSwgJ2d1aWxkSWQnIHwgJ2NoYW5uZWxJZCc+PikgPT4gUHJvbWlzZTx2b2lkPlxuICAvKipcbiAgICogRWRpdHMgdGhlIGJvdCBzdGF0dXMgaW4gYWxsIHNoYXJkcyB0aGF0IHRoaXMgZ2F0ZXdheSBtYW5hZ2VzLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YSBUaGUgc3RhdHVzIGRhdGEgdG8gc2V0IHRoZSBib3RzIHN0YXR1cyB0by5cbiAgICogQHJldHVybnMgbm90aGluZ1xuICAgKi9cbiAgZWRpdEJvdFN0YXR1czogKGRhdGE6IFN0YXR1c1VwZGF0ZSkgPT4gUHJvbWlzZTx2b2lkPlxuICAvKipcbiAgICogRWRpdHMgdGhlIGJvdCdzIHN0YXR1cyBvbiBvbmUgc2hhcmQuXG4gICAqXG4gICAqIEBwYXJhbSBzaGFyZElkIFRoZSBzaGFyZCBpZCB0byBlZGl0IHRoZSBzdGF0dXMgZm9yLlxuICAgKiBAcGFyYW0gZGF0YSBUaGUgc3RhdHVzIGRhdGEgdG8gc2V0IHRoZSBib3RzIHN0YXR1cyB0by5cbiAgICogQHJldHVybnMgbm90aGluZ1xuICAgKi9cbiAgZWRpdFNoYXJkU3RhdHVzOiAoc2hhcmRJZDogbnVtYmVyLCBkYXRhOiBTdGF0dXNVcGRhdGUpID0+IFByb21pc2U8dm9pZD5cbiAgLyoqXG4gICAqIEZldGNoZXMgdGhlIGxpc3Qgb2YgbWVtYmVycyBmb3IgYSBndWlsZCBvdmVyIHRoZSBnYXRld2F5LlxuICAgKlxuICAgKiBAcGFyYW0gZ3VpbGRJZCAtIFRoZSBJRCBvZiB0aGUgZ3VpbGQgdG8gZ2V0IHRoZSBsaXN0IG9mIG1lbWJlcnMgZm9yLlxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgZmV0Y2hpbmcgb2YgdGhlIG1lbWJlcnMuXG4gICAqXG4gICAqIEByZW1hcmtzXG4gICAqIElmIHJlcXVlc3RpbmcgdGhlIGVudGlyZSBtZW1iZXIgbGlzdDpcbiAgICogLSBSZXF1aXJlcyB0aGUgYEdVSUxEX01FTUJFUlNgIGludGVudC5cbiAgICpcbiAgICogSWYgcmVxdWVzdGluZyBwcmVzZW5jZXMgKHtAbGluayBSZXF1ZXN0R3VpbGRNZW1iZXJzLnByZXNlbmNlcyB8IHByZXNlbmNlc30gc2V0IHRvIGB0cnVlYCk6XG4gICAqIC0gUmVxdWlyZXMgdGhlIGBHVUlMRF9QUkVTRU5DRVNgIGludGVudC5cbiAgICpcbiAgICogSWYgcmVxdWVzdGluZyBhIHByZWZpeCAoe0BsaW5rIFJlcXVlc3RHdWlsZE1lbWJlcnMucXVlcnkgfCBxdWVyeX0gbm9uLWB1bmRlZmluZWRgKTpcbiAgICogLSBSZXR1cm5zIGEgbWF4aW11bSBvZiAxMDAgbWVtYmVycy5cbiAgICpcbiAgICogSWYgcmVxdWVzdGluZyBhIHVzZXJzIGJ5IElEICh7QGxpbmsgUmVxdWVzdEd1aWxkTWVtYmVycy51c2VySWRzIHwgdXNlcklkc30gbm9uLWB1bmRlZmluZWRgKTpcbiAgICogLSBSZXR1cm5zIGEgbWF4aW11bSBvZiAxMDAgbWVtYmVycy5cbiAgICpcbiAgICogRmlyZXMgYSBfR3VpbGQgTWVtYmVycyBDaHVua18gZ2F0ZXdheSBldmVudCBmb3IgZXZlcnkgMTAwMCBtZW1iZXJzIGZldGNoZWQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGlzY29yZC5jb20vZGV2ZWxvcGVycy9kb2NzL3RvcGljcy9nYXRld2F5I3JlcXVlc3QtZ3VpbGQtbWVtYmVyc31cbiAgICovXG4gIHJlcXVlc3RNZW1iZXJzOiAoZ3VpbGRJZDogQmlnU3RyaW5nLCBvcHRpb25zPzogT21pdDxSZXF1ZXN0R3VpbGRNZW1iZXJzLCAnZ3VpbGRJZCc+KSA9PiBQcm9taXNlPENhbWVsaXplPERpc2NvcmRNZW1iZXJXaXRoVXNlcltdPj5cbiAgLyoqXG4gICAqIExlYXZlcyB0aGUgdm9pY2UgY2hhbm5lbCB0aGUgYm90IHVzZXIgaXMgY3VycmVudGx5IGluLlxuICAgKlxuICAgKiBUaGlzIGZ1bmN0aW9uIHNlbmRzIHRoZSBfVXBkYXRlIFZvaWNlIFN0YXRlXyBnYXRld2F5IGNvbW1hbmQgb3ZlciB0aGUgZ2F0ZXdheSBiZWhpbmQgdGhlIHNjZW5lcy5cbiAgICpcbiAgICogQHBhcmFtIGd1aWxkSWQgLSBUaGUgSUQgb2YgdGhlIGd1aWxkIHRoZSB2b2ljZSBjaGFubmVsIHRvIGxlYXZlIGlzIGluLlxuICAgKlxuICAgKiBAcmVtYXJrc1xuICAgKiBGaXJlcyBhIF9Wb2ljZSBTdGF0ZSBVcGRhdGVfIGdhdGV3YXkgZXZlbnQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGlzY29yZC5jb20vZGV2ZWxvcGVycy9kb2NzL3RvcGljcy9nYXRld2F5I3VwZGF0ZS12b2ljZS1zdGF0ZX1cbiAgICovXG4gIGxlYXZlVm9pY2VDaGFubmVsOiAoZ3VpbGRJZDogQmlnU3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+XG4gIC8qKiBUaGlzIG1hbmFnZXJzIGNhY2hlIHJlbGF0ZWQgc2V0dGluZ3MuICovXG4gIGNhY2hlOiB7XG4gICAgcmVxdWVzdE1lbWJlcnM6IHtcbiAgICAgIC8qKlxuICAgICAgICogV2hldGhlciBvciBub3QgcmVxdWVzdCBtZW1iZXIgcmVxdWVzdHMgc2hvdWxkIGJlIGNhY2hlZC5cbiAgICAgICAqIEBkZWZhdWx0IGZhbHNlXG4gICAgICAgKi9cbiAgICAgIGVuYWJsZWQ6IGJvb2xlYW5cbiAgICAgIC8qKiBUaGUgcGVuZGluZyByZXF1ZXN0cy4gKi9cbiAgICAgIHBlbmRpbmc6IENvbGxlY3Rpb248c3RyaW5nLCBSZXF1ZXN0TWVtYmVyUmVxdWVzdD5cbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXF1ZXN0TWVtYmVyUmVxdWVzdCB7XG4gIC8qKiBUaGUgdW5pcXVlIG5vbmNlIGZvciB0aGlzIHJlcXVlc3QuICovXG4gIG5vbmNlOiBzdHJpbmdcbiAgLyoqIFRoZSByZXNvbHZlciBoYW5kbGVyIHRvIHJ1biB3aGVuIGFsbCBtZW1iZXJzIGFycml2ZS4gKi9cbiAgcmVzb2x2ZTogKHZhbHVlOiBDYW1lbGl6ZTxEaXNjb3JkTWVtYmVyV2l0aFVzZXJbXT4gfCBQcm9taXNlTGlrZTxDYW1lbGl6ZTxEaXNjb3JkTWVtYmVyV2l0aFVzZXJbXT4+KSA9PiB2b2lkXG4gIC8qKiBUaGUgbWVtYmVycyB0aGF0IGhhdmUgYWxyZWFkeSBhcnJpdmVkIGZvciB0aGlzIHJlcXVlc3QuICovXG4gIG1lbWJlcnM6IERpc2NvcmRNZW1iZXJXaXRoVXNlcltdXG59XG4iXSwibmFtZXMiOlsiY3JlYXRlR2F0ZXdheU1hbmFnZXIiLCJvcHRpb25zIiwiY29ubmVjdGlvbk9wdGlvbnMiLCJjb25uZWN0aW9uIiwidXJsIiwic2hhcmRzIiwic2Vzc2lvblN0YXJ0TGltaXQiLCJtYXhDb25jdXJyZW5jeSIsInJlbWFpbmluZyIsInRvdGFsIiwicmVzZXRBZnRlciIsImdhdGV3YXkiLCJldmVudHMiLCJjb21wcmVzcyIsImludGVudHMiLCJwcm9wZXJ0aWVzIiwib3MiLCJwcm9jZXNzIiwicGxhdGZvcm0iLCJicm93c2VyIiwiZGV2aWNlIiwidG9rZW4iLCJ2ZXJzaW9uIiwidG90YWxTaGFyZHMiLCJsYXN0U2hhcmRJZCIsImZpcnN0U2hhcmRJZCIsInRvdGFsV29ya2VycyIsInNoYXJkc1BlcldvcmtlciIsInNwYXduU2hhcmREZWxheSIsInByZWZlclNuYWtlQ2FzZSIsIk1hcCIsImJ1Y2tldHMiLCJjYWNoZSIsInJlcXVlc3RNZW1iZXJzIiwiZW5hYmxlZCIsInBlbmRpbmciLCJDb2xsZWN0aW9uIiwibG9nZ2VyIiwicmVzaGFyZGluZyIsInNoYXJkc0Z1bGxQZXJjZW50YWdlIiwiY2hlY2tJbnRlcnZhbCIsInBlbmRpbmdTaGFyZHMiLCJnZXRTZXNzaW9uSW5mbyIsIkVycm9yIiwiY2hlY2tJZlJlc2hhcmRpbmdJc05lZWRlZCIsIndhcm4iLCJuZWVkZWQiLCJzZXNzaW9uSW5mbyIsImluZm8iLCJwZXJjZW50YWdlIiwicmVzaGFyZCIsImNhbGN1bGF0ZVRvdGFsU2hhcmRzIiwiY2xlYXIiLCJwcmVwYXJlQnVja2V0cyIsImZvckVhY2giLCJidWNrZXQiLCJidWNrZXRJZCIsIndvcmtlciIsIndvcmtlcnMiLCJzaGFyZElkIiwicXVldWUiLCJ0ZWxsV29ya2VyVG9QcmVwYXJlIiwiaWQiLCJ3b3JrZXJJZCIsInNoYXJkIiwiU2hhcmQiLCJtZXNzYWdlIiwiX3NoYXJkIiwicGF5bG9hZCIsInQiLCJ1cGRhdGVHdWlsZHNTaGFyZElkIiwiZCIsImd1aWxkcyIsIm1hcCIsImciLCJyZXF1ZXN0SWRlbnRpZnkiLCJpZGVudGlmeSIsInNoYXJkSXNSZWFkeSIsImRlYnVnIiwiZGVsYXkiLCJnZXQiLCJpZGVudGlmeVJlcXVlc3RzIiwic2hpZnQiLCJmb3J3YXJkVG9Cb3QiLCJzZXQiLCJQcm9taXNlIiwicmVzb2x2ZSIsInB1c2giLCJ0aGVuIiwic2hhcmRJc1BlbmRpbmciLCJndWlsZElkcyIsImpvaW4iLCJzaXplIiwidmFsdWVzIiwiZXZlbnQiLCJvbGRIYW5kbGVyIiwiXyIsInNodXRkb3duIiwiU2hhcmRTb2NrZXRDbG9zZUNvZGVzIiwiUmVzaGFyZGVkIiwiTWF0aCIsImNlaWwiLCJjYWxjdWxhdGVXb3JrZXJJZCIsIm1pbiIsImkiLCJmaW5kIiwidyIsInNvcnQiLCJhIiwiYiIsInNwYXduU2hhcmRzIiwiYWxsIiwiZW50cmllcyIsInRlbGxXb3JrZXJUb0lkZW50aWZ5IiwiY2hlY2tJbnRlcnZhbElkIiwic2V0SW50ZXJ2YWwiLCJyZXNoYXJkaW5nSW5mbyIsImNvZGUiLCJyZWFzb24iLCJjbGVhclJlc2hhcmRpbmdJbnRlcnZhbCIsImNsb3NlIiwiY2xlYXJJbnRlcnZhbCIsInNlbmRQYXlsb2FkIiwic2VuZCIsImtpbGwiLCJkZWxldGUiLCJfc2hhcmRJZCIsImNhbGN1bGF0ZVNoYXJkSWQiLCJndWlsZElkIiwiTnVtYmVyIiwiQmlnSW50Iiwiam9pblZvaWNlQ2hhbm5lbCIsImNoYW5uZWxJZCIsIm9wIiwiR2F0ZXdheU9wY29kZXMiLCJWb2ljZVN0YXRlVXBkYXRlIiwiZ3VpbGRfaWQiLCJ0b1N0cmluZyIsImNoYW5uZWxfaWQiLCJzZWxmX211dGUiLCJzZWxmTXV0ZSIsInNlbGZfZGVhZiIsInNlbGZEZWFmIiwiZWRpdEJvdFN0YXR1cyIsImRhdGEiLCJKU09OIiwic3RyaW5naWZ5IiwiZWRpdFNoYXJkU3RhdHVzIiwiUHJlc2VuY2VVcGRhdGUiLCJzaW5jZSIsImFmayIsImFjdGl2aXRpZXMiLCJzdGF0dXMiLCJsaW1pdCIsIkdhdGV3YXlJbnRlbnRzIiwiR3VpbGRNZW1iZXJzIiwidXNlcklkcyIsImxlbmd0aCIsIm1lbWJlcnMiLCJub25jZSIsInJlamVjdCIsIlJlcXVlc3RHdWlsZE1lbWJlcnMiLCJxdWVyeSIsInVuZGVmaW5lZCIsInByZXNlbmNlcyIsInVzZXJfaWRzIiwibGVhdmVWb2ljZUNoYW5uZWwiXSwibWFwcGluZ3MiOiI7Ozs7K0JBZWdCQTs7O2VBQUFBOzs7dUJBTFQ7dUJBQ21DOzhEQUN4Qjt3QkFDeUc7Ozs7OztBQUVwSCxTQUFTQSxxQkFBcUJDLE9BQW9DO0lBQ3ZFLE1BQU1DLG9CQUFvQkQsUUFBUUUsVUFBVSxJQUFJO1FBQzlDQyxLQUFLO1FBQ0xDLFFBQVE7UUFDUkMsbUJBQW1CO1lBQ2pCQyxnQkFBZ0I7WUFDaEJDLFdBQVc7WUFDWEMsT0FBTztZQUNQQyxZQUFZLE9BQU8sS0FBSyxLQUFLO1FBQy9CO0lBQ0Y7SUFFQSxNQUFNQyxVQUEwQjtRQUM5QkMsUUFBUVgsUUFBUVcsTUFBTSxJQUFJLENBQUM7UUFDM0JDLFVBQVVaLFFB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