@ruc-lib/screen-recorder 2.9.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,333 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { BehaviorSubject, Subject, timer } from 'rxjs';
3
- import { takeWhile, tap } from 'rxjs/operators';
4
- import { RecordingState } from '../models/screen-recorder.models';
5
- import { ScreenRecorderConstants } from '../screen-recorder/screen-recorder-constant';
6
- import * as i0 from "@angular/core";
7
- import * as i1 from "../screen-recorder/screen-recorder-constant";
8
- export class ScreenRecorderService {
9
- constructor(screenRecordingConstant) {
10
- this.screenRecordingConstant = screenRecordingConstant;
11
- this.stream = null;
12
- this.mediaRecorder = null;
13
- this.recordedBlobs = [];
14
- this.currentRecordedTime = 0;
15
- this.recordingStateSubject = new BehaviorSubject(RecordingState.Idle);
16
- this.recordingState$ = this.recordingStateSubject.asObservable();
17
- this.recordedTimeSubject = new BehaviorSubject(0);
18
- this.recordedTime$ = this.recordedTimeSubject.asObservable();
19
- this.recordedUrlSubject = new BehaviorSubject(null);
20
- this.recordedUrl$ = this.recordedUrlSubject.asObservable();
21
- this.recordingTimestampSubject = new BehaviorSubject('');
22
- this.recordingTimestamp$ = this.recordingTimestampSubject.asObservable();
23
- this.errorSubject = new Subject();
24
- this.error$ = this.errorSubject.asObservable();
25
- }
26
- /**
27
- * Starts the screen recording with optional audio
28
- *
29
- * @param options - Configuration options for recording
30
- * @param options.audio - Whether to include audio in the recording
31
- *
32
- * @throws Error if recording is already in progress or if media access is denied
33
- * @returns Promise<void>
34
- */
35
- async startRecording(options) {
36
- if (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused) {
37
- this.handleError(this.screenRecordingConstant.RECORDING_IN_PROGRESS_ERROR);
38
- return;
39
- }
40
- this.cleanupPreviousRecording();
41
- try {
42
- // The browser's native picker handles "specific area" selection (window, tab, screen).
43
- const displayStream = await navigator.mediaDevices.getDisplayMedia({
44
- video: true
45
- });
46
- // If audio is enabled, get the audio stream
47
- let audioStream = null;
48
- if (options.audio) {
49
- audioStream = await navigator.mediaDevices.getUserMedia({
50
- audio: {
51
- echoCancellation: true,
52
- noiseSuppression: true,
53
- sampleRate: 44100
54
- }
55
- });
56
- }
57
- // Combine the streams if audio is enabled
58
- if (audioStream) {
59
- this.stream = new MediaStream([...displayStream.getTracks(), ...audioStream.getTracks()]);
60
- }
61
- else {
62
- this.stream = displayStream;
63
- }
64
- // Listen for when the user stops sharing via browser UI
65
- this.stream.getVideoTracks()[0].onended = () => {
66
- if (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused) {
67
- this.stopRecordingInternal();
68
- }
69
- };
70
- // Handle errors
71
- if (!this.stream) {
72
- this.handleError(this.screenRecordingConstant.FAILED_TO_GET_DISPLAY_MEDIA_STREAM_ERROR);
73
- return;
74
- }
75
- // Set recording timestamp
76
- const now = new Date();
77
- const timestamp = now.toLocaleString('en-IN', {
78
- year: 'numeric',
79
- month: '2-digit',
80
- day: '2-digit',
81
- hour: '2-digit',
82
- minute: '2-digit',
83
- hour12: true
84
- });
85
- this.recordingTimestampSubject.next(timestamp);
86
- this.recordedBlobs = [];
87
- const mimeType = this.getSupportedMimeType();
88
- if (!mimeType) {
89
- this.handleError(this.screenRecordingConstant.NO_SUPPORT_MIME);
90
- this.stream?.getTracks().forEach(track => track.stop());
91
- this.stream = null;
92
- return;
93
- }
94
- // Create a canvas for timestamp overlay
95
- const canvas = document.createElement('canvas');
96
- const videoTrack = this.stream?.getVideoTracks()[0];
97
- if (videoTrack) {
98
- const video = document.createElement('video');
99
- video.srcObject = this.stream;
100
- // Wait for video to load metadata
101
- video.onloadedmetadata = () => {
102
- canvas.width = video.videoWidth;
103
- canvas.height = video.videoHeight;
104
- const ctx = canvas.getContext('2d');
105
- if (ctx) {
106
- // Draw video frame
107
- ctx.drawImage(video, 0, 0);
108
- // Draw timestamp
109
- ctx.font = '16px Arial';
110
- ctx.fillStyle = 'white';
111
- ctx.textAlign = 'right';
112
- ctx.textBaseline = 'top';
113
- ctx.fillText(`Recorded on: ${this.recordingTimestampSubject.value}`, canvas.width - 10, 10);
114
- }
115
- };
116
- }
117
- // Create a new stream with the canvas
118
- const canvasStream = canvas.captureStream();
119
- const combinedStream = new MediaStream([...this.stream?.getTracks() ?? [], canvasStream.getVideoTracks()[0]]);
120
- this.mediaRecorder = new MediaRecorder(combinedStream, { mimeType });
121
- this.mediaRecorder.ondataavailable = (event) => {
122
- if (event.data && event.data.size > 0) {
123
- this.recordedBlobs.push(event.data);
124
- }
125
- };
126
- this.mediaRecorder.onstop = () => {
127
- const superBuffer = new Blob(this.recordedBlobs, { type: mimeType });
128
- const url = window.URL.createObjectURL(superBuffer);
129
- this.recordedUrlSubject.next(url);
130
- this.recordingStateSubject.next(RecordingState.Stopped);
131
- this.stopTimer();
132
- };
133
- this.mediaRecorder.onerror = (event) => {
134
- const errorEvent = event; // More specific type if available
135
- let message = this.screenRecordingConstant.MEDIA_ERROR;
136
- if (errorEvent.error && errorEvent.error.name) {
137
- message += `: ${errorEvent.error.name}`;
138
- if (errorEvent.error.message)
139
- message += ` - ${errorEvent.error.message}`;
140
- }
141
- this.handleError(message);
142
- this.recordingStateSubject.next(RecordingState.Idle);
143
- this.stopTimer();
144
- };
145
- this.mediaRecorder.start(); // Start recording
146
- this.recordingStateSubject.next(RecordingState.Recording);
147
- this.startTimer();
148
- }
149
- catch (err) {
150
- this.handleError(`Error starting screen recording: ${err.name} - ${err.message}`);
151
- this.recordingStateSubject.next(RecordingState.Idle);
152
- }
153
- }
154
- /**
155
- * Gets the first supported MIME type for MediaRecorder
156
- *
157
- * @returns string|null - The supported MIME type or null if none found
158
- */
159
- getSupportedMimeType() {
160
- const mimeTypes = [
161
- 'video/webm;codecs=vp9,opus',
162
- 'video/webm;codecs=vp8,opus',
163
- 'video/webm;codecs=h264,opus',
164
- 'video/mp4;codecs=h264,aac',
165
- 'video/webm',
166
- ];
167
- for (const mimeType of mimeTypes) {
168
- if (MediaRecorder.isTypeSupported(mimeType)) {
169
- return mimeType;
170
- }
171
- }
172
- return null;
173
- }
174
- /**
175
- * Internal method to stop the recording process
176
- *
177
- * @private
178
- * @returns void
179
- */
180
- stopRecordingInternal() {
181
- if (this.mediaRecorder && (this.recordingStateSubject.value === RecordingState.Recording || this.recordingStateSubject.value === RecordingState.Paused)) {
182
- this.mediaRecorder.stop();
183
- }
184
- this.stream?.getTracks().forEach(track => track.stop());
185
- this.stream = null;
186
- // State will be updated by onstop handler
187
- }
188
- /**
189
- *
190
- * @returns Promise<void>
191
- * @throws Error if recording is not in progress
192
- */
193
- stopRecording() {
194
- this.stopRecordingInternal();
195
- }
196
- /**
197
- * Pauses the current recording
198
- *
199
- * @returns Promise<void>
200
- * @throws Error if recording is not in progress
201
- */
202
- pauseRecording() {
203
- if (this.mediaRecorder && this.recordingStateSubject.value === RecordingState.Recording) {
204
- this.mediaRecorder.pause();
205
- this.recordingStateSubject.next(RecordingState.Paused);
206
- this.stopTimer(); // Pauses the timer display
207
- }
208
- }
209
- /**
210
- * Resumes a paused recording
211
- *
212
- * @returns Promise<void>
213
- * @throws Error if recording is not paused
214
- */
215
- resumeRecording() {
216
- if (this.mediaRecorder && this.recordingStateSubject.value === RecordingState.Paused) {
217
- this.mediaRecorder.resume();
218
- this.recordingStateSubject.next(RecordingState.Recording);
219
- this.startTimer(this.currentRecordedTime); // Resumes timer display
220
- }
221
- }
222
- /**
223
- *
224
- * @param fileName
225
- */
226
- downloadRecording(fileName = 'recording.webm') {
227
- const url = this.recordedUrlSubject.value;
228
- const timestamp = this.recordingTimestampSubject.value;
229
- if (url && timestamp) {
230
- // Format the timestamp for filename (remove spaces and special characters)
231
- const formattedTimestamp = timestamp.replace(/[^a-zA-Z0-9]/g, '_');
232
- // Create filename with timestamp
233
- const fileExtension = fileName.split('.').pop() || 'webm';
234
- const newFileName = `screen_recording_${formattedTimestamp}.${fileExtension}`;
235
- const a = document.createElement('a');
236
- a.style.display = 'none';
237
- a.href = url;
238
- a.download = newFileName;
239
- document.body.appendChild(a);
240
- a.click();
241
- document.body.removeChild(a);
242
- // No need to revoke URL here if user might want to play it again.
243
- // Revoke on cleanup or new recording.
244
- }
245
- else {
246
- this.handleError(this.screenRecordingConstant.NO_RECORDING_DOWNLOAD);
247
- }
248
- }
249
- /**
250
- * Starts the recording timer
251
- *
252
- * @param startTime - Optional start time for the timer
253
- * @private
254
- * @returns void
255
- */
256
- startTimer(startTime = 0) {
257
- this.stopTimer(); // Ensure no multiple timers
258
- this.currentRecordedTime = startTime;
259
- this.recordedTimeSubject.next(this.currentRecordedTime);
260
- this.timerSubscription = timer(0, 1000)
261
- .pipe(tap(() => {
262
- if (this.recordingStateSubject.value === RecordingState.Recording) {
263
- this.currentRecordedTime++;
264
- this.recordedTimeSubject.next(this.currentRecordedTime);
265
- }
266
- }), takeWhile(() => this.recordingStateSubject.value === RecordingState.Recording))
267
- .subscribe();
268
- }
269
- /**
270
- * Stops the recording timer
271
- *
272
- * @private
273
- * @returns void
274
- */
275
- stopTimer() {
276
- if (this.timerSubscription) {
277
- this.timerSubscription.unsubscribe();
278
- this.timerSubscription = null;
279
- }
280
- }
281
- /**
282
- * Cleans up resources from previous recording
283
- *
284
- * @private
285
- * @returns void
286
- */
287
- cleanupPreviousRecording() {
288
- if (this.recordedUrlSubject.value) {
289
- window.URL.revokeObjectURL(this.recordedUrlSubject.value);
290
- this.recordedUrlSubject.next(null);
291
- }
292
- this.recordedBlobs = [];
293
- this.currentRecordedTime = 0;
294
- this.recordedTimeSubject.next(0);
295
- if (this.stream) {
296
- this.stream.getTracks().forEach(track => track.stop());
297
- this.stream = null;
298
- }
299
- if (this.mediaRecorder && this.mediaRecorder.state !== this.screenRecordingConstant.INACTIVE) {
300
- this.mediaRecorder.stop();
301
- }
302
- this.mediaRecorder = null;
303
- }
304
- /**
305
- * Resets the recording state to idle
306
- *
307
- * @returns void
308
- */
309
- resetToIdle() {
310
- this.cleanupPreviousRecording();
311
- this.recordingStateSubject.next(RecordingState.Idle);
312
- this.errorSubject.next(''); // Clear any previous errors
313
- }
314
- /**
315
- * Handles and broadcasts recording errors
316
- *
317
- * @private
318
- * @param error - The error message to handle
319
- * @returns void
320
- */
321
- handleError(error) {
322
- this.errorSubject.next(error);
323
- }
324
- }
325
- ScreenRecorderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ScreenRecorderService, deps: [{ token: i1.ScreenRecorderConstants }], target: i0.ɵɵFactoryTarget.Injectable });
326
- ScreenRecorderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ScreenRecorderService, providedIn: 'root' });
327
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: ScreenRecorderService, decorators: [{
328
- type: Injectable,
329
- args: [{
330
- providedIn: 'root', // Or provide in your module if preferred
331
- }]
332
- }], ctorParameters: function () { return [{ type: i1.ScreenRecorderConstants }]; } });
333
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyZWVuLXJlY29yZGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL3J1Y2xpYi9zY3JlZW4tcmVjb3JkZXIvc3JjL2xpYi9zZXJ2aWNlcy9zY3JlZW4tcmVjb3JkZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQWMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNuRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQzs7O0FBSXRGLE1BQU0sT0FBTyxxQkFBcUI7SUFzQmhDLFlBQW1CLHVCQUFnRDtRQUFoRCw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQXlCO1FBckIzRCxXQUFNLEdBQXVCLElBQUksQ0FBQztRQUNsQyxrQkFBYSxHQUF5QixJQUFJLENBQUM7UUFDM0Msa0JBQWEsR0FBVyxFQUFFLENBQUM7UUFFM0Isd0JBQW1CLEdBQVcsQ0FBQyxDQUFDO1FBRXZCLDBCQUFxQixHQUFHLElBQUksZUFBZSxDQUFpQixjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekYsb0JBQWUsR0FBK0IsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBRWhGLHdCQUFtQixHQUFHLElBQUksZUFBZSxDQUFTLENBQUMsQ0FBQyxDQUFDO1FBQzdELGtCQUFhLEdBQXVCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUVwRSx1QkFBa0IsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsSUFBSSxDQUFDLENBQUM7UUFDdEUsaUJB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QXVCLENBQUMsUUFBUSxFQUFFO1lBQzVGLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDM0I7UUFDRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztJQUM1QixDQUFDO0lBR0Q7Ozs7S0FJQztJQUNELFdBQVc7UUFDVCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLDRCQUE0QjtJQUMxRCxDQUFDO0lBR0Q7Ozs7OztLQU1DO0lBQ08sV0FBVyxDQUFDLEtBQWE7UUFDL0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsQ0FBQzs7bUhBcFdVLHFCQUFxQjt1SEFBckIscUJBQXFCLGNBRnBCLE1BQU07NEZBRVAscUJBQXFCO2tCQUhqQyxVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNLEVBQUUseUNBQXlDO2lCQUM5RCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJqZWN0LCB0aW1lciB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyB0YWtlV2hpbGUsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgUmVjb3JkaW5nU3RhdGUgfSBmcm9tICcuLi9tb2RlbHMvc2NyZWVuLXJlY29yZGVyLm1vZGVscyc7XHJcbmltcG9ydCB7IFNjcmVlblJlY29yZGVyQ29uc3RhbnRzIH0gZnJvbSAnLi4vc2NyZWVuLXJlY29yZGVyL3NjcmVlbi1yZWNvcmRlci1jb25zdGFudCc7XHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCcsIC8vIE9yIHByb3ZpZGUgaW4geW91ciBtb2R1bGUgaWYgcHJlZmVycmVkXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBTY3JlZW5SZWNvcmRlclNlcnZpY2Uge1xyXG4gIHByaXZhdGUgc3RyZWFtOiBNZWRpYVN0cmVhbSB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgbWVkaWFSZWNvcmRlcjogTWVkaWFSZWNvcmRlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVjb3JkZWRCbG9iczogQmxvYltdID0gW107XHJcbiAgcHJpdmF0ZSB0aW1lclN1YnNjcmlwdGlvbjogYW55O1xyXG4gIHByaXZhdGUgY3VycmVudFJlY29yZGVkVGltZTogbnVtYmVyID0gMDtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZWNvcmRpbmdTdGF0ZVN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFJlY29yZGluZ1N0YXRlPihSZWNvcmRpbmdTdGF0ZS5JZGxlKTtcclxuICByZWFkb25seSByZWNvcmRpbmdTdGF0ZSQ6IE9ic2VydmFibGU8UmVjb3JkaW5nU3RhdGU+ID0gdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVjb3JkZWRUaW1lU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPigwKTtcclxuICByZWFkb25seSByZWNvcmRlZFRpbWUkOiBPYnNlcnZhYmxlPG51bWJlcj4gPSB0aGlzLnJlY29yZGVkVGltZVN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVjb3JkZWRVcmxTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuICByZWFkb25seSByZWNvcmRlZFVybCQ6IE9ic2VydmFibGU8c3RyaW5nIHwgbnVsbD4gPSB0aGlzLnJlY29yZGVkVXJsU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZWNvcmRpbmdUaW1lc3RhbXBTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcclxuICByZWFkb25seSByZWNvcmRpbmdUaW1lc3RhbXAkOiBPYnNlcnZhYmxlPHN0cmluZz4gPSB0aGlzLnJlY29yZGluZ1RpbWVzdGFtcFN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgZXJyb3JTdWJqZWN0ID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xyXG4gIHJlYWRvbmx5IGVycm9yJDogT2JzZXJ2YWJsZTxzdHJpbmc+ID0gdGhpcy5lcnJvclN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBzY3JlZW5SZWNvcmRpbmdDb25zdGFudDogU2NyZWVuUmVjb3JkZXJDb25zdGFudHMpIHsgfVxyXG5cclxuICAvKipcclxuICAgKiBTdGFydHMgdGhlIHNjcmVlbiByZWNvcmRpbmcgd2l0aCBvcHRpb25hbCBhdWRpb1xyXG4gICAqIFxyXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciByZWNvcmRpbmdcclxuICAgKiBAcGFyYW0gb3B0aW9ucy5hdWRpbyAtIFdoZXRoZXIgdG8gaW5jbHVkZSBhdWRpbyBpbiB0aGUgcmVjb3JkaW5nXHJcbiAgICogXHJcbiAgICogQHRocm93cyBFcnJvciBpZiByZWNvcmRpbmcgaXMgYWxyZWFkeSBpbiBwcm9ncmVzcyBvciBpZiBtZWRpYSBhY2Nlc3MgaXMgZGVuaWVkXHJcbiAgICogQHJldHVybnMgUHJvbWlzZTx2b2lkPlxyXG4gICAqL1xyXG4gIGFzeW5jIHN0YXJ0UmVjb3JkaW5nKG9wdGlvbnM6IHsgYXVkaW86IGJvb2xlYW4gfSk6IFByb21pc2U8dm9pZD4ge1xyXG5cclxuICAgIGlmICh0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUmVjb3JkaW5nIHx8IHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5QYXVzZWQpIHtcclxuICAgICAgdGhpcy5oYW5kbGVFcnJvcih0aGlzLnNjcmVlblJlY29yZGluZ0NvbnN0YW50LlJFQ09SRElOR19JTl9QUk9HUkVTU19FUlJPUik7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNsZWFudXBQcmV2aW91c1JlY29yZGluZygpO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIFRoZSBicm93c2VyJ3MgbmF0aXZlIHBpY2tlciBoYW5kbGVzIFwic3BlY2lmaWMgYXJlYVwiIHNlbGVjdGlvbiAod2luZG93LCB0YWIsIHNjcmVlbikuXHJcbiAgICAgIGNvbnN0IGRpc3BsYXlTdHJlYW0gPSBhd2FpdCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldERpc3BsYXlNZWRpYSh7XHJcbiAgICAgICAgdmlkZW86IHRydWVcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBJZiBhdWRpbyBpcyBlbmFibGVkLCBnZXQgdGhlIGF1ZGlvIHN0cmVhbVxyXG4gICAgICBsZXQgYXVkaW9TdHJlYW06IE1lZGlhU3RyZWFtIHwgbnVsbCA9IG51bGw7XHJcbiAgICAgIGlmIChvcHRpb25zLmF1ZGlvKSB7XHJcbiAgICAgICAgYXVkaW9TdHJlYW0gPSBhd2FpdCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XHJcbiAgICAgICAgICBhdWRpbzoge1xyXG4gICAgICAgICAgICBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlLFxyXG4gICAgICAgICAgICBub2lzZVN1cHByZXNzaW9uOiB0cnVlLFxyXG4gICAgICAgICAgICBzYW1wbGVSYXRlOiA0NDEwMFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDb21iaW5lIHRoZSBzdHJlYW1zIGlmIGF1ZGlvIGlzIGVuYWJsZWRcclxuICAgICAgaWYgKGF1ZGlvU3RyZWFtKSB7XHJcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBuZXcgTWVkaWFTdHJlYW0oWy4uLmRpc3BsYXlTdHJlYW0uZ2V0VHJhY2tzKCksIC4uLmF1ZGlvU3RyZWFtLmdldFRyYWNrcygpXSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBkaXNwbGF5U3RyZWFtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBMaXN0ZW4gZm9yIHdoZW4gdGhlIHVzZXIgc3RvcHMgc2hhcmluZyB2aWEgYnJvd3NlciBVSVxyXG4gICAgICB0aGlzLnN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLm9uZW5kZWQgPSAoKSA9PiB7XHJcbiAgICAgICAgaWYgKHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcgfHwgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlBhdXNlZCkge1xyXG4gICAgICAgICAgdGhpcy5zdG9wUmVjb3JkaW5nSW50ZXJuYWwoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcblxyXG4gICAgICAvLyBIYW5kbGUgZXJyb3JzXHJcbiAgICAgIGlmICghdGhpcy5zdHJlYW0pIHtcclxuICAgICAgICB0aGlzLmhhbmRsZUVycm9yKHRoaXMuc2NyZWVuUmVjb3JkaW5nQ29uc3RhbnQuRkFJTEVEX1RPX0dFVF9ESVNQTEFZX01FRElBX1NUUkVBTV9FUlJPUik7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBTZXQgcmVjb3JkaW5nIHRpbWVzdGFtcFxyXG4gICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSBub3cudG9Mb2NhbGVTdHJpbmcoJ2VuLUlOJywge1xyXG4gICAgICAgIHllYXI6ICdudW1lcmljJyxcclxuICAgICAgICBtb250aDogJzItZGlnaXQnLFxyXG4gICAgICAgIGRheTogJzItZGlnaXQnLFxyXG4gICAgICAgIGhvdXI6ICcyLWRpZ2l0JyxcclxuICAgICAgICBtaW51dGU6ICcyLWRpZ2l0JyxcclxuICAgICAgICBob3VyMTI6IHRydWVcclxuICAgICAgfSk7XHJcbiAgICAgIHRoaXMucmVjb3JkaW5nVGltZXN0YW1wU3ViamVjdC5uZXh0KHRpbWVzdGFtcCk7XHJcblxyXG5cclxuICAgICAgdGhpcy5yZWNvcmRlZEJsb2JzID0gW107XHJcbiAgICAgIGNvbnN0IG1pbWVUeXBlID0gdGhpcy5nZXRTdXBwb3J0ZWRNaW1lVHlwZSgpO1xyXG4gICAgICBpZiAoIW1pbWVUeXBlKSB7XHJcbiAgICAgICAgdGhpcy5oYW5kbGVFcnJvcih0aGlzLnNjcmVlblJlY29yZGluZ0NvbnN0YW50Lk5PX1NVUFBPUlRfTUlNRSk7XHJcbiAgICAgICAgdGhpcy5zdHJlYW0/LmdldFRyYWNrcygpLmZvckVhY2godHJhY2sgPT4gdHJhY2suc3RvcCgpKTtcclxuICAgICAgICB0aGlzLnN0cmVhbSA9IG51bGw7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDcmVhdGUgYSBjYW52YXMgZm9yIHRpbWVzdGFtcCBvdmVybGF5XHJcbiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xyXG4gICAgICBjb25zdCB2aWRlb1RyYWNrID0gdGhpcy5zdHJlYW0/LmdldFZpZGVvVHJhY2tzKClbMF07XHJcbiAgICAgIGlmICh2aWRlb1RyYWNrKSB7XHJcbiAgICAgICAgY29uc3QgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xyXG4gICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtO1xyXG5cclxuICAgICAgICAvLyBXYWl0IGZvciB2aWRlbyB0byBsb2FkIG1ldGFkYXRhXHJcbiAgICAgICAgdmlkZW8ub25sb2FkZWRtZXRhZGF0YSA9ICgpID0+IHtcclxuICAgICAgICAgIGNhbnZhcy53aWR0aCA9IHZpZGVvLnZpZGVvV2lkdGg7XHJcbiAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gdmlkZW8udmlkZW9IZWlnaHQ7XHJcbiAgICAgICAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcclxuICAgICAgICAgIGlmIChjdHgpIHtcclxuICAgICAgICAgICAgLy8gRHJhdyB2aWRlbyBmcmFtZVxyXG4gICAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwKTtcclxuXHJcbiAgICAgICAgICAgIC8vIERyYXcgdGltZXN0YW1wXHJcbiAgICAgICAgICAgIGN0eC5mb250ID0gJzE2cHggQXJpYWwnO1xyXG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gJ3doaXRlJztcclxuICAgICAgICAgICAgY3R4LnRleHRBbGlnbiA9ICdyaWdodCc7XHJcbiAgICAgICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAndG9wJztcclxuICAgICAgICAgICAgY3R4LmZpbGxUZXh0KGBSZWNvcmRlZCBvbjogJHt0aGlzLnJlY29yZGluZ1RpbWVzdGFtcFN1YmplY3QudmFsdWV9YCwgY2FudmFzLndpZHRoIC0gMTAsIDEwKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDcmVhdGUgYSBuZXcgc3RyZWFtIHdpdGggdGhlIGNhbnZhc1xyXG4gICAgICBjb25zdCBjYW52YXNTdHJlYW0gPSBjYW52YXMuY2FwdHVyZVN0cmVhbSgpO1xyXG4gICAgICBjb25zdCBjb21iaW5lZFN0cmVhbSA9IG5ldyBNZWRpYVN0cmVhbShbLi4udGhpcy5zdHJlYW0/LmdldFRyYWNrcygpID8/IFtdLCBjYW52YXNTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXV0pO1xyXG5cclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIoY29tYmluZWRTdHJlYW0sIHsgbWltZVR5cGUgfSk7XHJcblxyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGV2ZW50KSA9PiB7XHJcbiAgICAgICAgaWYgKGV2ZW50LmRhdGEgJiYgZXZlbnQuZGF0YS5zaXplID4gMCkge1xyXG4gICAgICAgICAgdGhpcy5yZWNvcmRlZEJsb2JzLnB1c2goZXZlbnQuZGF0YSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG5cclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcclxuICAgICAgICBjb25zdCBzdXBlckJ1ZmZlciA9IG5ldyBCbG9iKHRoaXMucmVjb3JkZWRCbG9icywgeyB0eXBlOiBtaW1lVHlwZSB9KTtcclxuICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChzdXBlckJ1ZmZlcik7XHJcbiAgICAgICAgdGhpcy5yZWNvcmRlZFVybFN1YmplY3QubmV4dCh1cmwpO1xyXG4gICAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoUmVjb3JkaW5nU3RhdGUuU3RvcHBlZCk7XHJcbiAgICAgICAgdGhpcy5zdG9wVGltZXIoKTtcclxuXHJcbiAgICAgIH07XHJcblxyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChldmVudDogRXZlbnQpID0+IHtcclxuICAgICAgICBjb25zdCBlcnJvckV2ZW50ID0gZXZlbnQgYXMgRXJyb3JFdmVudDsgLy8gTW9yZSBzcGVjaWZpYyB0eXBlIGlmIGF2YWlsYWJsZVxyXG4gICAgICAgIGxldCBtZXNzYWdlID0gdGhpcy5zY3JlZW5SZWNvcmRpbmdDb25zdGFudC5NRURJQV9FUlJPUjtcclxuICAgICAgICBpZiAoZXJyb3JFdmVudC5lcnJvciAmJiBlcnJvckV2ZW50LmVycm9yLm5hbWUpIHtcclxuICAgICAgICAgIG1lc3NhZ2UgKz0gYDogJHtlcnJvckV2ZW50LmVycm9yLm5hbWV9YDtcclxuICAgICAgICAgIGlmIChlcnJvckV2ZW50LmVycm9yLm1lc3NhZ2UpIG1lc3NhZ2UgKz0gYCAtICR7ZXJyb3JFdmVudC5lcnJvci5tZXNzYWdlfWA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuaGFuZGxlRXJyb3IobWVzc2FnZSk7XHJcbiAgICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChSZWNvcmRpbmdTdGF0ZS5JZGxlKTtcclxuICAgICAgICB0aGlzLnN0b3BUaW1lcigpO1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXJ0KCk7IC8vIFN0YXJ0IHJlY29yZGluZ1xyXG4gICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLlJlY29yZGluZyk7XHJcbiAgICAgIHRoaXMuc3RhcnRUaW1lcigpO1xyXG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcclxuICAgICAgdGhpcy5oYW5kbGVFcnJvcihgRXJyb3Igc3RhcnRpbmcgc2NyZWVuIHJlY29yZGluZzogJHtlcnIubmFtZX0gLSAke2Vyci5tZXNzYWdlfWApO1xyXG4gICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLklkbGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAqIEdldHMgdGhlIGZpcnN0IHN1cHBvcnRlZCBNSU1FIHR5cGUgZm9yIE1lZGlhUmVjb3JkZXJcclxuICogXHJcbiAqIEByZXR1cm5zIHN0cmluZ3xudWxsIC0gVGhlIHN1cHBvcnRlZCBNSU1FIHR5cGUgb3IgbnVsbCBpZiBub25lIGZvdW5kXHJcbiAqL1xyXG4gIHByaXZhdGUgZ2V0U3VwcG9ydGVkTWltZVR5cGUoKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBjb25zdCBtaW1lVHlwZXMgPSBbXHJcbiAgICAgICd2aWRlby93ZWJtO2NvZGVjcz12cDksb3B1cycsXHJcbiAgICAgICd2aWRlby93ZWJtO2NvZGVjcz12cDgsb3B1cycsXHJcbiAgICAgICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0LG9wdXMnLFxyXG4gICAgICAndmlkZW8vbXA0O2NvZGVjcz1oMjY0LGFhYycsIC8vIE1QNCBtaWdodCBoYXZlIGJyb2FkZXIgY29tcGF0aWJpbGl0eSBidXQgbGVzcyBicm93c2VyIHN1cHBvcnQgZm9yIHJlY29yZGluZ1xyXG4gICAgICAndmlkZW8vd2VibScsXHJcbiAgICBdO1xyXG4gICAgZm9yIChjb25zdCBtaW1lVHlwZSBvZiBtaW1lVHlwZXMpIHtcclxuICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKG1pbWVUeXBlKSkge1xyXG4gICAgICAgIHJldHVybiBtaW1lVHlwZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbnRlcm5hbCBtZXRob2QgdG8gc3RvcCB0aGUgcmVjb3JkaW5nIHByb2Nlc3NcclxuICAgKiBcclxuICAgKiBAcHJpdmF0ZVxyXG4gICAqIEByZXR1cm5zIHZvaWRcclxuICAgKi9cclxuICBwcml2YXRlIHN0b3BSZWNvcmRpbmdJbnRlcm5hbCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm1lZGlhUmVjb3JkZXIgJiYgKHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcgfHwgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlBhdXNlZCkpIHtcclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0b3AoKTtcclxuICAgIH1cclxuICAgIHRoaXMuc3RyZWFtPy5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHRyYWNrLnN0b3AoKSk7XHJcbiAgICB0aGlzLnN0cmVhbSA9IG51bGw7XHJcbiAgICAvLyBTdGF0ZSB3aWxsIGJlIHVwZGF0ZWQgYnkgb25zdG9wIGhhbmRsZXJcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2U8dm9pZD5cclxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHJlY29yZGluZyBpcyBub3QgaW4gcHJvZ3Jlc3NcclxuICAgKi9cclxuICBzdG9wUmVjb3JkaW5nKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zdG9wUmVjb3JkaW5nSW50ZXJuYWwoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBhdXNlcyB0aGUgY3VycmVudCByZWNvcmRpbmdcclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBQcm9taXNlPHZvaWQ+XHJcbiAgICogQHRocm93cyBFcnJvciBpZiByZWNvcmRpbmcgaXMgbm90IGluIHByb2dyZXNzXHJcbiAgICovXHJcbiAgcGF1c2VSZWNvcmRpbmcoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5tZWRpYVJlY29yZGVyICYmIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcpIHtcclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XHJcbiAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoUmVjb3JkaW5nU3RhdGUuUGF1c2VkKTtcclxuICAgICAgdGhpcy5zdG9wVGltZXIoKTsgLy8gUGF1c2VzIHRoZSB0aW1lciBkaXNwbGF5XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXN1bWVzIGEgcGF1c2VkIHJlY29yZGluZ1xyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2U8dm9pZD5cclxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHJlY29yZGluZyBpcyBub3QgcGF1c2VkXHJcbiAgICovXHJcbiAgcmVzdW1lUmVjb3JkaW5nKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMubWVkaWFSZWNvcmRlciAmJiB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUGF1c2VkKSB7XHJcbiAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcclxuICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcpO1xyXG4gICAgICB0aGlzLnN0YXJ0VGltZXIodGhpcy5jdXJyZW50UmVjb3JkZWRUaW1lKTsgLy8gUmVzdW1lcyB0aW1lciBkaXNwbGF5XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBcclxuICAgKiBAcGFyYW0gZmlsZU5hbWUgXHJcbiAgICovXHJcbiAgZG93bmxvYWRSZWNvcmRpbmcoZmlsZU5hbWU6IHN0cmluZyA9ICdyZWNvcmRpbmcud2VibScpOiB2b2lkIHtcclxuICAgIGNvbnN0IHVybCA9IHRoaXMucmVjb3JkZWRVcmxTdWJqZWN0LnZhbHVlO1xyXG4gICAgY29uc3QgdGltZXN0YW1wID0gdGhpcy5yZWNvcmRpbmdUaW1lc3RhbXBTdWJqZWN0LnZhbHVlO1xyXG5cclxuICAgIGlmICh1cmwgJiYgdGltZXN0YW1wKSB7XHJcbiAgICAgIC8vIEZvcm1hdCB0aGUgdGltZXN0YW1wIGZvciBmaWxlbmFtZSAocmVtb3ZlIHNwYWNlcyBhbmQgc3BlY2lhbCBjaGFyYWN0ZXJzKVxyXG4gICAgICBjb25zdCBmb3JtYXR0ZWRUaW1lc3RhbXAgPSB0aW1lc3RhbXAucmVwbGFjZSgvW15hLXpBLVowLTldL2csICdfJyk7XHJcbiAgICAgIC8vIENyZWF0ZSBmaWxlbmFtZSB3aXRoIHRpbWVzdGFtcFxyXG4gICAgICBjb25zdCBmaWxlRXh0ZW5zaW9uID0gZmlsZU5hbWUuc3BsaXQoJy4nKS5wb3AoKSB8fCAnd2VibSc7XHJcbiAgICAgIGNvbnN0IG5ld0ZpbGVOYW1lID0gYHNjcmVlbl9yZWNvcmRpbmdfJHtmb3JtYXR0ZWRUaW1lc3RhbXB9LiR7ZmlsZUV4dGVuc2lvbn1gO1xyXG5cclxuICAgICAgY29uc3QgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcclxuICAgICAgYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG4gICAgICBhLmhyZWYgPSB1cmw7XHJcbiAgICAgIGEuZG93bmxvYWQgPSBuZXdGaWxlTmFtZTtcclxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTtcclxuICAgICAgYS5jbGljaygpO1xyXG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xyXG4gICAgICAvLyBObyBuZWVkIHRvIHJldm9rZSBVUkwgaGVyZSBpZiB1c2VyIG1pZ2h0IHdhbnQgdG8gcGxheSBpdCBhZ2Fpbi5cclxuICAgICAgLy8gUmV2b2tlIG9uIGNsZWFudXAgb3IgbmV3IHJlY29yZGluZy5cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuaGFuZGxlRXJyb3IodGhpcy5zY3JlZW5SZWNvcmRpbmdDb25zdGFudC5OT19SRUNPUkRJTkdfRE9XTkxPQUQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIHRpbWVyXHJcbiAqIFxyXG4gKiBAcGFyYW0gc3RhcnRUaW1lIC0gT3B0aW9uYWwgc3RhcnQgdGltZSBmb3IgdGhlIHRpbWVyXHJcbiAqIEBwcml2YXRlXHJcbiAqIEByZXR1cm5zIHZvaWRcclxuICovXHJcbiAgcHJpdmF0ZSBzdGFydFRpbWVyKHN0YXJ0VGltZTogbnVtYmVyID0gMCk6IHZvaWQge1xyXG4gICAgdGhpcy5zdG9wVGltZXIoKTsgLy8gRW5zdXJlIG5vIG11bHRpcGxlIHRpbWVyc1xyXG4gICAgdGhpcy5jdXJyZW50UmVjb3JkZWRUaW1lID0gc3RhcnRUaW1lO1xyXG4gICAgdGhpcy5yZWNvcmRlZFRpbWVTdWJqZWN0Lm5leHQodGhpcy5jdXJyZW50UmVjb3JkZWRUaW1lKTtcclxuXHJcbiAgICB0aGlzLnRpbWVyU3Vic2NyaXB0aW9uID0gdGltZXIoMCwgMTAwMClcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgdGFwKCgpID0+IHtcclxuICAgICAgICAgIGlmICh0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUmVjb3JkaW5nKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFJlY29yZGVkVGltZSsrO1xyXG4gICAgICAgICAgICB0aGlzLnJlY29yZGVkVGltZVN1YmplY3QubmV4dCh0aGlzLmN1cnJlbnRSZWNvcmRlZFRpbWUpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pLFxyXG4gICAgICAgIHRha2VXaGlsZSgoKSA9PiB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUmVjb3JkaW5nKVxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFN0b3BzIHRoZSByZWNvcmRpbmcgdGltZXJcclxuICAgKiBcclxuICAgKiBAcHJpdmF0ZVxyXG4gICAqIEByZXR1cm5zIHZvaWRcclxuICAgKi9cclxuICBwcml2YXRlIHN0b3BUaW1lcigpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnRpbWVyU3Vic2NyaXB0aW9uKSB7XHJcbiAgICAgIHRoaXMudGltZXJTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgICAgdGhpcy50aW1lclN1YnNjcmlwdGlvbiA9IG51bGw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhbnMgdXAgcmVzb3VyY2VzIGZyb20gcHJldmlvdXMgcmVjb3JkaW5nXHJcbiAgICogXHJcbiAgICogQHByaXZhdGVcclxuICAgKiBAcmV0dXJucyB2b2lkXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjbGVhbnVwUHJldmlvdXNSZWNvcmRpbmcoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5yZWNvcmRlZFVybFN1YmplY3QudmFsdWUpIHtcclxuICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodGhpcy5yZWNvcmRlZFVybFN1YmplY3QudmFsdWUpO1xyXG4gICAgICB0aGlzLnJlY29yZGVkVXJsU3ViamVjdC5uZXh0KG51bGwpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5yZWNvcmRlZEJsb2JzID0gW107XHJcbiAgICB0aGlzLmN1cnJlbnRSZWNvcmRlZFRpbWUgPSAwO1xyXG4gICAgdGhpcy5yZWNvcmRlZFRpbWVTdWJqZWN0Lm5leHQoMCk7XHJcbiAgICBpZiAodGhpcy5zdHJlYW0pIHtcclxuICAgICAgdGhpcy5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5zdG9wKCkpO1xyXG4gICAgICB0aGlzLnN0cmVhbSA9IG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5tZWRpYVJlY29yZGVyICYmIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSAhPT0gdGhpcy5zY3JlZW5SZWNvcmRpbmdDb25zdGFudC5JTkFDVElWRSkge1xyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbnVsbDtcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICogUmVzZXRzIHRoZSByZWNvcmRpbmcgc3RhdGUgdG8gaWRsZVxyXG4gKiBcclxuICogQHJldHVybnMgdm9pZFxyXG4gKi9cclxuICByZXNldFRvSWRsZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xlYW51cFByZXZpb3VzUmVjb3JkaW5nKCk7XHJcbiAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLklkbGUpO1xyXG4gICAgdGhpcy5lcnJvclN1YmplY3QubmV4dCgnJyk7IC8vIENsZWFyIGFueSBwcmV2aW91cyBlcnJvcnNcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICogSGFuZGxlcyBhbmQgYnJvYWRjYXN0cyByZWNvcmRpbmcgZXJyb3JzXHJcbiAqIFxyXG4gKiBAcHJpdmF0ZVxyXG4gKiBAcGFyYW0gZXJyb3IgLSBUaGUgZXJyb3IgbWVzc2FnZSB0byBoYW5kbGVcclxuICogQHJldHVybnMgdm9pZFxyXG4gKi9cclxuICBwcml2YXRlIGhhbmRsZUVycm9yKGVycm9yOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuZXJyb3JTdWJqZWN0Lm5leHQoZXJyb3IpO1xyXG4gIH1cclxufVxyXG4iXX0=
@@ -1,5 +0,0 @@
1
- /**
2
- * Generated bundle index. Do not edit.
3
- */
4
- export * from './index';
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjLWxpYi1zY3JlZW4tcmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3J1Y2xpYi9zY3JlZW4tcmVjb3JkZXIvc3JjL3J1Yy1saWItc2NyZWVuLXJlY29yZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vaW5kZXgnO1xuIl19