jsforce2 1.11.1 → 5.2.1

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.

Potentially problematic release.


This version of jsforce2 might be problematic. Click here for more details.

Files changed (80) hide show
  1. package/index.js +46 -1
  2. package/package.json +7 -105
  3. package/LICENSE +0 -22
  4. package/README.md +0 -74
  5. package/bin/jsforce +0 -3
  6. package/bower.json +0 -30
  7. package/build/jsforce-api-analytics.js +0 -393
  8. package/build/jsforce-api-analytics.min.js +0 -2
  9. package/build/jsforce-api-analytics.min.js.map +0 -1
  10. package/build/jsforce-api-apex.js +0 -183
  11. package/build/jsforce-api-apex.min.js +0 -2
  12. package/build/jsforce-api-apex.min.js.map +0 -1
  13. package/build/jsforce-api-bulk.js +0 -1054
  14. package/build/jsforce-api-bulk.min.js +0 -2
  15. package/build/jsforce-api-bulk.min.js.map +0 -1
  16. package/build/jsforce-api-chatter.js +0 -320
  17. package/build/jsforce-api-chatter.min.js +0 -2
  18. package/build/jsforce-api-chatter.min.js.map +0 -1
  19. package/build/jsforce-api-metadata.js +0 -3020
  20. package/build/jsforce-api-metadata.min.js +0 -2
  21. package/build/jsforce-api-metadata.min.js.map +0 -1
  22. package/build/jsforce-api-soap.js +0 -403
  23. package/build/jsforce-api-soap.min.js +0 -2
  24. package/build/jsforce-api-soap.min.js.map +0 -1
  25. package/build/jsforce-api-streaming.js +0 -3479
  26. package/build/jsforce-api-streaming.min.js +0 -2
  27. package/build/jsforce-api-streaming.min.js.map +0 -1
  28. package/build/jsforce-api-tooling.js +0 -319
  29. package/build/jsforce-api-tooling.min.js +0 -2
  30. package/build/jsforce-api-tooling.min.js.map +0 -1
  31. package/build/jsforce-core.js +0 -25250
  32. package/build/jsforce-core.min.js +0 -2
  33. package/build/jsforce-core.min.js.map +0 -1
  34. package/build/jsforce.js +0 -31637
  35. package/build/jsforce.min.js +0 -2
  36. package/build/jsforce.min.js.map +0 -1
  37. package/core.js +0 -1
  38. package/lib/VERSION.js +0 -2
  39. package/lib/_required.js +0 -29
  40. package/lib/api/analytics.js +0 -387
  41. package/lib/api/apex.js +0 -177
  42. package/lib/api/bulk.js +0 -862
  43. package/lib/api/chatter.js +0 -314
  44. package/lib/api/index.js +0 -8
  45. package/lib/api/metadata.js +0 -848
  46. package/lib/api/soap.js +0 -397
  47. package/lib/api/streaming-extension.js +0 -136
  48. package/lib/api/streaming.js +0 -270
  49. package/lib/api/tooling.js +0 -313
  50. package/lib/browser/canvas.js +0 -90
  51. package/lib/browser/client.js +0 -241
  52. package/lib/browser/core.js +0 -5
  53. package/lib/browser/jsforce.js +0 -6
  54. package/lib/browser/jsonp.js +0 -52
  55. package/lib/browser/request.js +0 -70
  56. package/lib/cache.js +0 -252
  57. package/lib/cli/cli.js +0 -431
  58. package/lib/cli/repl.js +0 -337
  59. package/lib/connection.js +0 -1881
  60. package/lib/core.js +0 -16
  61. package/lib/csv.js +0 -50
  62. package/lib/date.js +0 -163
  63. package/lib/http-api.js +0 -300
  64. package/lib/jsforce.js +0 -10
  65. package/lib/logger.js +0 -52
  66. package/lib/oauth2.js +0 -206
  67. package/lib/process.js +0 -275
  68. package/lib/promise.js +0 -164
  69. package/lib/query.js +0 -881
  70. package/lib/quick-action.js +0 -90
  71. package/lib/record-stream.js +0 -305
  72. package/lib/record.js +0 -107
  73. package/lib/registry/file-registry.js +0 -48
  74. package/lib/registry/index.js +0 -3
  75. package/lib/registry/registry.js +0 -111
  76. package/lib/require.js +0 -14
  77. package/lib/soap.js +0 -207
  78. package/lib/sobject.js +0 -558
  79. package/lib/soql-builder.js +0 -236
  80. package/lib/transport.js +0 -233
