@ruc-lib/screen-recorder 3.1.0 → 3.2.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.
- package/README.md +174 -1
- package/esm2020/index.mjs +5 -0
- package/esm2020/lib/models/screen-recorder.models.mjs +20 -0
- package/esm2020/lib/ruclib-screen-recorder.module.mjs +20 -0
- package/esm2020/lib/screen-recorder/screen-recorder-constant.mjs +44 -0
- package/esm2020/lib/screen-recorder/screen-recorder.component.mjs +242 -0
- package/esm2020/lib/services/screen-recorder.service.mjs +333 -0
- package/esm2020/ruc-lib-screen-recorder.mjs +5 -0
- package/fesm2015/ruc-lib-screen-recorder.mjs +644 -0
- package/fesm2015/ruc-lib-screen-recorder.mjs.map +1 -0
- package/fesm2020/ruc-lib-screen-recorder.mjs +648 -0
- package/fesm2020/ruc-lib-screen-recorder.mjs.map +1 -0
- package/index.d.ts +4 -288
- package/lib/models/screen-recorder.models.d.ts +51 -0
- package/lib/ruclib-screen-recorder.module.d.ts +8 -0
- package/lib/screen-recorder/screen-recorder-constant.d.ts +27 -0
- package/lib/screen-recorder/screen-recorder.component.d.ts +100 -0
- package/lib/services/screen-recorder.service.d.ts +111 -0
- package/package.json +25 -13
- package/fesm2022/ruc-lib-screen-recorder.mjs +0 -636
- package/fesm2022/ruc-lib-screen-recorder.mjs.map +0 -1
|
@@ -0,0 +1,333 @@
|
|
|
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyZWVuLXJlY29yZGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL3NjcmVlbi1yZWNvcmRlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBYyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ25FLE9BQU8sRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDOzs7QUFJdEYsTUFBTSxPQUFPLHFCQUFxQjtJQXNCaEMsWUFBbUIsdUJBQWdEO1FBQWhELDRCQUF1QixHQUF2Qix1QkFBdUIsQ0FBeUI7UUFyQjNELFdBQU0sR0FBdUIsSUFBSSxDQUFDO1FBQ2xDLGtCQUFhLEdBQXlCLElBQUksQ0FBQztRQUMzQyxrQkFBYSxHQUFXLEVBQUUsQ0FBQztRQUUzQix3QkFBbUIsR0FBVyxDQUFDLENBQUM7UUFFdkIsMEJBQXFCLEdBQUcsSUFBSSxlQUFlLENBQWlCLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6RixvQkFBZSxHQUErQixJQUFJLENBQUMscUJBQXFCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFaEYsd0JBQW1CLEdBQUcsSUFBSSxlQUFlLENBQVMsQ0FBQyxDQUFDLENBQUM7UUFDN0Qsa0JBQWEsR0FBdUIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBRXBFLHVCQUFrQixHQUFHLElBQUksZUFBZSxDQUFnQixJQUFJLENBQUMsQ0FBQztRQUN0RSxpQkFBWSxHQUE4QixJQUFJLENBQUMsa0JBQWtCLENBQUMsWUFBWSxF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QWEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUMzQjtRQUNELElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO0lBQzVCLENBQUM7SUFHRDs7OztLQUlDO0lBQ0QsV0FBVztRQUNULElBQUksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO1FBQ2hDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsNEJBQTRCO0lBQzFELENBQUM7SUFHRDs7Ozs7O0tBTUM7SUFDTyxXQUFXLENBQUMsS0FBYTtRQUMvQixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNoQyxDQUFDOzttSEFwV1UscUJBQXFCO3VIQUFyQixxQkFBcUIsY0FGcEIsTUFBTTs0RkFFUCxxQkFBcUI7a0JBSGpDLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU0sRUFBRSx5Q0FBeUM7aUJBQzlEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUsIFN1YmplY3QsIHRpbWVyIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IHRha2VXaGlsZSwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBSZWNvcmRpbmdTdGF0ZSB9IGZyb20gJy4uL21vZGVscy9zY3JlZW4tcmVjb3JkZXIubW9kZWxzJztcclxuaW1wb3J0IHsgU2NyZWVuUmVjb3JkZXJDb25zdGFudHMgfSBmcm9tICcuLi9zY3JlZW4tcmVjb3JkZXIvc2NyZWVuLXJlY29yZGVyLWNvbnN0YW50JztcclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290JywgLy8gT3IgcHJvdmlkZSBpbiB5b3VyIG1vZHVsZSBpZiBwcmVmZXJyZWRcclxufSlcclxuZXhwb3J0IGNsYXNzIFNjcmVlblJlY29yZGVyU2VydmljZSB7XHJcbiAgcHJpdmF0ZSBzdHJlYW06IE1lZGlhU3RyZWFtIHwgbnVsbCA9IG51bGw7XHJcbiAgcHJpdmF0ZSBtZWRpYVJlY29yZGVyOiBNZWRpYVJlY29yZGVyIHwgbnVsbCA9IG51bGw7XHJcbiAgcHJpdmF0ZSByZWNvcmRlZEJsb2JzOiBCbG9iW10gPSBbXTtcclxuICBwcml2YXRlIHRpbWVyU3Vic2NyaXB0aW9uOiBhbnk7XHJcbiAgcHJpdmF0ZSBjdXJyZW50UmVjb3JkZWRUaW1lOiBudW1iZXIgPSAwO1xyXG5cclxuICBwcml2YXRlIHJlYWRvbmx5IHJlY29yZGluZ1N0YXRlU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8UmVjb3JkaW5nU3RhdGU+KFJlY29yZGluZ1N0YXRlLklkbGUpO1xyXG4gIHJlYWRvbmx5IHJlY29yZGluZ1N0YXRlJDogT2JzZXJ2YWJsZTxSZWNvcmRpbmdTdGF0ZT4gPSB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZWNvcmRlZFRpbWVTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+KDApO1xyXG4gIHJlYWRvbmx5IHJlY29yZGVkVGltZSQ6IE9ic2VydmFibGU8bnVtYmVyPiA9IHRoaXMucmVjb3JkZWRUaW1lU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZWNvcmRlZFVybFN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZyB8IG51bGw+KG51bGwpO1xyXG4gIHJlYWRvbmx5IHJlY29yZGVkVXJsJDogT2JzZXJ2YWJsZTxzdHJpbmcgfCBudWxsPiA9IHRoaXMucmVjb3JkZWRVcmxTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xyXG5cclxuICBwcml2YXRlIHJlYWRvbmx5IHJlY29yZGluZ1RpbWVzdGFtcFN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZz4oJycpO1xyXG4gIHJlYWRvbmx5IHJlY29yZGluZ1RpbWVzdGFtcCQ6IE9ic2VydmFibGU8c3RyaW5nPiA9IHRoaXMucmVjb3JkaW5nVGltZXN0YW1wU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSBlcnJvclN1YmplY3QgPSBuZXcgU3ViamVjdDxzdHJpbmc+KCk7XHJcbiAgcmVhZG9ubHkgZXJyb3IkOiBPYnNlcnZhYmxlPHN0cmluZz4gPSB0aGlzLmVycm9yU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgY29uc3RydWN0b3IocHVibGljIHNjcmVlblJlY29yZGluZ0NvbnN0YW50OiBTY3JlZW5SZWNvcmRlckNvbnN0YW50cykgeyB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFN0YXJ0cyB0aGUgc2NyZWVuIHJlY29yZGluZyB3aXRoIG9wdGlvbmFsIGF1ZGlvXHJcbiAgICogXHJcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBDb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHJlY29yZGluZ1xyXG4gICAqIEBwYXJhbSBvcHRpb25zLmF1ZGlvIC0gV2hldGhlciB0byBpbmNsdWRlIGF1ZGlvIGluIHRoZSByZWNvcmRpbmdcclxuICAgKiBcclxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHJlY29yZGluZyBpcyBhbHJlYWR5IGluIHByb2dyZXNzIG9yIGlmIG1lZGlhIGFjY2VzcyBpcyBkZW5pZWRcclxuICAgKiBAcmV0dXJucyBQcm9taXNlPHZvaWQ+XHJcbiAgICovXHJcbiAgYXN5bmMgc3RhcnRSZWNvcmRpbmcob3B0aW9uczogeyBhdWRpbzogYm9vbGVhbiB9KTogUHJvbWlzZTx2b2lkPiB7XHJcblxyXG4gICAgaWYgKHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcgfHwgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlBhdXNlZCkge1xyXG4gICAgICB0aGlzLmhhbmRsZUVycm9yKHRoaXMuc2NyZWVuUmVjb3JkaW5nQ29uc3RhbnQuUkVDT1JESU5HX0lOX1BST0dSRVNTX0VSUk9SKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuY2xlYW51cFByZXZpb3VzUmVjb3JkaW5nKCk7XHJcblxyXG4gICAgdHJ5IHtcclxuICAgICAgLy8gVGhlIGJyb3dzZXIncyBuYXRpdmUgcGlja2VyIGhhbmRsZXMgXCJzcGVjaWZpYyBhcmVhXCIgc2VsZWN0aW9uICh3aW5kb3csIHRhYiwgc2NyZWVuKS5cclxuICAgICAgY29uc3QgZGlzcGxheVN0cmVhbSA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0RGlzcGxheU1lZGlhKHtcclxuICAgICAgICB2aWRlbzogdHJ1ZVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIElmIGF1ZGlvIGlzIGVuYWJsZWQsIGdldCB0aGUgYXVkaW8gc3RyZWFtXHJcbiAgICAgIGxldCBhdWRpb1N0cmVhbTogTWVkaWFTdHJlYW0gfCBudWxsID0gbnVsbDtcclxuICAgICAgaWYgKG9wdGlvbnMuYXVkaW8pIHtcclxuICAgICAgICBhdWRpb1N0cmVhbSA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcclxuICAgICAgICAgIGF1ZGlvOiB7XHJcbiAgICAgICAgICAgIGVjaG9DYW5jZWxsYXRpb246IHRydWUsXHJcbiAgICAgICAgICAgIG5vaXNlU3VwcHJlc3Npb246IHRydWUsXHJcbiAgICAgICAgICAgIHNhbXBsZVJhdGU6IDQ0MTAwXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIENvbWJpbmUgdGhlIHN0cmVhbXMgaWYgYXVkaW8gaXMgZW5hYmxlZFxyXG4gICAgICBpZiAoYXVkaW9TdHJlYW0pIHtcclxuICAgICAgICB0aGlzLnN0cmVhbSA9IG5ldyBNZWRpYVN0cmVhbShbLi4uZGlzcGxheVN0cmVhbS5nZXRUcmFja3MoKSwgLi4uYXVkaW9TdHJlYW0uZ2V0VHJhY2tzKCldKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnN0cmVhbSA9IGRpc3BsYXlTdHJlYW07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIExpc3RlbiBmb3Igd2hlbiB0aGUgdXNlciBzdG9wcyBzaGFyaW5nIHZpYSBicm93c2VyIFVJXHJcbiAgICAgIHRoaXMuc3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF0ub25lbmRlZCA9ICgpID0+IHtcclxuICAgICAgICBpZiAodGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlJlY29yZGluZyB8fCB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUGF1c2VkKSB7XHJcbiAgICAgICAgICB0aGlzLnN0b3BSZWNvcmRpbmdJbnRlcm5hbCgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuXHJcbiAgICAgIC8vIEhhbmRsZSBlcnJvcnNcclxuICAgICAgaWYgKCF0aGlzLnN0cmVhbSkge1xyXG4gICAgICAgIHRoaXMuaGFuZGxlRXJyb3IodGhpcy5zY3JlZW5SZWNvcmRpbmdDb25zdGFudC5GQUlMRURfVE9fR0VUX0RJU1BMQVlfTUVESUFfU1RSRUFNX0VSUk9SKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFNldCByZWNvcmRpbmcgdGltZXN0YW1wXHJcbiAgICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XHJcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IG5vdy50b0xvY2FsZVN0cmluZygnZW4tSU4nLCB7XHJcbiAgICAgICAgeWVhcjogJ251bWVyaWMnLFxyXG4gICAgICAgIG1vbnRoOiAnMi1kaWdpdCcsXHJcbiAgICAgICAgZGF5OiAnMi1kaWdpdCcsXHJcbiAgICAgICAgaG91cjogJzItZGlnaXQnLFxyXG4gICAgICAgIG1pbnV0ZTogJzItZGlnaXQnLFxyXG4gICAgICAgIGhvdXIxMjogdHJ1ZVxyXG4gICAgICB9KTtcclxuICAgICAgdGhpcy5yZWNvcmRpbmdUaW1lc3RhbXBTdWJqZWN0Lm5leHQodGltZXN0YW1wKTtcclxuXHJcblxyXG4gICAgICB0aGlzLnJlY29yZGVkQmxvYnMgPSBbXTtcclxuICAgICAgY29uc3QgbWltZVR5cGUgPSB0aGlzLmdldFN1cHBvcnRlZE1pbWVUeXBlKCk7XHJcbiAgICAgIGlmICghbWltZVR5cGUpIHtcclxuICAgICAgICB0aGlzLmhhbmRsZUVycm9yKHRoaXMuc2NyZWVuUmVjb3JkaW5nQ29uc3RhbnQuTk9fU1VQUE9SVF9NSU1FKTtcclxuICAgICAgICB0aGlzLnN0cmVhbT8uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5zdG9wKCkpO1xyXG4gICAgICAgIHRoaXMuc3RyZWFtID0gbnVsbDtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIENyZWF0ZSBhIGNhbnZhcyBmb3IgdGltZXN0YW1wIG92ZXJsYXlcclxuICAgICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XHJcbiAgICAgIGNvbnN0IHZpZGVvVHJhY2sgPSB0aGlzLnN0cmVhbT8uZ2V0VmlkZW9UcmFja3MoKVswXTtcclxuICAgICAgaWYgKHZpZGVvVHJhY2spIHtcclxuICAgICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XHJcbiAgICAgICAgdmlkZW8uc3JjT2JqZWN0ID0gdGhpcy5zdHJlYW07XHJcblxyXG4gICAgICAgIC8vIFdhaXQgZm9yIHZpZGVvIHRvIGxvYWQgbWV0YWRhdGFcclxuICAgICAgICB2aWRlby5vbmxvYWRlZG1ldGFkYXRhID0gKCkgPT4ge1xyXG4gICAgICAgICAgY2FudmFzLndpZHRoID0gdmlkZW8udmlkZW9XaWR0aDtcclxuICAgICAgICAgIGNhbnZhcy5oZWlnaHQgPSB2aWRlby52aWRlb0hlaWdodDtcclxuICAgICAgICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xyXG4gICAgICAgICAgaWYgKGN0eCkge1xyXG4gICAgICAgICAgICAvLyBEcmF3IHZpZGVvIGZyYW1lXHJcbiAgICAgICAgICAgIGN0eC5kcmF3SW1hZ2UodmlkZW8sIDAsIDApO1xyXG5cclxuICAgICAgICAgICAgLy8gRHJhdyB0aW1lc3RhbXBcclxuICAgICAgICAgICAgY3R4LmZvbnQgPSAnMTZweCBBcmlhbCc7XHJcbiAgICAgICAgICAgIGN0eC5maWxsU3R5bGUgPSAnd2hpdGUnO1xyXG4gICAgICAgICAgICBjdHgudGV4dEFsaWduID0gJ3JpZ2h0JztcclxuICAgICAgICAgICAgY3R4LnRleHRCYXNlbGluZSA9ICd0b3AnO1xyXG4gICAgICAgICAgICBjdHguZmlsbFRleHQoYFJlY29yZGVkIG9uOiAke3RoaXMucmVjb3JkaW5nVGltZXN0YW1wU3ViamVjdC52YWx1ZX1gLCBjYW52YXMud2lkdGggLSAxMCwgMTApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIENyZWF0ZSBhIG5ldyBzdHJlYW0gd2l0aCB0aGUgY2FudmFzXHJcbiAgICAgIGNvbnN0IGNhbnZhc1N0cmVhbSA9IGNhbnZhcy5jYXB0dXJlU3RyZWFtKCk7XHJcbiAgICAgIGNvbnN0IGNvbWJpbmVkU3RyZWFtID0gbmV3IE1lZGlhU3RyZWFtKFsuLi50aGlzLnN0cmVhbT8uZ2V0VHJhY2tzKCkgPz8gW10sIGNhbnZhc1N0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdXSk7XHJcblxyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcihjb21iaW5lZFN0cmVhbSwgeyBtaW1lVHlwZSB9KTtcclxuXHJcbiAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZXZlbnQpID0+IHtcclxuICAgICAgICBpZiAoZXZlbnQuZGF0YSAmJiBldmVudC5kYXRhLnNpemUgPiAwKSB7XHJcbiAgICAgICAgICB0aGlzLnJlY29yZGVkQmxvYnMucHVzaChldmVudC5kYXRhKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcblxyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25zdG9wID0gKCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IHN1cGVyQnVmZmVyID0gbmV3IEJsb2IodGhpcy5yZWNvcmRlZEJsb2JzLCB7IHR5cGU6IG1pbWVUeXBlIH0pO1xyXG4gICAgICAgIGNvbnN0IHVybCA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKHN1cGVyQnVmZmVyKTtcclxuICAgICAgICB0aGlzLnJlY29yZGVkVXJsU3ViamVjdC5uZXh0KHVybCk7XHJcbiAgICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChSZWNvcmRpbmdTdGF0ZS5TdG9wcGVkKTtcclxuICAgICAgICB0aGlzLnN0b3BUaW1lcigpO1xyXG5cclxuICAgICAgfTtcclxuXHJcbiAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5vbmVycm9yID0gKGV2ZW50OiBFdmVudCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGVycm9yRXZlbnQgPSBldmVudCBhcyBFcnJvckV2ZW50OyAvLyBNb3JlIHNwZWNpZmljIHR5cGUgaWYgYXZhaWxhYmxlXHJcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSB0aGlzLnNjcmVlblJlY29yZGluZ0NvbnN0YW50Lk1FRElBX0VSUk9SO1xyXG4gICAgICAgIGlmIChlcnJvckV2ZW50LmVycm9yICYmIGVycm9yRXZlbnQuZXJyb3IubmFtZSkge1xyXG4gICAgICAgICAgbWVzc2FnZSArPSBgOiAke2Vycm9yRXZlbnQuZXJyb3IubmFtZX1gO1xyXG4gICAgICAgICAgaWYgKGVycm9yRXZlbnQuZXJyb3IubWVzc2FnZSkgbWVzc2FnZSArPSBgIC0gJHtlcnJvckV2ZW50LmVycm9yLm1lc3NhZ2V9YDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5oYW5kbGVFcnJvcihtZXNzYWdlKTtcclxuICAgICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLklkbGUpO1xyXG4gICAgICAgIHRoaXMuc3RvcFRpbWVyKCk7XHJcbiAgICAgIH07XHJcblxyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RhcnQoKTsgLy8gU3RhcnQgcmVjb3JkaW5nXHJcbiAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoUmVjb3JkaW5nU3RhdGUuUmVjb3JkaW5nKTtcclxuICAgICAgdGhpcy5zdGFydFRpbWVyKCk7XHJcbiAgICB9IGNhdGNoIChlcnI6IGFueSkge1xyXG4gICAgICB0aGlzLmhhbmRsZUVycm9yKGBFcnJvciBzdGFydGluZyBzY3JlZW4gcmVjb3JkaW5nOiAke2Vyci5uYW1lfSAtICR7ZXJyLm1lc3NhZ2V9YCk7XHJcbiAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoUmVjb3JkaW5nU3RhdGUuSWRsZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICogR2V0cyB0aGUgZmlyc3Qgc3VwcG9ydGVkIE1JTUUgdHlwZSBmb3IgTWVkaWFSZWNvcmRlclxyXG4gKiBcclxuICogQHJldHVybnMgc3RyaW5nfG51bGwgLSBUaGUgc3VwcG9ydGVkIE1JTUUgdHlwZSBvciBudWxsIGlmIG5vbmUgZm91bmRcclxuICovXHJcbiAgcHJpdmF0ZSBnZXRTdXBwb3J0ZWRNaW1lVHlwZSgpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGNvbnN0IG1pbWVUeXBlcyA9IFtcclxuICAgICAgJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOSxvcHVzJyxcclxuICAgICAgJ3ZpZGVvL3dlYm07Y29kZWNzPXZwOCxvcHVzJyxcclxuICAgICAgJ3ZpZGVvL3dlYm07Y29kZWNzPWgyNjQsb3B1cycsXHJcbiAgICAgICd2aWRlby9tcDQ7Y29kZWNzPWgyNjQsYWFjJywgLy8gTVA0IG1pZ2h0IGhhdmUgYnJvYWRlciBjb21wYXRpYmlsaXR5IGJ1dCBsZXNzIGJyb3dzZXIgc3VwcG9ydCBmb3IgcmVjb3JkaW5nXHJcbiAgICAgICd2aWRlby93ZWJtJyxcclxuICAgIF07XHJcbiAgICBmb3IgKGNvbnN0IG1pbWVUeXBlIG9mIG1pbWVUeXBlcykge1xyXG4gICAgICBpZiAoTWVkaWFSZWNvcmRlci5pc1R5cGVTdXBwb3J0ZWQobWltZVR5cGUpKSB7XHJcbiAgICAgICAgcmV0dXJuIG1pbWVUeXBlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEludGVybmFsIG1ldGhvZCB0byBzdG9wIHRoZSByZWNvcmRpbmcgcHJvY2Vzc1xyXG4gICAqIFxyXG4gICAqIEBwcml2YXRlXHJcbiAgICogQHJldHVybnMgdm9pZFxyXG4gICAqL1xyXG4gIHByaXZhdGUgc3RvcFJlY29yZGluZ0ludGVybmFsKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMubWVkaWFSZWNvcmRlciAmJiAodGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlJlY29yZGluZyB8fCB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUGF1c2VkKSkge1xyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5zdHJlYW0/LmdldFRyYWNrcygpLmZvckVhY2godHJhY2sgPT4gdHJhY2suc3RvcCgpKTtcclxuICAgIHRoaXMuc3RyZWFtID0gbnVsbDtcclxuICAgIC8vIFN0YXRlIHdpbGwgYmUgdXBkYXRlZCBieSBvbnN0b3AgaGFuZGxlclxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgUHJvbWlzZTx2b2lkPlxyXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgcmVjb3JkaW5nIGlzIG5vdCBpbiBwcm9ncmVzc1xyXG4gICAqL1xyXG4gIHN0b3BSZWNvcmRpbmcoKTogdm9pZCB7XHJcbiAgICB0aGlzLnN0b3BSZWNvcmRpbmdJbnRlcm5hbCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUGF1c2VzIHRoZSBjdXJyZW50IHJlY29yZGluZ1xyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2U8dm9pZD5cclxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHJlY29yZGluZyBpcyBub3QgaW4gcHJvZ3Jlc3NcclxuICAgKi9cclxuICBwYXVzZVJlY29yZGluZygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm1lZGlhUmVjb3JkZXIgJiYgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlJlY29yZGluZykge1xyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIucGF1c2UoKTtcclxuICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChSZWNvcmRpbmdTdGF0ZS5QYXVzZWQpO1xyXG4gICAgICB0aGlzLnN0b3BUaW1lcigpOyAvLyBQYXVzZXMgdGhlIHRpbWVyIGRpc3BsYXlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlc3VtZXMgYSBwYXVzZWQgcmVjb3JkaW5nXHJcbiAgICogXHJcbiAgICogQHJldHVybnMgUHJvbWlzZTx2b2lkPlxyXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgcmVjb3JkaW5nIGlzIG5vdCBwYXVzZWRcclxuICAgKi9cclxuICByZXN1bWVSZWNvcmRpbmcoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5tZWRpYVJlY29yZGVyICYmIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5QYXVzZWQpIHtcclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnJlc3VtZSgpO1xyXG4gICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLlJlY29yZGluZyk7XHJcbiAgICAgIHRoaXMuc3RhcnRUaW1lcih0aGlzLmN1cnJlbnRSZWNvcmRlZFRpbWUpOyAvLyBSZXN1bWVzIHRpbWVyIGRpc3BsYXlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFxyXG4gICAqIEBwYXJhbSBmaWxlTmFtZSBcclxuICAgKi9cclxuICBkb3dubG9hZFJlY29yZGluZyhmaWxlTmFtZTogc3RyaW5nID0gJ3JlY29yZGluZy53ZWJtJyk6IHZvaWQge1xyXG4gICAgY29uc3QgdXJsID0gdGhpcy5yZWNvcmRlZFVybFN1YmplY3QudmFsdWU7XHJcbiAgICBjb25zdCB0aW1lc3RhbXAgPSB0aGlzLnJlY29yZGluZ1RpbWVzdGFtcFN1YmplY3QudmFsdWU7XHJcblxyXG4gICAgaWYgKHVybCAmJiB0aW1lc3RhbXApIHtcclxuICAgICAgLy8gRm9ybWF0IHRoZSB0aW1lc3RhbXAgZm9yIGZpbGVuYW1lIChyZW1vdmUgc3BhY2VzIGFuZCBzcGVjaWFsIGNoYXJhY3RlcnMpXHJcbiAgICAgIGNvbnN0IGZvcm1hdHRlZFRpbWVzdGFtcCA9IHRpbWVzdGFtcC5yZXBsYWNlKC9bXmEtekEtWjAtOV0vZywgJ18nKTtcclxuICAgICAgLy8gQ3JlYXRlIGZpbGVuYW1lIHdpdGggdGltZXN0YW1wXHJcbiAgICAgIGNvbnN0IGZpbGVFeHRlbnNpb24gPSBmaWxlTmFtZS5zcGxpdCgnLicpLnBvcCgpIHx8ICd3ZWJtJztcclxuICAgICAgY29uc3QgbmV3RmlsZU5hbWUgPSBgc2NyZWVuX3JlY29yZGluZ18ke2Zvcm1hdHRlZFRpbWVzdGFtcH0uJHtmaWxlRXh0ZW5zaW9ufWA7XHJcblxyXG4gICAgICBjb25zdCBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xyXG4gICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XHJcbiAgICAgIGEuaHJlZiA9IHVybDtcclxuICAgICAgYS5kb3dubG9hZCA9IG5ld0ZpbGVOYW1lO1xyXG4gICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xyXG4gICAgICBhLmNsaWNrKCk7XHJcbiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XHJcbiAgICAgIC8vIE5vIG5lZWQgdG8gcmV2b2tlIFVSTCBoZXJlIGlmIHVzZXIgbWlnaHQgd2FudCB0byBwbGF5IGl0IGFnYWluLlxyXG4gICAgICAvLyBSZXZva2Ugb24gY2xlYW51cCBvciBuZXcgcmVjb3JkaW5nLlxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5oYW5kbGVFcnJvcih0aGlzLnNjcmVlblJlY29yZGluZ0NvbnN0YW50Lk5PX1JFQ09SRElOR19ET1dOTE9BRCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICogU3RhcnRzIHRoZSByZWNvcmRpbmcgdGltZXJcclxuICogXHJcbiAqIEBwYXJhbSBzdGFydFRpbWUgLSBPcHRpb25hbCBzdGFydCB0aW1lIGZvciB0aGUgdGltZXJcclxuICogQHByaXZhdGVcclxuICogQHJldHVybnMgdm9pZFxyXG4gKi9cclxuICBwcml2YXRlIHN0YXJ0VGltZXIoc3RhcnRUaW1lOiBudW1iZXIgPSAwKTogdm9pZCB7XHJcbiAgICB0aGlzLnN0b3BUaW1lcigpOyAvLyBFbnN1cmUgbm8gbXVsdGlwbGUgdGltZXJzXHJcbiAgICB0aGlzLmN1cnJlbnRSZWNvcmRlZFRpbWUgPSBzdGFydFRpbWU7XHJcbiAgICB0aGlzLnJlY29yZGVkVGltZVN1YmplY3QubmV4dCh0aGlzLmN1cnJlbnRSZWNvcmRlZFRpbWUpO1xyXG5cclxuICAgIHRoaXMudGltZXJTdWJzY3JpcHRpb24gPSB0aW1lcigwLCAxMDAwKVxyXG4gICAgICAucGlwZShcclxuICAgICAgICB0YXAoKCkgPT4ge1xyXG4gICAgICAgICAgaWYgKHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcpIHtcclxuICAgICAgICAgICAgdGhpcy5jdXJyZW50UmVjb3JkZWRUaW1lKys7XHJcbiAgICAgICAgICAgIHRoaXMucmVjb3JkZWRUaW1lU3ViamVjdC5uZXh0KHRoaXMuY3VycmVudFJlY29yZGVkVGltZSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgdGFrZVdoaWxlKCgpID0+IHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcpXHJcbiAgICAgIClcclxuICAgICAgLnN1YnNjcmliZSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU3RvcHMgdGhlIHJlY29yZGluZyB0aW1lclxyXG4gICAqIFxyXG4gICAqIEBwcml2YXRlXHJcbiAgICogQHJldHVybnMgdm9pZFxyXG4gICAqL1xyXG4gIHByaXZhdGUgc3RvcFRpbWVyKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMudGltZXJTdWJzY3JpcHRpb24pIHtcclxuICAgICAgdGhpcy50aW1lclN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xyXG4gICAgICB0aGlzLnRpbWVyU3Vic2NyaXB0aW9uID0gbnVsbDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENsZWFucyB1cCByZXNvdXJjZXMgZnJvbSBwcmV2aW91cyByZWNvcmRpbmdcclxuICAgKiBcclxuICAgKiBAcHJpdmF0ZVxyXG4gICAqIEByZXR1cm5zIHZvaWRcclxuICAgKi9cclxuICBwcml2YXRlIGNsZWFudXBQcmV2aW91c1JlY29yZGluZygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnJlY29yZGVkVXJsU3ViamVjdC52YWx1ZSkge1xyXG4gICAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh0aGlzLnJlY29yZGVkVXJsU3ViamVjdC52YWx1ZSk7XHJcbiAgICAgIHRoaXMucmVjb3JkZWRVcmxTdWJqZWN0Lm5leHQobnVsbCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnJlY29yZGVkQmxvYnMgPSBbXTtcclxuICAgIHRoaXMuY3VycmVudFJlY29yZGVkVGltZSA9IDA7XHJcbiAgICB0aGlzLnJlY29yZGVkVGltZVN1YmplY3QubmV4dCgwKTtcclxuICAgIGlmICh0aGlzLnN0cmVhbSkge1xyXG4gICAgICB0aGlzLnN0cmVhbS5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHRyYWNrLnN0b3AoKSk7XHJcbiAgICAgIHRoaXMuc3RyZWFtID0gbnVsbDtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLm1lZGlhUmVjb3JkZXIgJiYgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXRlICE9PSB0aGlzLnNjcmVlblJlY29yZGluZ0NvbnN0YW50LklOQUNUSVZFKSB7XHJcbiAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5zdG9wKCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLm1lZGlhUmVjb3JkZXIgPSBudWxsO1xyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gKiBSZXNldHMgdGhlIHJlY29yZGluZyBzdGF0ZSB0byBpZGxlXHJcbiAqIFxyXG4gKiBAcmV0dXJucyB2b2lkXHJcbiAqL1xyXG4gIHJlc2V0VG9JZGxlKCk6IHZvaWQge1xyXG4gICAgdGhpcy5jbGVhbnVwUHJldmlvdXNSZWNvcmRpbmcoKTtcclxuICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoUmVjb3JkaW5nU3RhdGUuSWRsZSk7XHJcbiAgICB0aGlzLmVycm9yU3ViamVjdC5uZXh0KCcnKTsgLy8gQ2xlYXIgYW55IHByZXZpb3VzIGVycm9yc1xyXG4gIH1cclxuXHJcblxyXG4gIC8qKlxyXG4gKiBIYW5kbGVzIGFuZCBicm9hZGNhc3RzIHJlY29yZGluZyBlcnJvcnNcclxuICogXHJcbiAqIEBwcml2YXRlXHJcbiAqIEBwYXJhbSBlcnJvciAtIFRoZSBlcnJvciBtZXNzYWdlIHRvIGhhbmRsZVxyXG4gKiBAcmV0dXJucyB2b2lkXHJcbiAqL1xyXG4gIHByaXZhdGUgaGFuZGxlRXJyb3IoZXJyb3I6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5lcnJvclN1YmplY3QubmV4dChlcnJvcik7XHJcbiAgfVxyXG59XHJcbiJdfQ==
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './index';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjLWxpYi1zY3JlZW4tcmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVjLWxpYi1zY3JlZW4tcmVjb3JkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLFNBQVMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9pbmRleCc7XG4iXX0=
|