@ruc-lib/screen-recorder 2.9.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 +134 -0
- 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/esm2020/ruclib-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/fesm2015/ruclib-screen-recorder.mjs +644 -0
- package/fesm2015/ruclib-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/fesm2020/ruclib-screen-recorder.mjs +648 -0
- package/fesm2020/ruclib-screen-recorder.mjs.map +1 -0
- package/index.d.ts +4 -0
- 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 +38 -0
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyZWVuLXJlY29yZGVyLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL3J1Y2xpYi9zY3JlZW4tcmVjb3JkZXIvc3JjL2xpYi9zZXJ2aWNlcy9zY3JlZW4tcmVjb3JkZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQWMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNuRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQzs7O0FBSXRGLE1BQU0sT0FBTyxxQkFBcUI7SUFzQmhDLFlBQW1CLHVCQUFnRDtRQUFoRCw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQXlCO1FBckIzRCxXQUFNLEdBQXVCLElBQUksQ0FBQztRQUNsQyxrQkFBYSxHQUF5QixJQUFJLENBQUM7UUFDM0Msa0JBQWEsR0FBVyxFQUFFLENBQUM7UUFFM0Isd0JBQW1CLEdBQVcsQ0FBQyxDQUFDO1FBRXZCLDBCQUFxQixHQUFHLElBQUksZUFBZSxDQUFpQixjQUFjLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekYsb0JBQWUsR0FBK0IsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFlBQVksRUFBRSxDQUFDO1FBRWhGLHdCQUFtQixHQUFHLElBQUksZUFBZSxDQUFTLENBQUMsQ0FBQyxDQUFDO1FBQzdELGtCQUFhLEdBQXVCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUVwRSx1QkFBa0IsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsSUFBSSxDQUFDLENBQUM7UUFDdEUsaUJB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QXVCLENBQUMsUUFBUSxFQUFFO1lBQzVGLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDM0I7UUFDRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztJQUM1QixDQUFDO0lBR0Q7Ozs7S0FJQztJQUNELFdBQVc7UUFDVCxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztRQUNoQyxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLDRCQUE0QjtJQUMxRCxDQUFDO0lBR0Q7Ozs7OztLQU1DO0lBQ08sV0FBVyxDQUFDLEtBQWE7UUFDL0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDaEMsQ0FBQzs7bUhBcFdVLHFCQUFxQjt1SEFBckIscUJBQXFCLGNBRnBCLE1BQU07NEZBRVAscUJBQXFCO2tCQUhqQyxVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNLEVBQUUseUNBQXlDO2lCQUM5RCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBTdWJqZWN0LCB0aW1lciB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyB0YWtlV2hpbGUsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgUmVjb3JkaW5nU3RhdGUgfSBmcm9tICcuLi9tb2RlbHMvc2NyZWVuLXJlY29yZGVyLm1vZGVscyc7XHJcbmltcG9ydCB7IFNjcmVlblJlY29yZGVyQ29uc3RhbnRzIH0gZnJvbSAnLi4vc2NyZWVuLXJlY29yZGVyL3NjcmVlbi1yZWNvcmRlci1jb25zdGFudCc7XHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCcsIC8vIE9yIHByb3ZpZGUgaW4geW91ciBtb2R1bGUgaWYgcHJlZmVycmVkXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBTY3JlZW5SZWNvcmRlclNlcnZpY2Uge1xyXG4gIHByaXZhdGUgc3RyZWFtOiBNZWRpYVN0cmVhbSB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgbWVkaWFSZWNvcmRlcjogTWVkaWFSZWNvcmRlciB8IG51bGwgPSBudWxsO1xyXG4gIHByaXZhdGUgcmVjb3JkZWRCbG9iczogQmxvYltdID0gW107XHJcbiAgcHJpdmF0ZSB0aW1lclN1YnNjcmlwdGlvbjogYW55O1xyXG4gIHByaXZhdGUgY3VycmVudFJlY29yZGVkVGltZTogbnVtYmVyID0gMDtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZWNvcmRpbmdTdGF0ZVN1YmplY3QgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFJlY29yZGluZ1N0YXRlPihSZWNvcmRpbmdTdGF0ZS5JZGxlKTtcclxuICByZWFkb25seSByZWNvcmRpbmdTdGF0ZSQ6IE9ic2VydmFibGU8UmVjb3JkaW5nU3RhdGU+ID0gdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVjb3JkZWRUaW1lU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8bnVtYmVyPigwKTtcclxuICByZWFkb25seSByZWNvcmRlZFRpbWUkOiBPYnNlcnZhYmxlPG51bWJlcj4gPSB0aGlzLnJlY29yZGVkVGltZVN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVjb3JkZWRVcmxTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuICByZWFkb25seSByZWNvcmRlZFVybCQ6IE9ic2VydmFibGU8c3RyaW5nIHwgbnVsbD4gPSB0aGlzLnJlY29yZGVkVXJsU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgcHJpdmF0ZSByZWFkb25seSByZWNvcmRpbmdUaW1lc3RhbXBTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcclxuICByZWFkb25seSByZWNvcmRpbmdUaW1lc3RhbXAkOiBPYnNlcnZhYmxlPHN0cmluZz4gPSB0aGlzLnJlY29yZGluZ1RpbWVzdGFtcFN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgZXJyb3JTdWJqZWN0ID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xyXG4gIHJlYWRvbmx5IGVycm9yJDogT2JzZXJ2YWJsZTxzdHJpbmc+ID0gdGhpcy5lcnJvclN1YmplY3QuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBzY3JlZW5SZWNvcmRpbmdDb25zdGFudDogU2NyZWVuUmVjb3JkZXJDb25zdGFudHMpIHsgfVxyXG5cclxuICAvKipcclxuICAgKiBTdGFydHMgdGhlIHNjcmVlbiByZWNvcmRpbmcgd2l0aCBvcHRpb25hbCBhdWRpb1xyXG4gICAqIFxyXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciByZWNvcmRpbmdcclxuICAgKiBAcGFyYW0gb3B0aW9ucy5hdWRpbyAtIFdoZXRoZXIgdG8gaW5jbHVkZSBhdWRpbyBpbiB0aGUgcmVjb3JkaW5nXHJcbiAgICogXHJcbiAgICogQHRocm93cyBFcnJvciBpZiByZWNvcmRpbmcgaXMgYWxyZWFkeSBpbiBwcm9ncmVzcyBvciBpZiBtZWRpYSBhY2Nlc3MgaXMgZGVuaWVkXHJcbiAgICogQHJldHVybnMgUHJvbWlzZTx2b2lkPlxyXG4gICAqL1xyXG4gIGFzeW5jIHN0YXJ0UmVjb3JkaW5nKG9wdGlvbnM6IHsgYXVkaW86IGJvb2xlYW4gfSk6IFByb21pc2U8dm9pZD4ge1xyXG5cclxuICAgIGlmICh0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUmVjb3JkaW5nIHx8IHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5QYXVzZWQpIHtcclxuICAgICAgdGhpcy5oYW5kbGVFcnJvcih0aGlzLnNjcmVlblJlY29yZGluZ0NvbnN0YW50LlJFQ09SRElOR19JTl9QUk9HUkVTU19FUlJPUik7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNsZWFudXBQcmV2aW91c1JlY29yZGluZygpO1xyXG5cclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIFRoZSBicm93c2VyJ3MgbmF0aXZlIHBpY2tlciBoYW5kbGVzIFwic3BlY2lmaWMgYXJlYVwiIHNlbGVjdGlvbiAod2luZG93LCB0YWIsIHNjcmVlbikuXHJcbiAgICAgIGNvbnN0IGRpc3BsYXlTdHJlYW0gPSBhd2FpdCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldERpc3BsYXlNZWRpYSh7XHJcbiAgICAgICAgdmlkZW86IHRydWVcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyBJZiBhdWRpbyBpcyBlbmFibGVkLCBnZXQgdGhlIGF1ZGlvIHN0cmVhbVxyXG4gICAgICBsZXQgYXVkaW9TdHJlYW06IE1lZGlhU3RyZWFtIHwgbnVsbCA9IG51bGw7XHJcbiAgICAgIGlmIChvcHRpb25zLmF1ZGlvKSB7XHJcbiAgICAgICAgYXVkaW9TdHJlYW0gPSBhd2FpdCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7XHJcbiAgICAgICAgICBhdWRpbzoge1xyXG4gICAgICAgICAgICBlY2hvQ2FuY2VsbGF0aW9uOiB0cnVlLFxyXG4gICAgICAgICAgICBub2lzZVN1cHByZXNzaW9uOiB0cnVlLFxyXG4gICAgICAgICAgICBzYW1wbGVSYXRlOiA0NDEwMFxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDb21iaW5lIHRoZSBzdHJlYW1zIGlmIGF1ZGlvIGlzIGVuYWJsZWRcclxuICAgICAgaWYgKGF1ZGlvU3RyZWFtKSB7XHJcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBuZXcgTWVkaWFTdHJlYW0oWy4uLmRpc3BsYXlTdHJlYW0uZ2V0VHJhY2tzKCksIC4uLmF1ZGlvU3RyZWFtLmdldFRyYWNrcygpXSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5zdHJlYW0gPSBkaXNwbGF5U3RyZWFtO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBMaXN0ZW4gZm9yIHdoZW4gdGhlIHVzZXIgc3RvcHMgc2hhcmluZyB2aWEgYnJvd3NlciBVSVxyXG4gICAgICB0aGlzLnN0cmVhbS5nZXRWaWRlb1RyYWNrcygpWzBdLm9uZW5kZWQgPSAoKSA9PiB7XHJcbiAgICAgICAgaWYgKHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcgfHwgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlBhdXNlZCkge1xyXG4gICAgICAgICAgdGhpcy5zdG9wUmVjb3JkaW5nSW50ZXJuYWwoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcblxyXG4gICAgICAvLyBIYW5kbGUgZXJyb3JzXHJcbiAgICAgIGlmICghdGhpcy5zdHJlYW0pIHtcclxuICAgICAgICB0aGlzLmhhbmRsZUVycm9yKHRoaXMuc2NyZWVuUmVjb3JkaW5nQ29uc3RhbnQuRkFJTEVEX1RPX0dFVF9ESVNQTEFZX01FRElBX1NUUkVBTV9FUlJPUik7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBTZXQgcmVjb3JkaW5nIHRpbWVzdGFtcFxyXG4gICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xyXG4gICAgICBjb25zdCB0aW1lc3RhbXAgPSBub3cudG9Mb2NhbGVTdHJpbmcoJ2VuLUlOJywge1xyXG4gICAgICAgIHllYXI6ICdudW1lcmljJyxcclxuICAgICAgICBtb250aDogJzItZGlnaXQnLFxyXG4gICAgICAgIGRheTogJzItZGlnaXQnLFxyXG4gICAgICAgIGhvdXI6ICcyLWRpZ2l0JyxcclxuICAgICAgICBtaW51dGU6ICcyLWRpZ2l0JyxcclxuICAgICAgICBob3VyMTI6IHRydWVcclxuICAgICAgfSk7XHJcbiAgICAgIHRoaXMucmVjb3JkaW5nVGltZXN0YW1wU3ViamVjdC5uZXh0KHRpbWVzdGFtcCk7XHJcblxyXG5cclxuICAgICAgdGhpcy5yZWNvcmRlZEJsb2JzID0gW107XHJcbiAgICAgIGNvbnN0IG1pbWVUeXBlID0gdGhpcy5nZXRTdXBwb3J0ZWRNaW1lVHlwZSgpO1xyXG4gICAgICBpZiAoIW1pbWVUeXBlKSB7XHJcbiAgICAgICAgdGhpcy5oYW5kbGVFcnJvcih0aGlzLnNjcmVlblJlY29yZGluZ0NvbnN0YW50Lk5PX1NVUFBPUlRfTUlNRSk7XHJcbiAgICAgICAgdGhpcy5zdHJlYW0/LmdldFRyYWNrcygpLmZvckVhY2godHJhY2sgPT4gdHJhY2suc3RvcCgpKTtcclxuICAgICAgICB0aGlzLnN0cmVhbSA9IG51bGw7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDcmVhdGUgYSBjYW52YXMgZm9yIHRpbWVzdGFtcCBvdmVybGF5XHJcbiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xyXG4gICAgICBjb25zdCB2aWRlb1RyYWNrID0gdGhpcy5zdHJlYW0/LmdldFZpZGVvVHJhY2tzKClbMF07XHJcbiAgICAgIGlmICh2aWRlb1RyYWNrKSB7XHJcbiAgICAgICAgY29uc3QgdmlkZW8gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpO1xyXG4gICAgICAgIHZpZGVvLnNyY09iamVjdCA9IHRoaXMuc3RyZWFtO1xyXG5cclxuICAgICAgICAvLyBXYWl0IGZvciB2aWRlbyB0byBsb2FkIG1ldGFkYXRhXHJcbiAgICAgICAgdmlkZW8ub25sb2FkZWRtZXRhZGF0YSA9ICgpID0+IHtcclxuICAgICAgICAgIGNhbnZhcy53aWR0aCA9IHZpZGVvLnZpZGVvV2lkdGg7XHJcbiAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gdmlkZW8udmlkZW9IZWlnaHQ7XHJcbiAgICAgICAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcclxuICAgICAgICAgIGlmIChjdHgpIHtcclxuICAgICAgICAgICAgLy8gRHJhdyB2aWRlbyBmcmFtZVxyXG4gICAgICAgICAgICBjdHguZHJhd0ltYWdlKHZpZGVvLCAwLCAwKTtcclxuXHJcbiAgICAgICAgICAgIC8vIERyYXcgdGltZXN0YW1wXHJcbiAgICAgICAgICAgIGN0eC5mb250ID0gJzE2cHggQXJpYWwnO1xyXG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gJ3doaXRlJztcclxuICAgICAgICAgICAgY3R4LnRleHRBbGlnbiA9ICdyaWdodCc7XHJcbiAgICAgICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAndG9wJztcclxuICAgICAgICAgICAgY3R4LmZpbGxUZXh0KGBSZWNvcmRlZCBvbjogJHt0aGlzLnJlY29yZGluZ1RpbWVzdGFtcFN1YmplY3QudmFsdWV9YCwgY2FudmFzLndpZHRoIC0gMTAsIDEwKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDcmVhdGUgYSBuZXcgc3RyZWFtIHdpdGggdGhlIGNhbnZhc1xyXG4gICAgICBjb25zdCBjYW52YXNTdHJlYW0gPSBjYW52YXMuY2FwdHVyZVN0cmVhbSgpO1xyXG4gICAgICBjb25zdCBjb21iaW5lZFN0cmVhbSA9IG5ldyBNZWRpYVN0cmVhbShbLi4udGhpcy5zdHJlYW0/LmdldFRyYWNrcygpID8/IFtdLCBjYW52YXNTdHJlYW0uZ2V0VmlkZW9UcmFja3MoKVswXV0pO1xyXG5cclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbmV3IE1lZGlhUmVjb3JkZXIoY29tYmluZWRTdHJlYW0sIHsgbWltZVR5cGUgfSk7XHJcblxyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25kYXRhYXZhaWxhYmxlID0gKGV2ZW50KSA9PiB7XHJcbiAgICAgICAgaWYgKGV2ZW50LmRhdGEgJiYgZXZlbnQuZGF0YS5zaXplID4gMCkge1xyXG4gICAgICAgICAgdGhpcy5yZWNvcmRlZEJsb2JzLnB1c2goZXZlbnQuZGF0YSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG5cclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLm9uc3RvcCA9ICgpID0+IHtcclxuICAgICAgICBjb25zdCBzdXBlckJ1ZmZlciA9IG5ldyBCbG9iKHRoaXMucmVjb3JkZWRCbG9icywgeyB0eXBlOiBtaW1lVHlwZSB9KTtcclxuICAgICAgICBjb25zdCB1cmwgPSB3aW5kb3cuVVJMLmNyZWF0ZU9iamVjdFVSTChzdXBlckJ1ZmZlcik7XHJcbiAgICAgICAgdGhpcy5yZWNvcmRlZFVybFN1YmplY3QubmV4dCh1cmwpO1xyXG4gICAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoUmVjb3JkaW5nU3RhdGUuU3RvcHBlZCk7XHJcbiAgICAgICAgdGhpcy5zdG9wVGltZXIoKTtcclxuXHJcbiAgICAgIH07XHJcblxyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIub25lcnJvciA9IChldmVudDogRXZlbnQpID0+IHtcclxuICAgICAgICBjb25zdCBlcnJvckV2ZW50ID0gZXZlbnQgYXMgRXJyb3JFdmVudDsgLy8gTW9yZSBzcGVjaWZpYyB0eXBlIGlmIGF2YWlsYWJsZVxyXG4gICAgICAgIGxldCBtZXNzYWdlID0gdGhpcy5zY3JlZW5SZWNvcmRpbmdDb25zdGFudC5NRURJQV9FUlJPUjtcclxuICAgICAgICBpZiAoZXJyb3JFdmVudC5lcnJvciAmJiBlcnJvckV2ZW50LmVycm9yLm5hbWUpIHtcclxuICAgICAgICAgIG1lc3NhZ2UgKz0gYDogJHtlcnJvckV2ZW50LmVycm9yLm5hbWV9YDtcclxuICAgICAgICAgIGlmIChlcnJvckV2ZW50LmVycm9yLm1lc3NhZ2UpIG1lc3NhZ2UgKz0gYCAtICR7ZXJyb3JFdmVudC5lcnJvci5tZXNzYWdlfWA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuaGFuZGxlRXJyb3IobWVzc2FnZSk7XHJcbiAgICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChSZWNvcmRpbmdTdGF0ZS5JZGxlKTtcclxuICAgICAgICB0aGlzLnN0b3BUaW1lcigpO1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0YXJ0KCk7IC8vIFN0YXJ0IHJlY29yZGluZ1xyXG4gICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLlJlY29yZGluZyk7XHJcbiAgICAgIHRoaXMuc3RhcnRUaW1lcigpO1xyXG4gICAgfSBjYXRjaCAoZXJyOiBhbnkpIHtcclxuICAgICAgdGhpcy5oYW5kbGVFcnJvcihgRXJyb3Igc3RhcnRpbmcgc2NyZWVuIHJlY29yZGluZzogJHtlcnIubmFtZX0gLSAke2Vyci5tZXNzYWdlfWApO1xyXG4gICAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLklkbGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAqIEdldHMgdGhlIGZpcnN0IHN1cHBvcnRlZCBNSU1FIHR5cGUgZm9yIE1lZGlhUmVjb3JkZXJcclxuICogXHJcbiAqIEByZXR1cm5zIHN0cmluZ3xudWxsIC0gVGhlIHN1cHBvcnRlZCBNSU1FIHR5cGUgb3IgbnVsbCBpZiBub25lIGZvdW5kXHJcbiAqL1xyXG4gIHByaXZhdGUgZ2V0U3VwcG9ydGVkTWltZVR5cGUoKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBjb25zdCBtaW1lVHlwZXMgPSBbXHJcbiAgICAgICd2aWRlby93ZWJtO2NvZGVjcz12cDksb3B1cycsXHJcbiAgICAgICd2aWRlby93ZWJtO2NvZGVjcz12cDgsb3B1cycsXHJcbiAgICAgICd2aWRlby93ZWJtO2NvZGVjcz1oMjY0LG9wdXMnLFxyXG4gICAgICAndmlkZW8vbXA0O2NvZGVjcz1oMjY0LGFhYycsIC8vIE1QNCBtaWdodCBoYXZlIGJyb2FkZXIgY29tcGF0aWJpbGl0eSBidXQgbGVzcyBicm93c2VyIHN1cHBvcnQgZm9yIHJlY29yZGluZ1xyXG4gICAgICAndmlkZW8vd2VibScsXHJcbiAgICBdO1xyXG4gICAgZm9yIChjb25zdCBtaW1lVHlwZSBvZiBtaW1lVHlwZXMpIHtcclxuICAgICAgaWYgKE1lZGlhUmVjb3JkZXIuaXNUeXBlU3VwcG9ydGVkKG1pbWVUeXBlKSkge1xyXG4gICAgICAgIHJldHVybiBtaW1lVHlwZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBJbnRlcm5hbCBtZXRob2QgdG8gc3RvcCB0aGUgcmVjb3JkaW5nIHByb2Nlc3NcclxuICAgKiBcclxuICAgKiBAcHJpdmF0ZVxyXG4gICAqIEByZXR1cm5zIHZvaWRcclxuICAgKi9cclxuICBwcml2YXRlIHN0b3BSZWNvcmRpbmdJbnRlcm5hbCgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLm1lZGlhUmVjb3JkZXIgJiYgKHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcgfHwgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QudmFsdWUgPT09IFJlY29yZGluZ1N0YXRlLlBhdXNlZCkpIHtcclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnN0b3AoKTtcclxuICAgIH1cclxuICAgIHRoaXMuc3RyZWFtPy5nZXRUcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHRyYWNrLnN0b3AoKSk7XHJcbiAgICB0aGlzLnN0cmVhbSA9IG51bGw7XHJcbiAgICAvLyBTdGF0ZSB3aWxsIGJlIHVwZGF0ZWQgYnkgb25zdG9wIGhhbmRsZXJcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2U8dm9pZD5cclxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHJlY29yZGluZyBpcyBub3QgaW4gcHJvZ3Jlc3NcclxuICAgKi9cclxuICBzdG9wUmVjb3JkaW5nKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zdG9wUmVjb3JkaW5nSW50ZXJuYWwoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBhdXNlcyB0aGUgY3VycmVudCByZWNvcmRpbmdcclxuICAgKiBcclxuICAgKiBAcmV0dXJucyBQcm9taXNlPHZvaWQ+XHJcbiAgICogQHRocm93cyBFcnJvciBpZiByZWNvcmRpbmcgaXMgbm90IGluIHByb2dyZXNzXHJcbiAgICovXHJcbiAgcGF1c2VSZWNvcmRpbmcoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5tZWRpYVJlY29yZGVyICYmIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0LnZhbHVlID09PSBSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcpIHtcclxuICAgICAgdGhpcy5tZWRpYVJlY29yZGVyLnBhdXNlKCk7XHJcbiAgICAgIHRoaXMucmVjb3JkaW5nU3RhdGVTdWJqZWN0Lm5leHQoUmVjb3JkaW5nU3RhdGUuUGF1c2VkKTtcclxuICAgICAgdGhpcy5zdG9wVGltZXIoKTsgLy8gUGF1c2VzIHRoZSB0aW1lciBkaXNwbGF5XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZXN1bWVzIGEgcGF1c2VkIHJlY29yZGluZ1xyXG4gICAqIFxyXG4gICAqIEByZXR1cm5zIFByb21pc2U8dm9pZD5cclxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHJlY29yZGluZyBpcyBub3QgcGF1c2VkXHJcbiAgICovXHJcbiAgcmVzdW1lUmVjb3JkaW5nKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMubWVkaWFSZWNvcmRlciAmJiB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUGF1c2VkKSB7XHJcbiAgICAgIHRoaXMubWVkaWFSZWNvcmRlci5yZXN1bWUoKTtcclxuICAgICAgdGhpcy5yZWNvcmRpbmdTdGF0ZVN1YmplY3QubmV4dChSZWNvcmRpbmdTdGF0ZS5SZWNvcmRpbmcpO1xyXG4gICAgICB0aGlzLnN0YXJ0VGltZXIodGhpcy5jdXJyZW50UmVjb3JkZWRUaW1lKTsgLy8gUmVzdW1lcyB0aW1lciBkaXNwbGF5XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBcclxuICAgKiBAcGFyYW0gZmlsZU5hbWUgXHJcbiAgICovXHJcbiAgZG93bmxvYWRSZWNvcmRpbmcoZmlsZU5hbWU6IHN0cmluZyA9ICdyZWNvcmRpbmcud2VibScpOiB2b2lkIHtcclxuICAgIGNvbnN0IHVybCA9IHRoaXMucmVjb3JkZWRVcmxTdWJqZWN0LnZhbHVlO1xyXG4gICAgY29uc3QgdGltZXN0YW1wID0gdGhpcy5yZWNvcmRpbmdUaW1lc3RhbXBTdWJqZWN0LnZhbHVlO1xyXG5cclxuICAgIGlmICh1cmwgJiYgdGltZXN0YW1wKSB7XHJcbiAgICAgIC8vIEZvcm1hdCB0aGUgdGltZXN0YW1wIGZvciBmaWxlbmFtZSAocmVtb3ZlIHNwYWNlcyBhbmQgc3BlY2lhbCBjaGFyYWN0ZXJzKVxyXG4gICAgICBjb25zdCBmb3JtYXR0ZWRUaW1lc3RhbXAgPSB0aW1lc3RhbXAucmVwbGFjZSgvW15hLXpBLVowLTldL2csICdfJyk7XHJcbiAgICAgIC8vIENyZWF0ZSBmaWxlbmFtZSB3aXRoIHRpbWVzdGFtcFxyXG4gICAgICBjb25zdCBmaWxlRXh0ZW5zaW9uID0gZmlsZU5hbWUuc3BsaXQoJy4nKS5wb3AoKSB8fCAnd2VibSc7XHJcbiAgICAgIGNvbnN0IG5ld0ZpbGVOYW1lID0gYHNjcmVlbl9yZWNvcmRpbmdfJHtmb3JtYXR0ZWRUaW1lc3RhbXB9LiR7ZmlsZUV4dGVuc2lvbn1gO1xyXG5cclxuICAgICAgY29uc3QgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcclxuICAgICAgYS5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xyXG4gICAgICBhLmhyZWYgPSB1cmw7XHJcbiAgICAgIGEuZG93bmxvYWQgPSBuZXdGaWxlTmFtZTtcclxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTtcclxuICAgICAgYS5jbGljaygpO1xyXG4gICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGEpO1xyXG4gICAgICAvLyBObyBuZWVkIHRvIHJldm9rZSBVUkwgaGVyZSBpZiB1c2VyIG1pZ2h0IHdhbnQgdG8gcGxheSBpdCBhZ2Fpbi5cclxuICAgICAgLy8gUmV2b2tlIG9uIGNsZWFudXAgb3IgbmV3IHJlY29yZGluZy5cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuaGFuZGxlRXJyb3IodGhpcy5zY3JlZW5SZWNvcmRpbmdDb25zdGFudC5OT19SRUNPUkRJTkdfRE9XTkxPQUQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAqIFN0YXJ0cyB0aGUgcmVjb3JkaW5nIHRpbWVyXHJcbiAqIFxyXG4gKiBAcGFyYW0gc3RhcnRUaW1lIC0gT3B0aW9uYWwgc3RhcnQgdGltZSBmb3IgdGhlIHRpbWVyXHJcbiAqIEBwcml2YXRlXHJcbiAqIEByZXR1cm5zIHZvaWRcclxuICovXHJcbiAgcHJpdmF0ZSBzdGFydFRpbWVyKHN0YXJ0VGltZTogbnVtYmVyID0gMCk6IHZvaWQge1xyXG4gICAgdGhpcy5zdG9wVGltZXIoKTsgLy8gRW5zdXJlIG5vIG11bHRpcGxlIHRpbWVyc1xyXG4gICAgdGhpcy5jdXJyZW50UmVjb3JkZWRUaW1lID0gc3RhcnRUaW1lO1xyXG4gICAgdGhpcy5yZWNvcmRlZFRpbWVTdWJqZWN0Lm5leHQodGhpcy5jdXJyZW50UmVjb3JkZWRUaW1lKTtcclxuXHJcbiAgICB0aGlzLnRpbWVyU3Vic2NyaXB0aW9uID0gdGltZXIoMCwgMTAwMClcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgdGFwKCgpID0+IHtcclxuICAgICAgICAgIGlmICh0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUmVjb3JkaW5nKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY3VycmVudFJlY29yZGVkVGltZSsrO1xyXG4gICAgICAgICAgICB0aGlzLnJlY29yZGVkVGltZVN1YmplY3QubmV4dCh0aGlzLmN1cnJlbnRSZWNvcmRlZFRpbWUpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pLFxyXG4gICAgICAgIHRha2VXaGlsZSgoKSA9PiB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC52YWx1ZSA9PT0gUmVjb3JkaW5nU3RhdGUuUmVjb3JkaW5nKVxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFN0b3BzIHRoZSByZWNvcmRpbmcgdGltZXJcclxuICAgKiBcclxuICAgKiBAcHJpdmF0ZVxyXG4gICAqIEByZXR1cm5zIHZvaWRcclxuICAgKi9cclxuICBwcml2YXRlIHN0b3BUaW1lcigpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnRpbWVyU3Vic2NyaXB0aW9uKSB7XHJcbiAgICAgIHRoaXMudGltZXJTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcclxuICAgICAgdGhpcy50aW1lclN1YnNjcmlwdGlvbiA9IG51bGw7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhbnMgdXAgcmVzb3VyY2VzIGZyb20gcHJldmlvdXMgcmVjb3JkaW5nXHJcbiAgICogXHJcbiAgICogQHByaXZhdGVcclxuICAgKiBAcmV0dXJucyB2b2lkXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjbGVhbnVwUHJldmlvdXNSZWNvcmRpbmcoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5yZWNvcmRlZFVybFN1YmplY3QudmFsdWUpIHtcclxuICAgICAgd2luZG93LlVSTC5yZXZva2VPYmplY3RVUkwodGhpcy5yZWNvcmRlZFVybFN1YmplY3QudmFsdWUpO1xyXG4gICAgICB0aGlzLnJlY29yZGVkVXJsU3ViamVjdC5uZXh0KG51bGwpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5yZWNvcmRlZEJsb2JzID0gW107XHJcbiAgICB0aGlzLmN1cnJlbnRSZWNvcmRlZFRpbWUgPSAwO1xyXG4gICAgdGhpcy5yZWNvcmRlZFRpbWVTdWJqZWN0Lm5leHQoMCk7XHJcbiAgICBpZiAodGhpcy5zdHJlYW0pIHtcclxuICAgICAgdGhpcy5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5zdG9wKCkpO1xyXG4gICAgICB0aGlzLnN0cmVhbSA9IG51bGw7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5tZWRpYVJlY29yZGVyICYmIHRoaXMubWVkaWFSZWNvcmRlci5zdGF0ZSAhPT0gdGhpcy5zY3JlZW5SZWNvcmRpbmdDb25zdGFudC5JTkFDVElWRSkge1xyXG4gICAgICB0aGlzLm1lZGlhUmVjb3JkZXIuc3RvcCgpO1xyXG4gICAgfVxyXG4gICAgdGhpcy5tZWRpYVJlY29yZGVyID0gbnVsbDtcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICogUmVzZXRzIHRoZSByZWNvcmRpbmcgc3RhdGUgdG8gaWRsZVxyXG4gKiBcclxuICogQHJldHVybnMgdm9pZFxyXG4gKi9cclxuICByZXNldFRvSWRsZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xlYW51cFByZXZpb3VzUmVjb3JkaW5nKCk7XHJcbiAgICB0aGlzLnJlY29yZGluZ1N0YXRlU3ViamVjdC5uZXh0KFJlY29yZGluZ1N0YXRlLklkbGUpO1xyXG4gICAgdGhpcy5lcnJvclN1YmplY3QubmV4dCgnJyk7IC8vIENsZWFyIGFueSBwcmV2aW91cyBlcnJvcnNcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICogSGFuZGxlcyBhbmQgYnJvYWRjYXN0cyByZWNvcmRpbmcgZXJyb3JzXHJcbiAqIFxyXG4gKiBAcHJpdmF0ZVxyXG4gKiBAcGFyYW0gZXJyb3IgLSBUaGUgZXJyb3IgbWVzc2FnZSB0byBoYW5kbGVcclxuICogQHJldHVybnMgdm9pZFxyXG4gKi9cclxuICBwcml2YXRlIGhhbmRsZUVycm9yKGVycm9yOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuZXJyb3JTdWJqZWN0Lm5leHQoZXJyb3IpO1xyXG4gIH1cclxufVxyXG4iXX0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './index';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjLWxpYi1zY3JlZW4tcmVjb3JkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3J1Y2xpYi9zY3JlZW4tcmVjb3JkZXIvc3JjL3J1Yy1saWItc2NyZWVuLXJlY29yZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxTQUFTLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmVyYXRlZCBidW5kbGUgaW5kZXguIERvIG5vdCBlZGl0LlxuICovXG5cbmV4cG9ydCAqIGZyb20gJy4vaW5kZXgnO1xuIl19
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './index';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVjbGliLXNjcmVlbi1yZWNvcmRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL2xpYnMvcnVjbGliL3NjcmVlbi1yZWNvcmRlci9zcmMvcnVjbGliLXNjcmVlbi1yZWNvcmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsU0FBUyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHZW5lcmF0ZWQgYnVuZGxlIGluZGV4LiBEbyBub3QgZWRpdC5cbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL2luZGV4JztcbiJdfQ==
|