@@ -1,1054 +0,0 @@
1
- (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g=(g.jsforce||(g.jsforce = {}));g=(g.modules||(g.modules = {}));g=(g.api||(g.api = {}));g.Bulk = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
2
- (function (process){
3
- /*global process*/
4
- /**
5
- * @file Manages Salesforce Bulk API related operations
6
- * @author Shinichi Tomita <shinichi.tomita@gmail.com>
7
- */
8
-
9
- 'use strict';
10
-
11
- var inherits = window.jsforce.require('inherits'),
12
- stream = window.jsforce.require('readable-stream'),
13
- Duplex = stream.Duplex,
14
- events = window.jsforce.require('events'),
15
- _ = window.jsforce.require('lodash/core'),
16
- joinStreams = window.jsforce.require('multistream'),
17
- jsforce = window.jsforce.require('./core'),
18
- RecordStream = window.jsforce.require('./record-stream'),
19
- Promise = window.jsforce.require('./promise'),
20
- HttpApi = window.jsforce.require('./http-api');
21
-
22
- /*--------------------------------------------*/
23
-
24
- /**
25
- * Class for Bulk API Job
26
- *
27
- * @protected
28
- * @class Bulk~Job
29
- * @extends events.EventEmitter
30
- *
31
- * @param {Bulk} bulk - Bulk API object
32
- * @param {String} [type] - SObject type
33
- * @param {String} [operation] - Bulk load operation ('insert', 'update', 'upsert', 'delete', or 'hardDelete')
34
- * @param {Object} [options] - Options for bulk loading operation
35
- * @param {String} [options.extIdField] - External ID field name (used when upsert operation).
36
- * @param {String} [options.concurrencyMode] - 'Serial' or 'Parallel'. Defaults to Parallel.
37
- * @param {String} [jobId] - Job ID (if already available)
38
- */
39
- var Job = function(bulk, type, operation, options, jobId) {
40
- this._bulk = bulk;
41
- this.type = type;
42
- this.operation = operation;
43
- this.options = options || {};
44
- this.id = jobId;
45
- this.state = this.id ? 'Open' : 'Unknown';
46
- this._batches = {};
47
- };
48
-
49
- inherits(Job, events.EventEmitter);
50
-
51
- /**
52
- * @typedef {Object} Bulk~JobInfo
53
- * @prop {String} id - Job ID
54
- * @prop {String} object - Object type name
55
- * @prop {String} operation - Operation type of the job
56
- * @prop {String} state - Job status
57
- */
58
-
59
- /**
60
- * Return latest jobInfo from cache
61
- *
62
- * @method Bulk~Job#info
63
- * @param {Callback.<Bulk~JobInfo>} [callback] - Callback function
64
- * @returns {Promise.<Bulk~JobInfo>}
65
- */
66
- Job.prototype.info = function(callback) {
67
- var self = this;
68
- // if cache is not available, check the latest
69
- if (!this._jobInfo) {
70
- this._jobInfo = this.check();
71
- }
72
- return this._jobInfo.thenCall(callback);
73
- };
74
-
75
- /**
76
- * Open new job and get jobinfo
77
- *
78
- * @method Bulk~Job#open
79
- * @param {Callback.<Bulk~JobInfo>} [callback] - Callback function
80
- * @returns {Promise.<Bulk~JobInfo>}
81
- */
82
- Job.prototype.open = function(callback) {
83
- var self = this;
84
- var bulk = this._bulk;
85
- var logger = bulk._logger;
86
-
87
- // if not requested opening job
88
- if (!this._jobInfo) {
89
- var operation = this.operation.toLowerCase();
90
- if (operation === 'harddelete') { operation = 'hardDelete'; }
91
- var body = [
92
- '<?xml version="1.0" encoding="UTF-8"?>',
93
- '<jobInfo xmlns="http://www.force.com/2009/06/asyncapi/dataload">',
94
- '<operation>' + operation + '</operation>',
95
- '<object>' + this.type + '</object>',
96
- (this.options.extIdField ?
97
- '<externalIdFieldName>'+this.options.extIdField+'</externalIdFieldName>' :
98
- ''),
99
- (this.options.concurrencyMode ?
100
- '<concurrencyMode>'+this.options.concurrencyMode+'</concurrencyMode>' :
101
- ''),
102
- (this.options.assignmentRuleId ?
103
- '<assignmentRuleId>' + this.options.assignmentRuleId + '</assignmentRuleId>' :
104
- ''),
105
- '<contentType>CSV</contentType>',
106
- '</jobInfo>'
107
- ].join('');
108
-
109
- this._jobInfo = bulk._request({
110
- method : 'POST',
111
- path : "/job",
112
- body : body,
113
- headers : {
114
- "Content-Type" : "application/xml; charset=utf-8"
115
- },
116
- responseType: "application/xml"
117
- }).then(function(res) {
118
- self.emit("open", res.jobInfo);
119
- self.id = res.jobInfo.id;
120
- self.state = res.jobInfo.state;
121
- return res.jobInfo;
122
- }, function(err) {
123
- self.emit("error", err);
124
- throw err;
125
- });
126
- }
127
- return this._jobInfo.thenCall(callback);
128
- };
129
-
130
- /**
131
- * Create a new batch instance in the job
132
- *
133
- * @method Bulk~Job#createBatch
134
- * @returns {Bulk~Batch}
135
- */
136
- Job.prototype.createBatch = function() {
137
- var batch = new Batch(this);
138
- var self = this;
139
- batch.on('queue', function() {
140
- self._batches[batch.id] = batch;
141
- });
142
- return batch;
143
- };
144
-
145
- /**
146
- * Get a batch instance specified by given batch ID
147
- *
148
- * @method Bulk~Job#batch
149
- * @param {String} batchId - Batch ID
150
- * @returns {Bulk~Batch}
151
- */
152
- Job.prototype.batch = function(batchId) {
153
- var batch = this._batches[batchId];
154
- if (!batch) {
155
- batch = new Batch(this, batchId);
156
- this._batches[batchId] = batch;
157
- }
158
- return batch;
159
- };
160
-
161
- /**
162
- * Check the latest job status from server
163
- *
164
- * @method Bulk~Job#check
165
- * @param {Callback.<Bulk~JobInfo>} [callback] - Callback function
166
- * @returns {Promise.<Bulk~JobInfo>}
167
- */
168
- Job.prototype.check = function(callback) {
169
- var self = this;
170
- var bulk = this._bulk;
171
- var logger = bulk._logger;
172
-
173
- this._jobInfo = this._waitAssign().then(function() {
174
- return bulk._request({
175
- method : 'GET',
176
- path : "/job/" + self.id,
177
- responseType: "application/xml"
178
- });
179
- }).then(function(res) {
180
- logger.debug(res.jobInfo);
181
- self.id = res.jobInfo.id;
182
- self.type = res.jobInfo.object;
183
- self.operation = res.jobInfo.operation;
184
- self.state = res.jobInfo.state;
185
- return res.jobInfo;
186
- });
187
- return this._jobInfo.thenCall(callback);
188
- };
189
-
190
- /**
191
- * Wait till the job is assigned to server
192
- *
193
- * @method Bulk~Job#info
194
- * @param {Callback.<Bulk~JobInfo>} [callback] - Callback function
195
- * @returns {Promise.<Bulk~JobInfo>}
196
- */
197
- Job.prototype._waitAssign = function(callback) {
198
- return (this.id ? Promise.resolve({ id: this.id }) : this.open()).thenCall(callback);
199
- };
200
-
201
-
202
- /**
203
- * List all registered batch info in job
204
- *
205
- * @method Bulk~Job#list
206
- * @param {Callback.<Array.<Bulk~BatchInfo>>} [callback] - Callback function
207
- * @returns {Promise.<Array.<Bulk~BatchInfo>>}
208
- */
209
- Job.prototype.list = function(callback) {
210
- var self = this;
211
- var bulk = this._bulk;
212
- var logger = bulk._logger;
213
-
214
- return this._waitAssign().then(function() {
215
- return bulk._request({
216
- method : 'GET',
217
- path : "/job/" + self.id + "/batch",
218
- responseType: "application/xml"
219
- });
220
- }).then(function(res) {
221
- logger.debug(res.batchInfoList.batchInfo);
222
- var batchInfoList = res.batchInfoList;
223
- batchInfoList = _.isArray(batchInfoList.batchInfo) ? batchInfoList.batchInfo : [ batchInfoList.batchInfo ];
224
- return batchInfoList;
225
- }).thenCall(callback);
226
-
227
- };
228
-
229
- /**
230
- * Close opened job
231
- *
232
- * @method Bulk~Job#close
233
- * @param {Callback.<Bulk~JobInfo>} [callback] - Callback function
234
- * @returns {Promise.<Bulk~JobInfo>}
235
- */
236
- Job.prototype.close = function() {
237
- var self = this;
238
- return this._changeState("Closed").then(function(jobInfo) {
239
- self.id = null;
240
- self.emit("close", jobInfo);
241
- return jobInfo;
242
- }, function(err) {
243
- self.emit("error", err);
244
- throw err;
245
- });
246
- };
247
-
248
- /**
249
- * Set the status to abort
250
- *
251
- * @method Bulk~Job#abort
252
- * @param {Callback.<Bulk~JobInfo>} [callback] - Callback function
253
- * @returns {Promise.<Bulk~JobInfo>}
254
- */
255
- Job.prototype.abort = function() {
256
- var self = this;
257
- return this._changeState("Aborted").then(function(jobInfo) {
258
- self.id = null;
259
- self.emit("abort", jobInfo);
260
- return jobInfo;
261
- }, function(err) {
262
- self.emit("error", err);
263
- throw err;
264
- });
265
- };
266
-
267
- /**
268
- * @private
269
- */
270
- Job.prototype._changeState = function(state, callback) {
271
- var self = this;
272
- var bulk = this._bulk;
273
- var logger = bulk._logger;
274
-
275
- this._jobInfo = this._waitAssign().then(function() {
276
- var body = [
277
- '<?xml version="1.0" encoding="UTF-8"?>',
278
- '<jobInfo xmlns="http://www.force.com/2009/06/asyncapi/dataload">',
279
- '<state>' + state + '</state>',
280
- '</jobInfo>'
281
- ].join('');
282
- return bulk._request({
283
- method : 'POST',
284
- path : "/job/" + self.id,
285
- body : body,
286
- headers : {
287
- "Content-Type" : "application/xml; charset=utf-8"
288
- },
289
- responseType: "application/xml"
290
- });
291
- }).then(function(res) {
292
- logger.debug(res.jobInfo);
293
- self.state = res.jobInfo.state;
294
- return res.jobInfo;
295
- });
296
- return this._jobInfo.thenCall(callback);
297
-
298
- };
299
-
300
-
301
- /*--------------------------------------------*/
302
-
303
- /**
304
- * Batch (extends RecordStream)
305
- *
306
- * @protected
307
- * @class Bulk~Batch
308
- * @extends {stream.Writable}
309
- * @implements {Promise.<Array.<RecordResult>>}
310
- * @param {Bulk~Job} job - Bulk job object
311
- * @param {String} [batchId] - Batch ID (if already available)
312
- */
313
- var Batch = function(job, batchId) {
314
- Batch.super_.call(this, { objectMode: true });
315
- this.job = job;
316
- this.id = batchId;
317
- this._bulk = job._bulk;
318
- this._deferred = Promise.defer();
319
- this._setupDataStreams();
320
- };
321
-
322
- inherits(Batch, stream.Writable);
323
-
324
-
325
- /**
326
- * @private
327
- */
328
- Batch.prototype._setupDataStreams = function() {
329
- var batch = this;
330
- var converterOptions = { nullValue : '#N/A' };
331
- this._uploadStream = new RecordStream.Serializable();
332
- this._uploadDataStream = this._uploadStream.stream('csv', converterOptions);
333
- this._downloadStream = new RecordStream.Parsable();
334
- this._downloadDataStream = this._downloadStream.stream('csv', converterOptions);
335
-
336
- this.on('finish', function() {
337
- batch._uploadStream.end();
338
- });
339
- this._uploadDataStream.once('readable', function() {
340
- batch.job.open().then(function() {
341
- // pipe upload data to batch API request stream
342
- batch._uploadDataStream.pipe(batch._createRequestStream());
343
- });
344
- });
345
-
346
- // duplex data stream, opened access to API programmers by Batch#stream()
347
- var dataStream = this._dataStream = new Duplex();
348
- dataStream._write = function(data, enc, cb) {
349
- batch._uploadDataStream.write(data, enc, cb);
350
- };
351
- dataStream.on('finish', function() {
352
- batch._uploadDataStream.end();
353
- });
354
-
355
- this._downloadDataStream.on('readable', function() {
356
- dataStream.read(0);
357
- });
358
- this._downloadDataStream.on('end', function() {
359
- dataStream.push(null);
360
- });
361
- dataStream._read = function(size) {
362
- var chunk;
363
- while ((chunk = batch._downloadDataStream.read()) !== null) {
364
- dataStream.push(chunk);
365
- }
366
- };
367
- };
368
-
369
- /**
370
- * Connect batch API and create stream instance of request/response
371
- *
372
- * @private
373
- * @returns {stream.Duplex}
374
- */
375
- Batch.prototype._createRequestStream = function() {
376
- var batch = this;
377
- var bulk = batch._bulk;
378
- var logger = bulk._logger;
379
-
380
- return bulk._request({
381
- method : 'POST',
382
- path : "/job/" + batch.job.id + "/batch",
383
- headers: {
384
- "Content-Type": "text/csv"
385
- },
386
- responseType: "application/xml"
387
- }, function(err, res) {
388
- if (err) {
389
- batch.emit('error', err);
390
- } else {
391
- logger.debug(res.batchInfo);
392
- batch.id = res.batchInfo.id;
393
- batch.emit('queue', res.batchInfo);
394
- }
395
- }).stream();
396
- };
397
-
398
- /**
399
- * Implementation of Writable
400
- *
401
- * @override
402
- * @private
403
- */
404
- Batch.prototype._write = function(record, enc, cb) {
405
- record = _.clone(record);
406
- if (this.job.operation === "insert") {
407
- delete record.Id;
408
- } else if (this.job.operation === "delete") {
409
- record = { Id: record.Id };
410
- }
411
- delete record.type;
412
- delete record.attributes;
413
- this._uploadStream.write(record, enc, cb);
414
- };
415
-
416
- /**
417
- * Returns duplex stream which accepts CSV data input and batch result output
418
- *
419
- * @returns {stream.Duplex}
420
- */
421
- Batch.prototype.stream = function() {
422
- return this._dataStream;
423
- };
424
-
425
- /**
426
- * Execute batch operation
427
- *
428
- * @method Bulk~Batch#execute
429
- * @param {Array.<Record>|stream.Stream|String} [input] - Input source for batch operation. Accepts array of records, CSV string, and CSV data input stream in insert/update/upsert/delete/hardDelete operation, SOQL string in query operation.
430
- * @param {Callback.<Array.<RecordResult>|Array.<BatchResultInfo>>} [callback] - Callback function
431
- * @returns {Bulk~Batch}
432
- */
433
- Batch.prototype.run =
434
- Batch.prototype.exec =
435
- Batch.prototype.execute = function(input, callback) {
436
- var self = this;
437
-
438
- if (typeof input === 'function') { // if input argument is omitted
439
- callback = input;
440
- input = null;
441
- }
442
-
443
- // if batch is already executed
444
- if (this._result) {
445
- throw new Error("Batch already executed.");
446
- }
447
-
448
- var rdeferred = Promise.defer();
449
- this._result = rdeferred.promise;
450
- this._result.then(function(res) {
451
- self._deferred.resolve(res);
452
- }, function(err) {
453
- self._deferred.reject(err);
454
- });
455
- this.once('response', function(res) {
456
- rdeferred.resolve(res);
457
- });
458
- this.once('error', function(err) {
459
- rdeferred.reject(err);
460
- });
461
-
462
- if (_.isObject(input) && _.isFunction(input.pipe)) { // if input has stream.Readable interface
463
- input.pipe(this._dataStream);
464
- } else {
465
- var data;
466
- if (_.isArray(input)) {
467
- _.forEach(input, function(record) {
468
- Object.keys(record).forEach(function(key) {
469
- if (typeof record[key] === 'boolean') {
470
- record[key] = String(record[key])
471
- }
472
- })
473
- self.write(record);
474
- });
475
- self.end();
476
- } else if (_.isString(input)){
477
- data = input;
478
- this._dataStream.write(data, 'utf8');
479
- this._dataStream.end();
480
- }
481
- }
482
-
483
- // return Batch instance for chaining
484
- return this.thenCall(callback);
485
- };
486
-
487
- /**
488
- * Promise/A+ interface
489
- * http://promises-aplus.github.io/promises-spec/
490
- *
491
- * Delegate to deferred promise, return promise instance for batch result
492
- *
493
- * @method Bulk~Batch#then
494
- */
495
- Batch.prototype.then = function(onResolved, onReject, onProgress) {
496
- return this._deferred.promise.then(onResolved, onReject, onProgress);
497
- };
498
-
499
- /**
500
- * Promise/A+ extension
501
- * Call "then" using given node-style callback function
502
- *
503
- * @method Bulk~Batch#thenCall
504
- */
505
- Batch.prototype.thenCall = function(callback) {
506
- if (_.isFunction(callback)) {
507
- this.then(function(res) {
508
- process.nextTick(function() {
509
- callback(null, res);
510
- });
511
- }, function(err) {
512
- process.nextTick(function() {
513
- callback(err);
514
- });
515
- });
516
- }
517
- return this;
518
- };
519
-
520
- /**
521
- * @typedef {Object} Bulk~BatchInfo
522
- * @prop {String} id - Batch ID
523
- * @prop {String} jobId - Job ID
524
- * @prop {String} state - Batch state
525
- * @prop {String} stateMessage - Batch state message
526
- */
527
-
528
- /**
529
- * Check the latest batch status in server
530
- *
531
- * @method Bulk~Batch#check
532
- * @param {Callback.<Bulk~BatchInfo>} [callback] - Callback function
533
- * @returns {Promise.<Bulk~BatchInfo>}
534
- */
535
- Batch.prototype.check = function(callback) {
536
- var self = this;
537
- var bulk = this._bulk;
538
- var logger = bulk._logger;
539
- var jobId = this.job.id;
540
- var batchId = this.id;
541
-
542
- if (!jobId || !batchId) {
543
- throw new Error("Batch not started.");
544
- }
545
- return bulk._request({
546
- method : 'GET',
547
- path : "/job/" + jobId + "/batch/" + batchId,
548
- responseType: "application/xml"
549
- }).then(function(res) {
550
- logger.debug(res.batchInfo);
551
- return res.batchInfo;
552
- }).thenCall(callback);
553
- };
554
-
555
-
556
- /**
557
- * Polling the batch result and retrieve
558
- *
559
- * @method Bulk~Batch#poll
560
- * @param {Number} interval - Polling interval in milliseconds
561
- * @param {Number} timeout - Polling timeout in milliseconds
562
- */
563
- Batch.prototype.poll = function(interval, timeout) {
564
- var self = this;
565
- var jobId = this.job.id;
566
- var batchId = this.id;
567
-
568
- if (!jobId || !batchId) {
569
- throw new Error("Batch not started.");
570
- }
571
- var startTime = new Date().getTime();
572
- var poll = function() {
573
- var now = new Date().getTime();
574
- if (startTime + timeout < now) {
575
- var err = new Error("Polling time out. Job Id = " + jobId + " , batch Id = " + batchId);
576
- err.name = 'PollingTimeout';
577
- err.jobId = jobId;
578
- err.batchId = batchId;
579
- self.emit('error', err);
580
- return;
581
- }
582
- self.check(function(err, res) {
583
- if (err) {
584
- self.emit('error', err);
585
- } else {
586
- if (res.state === "Failed") {
587
- if (parseInt(res.numberRecordsProcessed, 10) > 0) {
588
- self.retrieve();
589
- } else {
590
- self.emit('error', new Error(res.stateMessage));
591
- }
592
- } else if (res.state === "Completed") {
593
- self.retrieve();
594
- } else {
595
- self.emit('progress', res);
596
- setTimeout(poll, interval);
597
- }
598
- }
599
- });
600
- };
601
- setTimeout(poll, interval);
602
- };
603
-
604
- /**
605
- * @typedef {Object} Bulk~BatchResultInfo
606
- * @prop {String} id - Batch result ID
607
- * @prop {String} batchId - Batch ID which includes this batch result.
608
- * @prop {String} jobId - Job ID which includes this batch result.
609
- */
610
-
611
- /**
612
- * Retrieve batch result
613
- *
614
- * @method Bulk~Batch#retrieve
615
- * @param {Callback.<Array.<RecordResult>|Array.<Bulk~BatchResultInfo>>} [callback] - Callback function
616
- * @returns {Promise.<Array.<RecordResult>|Array.<Bulk~BatchResultInfo>>}
617
- */
618
- Batch.prototype.retrieve = function(callback) {
619
- var self = this;
620
- var bulk = this._bulk;
621
- var jobId = this.job.id;
622
- var job = this.job;
623
- var batchId = this.id;
624
-
625
- if (!jobId || !batchId) {
626
- throw new Error("Batch not started.");
627
- }
628
-
629
- return job.info().then(function(jobInfo) {
630
- return bulk._request({
631
- method : 'GET',
632
- path : "/job/" + jobId + "/batch/" + batchId + "/result"
633
- });
634
- }).then(function(res) {
635
- var results;
636
- if (job.operation === 'query') {
637
- var conn = bulk._conn;
638
- var resultIds = res['result-list'].result;
639
- results = res['result-list'].result;
640
- results = _.map(_.isArray(results) ? results : [ results ], function(id) {
641
- return {
642
- id: id,
643
- batchId: batchId,
644
- jobId: jobId
645
- };
646
- });
647
- } else {
648
- results = _.map(res, function(ret) {
649
- return {
650
- id: ret.Id || null,
651
- success: ret.Success === "true",
652
- errors: ret.Error ? [ ret.Error ] : []
653
- };
654
- });
655
- }
656
- self.emit('response', results);
657
- return results;
658
- }).fail(function(err) {
659
- self.emit('error', err);
660
- throw err;
661
- }).thenCall(callback);
662
- };
663
-
664
- /**
665
- * Fetch query result as a record stream
666
- * @param {String} resultId - Result id
667
- * @returns {RecordStream} - Record stream, convertible to CSV data stream
668
- */
669
- Batch.prototype.result = function(resultId) {
670
- var jobId = this.job.id;
671
- var batchId = this.id;
672
- if (!jobId || !batchId) {
673
- throw new Error("Batch not started.");
674
- }
675
- var resultStream = new RecordStream.Parsable();
676
- var resultDataStream = resultStream.stream('csv');
677
- var reqStream = this._bulk._request({
678
- method : 'GET',
679
- path : "/job/" + jobId + "/batch/" + batchId + "/result/" + resultId,
680
- responseType: "application/octet-stream"
681
- }).stream().pipe(resultDataStream);
682
- return resultStream;
683
- };
684
-
685
- /*--------------------------------------------*/
686
- /**
687
- * @private
688
- */
689
- var BulkApi = function() {
690
- BulkApi.super_.apply(this, arguments);
691
- };
692
-
693
- inherits(BulkApi, HttpApi);
694
-
695
- BulkApi.prototype.beforeSend = function(request) {
696
- request.headers = request.headers || {};
697
- request.headers["X-SFDC-SESSION"] = this._conn.accessToken;
698
- };
699
-
700
- BulkApi.prototype.isSessionExpired = function(response) {
701
- return response.statusCode === 400 &&
702
- /<exceptionCode>InvalidSessionId<\/exceptionCode>/.test(response.body);
703
- };
704
-
705
- BulkApi.prototype.hasErrorInResponseBody = function(body) {
706
- return !!body.error;
707
- };
708
-
709
- BulkApi.prototype.parseError = function(body) {
710
- return {
711
- errorCode: body.error.exceptionCode,
712
- message: body.error.exceptionMessage
713
- };
714
- };
715
-
716
- /*--------------------------------------------*/
717
-
718
- /**
719
- * Class for Bulk API
720
- *
721
- * @class
722
- * @param {Connection} conn - Connection object
723
- */
724
- var Bulk = function(conn) {
725
- this._conn = conn;
726
- this._logger = conn._logger;
727
- };
728
-
729
- /**
730
- * Polling interval in milliseconds
731
- * @type {Number}
732
- */
733
- Bulk.prototype.pollInterval = 1000;
734
-
735
- /**
736
- * Polling timeout in milliseconds
737
- * @type {Number}
738
- */
739
- Bulk.prototype.pollTimeout = 10000;
740
-
741
- /** @private **/
742
- Bulk.prototype._request = function(request, callback) {
743
- var conn = this._conn;
744
- request = _.clone(request);
745
- var baseUrl = [ conn.instanceUrl, "services/async", conn.version ].join('/');
746
- request.url = baseUrl + request.path;
747
- var options = { responseType: request.responseType };
748
- delete request.path;
749
- delete request.responseType;
750
- return new BulkApi(this._conn, options).request(request).thenCall(callback);
751
- };
752
-
753
- /**
754
- * Create and start bulkload job and batch
755
- *
756
- * @param {String} type - SObject type
757
- * @param {String} operation - Bulk load operation ('insert', 'update', 'upsert', 'delete', or 'hardDelete')
758
- * @param {Object} [options] - Options for bulk loading operation
759
- * @param {String} [options.extIdField] - External ID field name (used when upsert operation).
760
- * @param {String} [options.concurrencyMode] - 'Serial' or 'Parallel'. Defaults to Parallel.
761
- * @param {Array.<Record>|stream.Stream|String} [input] - Input source for bulkload. Accepts array of records, CSV string, and CSV data input stream in insert/update/upsert/delete/hardDelete operation, SOQL string in query operation.
762
- * @param {Callback.<Array.<RecordResult>|Array.<Bulk~BatchResultInfo>>} [callback] - Callback function
763
- * @returns {Bulk~Batch}
764
- */
765
- Bulk.prototype.load = function(type, operation, options, input, callback) {
766
- var self = this;
767
- if (!type || !operation) {
768
- throw new Error("Insufficient arguments. At least, 'type' and 'operation' are required.");
769
- }
770
- if (!_.isObject(options) || options.constructor !== Object) { // when options is not plain hash object, it is omitted
771
- callback = input;
772
- input = options;
773
- options = null;
774
- }
775
- var job = this.createJob(type, operation, options);
776
- job.once('error', function (error) {
777
- if (batch) {
778
- batch.emit('error', error); // pass job error to batch
779
- }
780
- });
781
- var batch = job.createBatch();
782
- var cleanup = function() {
783
- batch = null;
784
- job.close();
785
- };
786
- var cleanupOnError = function(err) {
787
- if (err.name !== 'PollingTimeout') {
788
- cleanup();
789
- }
790
- };
791
- batch.on('response', cleanup);
792
- batch.on('error', cleanupOnError);
793
- batch.on('queue', function() { batch.poll(self.pollInterval, self.pollTimeout); });
794
- return batch.execute(input, callback);
795
- };
796
-
797
- /**
798
- * Execute bulk query and get record stream
799
- *
800
- * @param {String} soql - SOQL to execute in bulk job
801
- * @returns {RecordStream.Parsable} - Record stream, convertible to CSV data stream
802
- */
803
- Bulk.prototype.query = function(soql) {
804
- var m = soql.replace(/\([\s\S]+\)/g, '').match(/FROM\s+(\w+)/i);
805
- if (!m) {
806
- throw new Error("No sobject type found in query, maybe caused by invalid SOQL.");
807
- }
808
- var type = m[1];
809
- var self = this;
810
- var recordStream = new RecordStream.Parsable();
811
- var dataStream = recordStream.stream('csv');
812
- this.load(type, "query", soql).then(function(results) {
813
- var streams = results.map(function(result) {
814
- return self
815
- .job(result.jobId)
816
- .batch(result.batchId)
817
- .result(result.id)
818
- .stream();
819
- });
820
-
821
- joinStreams(streams).pipe(dataStream);
822
- }).fail(function(err) {
823
- recordStream.emit('error', err);
824
- });
825
- return recordStream;
826
- };
827
-
828
-
829
- /**
830
- * Create a new job instance
831
- *
832
- * @param {String} type - SObject type
833
- * @param {String} operation - Bulk load operation ('insert', 'update', 'upsert', 'delete', 'hardDelete', or 'query')
834
- * @param {Object} [options] - Options for bulk loading operation
835
- * @returns {Bulk~Job}
836
- */
837
- Bulk.prototype.createJob = function(type, operation, options) {
838
- return new Job(this, type, operation, options);
839
- };
840
-
841
- /**
842
- * Get a job instance specified by given job ID
843
- *
844
- * @param {String} jobId - Job ID
845
- * @returns {Bulk~Job}
846
- */
847
- Bulk.prototype.job = function(jobId) {
848
- return new Job(this, null, null, null, jobId);
849
- };
850
-
851
-
852
- /*--------------------------------------------*/
853
- /*
854
- * Register hook in connection instantiation for dynamically adding this API module features
855
- */
856
- jsforce.on('connection:new', function(conn) {
857
- conn.bulk = new Bulk(conn);
858
- });
859
-
860
-
861
- module.exports = Bulk;
862
-
863
- }).call(this,require('_process'))
864
-
865
- },{"_process":2}],2:[function(require,module,exports){
866
- // shim for using process in browser
867
- var process = module.exports = {};
868
-
869
- // cached from whatever global is present so that test runners that stub it
870
- // don't break things. But we need to wrap it in a try catch in case it is
871
- // wrapped in strict mode code which doesn't define any globals. It's inside a
872
- // function because try/catches deoptimize in certain engines.
873
-
874
- var cachedSetTimeout;
875
- var cachedClearTimeout;
876
-
877
- function defaultSetTimout() {
878
- throw new Error('setTimeout has not been defined');
879
- }
880
- function defaultClearTimeout () {
881
- throw new Error('clearTimeout has not been defined');
882
- }
883
- (function () {
884
- try {
885
- if (typeof setTimeout === 'function') {
886
- cachedSetTimeout = setTimeout;
887
- } else {
888
- cachedSetTimeout = defaultSetTimout;
889
- }
890
- } catch (e) {
891
- cachedSetTimeout = defaultSetTimout;
892
- }
893
- try {
894
- if (typeof clearTimeout === 'function') {
895
- cachedClearTimeout = clearTimeout;
896
- } else {
897
- cachedClearTimeout = defaultClearTimeout;
898
- }
899
- } catch (e) {
900
- cachedClearTimeout = defaultClearTimeout;
901
- }
902
- } ())
903
- function runTimeout(fun) {
904
- if (cachedSetTimeout === setTimeout) {
905
- //normal enviroments in sane situations
906
- return setTimeout(fun, 0);
907
- }
908
- // if setTimeout wasn't available but was latter defined
909
- if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
910
- cachedSetTimeout = setTimeout;
911
- return setTimeout(fun, 0);
912
- }
913
- try {
914
- // when when somebody has screwed with setTimeout but no I.E. maddness
915
- return cachedSetTimeout(fun, 0);
916
- } catch(e){
917
- try {
918
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
919
- return cachedSetTimeout.call(null, fun, 0);
920
- } catch(e){
921
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
922
- return cachedSetTimeout.call(this, fun, 0);
923
- }
924
- }
925
-
926
-
927
- }
928
- function runClearTimeout(marker) {
929
- if (cachedClearTimeout === clearTimeout) {
930
- //normal enviroments in sane situations
931
- return clearTimeout(marker);
932
- }
933
- // if clearTimeout wasn't available but was latter defined
934
- if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
935
- cachedClearTimeout = clearTimeout;
936
- return clearTimeout(marker);
937
- }
938
- try {
939
- // when when somebody has screwed with setTimeout but no I.E. maddness
940
- return cachedClearTimeout(marker);
941
- } catch (e){
942
- try {
943
- // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
944
- return cachedClearTimeout.call(null, marker);
945
- } catch (e){
946
- // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
947
- // Some versions of I.E. have different rules for clearTimeout vs setTimeout
948
- return cachedClearTimeout.call(this, marker);
949
- }
950
- }
951
-
952
-
953
-
954
- }
955
- var queue = [];
956
- var draining = false;
957
- var currentQueue;
958
- var queueIndex = -1;
959
-
960
- function cleanUpNextTick() {
961
- if (!draining || !currentQueue) {
962
- return;
963
- }
964
- draining = false;
965
- if (currentQueue.length) {
966
- queue = currentQueue.concat(queue);
967
- } else {
968
- queueIndex = -1;
969
- }
970
- if (queue.length) {
971
- drainQueue();
972
- }
973
- }
974
-
975
- function drainQueue() {
976
- if (draining) {
977
- return;
978
- }
979
- var timeout = runTimeout(cleanUpNextTick);
980
- draining = true;
981
-
982
- var len = queue.length;
983
- while(len) {
984
- currentQueue = queue;
985
- queue = [];
986
- while (++queueIndex < len) {
987
- if (currentQueue) {
988
- currentQueue[queueIndex].run();
989
- }
990
- }
991
- queueIndex = -1;
992
- len = queue.length;
993
- }
994
- currentQueue = null;
995
- draining = false;
996
- runClearTimeout(timeout);
997
- }
998
-
999
- process.nextTick = function (fun) {
1000
- var args = new Array(arguments.length - 1);
1001
- if (arguments.length > 1) {
1002
- for (var i = 1; i < arguments.length; i++) {
1003
- args[i - 1] = arguments[i];
1004
- }
1005
- }
1006
- queue.push(new Item(fun, args));
1007
- if (queue.length === 1 && !draining) {
1008
- runTimeout(drainQueue);
1009
- }
1010
- };
1011
-
1012
- // v8 likes predictible objects
1013
- function Item(fun, array) {
1014
- this.fun = fun;
1015
- this.array = array;
1016
- }
1017
- Item.prototype.run = function () {
1018
- this.fun.apply(null, this.array);
1019
- };
1020
- process.title = 'browser';
1021
- process.browser = true;
1022
- process.env = {};
1023
- process.argv = [];
1024
- process.version = ''; // empty string to avoid regexp issues
1025
- process.versions = {};
1026
-
1027
- function noop() {}
1028
-
1029
- process.on = noop;
1030
- process.addListener = noop;
1031
- process.once = noop;
1032
- process.off = noop;
1033
- process.removeListener = noop;
1034
- process.removeAllListeners = noop;
1035
- process.emit = noop;
1036
- process.prependListener = noop;
1037
- process.prependOnceListener = noop;
1038
-
1039
- process.listeners = function (name) { return [] }
1040
-
1041
- process.binding = function (name) {
1042
- throw new Error('process.binding is not supported');
1043
- };
1044
-
1045
- process.cwd = function () { return '/' };
1046
- process.chdir = function (dir) {
1047
- throw new Error('process.chdir is not supported');
1048
- };
1049
- process.umask = function() { return 0; };
1050
-
1051
- },{}]},{},[1])(1)
1052
- });
1053
-
1054
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJsaWIvYXBpL2J1bGsuanMiLCJub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMzMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbigpe2Z1bmN0aW9uIHIoZSxuLHQpe2Z1bmN0aW9uIG8oaSxmKXtpZighbltpXSl7aWYoIWVbaV0pe3ZhciBjPVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmU7aWYoIWYmJmMpcmV0dXJuIGMoaSwhMCk7aWYodSlyZXR1cm4gdShpLCEwKTt2YXIgYT1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK2krXCInXCIpO3Rocm93IGEuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixhfXZhciBwPW5baV09e2V4cG9ydHM6e319O2VbaV1bMF0uY2FsbChwLmV4cG9ydHMsZnVuY3Rpb24ocil7dmFyIG49ZVtpXVsxXVtyXTtyZXR1cm4gbyhufHxyKX0scCxwLmV4cG9ydHMscixlLG4sdCl9cmV0dXJuIG5baV0uZXhwb3J0c31mb3IodmFyIHU9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZSxpPTA7aTx0Lmxlbmd0aDtpKyspbyh0W2ldKTtyZXR1cm4gb31yZXR1cm4gcn0pKCkiLCIvKmdsb2JhbCBwcm9jZXNzKi9cbi8qKlxuICogQGZpbGUgTWFuYWdlcyBTYWxlc2ZvcmNlIEJ1bGsgQVBJIHJlbGF0ZWQgb3BlcmF0aW9uc1xuICogQGF1dGhvciBTaGluaWNoaSBUb21pdGEgPHNoaW5pY2hpLnRvbWl0YUBnbWFpbC5jb20+XG4gKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaW5oZXJpdHMgICAgID0gd2luZG93LmpzZm9yY2UucmVxdWlyZSgnaW5oZXJpdHMnKSxcbiAgICBzdHJlYW0gICAgICAgPSB3aW5kb3cuanNmb3JjZS5yZXF1aXJlKCdyZWFkYWJsZS1zdHJlYW0nKSxcbiAgICBEdXBsZXggICAgICAgPSBzdHJlYW0uRHVwbGV4LFxuICAgIGV2ZW50cyAgICAgICA9IHdpbmRvdy5qc2ZvcmNlLnJlcXVpcmUoJ2V2ZW50cycpLFxuICAgIF8gICAgICAgICAgICA9IHdpbmRvdy5qc2ZvcmNlLnJlcXVpcmUoJ2xvZGFzaC9jb3JlJyksXG4gICAgam9pblN0cmVhbXMgID0gd2luZG93LmpzZm9yY2UucmVxdWlyZSgnbXVsdGlzdHJlYW0nKSxcbiAgICBqc2ZvcmNlICAgICAgPSB3aW5kb3cuanNmb3JjZS5yZXF1aXJlKCcuL2NvcmUnKSxcbiAgICBSZWNvcmRTdHJlYW0gPSB3aW5kb3cuanNmb3JjZS5yZXF1aXJlKCcuL3JlY29yZC1zdHJlYW0nKSxcbiAgICBQcm9taXNlICAgICAgPSB3aW5kb3cuanNmb3JjZS5yZXF1aXJlKCcuL3Byb21pc2UnKSxcbiAgICBIdHRwQXBpICAgICAgPSB3aW5kb3cuanNmb3JjZS5yZXF1aXJlKCcuL2h0dHAtYXBpJyk7XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4vKipcbiAqIENsYXNzIGZvciBCdWxrIEFQSSBKb2JcbiAqXG4gKiBAcHJvdGVjdGVkXG4gKiBAY2xhc3MgQnVsa35Kb2JcbiAqIEBleHRlbmRzIGV2ZW50cy5FdmVudEVtaXR0ZXJcbiAqXG4gKiBAcGFyYW0ge0J1bGt9IGJ1bGsgLSBCdWxrIEFQSSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSBbdHlwZV0gLSBTT2JqZWN0IHR5cGVcbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3BlcmF0aW9uXSAtIEJ1bGsgbG9hZCBvcGVyYXRpb24gKCdpbnNlcnQnLCAndXBkYXRlJywgJ3Vwc2VydCcsICdkZWxldGUnLCBvciAnaGFyZERlbGV0ZScpXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0gT3B0aW9ucyBmb3IgYnVsayBsb2FkaW5nIG9wZXJhdGlvblxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmV4dElkRmllbGRdIC0gRXh0ZXJuYWwgSUQgZmllbGQgbmFtZSAodXNlZCB3aGVuIHVwc2VydCBvcGVyYXRpb24pLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmNvbmN1cnJlbmN5TW9kZV0gLSAnU2VyaWFsJyBvciAnUGFyYWxsZWwnLiBEZWZhdWx0cyB0byBQYXJhbGxlbC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBbam9iSWRdIC0gSm9iIElEIChpZiBhbHJlYWR5IGF2YWlsYWJsZSlcbiAqL1xudmFyIEpvYiA9IGZ1bmN0aW9uKGJ1bGssIHR5cGUsIG9wZXJhdGlvbiwgb3B0aW9ucywgam9iSWQpIHtcbiAgdGhpcy5fYnVsayA9IGJ1bGs7XG4gIHRoaXMudHlwZSA9IHR5cGU7XG4gIHRoaXMub3BlcmF0aW9uID0gb3BlcmF0aW9uO1xuICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICB0aGlzLmlkID0gam9iSWQ7XG4gIHRoaXMuc3RhdGUgPSB0aGlzLmlkID8gJ09wZW4nIDogJ1Vua25vd24nO1xuICB0aGlzLl9iYXRjaGVzID0ge307XG59O1xuXG5pbmhlcml0cyhKb2IsIGV2ZW50cy5FdmVudEVtaXR0ZXIpO1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEJ1bGt+Sm9iSW5mb1xuICogQHByb3Age1N0cmluZ30gaWQgLSBKb2IgSURcbiAqIEBwcm9wIHtTdHJpbmd9IG9iamVjdCAtIE9iamVjdCB0eXBlIG5hbWVcbiAqIEBwcm9wIHtTdHJpbmd9IG9wZXJhdGlvbiAtIE9wZXJhdGlvbiB0eXBlIG9mIHRoZSBqb2JcbiAqIEBwcm9wIHtTdHJpbmd9IHN0YXRlIC0gSm9iIHN0YXR1c1xuICovXG5cbi8qKlxuICogUmV0dXJuIGxhdGVzdCBqb2JJbmZvIGZyb20gY2FjaGVcbiAqXG4gKiBAbWV0aG9kIEJ1bGt+Sm9iI2luZm9cbiAqIEBwYXJhbSB7Q2FsbGJhY2suPEJ1bGt+Sm9iSW5mbz59IFtjYWxsYmFja10gLSBDYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybnMge1Byb21pc2UuPEJ1bGt+Sm9iSW5mbz59XG4gKi9cbkpvYi5wcm90b3R5cGUuaW5mbyA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgLy8gaWYgY2FjaGUgaXMgbm90IGF2YWlsYWJsZSwgY2hlY2sgdGhlIGxhdGVzdFxuICBpZiAoIXRoaXMuX2pvYkluZm8pIHtcbiAgICB0aGlzLl9qb2JJbmZvID0gdGhpcy5jaGVjaygpO1xuICB9XG4gIHJldHVybiB0aGlzLl9qb2JJbmZvLnRoZW5DYWxsKGNhbGxiYWNrKTtcbn07XG5cbi8qKlxuICogT3BlbiBuZXcgam9iIGFuZCBnZXQgam9iaW5mb1xuICpcbiAqIEBtZXRob2QgQnVsa35Kb2Ijb3BlblxuICogQHBhcmFtIHtDYWxsYmFjay48QnVsa35Kb2JJbmZvPn0gW2NhbGxiYWNrXSAtIENhbGxiYWNrIGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7UHJvbWlzZS48QnVsa35Kb2JJbmZvPn1cbiAqL1xuSm9iLnByb3RvdHlwZS5vcGVuID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgYnVsayA9IHRoaXMuX2J1bGs7XG4gIHZhciBsb2dnZXIgPSBidWxrLl9sb2dnZXI7XG5cbiAgLy8gaWYgbm90IHJlcXVlc3RlZCBvcGVuaW5nIGpvYlxuICBpZiAoIXRoaXMuX2pvYkluZm8pIHtcbiAgICB2YXIgb3BlcmF0aW9uID0gdGhpcy5vcGVyYXRpb24udG9Mb3dlckNhc2UoKTtcbiAgICBpZiAob3BlcmF0aW9uID09PSAnaGFyZGRlbGV0ZScpIHsgb3BlcmF0aW9uID0gJ2hhcmREZWxldGUnOyB9XG4gICAgdmFyIGJvZHkgPSBbXG4gICAgICAnPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwiVVRGLThcIj8+JyxcbiAgICAgICc8am9iSW5mbyAgeG1sbnM9XCJodHRwOi8vd3d3LmZvcmNlLmNvbS8yMDA5LzA2L2FzeW5jYXBpL2RhdGFsb2FkXCI+JyxcbiAgICAgICAgJzxvcGVyYXRpb24+JyArIG9wZXJhdGlvbiArICc8L29wZXJhdGlvbj4nLFxuICAgICAgICAnPG9iamVjdD4nICsgdGhpcy50eXBlICsgJzwvb2JqZWN0PicsXG4gICAgICAgICh0aGlzLm9wdGlvbnMuZXh0SWRGaWVsZCA/XG4gICAgICAgICAnPGV4dGVybmFsSWRGaWVsZE5hbWU+Jyt0aGlzLm9wdGlvbnMuZXh0SWRGaWVsZCsnPC9leHRlcm5hbElkRmllbGROYW1lPicgOlxuICAgICAgICAgJycpLFxuICAgICAgICAodGhpcy5vcHRpb25zLmNvbmN1cnJlbmN5TW9kZSA/XG4gICAgICAgICAnPGNvbmN1cnJlbmN5TW9kZT4nK3RoaXMub3B0aW9ucy5jb25jdXJyZW5jeU1vZGUrJzwvY29uY3VycmVuY3lNb2RlPicgOlxuICAgICAgICAgJycpLFxuICAgICAgICAodGhpcy5vcHRpb25zLmFzc2lnbm1lbnRSdWxlSWQgP1xuICAgICAgICAgICc8YXNzaWdubWVudFJ1bGVJZD4nICsgdGhpcy5vcHRpb25zLmFzc2lnbm1lbnRSdWxlSWQgKyAnPC9hc3NpZ25tZW50UnVsZUlkPicgOlxuICAgICAgICAgICcnKSxcbiAgICAgICAgJzxjb250ZW50VHlwZT5DU1Y8L2NvbnRlbnRUeXBlPicsXG4gICAgICAnPC9qb2JJbmZvPidcbiAgICBdLmpvaW4oJycpO1xuXG4gICAgdGhpcy5fam9iSW5mbyA9IGJ1bGsuX3JlcXVlc3Qoe1xuICAgICAgbWV0aG9kIDogJ1BPU1QnLFxuICAgICAgcGF0aCA6IFwiL2pvYlwiLFxuICAgICAgYm9keSA6IGJvZHksXG4gICAgICBoZWFkZXJzIDoge1xuICAgICAgICBcIkNvbnRlbnQtVHlwZVwiIDogXCJhcHBsaWNhdGlvbi94bWw7IGNoYXJzZXQ9dXRmLThcIlxuICAgICAgfSxcbiAgICAgIHJlc3BvbnNlVHlwZTogXCJhcHBsaWNhdGlvbi94bWxcIlxuICAgIH0pLnRoZW4oZnVuY3Rpb24ocmVzKSB7XG4gICAgICBzZWxmLmVtaXQoXCJvcGVuXCIsIHJlcy5qb2JJbmZvKTtcbiAgICAgIHNlbGYuaWQgPSByZXMuam9iSW5mby5pZDtcbiAgICAgIHNlbGYuc3RhdGUgPSByZXMuam9iSW5mby5zdGF0ZTtcbiAgICAgIHJldHVybiByZXMuam9iSW5mbztcbiAgICB9LCBmdW5jdGlvbihlcnIpIHtcbiAgICAgIHNlbGYuZW1pdChcImVycm9yXCIsIGVycik7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIHRoaXMuX2pvYkluZm8udGhlbkNhbGwoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgYmF0Y2ggaW5zdGFuY2UgaW4gdGhlIGpvYlxuICpcbiAqIEBtZXRob2QgQnVsa35Kb2IjY3JlYXRlQmF0Y2hcbiAqIEByZXR1cm5zIHtCdWxrfkJhdGNofVxuICovXG5Kb2IucHJvdG90eXBlLmNyZWF0ZUJhdGNoID0gZnVuY3Rpb24oKSB7XG4gIHZhciBiYXRjaCA9IG5ldyBCYXRjaCh0aGlzKTtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICBiYXRjaC5vbigncXVldWUnLCBmdW5jdGlvbigpIHtcbiAgICBzZWxmLl9iYXRjaGVzW2JhdGNoLmlkXSA9IGJhdGNoO1xuICB9KTtcbiAgcmV0dXJuIGJhdGNoO1xufTtcblxuLyoqXG4gKiBHZXQgYSBiYXRjaCBpbnN0YW5jZSBzcGVjaWZpZWQgYnkgZ2l2ZW4gYmF0Y2ggSURcbiAqXG4gKiBAbWV0aG9kIEJ1bGt+Sm9iI2JhdGNoXG4gKiBAcGFyYW0ge1N0cmluZ30gYmF0Y2hJZCAtIEJhdGNoIElEXG4gKiBAcmV0dXJucyB7QnVsa35CYXRjaH1cbiAqL1xuSm9iLnByb3RvdHlwZS5iYXRjaCA9IGZ1bmN0aW9uKGJhdGNoSWQpIHtcbiAgdmFyIGJhdGNoID0gdGhpcy5fYmF0Y2hlc1tiYXRjaElkXTtcbiAgaWYgKCFiYXRjaCkge1xuICAgIGJhdGNoID0gbmV3IEJhdGNoKHRoaXMsIGJhdGNoSWQpO1xuICAgIHRoaXMuX2JhdGNoZXNbYmF0Y2hJZF0gPSBiYXRjaDtcbiAgfVxuICByZXR1cm4gYmF0Y2g7XG59O1xuXG4vKipcbiAqIENoZWNrIHRoZSBsYXRlc3Qgam9iIHN0YXR1cyBmcm9tIHNlcnZlclxuICpcbiAqIEBtZXRob2QgQnVsa35Kb2IjY2hlY2tcbiAqIEBwYXJhbSB7Q2FsbGJhY2suPEJ1bGt+Sm9iSW5mbz59IFtjYWxsYmFja10gLSBDYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybnMge1Byb21pc2UuPEJ1bGt+Sm9iSW5mbz59XG4gKi9cbkpvYi5wcm90b3R5cGUuY2hlY2sgPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBidWxrID0gdGhpcy5fYnVsaztcbiAgdmFyIGxvZ2dlciA9IGJ1bGsuX2xvZ2dlcjtcblxuICB0aGlzLl9qb2JJbmZvID0gdGhpcy5fd2FpdEFzc2lnbigpLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGJ1bGsuX3JlcXVlc3Qoe1xuICAgICAgbWV0aG9kIDogJ0dFVCcsXG4gICAgICBwYXRoIDogXCIvam9iL1wiICsgc2VsZi5pZCxcbiAgICAgIHJlc3BvbnNlVHlwZTogXCJhcHBsaWNhdGlvbi94bWxcIlxuICAgIH0pO1xuICB9KS50aGVuKGZ1bmN0aW9uKHJlcykge1xuICAgIGxvZ2dlci5kZWJ1ZyhyZXMuam9iSW5mbyk7XG4gICAgc2VsZi5pZCA9IHJlcy5qb2JJbmZvLmlkO1xuICAgIHNlbGYudHlwZSA9IHJlcy5qb2JJbmZvLm9iamVjdDtcbiAgICBzZWxmLm9wZXJhdGlvbiA9IHJlcy5qb2JJbmZvLm9wZXJhdGlvbjtcbiAgICBzZWxmLnN0YXRlID0gcmVzLmpvYkluZm8uc3RhdGU7XG4gICAgcmV0dXJuIHJlcy5qb2JJbmZvO1xuICB9KTtcbiAgcmV0dXJuIHRoaXMuX2pvYkluZm8udGhlbkNhbGwoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBXYWl0IHRpbGwgdGhlIGpvYiBpcyBhc3NpZ25lZCB0byBzZXJ2ZXJcbiAqXG4gKiBAbWV0aG9kIEJ1bGt+Sm9iI2luZm9cbiAqIEBwYXJhbSB7Q2FsbGJhY2suPEJ1bGt+Sm9iSW5mbz59IFtjYWxsYmFja10gLSBDYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybnMge1Byb21pc2UuPEJ1bGt+Sm9iSW5mbz59XG4gKi9cbkpvYi5wcm90b3R5cGUuX3dhaXRBc3NpZ24gPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICByZXR1cm4gKHRoaXMuaWQgPyBQcm9taXNlLnJlc29sdmUoeyBpZDogdGhpcy5pZCB9KSA6IHRoaXMub3BlbigpKS50aGVuQ2FsbChjYWxsYmFjayk7XG59O1xuXG5cbi8qKlxuICogTGlzdCBhbGwgcmVnaXN0ZXJlZCBiYXRjaCBpbmZvIGluIGpvYlxuICpcbiAqIEBtZXRob2QgQnVsa35Kb2IjbGlzdFxuICogQHBhcmFtIHtDYWxsYmFjay48QXJyYXkuPEJ1bGt+QmF0Y2hJbmZvPj59IFtjYWxsYmFja10gLSBDYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybnMge1Byb21pc2UuPEFycmF5LjxCdWxrfkJhdGNoSW5mbz4+fVxuICovXG5Kb2IucHJvdG90eXBlLmxpc3QgPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBidWxrID0gdGhpcy5fYnVsaztcbiAgdmFyIGxvZ2dlciA9IGJ1bGsuX2xvZ2dlcjtcblxuICByZXR1cm4gdGhpcy5fd2FpdEFzc2lnbigpLnRoZW4oZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGJ1bGsuX3JlcXVlc3Qoe1xuICAgICAgbWV0aG9kIDogJ0dFVCcsXG4gICAgICBwYXRoIDogXCIvam9iL1wiICsgc2VsZi5pZCArIFwiL2JhdGNoXCIsXG4gICAgICByZXNwb25zZVR5cGU6IFwiYXBwbGljYXRpb24veG1sXCJcbiAgICB9KTtcbiAgfSkudGhlbihmdW5jdGlvbihyZXMpIHtcbiAgICBsb2dnZXIuZGVidWcocmVzLmJhdGNoSW5mb0xpc3QuYmF0Y2hJbmZvKTtcbiAgICB2YXIgYmF0Y2hJbmZvTGlzdCA9IHJlcy5iYXRjaEluZm9MaXN0O1xuICAgIGJhdGNoSW5mb0xpc3QgPSBfLmlzQXJyYXkoYmF0Y2hJbmZvTGlzdC5iYXRjaEluZm8pID8gYmF0Y2hJbmZvTGlzdC5iYXRjaEluZm8gOiBbIGJhdGNoSW5mb0xpc3QuYmF0Y2hJbmZvIF07XG4gICAgcmV0dXJuIGJhdGNoSW5mb0xpc3Q7XG4gIH0pLnRoZW5DYWxsKGNhbGxiYWNrKTtcblxufTtcblxuLyoqXG4gKiBDbG9zZSBvcGVuZWQgam9iXG4gKlxuICogQG1ldGhvZCBCdWxrfkpvYiNjbG9zZVxuICogQHBhcmFtIHtDYWxsYmFjay48QnVsa35Kb2JJbmZvPn0gW2NhbGxiYWNrXSAtIENhbGxiYWNrIGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7UHJvbWlzZS48QnVsa35Kb2JJbmZvPn1cbiAqL1xuSm9iLnByb3RvdHlwZS5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHJldHVybiB0aGlzLl9jaGFuZ2VTdGF0ZShcIkNsb3NlZFwiKS50aGVuKGZ1bmN0aW9uKGpvYkluZm8pIHtcbiAgICBzZWxmLmlkID0gbnVsbDtcbiAgICBzZWxmLmVtaXQoXCJjbG9zZVwiLCBqb2JJbmZvKTtcbiAgICByZXR1cm4gam9iSW5mbztcbiAgfSwgZnVuY3Rpb24oZXJyKSB7XG4gICAgc2VsZi5lbWl0KFwiZXJyb3JcIiwgZXJyKTtcbiAgICB0aHJvdyBlcnI7XG4gIH0pO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIHN0YXR1cyB0byBhYm9ydFxuICpcbiAqIEBtZXRob2QgQnVsa35Kb2IjYWJvcnRcbiAqIEBwYXJhbSB7Q2FsbGJhY2suPEJ1bGt+Sm9iSW5mbz59IFtjYWxsYmFja10gLSBDYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybnMge1Byb21pc2UuPEJ1bGt+Sm9iSW5mbz59XG4gKi9cbkpvYi5wcm90b3R5cGUuYWJvcnQgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICByZXR1cm4gdGhpcy5fY2hhbmdlU3RhdGUoXCJBYm9ydGVkXCIpLnRoZW4oZnVuY3Rpb24oam9iSW5mbykge1xuICAgIHNlbGYuaWQgPSBudWxsO1xuICAgIHNlbGYuZW1pdChcImFib3J0XCIsIGpvYkluZm8pO1xuICAgIHJldHVybiBqb2JJbmZvO1xuICB9LCBmdW5jdGlvbihlcnIpIHtcbiAgICBzZWxmLmVtaXQoXCJlcnJvclwiLCBlcnIpO1xuICAgIHRocm93IGVycjtcbiAgfSk7XG59O1xuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbkpvYi5wcm90b3R5cGUuX2NoYW5nZVN0YXRlID0gZnVuY3Rpb24oc3RhdGUsIGNhbGxiYWNrKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGJ1bGsgPSB0aGlzLl9idWxrO1xuICB2YXIgbG9nZ2VyID0gYnVsay5fbG9nZ2VyO1xuXG4gIHRoaXMuX2pvYkluZm8gPSB0aGlzLl93YWl0QXNzaWduKCkudGhlbihmdW5jdGlvbigpIHtcbiAgICB2YXIgYm9keSA9IFtcbiAgICAgICc8P3htbCB2ZXJzaW9uPVwiMS4wXCIgZW5jb2Rpbmc9XCJVVEYtOFwiPz4nLFxuICAgICAgJzxqb2JJbmZvIHhtbG5zPVwiaHR0cDovL3d3dy5mb3JjZS5jb20vMjAwOS8wNi9hc3luY2FwaS9kYXRhbG9hZFwiPicsXG4gICAgICAgICc8c3RhdGU+JyArIHN0YXRlICsgJzwvc3RhdGU+JyxcbiAgICAgICc8L2pvYkluZm8+J1xuICAgIF0uam9pbignJyk7XG4gICAgcmV0dXJuIGJ1bGsuX3JlcXVlc3Qoe1xuICAgICAgbWV0aG9kIDogJ1BPU1QnLFxuICAgICAgcGF0aCA6IFwiL2pvYi9cIiArIHNlbGYuaWQsXG4gICAgICBib2R5IDogYm9keSxcbiAgICAgIGhlYWRlcnMgOiB7XG4gICAgICAgIFwiQ29udGVudC1UeXBlXCIgOiBcImFwcGxpY2F0aW9uL3htbDsgY2hhcnNldD11dGYtOFwiXG4gICAgICB9LFxuICAgICAgcmVzcG9uc2VUeXBlOiBcImFwcGxpY2F0aW9uL3htbFwiXG4gICAgfSk7XG4gIH0pLnRoZW4oZnVuY3Rpb24ocmVzKSB7XG4gICAgbG9nZ2VyLmRlYnVnKHJlcy5qb2JJbmZvKTtcbiAgICBzZWxmLnN0YXRlID0gcmVzLmpvYkluZm8uc3RhdGU7XG4gICAgcmV0dXJuIHJlcy5qb2JJbmZvO1xuICB9KTtcbiAgcmV0dXJuIHRoaXMuX2pvYkluZm8udGhlbkNhbGwoY2FsbGJhY2spO1xuXG59O1xuXG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4vKipcbiAqIEJhdGNoIChleHRlbmRzIFJlY29yZFN0cmVhbSlcbiAqXG4gKiBAcHJvdGVjdGVkXG4gKiBAY2xhc3MgQnVsa35CYXRjaFxuICogQGV4dGVuZHMge3N0cmVhbS5Xcml0YWJsZX1cbiAqIEBpbXBsZW1lbnRzIHtQcm9taXNlLjxBcnJheS48UmVjb3JkUmVzdWx0Pj59XG4gKiBAcGFyYW0ge0J1bGt+Sm9ifSBqb2IgLSBCdWxrIGpvYiBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSBbYmF0Y2hJZF0gLSBCYXRjaCBJRCAoaWYgYWxyZWFkeSBhdmFpbGFibGUpXG4gKi9cbnZhciBCYXRjaCA9IGZ1bmN0aW9uKGpvYiwgYmF0Y2hJZCkge1xuICBCYXRjaC5zdXBlcl8uY2FsbCh0aGlzLCB7IG9iamVjdE1vZGU6IHRydWUgfSk7XG4gIHRoaXMuam9iID0gam9iO1xuICB0aGlzLmlkID0gYmF0Y2hJZDtcbiAgdGhpcy5fYnVsayA9IGpvYi5fYnVsaztcbiAgdGhpcy5fZGVmZXJyZWQgPSBQcm9taXNlLmRlZmVyKCk7XG4gIHRoaXMuX3NldHVwRGF0YVN0cmVhbXMoKTtcbn07XG5cbmluaGVyaXRzKEJhdGNoLCBzdHJlYW0uV3JpdGFibGUpO1xuXG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuQmF0Y2gucHJvdG90eXBlLl9zZXR1cERhdGFTdHJlYW1zID0gZnVuY3Rpb24oKSB7XG4gIHZhciBiYXRjaCA9IHRoaXM7XG4gIHZhciBjb252ZXJ0ZXJPcHRpb25zID0geyBudWxsVmFsdWUgOiAnI04vQScgfTtcbiAgdGhpcy5fdXBsb2FkU3RyZWFtID0gbmV3IFJlY29yZFN0cmVhbS5TZXJpYWxpemFibGUoKTtcbiAgdGhpcy5fdXBsb2FkRGF0YVN0cmVhbSA9IHRoaXMuX3VwbG9hZFN0cmVhbS5zdHJlYW0oJ2NzdicsIGNvbnZlcnRlck9wdGlvbnMpO1xuICB0aGlzLl9kb3dubG9hZFN0cmVhbSA9IG5ldyBSZWNvcmRTdHJlYW0uUGFyc2FibGUoKTtcbiAgdGhpcy5fZG93bmxvYWREYXRhU3RyZWFtID0gdGhpcy5fZG93bmxvYWRTdHJlYW0uc3RyZWFtKCdjc3YnLCBjb252ZXJ0ZXJPcHRpb25zKTtcblxuICB0aGlzLm9uKCdmaW5pc2gnLCBmdW5jdGlvbigpIHtcbiAgICBiYXRjaC5fdXBsb2FkU3RyZWFtLmVuZCgpO1xuICB9KTtcbiAgdGhpcy5fdXBsb2FkRGF0YVN0cmVhbS5vbmNlKCdyZWFkYWJsZScsIGZ1bmN0aW9uKCkge1xuICAgIGJhdGNoLmpvYi5vcGVuKCkudGhlbihmdW5jdGlvbigpIHtcbiAgICAgIC8vIHBpcGUgdXBsb2FkIGRhdGEgdG8gYmF0Y2ggQVBJIHJlcXVlc3Qgc3RyZWFtXG4gICAgICBiYXRjaC5fdXBsb2FkRGF0YVN0cmVhbS5waXBlKGJhdGNoLl9jcmVhdGVSZXF1ZXN0U3RyZWFtKCkpO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyBkdXBsZXggZGF0YSBzdHJlYW0sIG9wZW5lZCBhY2Nlc3MgdG8gQVBJIHByb2dyYW1tZXJzIGJ5IEJhdGNoI3N0cmVhbSgpXG4gIHZhciBkYXRhU3RyZWFtID0gdGhpcy5fZGF0YVN0cmVhbSA9IG5ldyBEdXBsZXgoKTtcbiAgZGF0YVN0cmVhbS5fd3JpdGUgPSBmdW5jdGlvbihkYXRhLCBlbmMsIGNiKSB7XG4gICAgYmF0Y2guX3VwbG9hZERhdGFTdHJlYW0ud3JpdGUoZGF0YSwgZW5jLCBjYik7XG4gIH07XG4gIGRhdGFTdHJlYW0ub24oJ2ZpbmlzaCcsIGZ1bmN0aW9uKCkge1xuICAgIGJhdGNoLl91cGxvYWREYXRhU3RyZWFtLmVuZCgpO1xuICB9KTtcblxuICB0aGlzLl9kb3dubG9hZERhdGFTdHJlYW0ub24oJ3JlYWRhYmxlJywgZnVuY3Rpb24oKSB7XG4gICAgZGF0YVN0cmVhbS5yZWFkKDApO1xuICB9KTtcbiAgdGhpcy5fZG93bmxvYWREYXRhU3RyZWFtLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcbiAgICBkYXRhU3RyZWFtLnB1c2gobnVsbCk7XG4gIH0pO1xuICBkYXRhU3RyZWFtLl9yZWFkID0gZnVuY3Rpb24oc2l6ZSkge1xuICAgIHZhciBjaHVuaztcbiAgICB3aGlsZSAoKGNodW5rID0gYmF0Y2guX2Rvd25sb2FkRGF0YVN0cmVhbS5yZWFkKCkpICE9PSBudWxsKSB7XG4gICAgICBkYXRhU3RyZWFtLnB1c2goY2h1bmspO1xuICAgIH1cbiAgfTtcbn07XG5cbi8qKlxuICogQ29ubmVjdCBiYXRjaCBBUEkgYW5kIGNyZWF0ZSBzdHJlYW0gaW5zdGFuY2Ugb2YgcmVxdWVzdC9yZXNwb25zZVxuICpcbiAqIEBwcml2YXRlXG4gKiBAcmV0dXJucyB7c3RyZWFtLkR1cGxleH1cbiAqL1xuQmF0Y2gucHJvdG90eXBlLl9jcmVhdGVSZXF1ZXN0U3RyZWFtID0gZnVuY3Rpb24oKSB7XG4gIHZhciBiYXRjaCA9IHRoaXM7XG4gIHZhciBidWxrID0gYmF0Y2guX2J1bGs7XG4gIHZhciBsb2dnZXIgPSBidWxrLl9sb2dnZXI7XG5cbiAgcmV0dXJuIGJ1bGsuX3JlcXVlc3Qoe1xuICAgIG1ldGhvZCA6ICdQT1NUJyxcbiAgICBwYXRoIDogXCIvam9iL1wiICsgYmF0Y2guam9iLmlkICsgXCIvYmF0Y2hcIixcbiAgICBoZWFkZXJzOiB7XG4gICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcInRleHQvY3N2XCJcbiAgICB9LFxuICAgIHJlc3BvbnNlVHlwZTogXCJhcHBsaWNhdGlvbi94bWxcIlxuICB9LCBmdW5jdGlvbihlcnIsIHJlcykge1xuICAgIGlmIChlcnIpIHtcbiAgICAgIGJhdGNoLmVtaXQoJ2Vycm9yJywgZXJyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nZ2VyLmRlYnVnKHJlcy5iYXRjaEluZm8pO1xuICAgICAgYmF0Y2guaWQgPSByZXMuYmF0Y2hJbmZvLmlkO1xuICAgICAgYmF0Y2guZW1pdCgncXVldWUnLCByZXMuYmF0Y2hJbmZvKTtcbiAgICB9XG4gIH0pLnN0cmVhbSgpO1xufTtcblxuLyoqXG4gKiBJbXBsZW1lbnRhdGlvbiBvZiBXcml0YWJsZVxuICpcbiAqIEBvdmVycmlkZVxuICogQHByaXZhdGVcbiAqL1xuQmF0Y2gucHJvdG90eXBlLl93cml0ZSA9IGZ1bmN0aW9uKHJlY29yZCwgZW5jLCBjYikge1xuICByZWNvcmQgPSBfLmNsb25lKHJlY29yZCk7XG4gIGlmICh0aGlzLmpvYi5vcGVyYXRpb24gPT09IFwiaW5zZXJ0XCIpIHtcbiAgICBkZWxldGUgcmVjb3JkLklkO1xuICB9IGVsc2UgaWYgKHRoaXMuam9iLm9wZXJhdGlvbiA9PT0gXCJkZWxldGVcIikge1xuICAgIHJlY29yZCA9IHsgSWQ6IHJlY29yZC5JZCB9O1xuICB9XG4gIGRlbGV0ZSByZWNvcmQudHlwZTtcbiAgZGVsZXRlIHJlY29yZC5hdHRyaWJ1dGVzO1xuICB0aGlzLl91cGxvYWRTdHJlYW0ud3JpdGUocmVjb3JkLCBlbmMsIGNiKTtcbn07XG5cbi8qKlxuICogUmV0dXJucyBkdXBsZXggc3RyZWFtIHdoaWNoIGFjY2VwdHMgQ1NWIGRhdGEgaW5wdXQgYW5kIGJhdGNoIHJlc3VsdCBvdXRwdXRcbiAqXG4gKiBAcmV0dXJucyB7c3RyZWFtLkR1cGxleH1cbiAqL1xuQmF0Y2gucHJvdG90eXBlLnN0cmVhbSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5fZGF0YVN0cmVhbTtcbn07XG5cbi8qKlxuICogRXhlY3V0ZSBiYXRjaCBvcGVyYXRpb25cbiAqXG4gKiBAbWV0aG9kIEJ1bGt+QmF0Y2gjZXhlY3V0ZVxuICogQHBhcmFtIHtBcnJheS48UmVjb3JkPnxzdHJlYW0uU3RyZWFtfFN0cmluZ30gW2lucHV0XSAtIElucHV0IHNvdXJjZSBmb3IgYmF0Y2ggb3BlcmF0aW9uLiBBY2NlcHRzIGFycmF5IG9mIHJlY29yZHMsIENTViBzdHJpbmcsIGFuZCBDU1YgZGF0YSBpbnB1dCBzdHJlYW0gaW4gaW5zZXJ0L3VwZGF0ZS91cHNlcnQvZGVsZXRlL2hhcmREZWxldGUgb3BlcmF0aW9uLCBTT1FMIHN0cmluZyBpbiBxdWVyeSBvcGVyYXRpb24uXG4gKiBAcGFyYW0ge0NhbGxiYWNrLjxBcnJheS48UmVjb3JkUmVzdWx0PnxBcnJheS48QmF0Y2hSZXN1bHRJbmZvPj59IFtjYWxsYmFja10gLSBDYWxsYmFjayBmdW5jdGlvblxuICogQHJldHVybnMge0J1bGt+QmF0Y2h9XG4gKi9cbkJhdGNoLnByb3RvdHlwZS5ydW4gPVxuQmF0Y2gucHJvdG90eXBlLmV4ZWMgPVxuQmF0Y2gucHJvdG90eXBlLmV4ZWN1dGUgPSBmdW5jdGlvbihpbnB1dCwgY2FsbGJhY2spIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gIGlmICh0eXBlb2YgaW5wdXQgPT09ICdmdW5jdGlvbicpIHsgLy8gaWYgaW5wdXQgYXJndW1lbnQgaXMgb21pdHRlZFxuICAgIGNhbGxiYWNrID0gaW5wdXQ7XG4gICAgaW5wdXQgPSBudWxsO1xuICB9XG5cbiAgLy8gaWYgYmF0Y2ggaXMgYWxyZWFkeSBleGVjdXRlZFxuICBpZiAodGhpcy5fcmVzdWx0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQmF0Y2ggYWxyZWFkeSBleGVjdXRlZC5cIik7XG4gIH1cblxuICB2YXIgcmRlZmVycmVkID0gUHJvbWlzZS5kZWZlcigpO1xuICB0aGlzLl9yZXN1bHQgPSByZGVmZXJyZWQucHJvbWlzZTtcbiAgdGhpcy5fcmVzdWx0LnRoZW4oZnVuY3Rpb24ocmVzKSB7XG4gICAgc2VsZi5fZGVmZXJyZWQucmVzb2x2ZShyZXMpO1xuICB9LCBmdW5jdGlvbihlcnIpIHtcbiAgICBzZWxmLl9kZWZlcnJlZC5yZWplY3QoZXJyKTtcbiAgfSk7XG4gIHRoaXMub25jZSgncmVzcG9uc2UnLCBmdW5jdGlvbihyZXMpIHtcbiAgICByZGVmZXJyZWQucmVzb2x2ZShyZXMpO1xuICB9KTtcbiAgdGhpcy5vbmNlKCdlcnJvcicsIGZ1bmN0aW9uKGVycikge1xuICAgIHJkZWZlcnJlZC5yZWplY3QoZXJyKTtcbiAgfSk7XG5cbiAgaWYgKF8uaXNPYmplY3QoaW5wdXQpICYmIF8uaXNGdW5jdGlvbihpbnB1dC5waXBlKSkgeyAvLyBpZiBpbnB1dCBoYXMgc3RyZWFtLlJlYWRhYmxlIGludGVyZmFjZVxuICAgIGlucHV0LnBpcGUodGhpcy5fZGF0YVN0cmVhbSk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGRhdGE7XG4gICAgaWYgKF8uaXNBcnJheShpbnB1dCkpIHtcbiAgICAgIF8uZm9yRWFjaChpbnB1dCwgZnVuY3Rpb24ocmVjb3JkKSB7XG4gICAgICAgIE9iamVjdC5rZXlzKHJlY29yZCkuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHJlY29yZFtrZXldID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIHJlY29yZFtrZXldID0gU3RyaW5nKHJlY29yZFtrZXldKVxuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgc2VsZi53cml0ZShyZWNvcmQpO1xuICAgICAgfSk7XG4gICAgICBzZWxmLmVuZCgpO1xuICAgIH0gZWxzZSBpZiAoXy5pc1N0cmluZyhpbnB1dCkpe1xuICAgICAgZGF0YSA9IGlucHV0O1xuICAgICAgdGhpcy5fZGF0YVN0cmVhbS53cml0ZShkYXRhLCAndXRmOCcpO1xuICAgICAgdGhpcy5fZGF0YVN0cmVhbS5lbmQoKTtcbiAgICB9XG4gIH1cblxuICAvLyByZXR1cm4gQmF0Y2ggaW5zdGFuY2UgZm9yIGNoYWluaW5nXG4gIHJldHVybiB0aGlzLnRoZW5DYWxsKGNhbGxiYWNrKTtcbn07XG5cbi8qKlxuICogUHJvbWlzZS9BKyBpbnRlcmZhY2VcbiAqIGh0dHA6Ly9wcm9taXNlcy1hcGx1cy5naXRodWIuaW8vcHJvbWlzZXMtc3BlYy9cbiAqXG4gKiBEZWxlZ2F0ZSB0byBkZWZlcnJlZCBwcm9taXNlLCByZXR1cm4gcHJvbWlzZSBpbnN0YW5jZSBmb3IgYmF0Y2ggcmVzdWx0XG4gKlxuICogQG1ldGhvZCBCdWxrfkJhdGNoI3RoZW5cbiAqL1xuQmF0Y2gucHJvdG90eXBlLnRoZW4gPSBmdW5jdGlvbihvblJlc29sdmVkLCBvblJlamVjdCwgb25Qcm9ncmVzcykge1xuICByZXR1cm4gdGhpcy5fZGVmZXJyZWQucHJvbWlzZS50aGVuKG9uUmVzb2x2ZWQsIG9uUmVqZWN0LCBvblByb2dyZXNzKTtcbn07XG5cbi8qKlxuICogUHJvbWlzZS9BKyBleHRlbnNpb25cbiAqIENhbGwgXCJ0aGVuXCIgdXNpbmcgZ2l2ZW4gbm9kZS1zdHlsZSBjYWxsYmFjayBmdW5jdGlvblxuICpcbiAqIEBtZXRob2QgQnVsa35CYXRjaCN0aGVuQ2FsbFxuICovXG5CYXRjaC5wcm90b3R5cGUudGhlbkNhbGwgPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICBpZiAoXy5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgIHRoaXMudGhlbihmdW5jdGlvbihyZXMpIHtcbiAgICAgIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24oKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIHJlcyk7XG4gICAgICB9KTtcbiAgICB9LCBmdW5jdGlvbihlcnIpIHtcbiAgICAgIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24oKSB7XG4gICAgICAgIGNhbGxiYWNrKGVycik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogQHR5cGVkZWYge09iamVjdH0gQnVsa35CYXRjaEluZm9cbiAqIEBwcm9wIHtTdHJpbmd9IGlkIC0gQmF0Y2ggSURcbiAqIEBwcm9wIHtTdHJpbmd9IGpvYklkIC0gSm9iIElEXG4gKiBAcHJvcCB7U3RyaW5nfSBzdGF0ZSAtIEJhdGNoIHN0YXRlXG4gKiBAcHJvcCB7U3RyaW5nfSBzdGF0ZU1lc3NhZ2UgLSBCYXRjaCBzdGF0ZSBtZXNzYWdlXG4gKi9cblxuLyoqXG4gKiBDaGVjayB0aGUgbGF0ZXN0IGJhdGNoIHN0YXR1cyBpbiBzZXJ2ZXJcbiAqXG4gKiBAbWV0aG9kIEJ1bGt+QmF0Y2gjY2hlY2tcbiAqIEBwYXJhbSB7Q2FsbGJhY2suPEJ1bGt+QmF0Y2hJbmZvPn0gW2NhbGxiYWNrXSAtIENhbGxiYWNrIGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7UHJvbWlzZS48QnVsa35CYXRjaEluZm8+fVxuICovXG5CYXRjaC5wcm90b3R5cGUuY2hlY2sgPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciBidWxrID0gdGhpcy5fYnVsaztcbiAgdmFyIGxvZ2dlciA9IGJ1bGsuX2xvZ2dlcjtcbiAgdmFyIGpvYklkID0gdGhpcy5qb2IuaWQ7XG4gIHZhciBiYXRjaElkID0gdGhpcy5pZDtcblxuICBpZiAoIWpvYklkIHx8ICFiYXRjaElkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQmF0Y2ggbm90IHN0YXJ0ZWQuXCIpO1xuICB9XG4gIHJldHVybiBidWxrLl9yZXF1ZXN0KHtcbiAgICBtZXRob2QgOiAnR0VUJyxcbiAgICBwYXRoIDogXCIvam9iL1wiICsgam9iSWQgKyBcIi9iYXRjaC9cIiArIGJhdGNoSWQsXG4gICAgcmVzcG9uc2VUeXBlOiBcImFwcGxpY2F0aW9uL3htbFwiXG4gIH0pLnRoZW4oZnVuY3Rpb24ocmVzKSB7XG4gICAgbG9nZ2VyLmRlYnVnKHJlcy5iYXRjaEluZm8pO1xuICAgIHJldHVybiByZXMuYmF0Y2hJbmZvO1xuICB9KS50aGVuQ2FsbChjYWxsYmFjayk7XG59O1xuXG5cbi8qKlxuICogUG9sbGluZyB0aGUgYmF0Y2ggcmVzdWx0IGFuZCByZXRyaWV2ZVxuICpcbiAqIEBtZXRob2QgQnVsa35CYXRjaCNwb2xsXG4gKiBAcGFyYW0ge051bWJlcn0gaW50ZXJ2YWwgLSBQb2xsaW5nIGludGVydmFsIGluIG1pbGxpc2Vjb25kc1xuICogQHBhcmFtIHtOdW1iZXJ9IHRpbWVvdXQgLSBQb2xsaW5nIHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzXG4gKi9cbkJhdGNoLnByb3RvdHlwZS5wb2xsID0gZnVuY3Rpb24oaW50ZXJ2YWwsIHRpbWVvdXQpIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgam9iSWQgPSB0aGlzLmpvYi5pZDtcbiAgdmFyIGJhdGNoSWQgPSB0aGlzLmlkO1xuXG4gIGlmICgham9iSWQgfHwgIWJhdGNoSWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJCYXRjaCBub3Qgc3RhcnRlZC5cIik7XG4gIH1cbiAgdmFyIHN0YXJ0VGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICB2YXIgcG9sbCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBub3cgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICBpZiAoc3RhcnRUaW1lICsgdGltZW91dCA8IG5vdykge1xuICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcihcIlBvbGxpbmcgdGltZSBvdXQuIEpvYiBJZCA9IFwiICsgam9iSWQgKyBcIiAsIGJhdGNoIElkID0gXCIgKyBiYXRjaElkKTtcbiAgICAgIGVyci5uYW1lID0gJ1BvbGxpbmdUaW1lb3V0JztcbiAgICAgIGVyci5qb2JJZCA9IGpvYklkO1xuICAgICAgZXJyLmJhdGNoSWQgPSBiYXRjaElkO1xuICAgICAgc2VsZi5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHNlbGYuY2hlY2soZnVuY3Rpb24oZXJyLCByZXMpIHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgc2VsZi5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAocmVzLnN0YXRlID09PSBcIkZhaWxlZFwiKSB7XG4gICAgICAgICAgaWYgKHBhcnNlSW50KHJlcy5udW1iZXJSZWNvcmRzUHJvY2Vzc2VkLCAxMCkgPiAwKSB7XG4gICAgICAgICAgICBzZWxmLnJldHJpZXZlKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGYuZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IocmVzLnN0YXRlTWVzc2FnZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChyZXMuc3RhdGUgPT09IFwiQ29tcGxldGVkXCIpIHtcbiAgICAgICAgICBzZWxmLnJldHJpZXZlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2VsZi5lbWl0KCdwcm9ncmVzcycsIHJlcyk7XG4gICAgICAgICAgc2V0VGltZW91dChwb2xsLCBpbnRlcnZhbCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbiAgc2V0VGltZW91dChwb2xsLCBpbnRlcnZhbCk7XG59O1xuXG4vKipcbiAqIEB0eXBlZGVmIHtPYmplY3R9IEJ1bGt+QmF0Y2hSZXN1bHRJbmZvXG4gKiBAcHJvcCB7U3RyaW5nfSBpZCAtIEJhdGNoIHJlc3VsdCBJRFxuICogQHByb3Age1N0cmluZ30gYmF0Y2hJZCAtIEJhdGNoIElEIHdoaWNoIGluY2x1ZGVzIHRoaXMgYmF0Y2ggcmVzdWx0LlxuICogQHByb3Age1N0cmluZ30gam9iSWQgLSBKb2IgSUQgd2hpY2ggaW5jbHVkZXMgdGhpcyBiYXRjaCByZXN1bHQuXG4gKi9cblxuLyoqXG4gKiBSZXRyaWV2ZSBiYXRjaCByZXN1bHRcbiAqXG4gKiBAbWV0aG9kIEJ1bGt+QmF0Y2gjcmV0cmlldmVcbiAqIEBwYXJhbSB7Q2FsbGJhY2suPEFycmF5LjxSZWNvcmRSZXN1bHQ+fEFycmF5LjxCdWxrfkJhdGNoUmVzdWx0SW5mbz4+fSBbY2FsbGJhY2tdIC0gQ2FsbGJhY2sgZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtQcm9taXNlLjxBcnJheS48UmVjb3JkUmVzdWx0PnxBcnJheS48QnVsa35CYXRjaFJlc3VsdEluZm8+Pn1cbiAqL1xuQmF0Y2gucHJvdG90eXBlLnJldHJpZXZlID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICB2YXIgYnVsayA9IHRoaXMuX2J1bGs7XG4gIHZhciBqb2JJZCA9IHRoaXMuam9iLmlkO1xuICB2YXIgam9iID0gdGhpcy5qb2I7XG4gIHZhciBiYXRjaElkID0gdGhpcy5pZDtcblxuICBpZiAoIWpvYklkIHx8ICFiYXRjaElkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQmF0Y2ggbm90IHN0YXJ0ZWQuXCIpO1xuICB9XG5cbiAgcmV0dXJuIGpvYi5pbmZvKCkudGhlbihmdW5jdGlvbihqb2JJbmZvKSB7XG4gICAgcmV0dXJuIGJ1bGsuX3JlcXVlc3Qoe1xuICAgICAgbWV0aG9kIDogJ0dFVCcsXG4gICAgICBwYXRoIDogXCIvam9iL1wiICsgam9iSWQgKyBcIi9iYXRjaC9cIiArIGJhdGNoSWQgKyBcIi9yZXN1bHRcIlxuICAgIH0pO1xuICB9KS50aGVuKGZ1bmN0aW9uKHJlcykge1xuICAgIHZhciByZXN1bHRzO1xuICAgIGlmIChqb2Iub3BlcmF0aW9uID09PSAncXVlcnknKSB7XG4gICAgICB2YXIgY29ubiA9IGJ1bGsuX2Nvbm47XG4gICAgICB2YXIgcmVzdWx0SWRzID0gcmVzWydyZXN1bHQtbGlzdCddLnJlc3VsdDtcbiAgICAgIHJlc3VsdHMgPSByZXNbJ3Jlc3VsdC1saXN0J10ucmVzdWx0O1xuICAgICAgcmVzdWx0cyA9IF8ubWFwKF8uaXNBcnJheShyZXN1bHRzKSA/IHJlc3VsdHMgOiBbIHJlc3VsdHMgXSwgZnVuY3Rpb24oaWQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpZDogaWQsXG4gICAgICAgICAgYmF0Y2hJZDogYmF0Y2hJZCxcbiAgICAgICAgICBqb2JJZDogam9iSWRcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRzID0gXy5tYXAocmVzLCBmdW5jdGlvbihyZXQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpZDogcmV0LklkIHx8IG51bGwsXG4gICAgICAgICAgc3VjY2VzczogcmV0LlN1Y2Nlc3MgPT09IFwidHJ1ZVwiLFxuICAgICAgICAgIGVycm9yczogcmV0LkVycm9yID8gWyByZXQuRXJyb3IgXSA6IFtdXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9XG4gICAgc2VsZi5lbWl0KCdyZXNwb25zZScsIHJlc3VsdHMpO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9KS5mYWlsKGZ1bmN0aW9uKGVycikge1xuICAgIHNlbGYuZW1pdCgnZXJyb3InLCBlcnIpO1xuICAgIHRocm93IGVycjtcbiAgfSkudGhlbkNhbGwoY2FsbGJhY2spO1xufTtcblxuLyoqXG4gKiBGZXRjaCBxdWVyeSByZXN1bHQgYXMgYSByZWNvcmQgc3RyZWFtXG4gKiBAcGFyYW0ge1N0cmluZ30gcmVzdWx0SWQgLSBSZXN1bHQgaWRcbiAqIEByZXR1cm5zIHtSZWNvcmRTdHJlYW19IC0gUmVjb3JkIHN0cmVhbSwgY29udmVydGlibGUgdG8gQ1NWIGRhdGEgc3RyZWFtXG4gKi9cbkJhdGNoLnByb3RvdHlwZS5yZXN1bHQgPSBmdW5jdGlvbihyZXN1bHRJZCkge1xuICB2YXIgam9iSWQgPSB0aGlzLmpvYi5pZDtcbiAgdmFyIGJhdGNoSWQgPSB0aGlzLmlkO1xuICBpZiAoIWpvYklkIHx8ICFiYXRjaElkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiQmF0Y2ggbm90IHN0YXJ0ZWQuXCIpO1xuICB9XG4gIHZhciByZXN1bHRTdHJlYW0gPSBuZXcgUmVjb3JkU3RyZWFtLlBhcnNhYmxlKCk7XG4gIHZhciByZXN1bHREYXRhU3RyZWFtID0gcmVzdWx0U3RyZWFtLnN0cmVhbSgnY3N2Jyk7XG4gIHZhciByZXFTdHJlYW0gPSB0aGlzLl9idWxrLl9yZXF1ZXN0KHtcbiAgICBtZXRob2QgOiAnR0VUJyxcbiAgICBwYXRoIDogXCIvam9iL1wiICsgam9iSWQgKyBcIi9iYXRjaC9cIiArIGJhdGNoSWQgKyBcIi9yZXN1bHQvXCIgKyByZXN1bHRJZCxcbiAgICByZXNwb25zZVR5cGU6IFwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtXCJcbiAgfSkuc3RyZWFtKCkucGlwZShyZXN1bHREYXRhU3RyZWFtKTtcbiAgcmV0dXJuIHJlc3VsdFN0cmVhbTtcbn07XG5cbi8qLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG52YXIgQnVsa0FwaSA9IGZ1bmN0aW9uKCkge1xuICBCdWxrQXBpLnN1cGVyXy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufTtcblxuaW5oZXJpdHMoQnVsa0FwaSwgSHR0cEFwaSk7XG5cbkJ1bGtBcGkucHJvdG90eXBlLmJlZm9yZVNlbmQgPSBmdW5jdGlvbihyZXF1ZXN0KSB7XG4gIHJlcXVlc3QuaGVhZGVycyA9IHJlcXVlc3QuaGVhZGVycyB8fCB7fTtcbiAgcmVxdWVzdC5oZWFkZXJzW1wiWC1TRkRDLVNFU1NJT05cIl0gPSB0aGlzLl9jb25uLmFjY2Vzc1Rva2VuO1xufTtcblxuQnVsa0FwaS5wcm90b3R5cGUuaXNTZXNzaW9uRXhwaXJlZCA9IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gIHJldHVybiByZXNwb25zZS5zdGF0dXNDb2RlID09PSA0MDAgJiZcbiAgICAvPGV4Y2VwdGlvbkNvZGU+SW52YWxpZFNlc3Npb25JZDxcXC9leGNlcHRpb25Db2RlPi8udGVzdChyZXNwb25zZS5ib2R5KTtcbn07XG5cbkJ1bGtBcGkucHJvdG90eXBlLmhhc0Vycm9ySW5SZXNwb25zZUJvZHkgPSBmdW5jdGlvbihib2R5KSB7XG4gIHJldHVybiAhIWJvZHkuZXJyb3I7XG59O1xuXG5CdWxrQXBpLnByb3RvdHlwZS5wYXJzZUVycm9yID0gZnVuY3Rpb24oYm9keSkge1xuICByZXR1cm4ge1xuICAgIGVycm9yQ29kZTogYm9keS5lcnJvci5leGNlcHRpb25Db2RlLFxuICAgIG1lc3NhZ2U6IGJvZHkuZXJyb3IuZXhjZXB0aW9uTWVzc2FnZVxuICB9O1xufTtcblxuLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbi8qKlxuICogQ2xhc3MgZm9yIEJ1bGsgQVBJXG4gKlxuICogQGNsYXNzXG4gKiBAcGFyYW0ge0Nvbm5lY3Rpb259IGNvbm4gLSBDb25uZWN0aW9uIG9iamVjdFxuICovXG52YXIgQnVsayA9IGZ1bmN0aW9uKGNvbm4pIHtcbiAgdGhpcy5fY29ubiA9IGNvbm47XG4gIHRoaXMuX2xvZ2dlciA9IGNvbm4uX2xvZ2dlcjtcbn07XG5cbi8qKlxuICogUG9sbGluZyBpbnRlcnZhbCBpbiBtaWxsaXNlY29uZHNcbiAqIEB0eXBlIHtOdW1iZXJ9XG4gKi9cbkJ1bGsucHJvdG90eXBlLnBvbGxJbnRlcnZhbCA9IDEwMDA7XG5cbi8qKlxuICogUG9sbGluZyB0aW1lb3V0IGluIG1pbGxpc2Vjb25kc1xuICogQHR5cGUge051bWJlcn1cbiAqL1xuQnVsay5wcm90b3R5cGUucG9sbFRpbWVvdXQgPSAxMDAwMDtcblxuLyoqIEBwcml2YXRlICoqL1xuQnVsay5wcm90b3R5cGUuX3JlcXVlc3QgPSBmdW5jdGlvbihyZXF1ZXN0LCBjYWxsYmFjaykge1xuICB2YXIgY29ubiA9IHRoaXMuX2Nvbm47XG4gIHJlcXVlc3QgPSBfLmNsb25lKHJlcXVlc3QpO1xuICB2YXIgYmFzZVVybCA9IFsgY29ubi5pbnN0YW5jZVVybCwgXCJzZXJ2aWNlcy9hc3luY1wiLCBjb25uLnZlcnNpb24gXS5qb2luKCcvJyk7XG4gIHJlcXVlc3QudXJsID0gYmFzZVVybCArIHJlcXVlc3QucGF0aDtcbiAgdmFyIG9wdGlvbnMgPSB7IHJlc3BvbnNlVHlwZTogcmVxdWVzdC5yZXNwb25zZVR5cGUgfTtcbiAgZGVsZXRlIHJlcXVlc3QucGF0aDtcbiAgZGVsZXRlIHJlcXVlc3QucmVzcG9uc2VUeXBlO1xuICByZXR1cm4gbmV3IEJ1bGtBcGkodGhpcy5fY29ubiwgb3B0aW9ucykucmVxdWVzdChyZXF1ZXN0KS50aGVuQ2FsbChjYWxsYmFjayk7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhbmQgc3RhcnQgYnVsa2xvYWQgam9iIGFuZCBiYXRjaFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlIC0gU09iamVjdCB0eXBlXG4gKiBAcGFyYW0ge1N0cmluZ30gb3BlcmF0aW9uIC0gQnVsayBsb2FkIG9wZXJhdGlvbiAoJ2luc2VydCcsICd1cGRhdGUnLCAndXBzZXJ0JywgJ2RlbGV0ZScsIG9yICdoYXJkRGVsZXRlJylcbiAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0aW9uc10gLSBPcHRpb25zIGZvciBidWxrIGxvYWRpbmcgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuZXh0SWRGaWVsZF0gLSBFeHRlcm5hbCBJRCBmaWVsZCBuYW1lICh1c2VkIHdoZW4gdXBzZXJ0IG9wZXJhdGlvbikuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuY29uY3VycmVuY3lNb2RlXSAtICdTZXJpYWwnIG9yICdQYXJhbGxlbCcuIERlZmF1bHRzIHRvIFBhcmFsbGVsLlxuICogQHBhcmFtIHtBcnJheS48UmVjb3JkPnxzdHJlYW0uU3RyZWFtfFN0cmluZ30gW2lucHV0XSAtIElucHV0IHNvdXJjZSBmb3IgYnVsa2xvYWQuIEFjY2VwdHMgYXJyYXkgb2YgcmVjb3JkcywgQ1NWIHN0cmluZywgYW5kIENTViBkYXRhIGlucHV0IHN0cmVhbSBpbiBpbnNlcnQvdXBkYXRlL3Vwc2VydC9kZWxldGUvaGFyZERlbGV0ZSBvcGVyYXRpb24sIFNPUUwgc3RyaW5nIGluIHF1ZXJ5IG9wZXJhdGlvbi5cbiAqIEBwYXJhbSB7Q2FsbGJhY2suPEFycmF5LjxSZWNvcmRSZXN1bHQ+fEFycmF5LjxCdWxrfkJhdGNoUmVzdWx0SW5mbz4+fSBbY2FsbGJhY2tdIC0gQ2FsbGJhY2sgZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtCdWxrfkJhdGNofVxuICovXG5CdWxrLnByb3RvdHlwZS5sb2FkID0gZnVuY3Rpb24odHlwZSwgb3BlcmF0aW9uLCBvcHRpb25zLCBpbnB1dCwgY2FsbGJhY2spIHtcbiAgdmFyIHNlbGYgPSB0aGlzO1xuICBpZiAoIXR5cGUgfHwgIW9wZXJhdGlvbikge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkluc3VmZmljaWVudCBhcmd1bWVudHMuIEF0IGxlYXN0LCAndHlwZScgYW5kICdvcGVyYXRpb24nIGFyZSByZXF1aXJlZC5cIik7XG4gIH1cbiAgaWYgKCFfLmlzT2JqZWN0KG9wdGlvbnMpIHx8IG9wdGlvbnMuY29uc3RydWN0b3IgIT09IE9iamVjdCkgeyAvLyB3aGVuIG9wdGlvbnMgaXMgbm90IHBsYWluIGhhc2ggb2JqZWN0LCBpdCBpcyBvbWl0dGVkXG4gICAgY2FsbGJhY2sgPSBpbnB1dDtcbiAgICBpbnB1dCA9IG9wdGlvbnM7XG4gICAgb3B0aW9ucyA9IG51bGw7XG4gIH1cbiAgdmFyIGpvYiA9IHRoaXMuY3JlYXRlSm9iKHR5cGUsIG9wZXJhdGlvbiwgb3B0aW9ucyk7XG4gIGpvYi5vbmNlKCdlcnJvcicsIGZ1bmN0aW9uIChlcnJvcikge1xuICAgIGlmIChiYXRjaCkge1xuICAgICAgYmF0Y2guZW1pdCgnZXJyb3InLCBlcnJvcik7IC8vIHBhc3Mgam9iIGVycm9yIHRvIGJhdGNoXG4gICAgfVxuICB9KTtcbiAgdmFyIGJhdGNoID0gam9iLmNyZWF0ZUJhdGNoKCk7XG4gIHZhciBjbGVhbnVwID0gZnVuY3Rpb24oKSB7XG4gICAgYmF0Y2ggPSBudWxsO1xuICAgIGpvYi5jbG9zZSgpO1xuICB9O1xuICB2YXIgY2xlYW51cE9uRXJyb3IgPSBmdW5jdGlvbihlcnIpIHtcbiAgICBpZiAoZXJyLm5hbWUgIT09ICdQb2xsaW5nVGltZW91dCcpIHtcbiAgICAgIGNsZWFudXAoKTtcbiAgICB9XG4gIH07XG4gIGJhdGNoLm9uKCdyZXNwb25zZScsIGNsZWFudXApO1xuICBiYXRjaC5vbignZXJyb3InLCBjbGVhbnVwT25FcnJvcik7XG4gIGJhdGNoLm9uKCdxdWV1ZScsIGZ1bmN0aW9uKCkgeyBiYXRjaC5wb2xsKHNlbGYucG9sbEludGVydmFsLCBzZWxmLnBvbGxUaW1lb3V0KTsgfSk7XG4gIHJldHVybiBiYXRjaC5leGVjdXRlKGlucHV0LCBjYWxsYmFjayk7XG59O1xuXG4vKipcbiAqIEV4ZWN1dGUgYnVsayBxdWVyeSBhbmQgZ2V0IHJlY29yZCBzdHJlYW1cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc29xbCAtIFNPUUwgdG8gZXhlY3V0ZSBpbiBidWxrIGpvYlxuICogQHJldHVybnMge1JlY29yZFN0cmVhbS5QYXJzYWJsZX0gLSBSZWNvcmQgc3RyZWFtLCBjb252ZXJ0aWJsZSB0byBDU1YgZGF0YSBzdHJlYW1cbiAqL1xuQnVsay5wcm90b3R5cGUucXVlcnkgPSBmdW5jdGlvbihzb3FsKSB7XG4gIHZhciBtID0gc29xbC5yZXBsYWNlKC9cXChbXFxzXFxTXStcXCkvZywgJycpLm1hdGNoKC9GUk9NXFxzKyhcXHcrKS9pKTtcbiAgaWYgKCFtKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gc29iamVjdCB0eXBlIGZvdW5kIGluIHF1ZXJ5LCBtYXliZSBjYXVzZWQgYnkgaW52YWxpZCBTT1FMLlwiKTtcbiAgfVxuICB2YXIgdHlwZSA9IG1bMV07XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIHJlY29yZFN0cmVhbSA9IG5ldyBSZWNvcmRTdHJlYW0uUGFyc2FibGUoKTtcbiAgdmFyIGRhdGFTdHJlYW0gPSByZWNvcmRTdHJlYW0uc3RyZWFtKCdjc3YnKTtcbiAgdGhpcy5sb2FkKHR5cGUsIFwicXVlcnlcIiwgc29xbCkudGhlbihmdW5jdGlvbihyZXN1bHRzKSB7XG4gICAgdmFyIHN0cmVhbXMgPSByZXN1bHRzLm1hcChmdW5jdGlvbihyZXN1bHQpIHtcbiAgICAgIHJldHVybiBzZWxmXG4gICAgICAgIC5qb2IocmVzdWx0LmpvYklkKVxuICAgICAgICAuYmF0Y2gocmVzdWx0LmJhdGNoSWQpXG4gICAgICAgIC5yZXN1bHQocmVzdWx0LmlkKVxuICAgICAgICAuc3RyZWFtKCk7XG4gICAgfSk7XG5cbiAgICBqb2luU3RyZWFtcyhzdHJlYW1zKS5waXBlKGRhdGFTdHJlYW0pO1xuICB9KS5mYWlsKGZ1bmN0aW9uKGVycikge1xuICAgIHJlY29yZFN0cmVhbS5lbWl0KCdlcnJvcicsIGVycik7XG4gIH0pO1xuICByZXR1cm4gcmVjb3JkU3RyZWFtO1xufTtcblxuXG4vKipcbiAqIENyZWF0ZSBhIG5ldyBqb2IgaW5zdGFuY2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdHlwZSAtIFNPYmplY3QgdHlwZVxuICogQHBhcmFtIHtTdHJpbmd9IG9wZXJhdGlvbiAtIEJ1bGsgbG9hZCBvcGVyYXRpb24gKCdpbnNlcnQnLCAndXBkYXRlJywgJ3Vwc2VydCcsICdkZWxldGUnLCAnaGFyZERlbGV0ZScsIG9yICdxdWVyeScpXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0gT3B0aW9ucyBmb3IgYnVsayBsb2FkaW5nIG9wZXJhdGlvblxuICogQHJldHVybnMge0J1bGt+Sm9ifVxuICovXG5CdWxrLnByb3RvdHlwZS5jcmVhdGVKb2IgPSBmdW5jdGlvbih0eXBlLCBvcGVyYXRpb24sIG9wdGlvbnMpIHtcbiAgcmV0dXJuIG5ldyBKb2IodGhpcywgdHlwZSwgb3BlcmF0aW9uLCBvcHRpb25zKTtcbn07XG5cbi8qKlxuICogR2V0IGEgam9iIGluc3RhbmNlIHNwZWNpZmllZCBieSBnaXZlbiBqb2IgSURcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gam9iSWQgLSBKb2IgSURcbiAqIEByZXR1cm5zIHtCdWxrfkpvYn1cbiAqL1xuQnVsay5wcm90b3R5cGUuam9iID0gZnVuY3Rpb24oam9iSWQpIHtcbiAgcmV0dXJuIG5ldyBKb2IodGhpcywgbnVsbCwgbnVsbCwgbnVsbCwgam9iSWQpO1xufTtcblxuXG4vKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tKi9cbi8qXG4gKiBSZWdpc3RlciBob29rIGluIGNvbm5lY3Rpb24gaW5zdGFudGlhdGlvbiBmb3IgZHluYW1pY2FsbHkgYWRkaW5nIHRoaXMgQVBJIG1vZHVsZSBmZWF0dXJlc1xuICovXG5qc2ZvcmNlLm9uKCdjb25uZWN0aW9uOm5ldycsIGZ1bmN0aW9uKGNvbm4pIHtcbiAgY29ubi5idWxrID0gbmV3IEJ1bGsoY29ubik7XG59KTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IEJ1bGs7XG4iLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIl19