@macedon-technologies/batman 1.26.1 → 1.28.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/.jsii +12 -12
- package/API.md +4 -2
- package/lib/ApiConstructFile.js +2 -2
- package/lib/Application.js +5 -1
- package/lib/BatmanProject.js +2 -3
- package/lib/BootcampApplication.js +5 -1
- package/lib/BootcampProject.js +2 -3
- package/lib/CodeOwnersFile.js +1 -1
- package/lib/ProductionDeployWorkflow.js +1 -1
- package/lib/SecretConstructFile.d.ts +10 -0
- package/lib/SecretConstructFile.js +68 -0
- package/lib/SecretHandlerFiles.d.ts +11 -0
- package/lib/SecretHandlerFiles.js +189 -0
- package/lib/SoftwareFactoryBootstrap.d.ts +10 -0
- package/lib/SoftwareFactoryBootstrap.js +101 -0
- package/lib/SoftwareFactoryFiles.d.ts +4 -2
- package/lib/SoftwareFactoryFiles.js +10 -8
- package/lib/StagingDeployWorkflow.js +1 -1
- package/lib/ViteReactProject.js +471 -74
- package/lib/WorkflowAutoDiscover.js +1 -1
- package/lib/utils.js +26 -10
- package/package.json +1 -1
- package/swamp-bootstrap/pull-extensions.ts +68 -0
- package/swamp-bootstrap/tsconfig.json +13 -0
package/lib/ViteReactProject.js
CHANGED
|
@@ -295,23 +295,82 @@ ${baseConfigType}
|
|
|
295
295
|
|
|
296
296
|
${configTypeDefinition}
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
298
|
+
let shared: Promise<Config> | undefined;
|
|
299
|
+
let loaded: Config | undefined;
|
|
301
300
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
301
|
+
/** How long the shared load of /config.json may take before it is abandoned and fails. */
|
|
302
|
+
export const CONFIG_LOAD_TIMEOUT_MS = 15 * 1000;
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* The runtime config, loaded once and shared by every useConfig(); a failed load, including one
|
|
306
|
+
* abandoned after CONFIG_LOAD_TIMEOUT_MS, is tried again by the next caller.
|
|
307
|
+
*/
|
|
308
|
+
export function loadConfig(): Promise<Config> {
|
|
309
|
+
if (!shared) {
|
|
310
|
+
const controller = new AbortController();
|
|
311
|
+
const timer = setTimeout(() => controller.abort(), CONFIG_LOAD_TIMEOUT_MS);
|
|
312
|
+
const load: Promise<Config> = fetch('/config.json', { cache: 'no-store', signal: controller.signal })
|
|
313
|
+
.then((response) => {
|
|
314
|
+
if (!response.ok) {
|
|
315
|
+
throw new Error(\`Loading /config.json failed with status \${response.status}\`);
|
|
316
|
+
}
|
|
317
|
+
return response.json() as Promise<Config>;
|
|
318
|
+
})
|
|
319
|
+
.finally(() => clearTimeout(timer))
|
|
320
|
+
.then((config) => {
|
|
321
|
+
if (shared === load) {
|
|
322
|
+
loaded = config;
|
|
323
|
+
}
|
|
324
|
+
return config;
|
|
309
325
|
});
|
|
326
|
+
load.catch(() => {
|
|
327
|
+
if (shared === load) {
|
|
328
|
+
shared = undefined;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
shared = load;
|
|
332
|
+
}
|
|
333
|
+
return shared;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Forgets the shared config, so each test loads its own. */
|
|
337
|
+
export function resetConfigForTests(): void {
|
|
338
|
+
shared = undefined;
|
|
339
|
+
loaded = undefined;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export function useConfig() {
|
|
343
|
+
const [loadedConfig, setLoadedConfig] = useState<Config | undefined>(loaded);
|
|
344
|
+
const [isLoading, setIsLoading] = useState(!loaded);
|
|
345
|
+
const [error, setError] = useState<unknown>();
|
|
310
346
|
|
|
347
|
+
useEffect(() => {
|
|
348
|
+
if (loadedConfig) {
|
|
349
|
+
return undefined;
|
|
311
350
|
}
|
|
351
|
+
let live = true;
|
|
352
|
+
setIsLoading(true);
|
|
353
|
+
setError(undefined);
|
|
354
|
+
loadConfig().then(
|
|
355
|
+
(config) => {
|
|
356
|
+
if (live) {
|
|
357
|
+
setLoadedConfig(config);
|
|
358
|
+
setIsLoading(false);
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
(err) => {
|
|
362
|
+
if (live) {
|
|
363
|
+
setError(err);
|
|
364
|
+
setIsLoading(false);
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
);
|
|
368
|
+
return () => {
|
|
369
|
+
live = false;
|
|
370
|
+
};
|
|
312
371
|
}, [loadedConfig]);
|
|
313
372
|
|
|
314
|
-
return { config: loadedConfig, isLoading };
|
|
373
|
+
return { config: loadedConfig, isLoading, error };
|
|
315
374
|
}
|
|
316
375
|
`;
|
|
317
376
|
}
|
|
@@ -437,11 +496,11 @@ class ViteSampleCode extends projen_1.Component {
|
|
|
437
496
|
new projen_1.SampleFile(project, `${options.srcdir}/App.tsx`, {
|
|
438
497
|
contents: `import './App.css'
|
|
439
498
|
import { SignedIn, UserButton } from '@clerk/clerk-react';
|
|
440
|
-
import {
|
|
499
|
+
import { useApiQuery } from "./services/ApiService.ts";
|
|
441
500
|
|
|
442
501
|
|
|
443
502
|
function App() {
|
|
444
|
-
const {data, isLoading} =
|
|
503
|
+
const {data, isLoading} = useApiQuery('/', {retryOnMount: true});
|
|
445
504
|
|
|
446
505
|
|
|
447
506
|
return (
|
|
@@ -462,65 +521,7 @@ function App() {
|
|
|
462
521
|
export default App
|
|
463
522
|
`,
|
|
464
523
|
});
|
|
465
|
-
|
|
466
|
-
new projen_1.TextFile(project, `${options.srcdir}/services/BaseService.ts`, {
|
|
467
|
-
marker: true,
|
|
468
|
-
readonly: true,
|
|
469
|
-
lines: [
|
|
470
|
-
'import { useQuery, UseQueryOptions } from \'@tanstack/react-query\';',
|
|
471
|
-
'import { useAuth } from \'@clerk/clerk-react\';',
|
|
472
|
-
'import { useConfig } from \'../config\';',
|
|
473
|
-
'',
|
|
474
|
-
'export function useBaseQuery<TData = unknown>(',
|
|
475
|
-
' path: string,',
|
|
476
|
-
' options?: Omit<UseQueryOptions<TData>, \'queryKey\' | \'queryFn\'>',
|
|
477
|
-
') {',
|
|
478
|
-
' const { config } = useConfig();',
|
|
479
|
-
' const { getToken } = useAuth();',
|
|
480
|
-
'',
|
|
481
|
-
' return useQuery<TData>({',
|
|
482
|
-
' queryKey: [\'base\'],',
|
|
483
|
-
' queryFn: async () => {',
|
|
484
|
-
' if (!config?.apiBaseUrl) {',
|
|
485
|
-
' throw new Error(\'API base URL not configured\');',
|
|
486
|
-
' }',
|
|
487
|
-
'',
|
|
488
|
-
' const token = await getToken();',
|
|
489
|
-
'',
|
|
490
|
-
' // Normalize URL by removing trailing slash from baseUrl and ensuring path starts with slash',
|
|
491
|
-
' const baseUrl = config.apiBaseUrl.replace(/\\/+$/, \'\');',
|
|
492
|
-
' const normalizedPath = path.startsWith(\'/\') ? path : `/${path}`;',
|
|
493
|
-
' ',
|
|
494
|
-
' const response = await fetch(`${baseUrl}${normalizedPath}`, {',
|
|
495
|
-
' headers: {',
|
|
496
|
-
' \'Authorization\': `Bearer ${token}`,',
|
|
497
|
-
' },',
|
|
498
|
-
' });',
|
|
499
|
-
'',
|
|
500
|
-
' if (!response.ok) {',
|
|
501
|
-
' throw new Error(`HTTP error! status: ${response.status}`);',
|
|
502
|
-
' }',
|
|
503
|
-
'',
|
|
504
|
-
' return response.json();',
|
|
505
|
-
' },',
|
|
506
|
-
' enabled: !!config?.apiBaseUrl,',
|
|
507
|
-
' ...options,',
|
|
508
|
-
' });',
|
|
509
|
-
'}',
|
|
510
|
-
],
|
|
511
|
-
});
|
|
512
|
-
// Create RootService.ts
|
|
513
|
-
new projen_1.SampleFile(project, `${options.srcdir}/services/RootService.ts`, {
|
|
514
|
-
contents: `import { UseQueryOptions } from '@tanstack/react-query';
|
|
515
|
-
import { useBaseQuery } from './BaseService';
|
|
516
|
-
|
|
517
|
-
export function useRootQuery<TData = unknown>(
|
|
518
|
-
options?: Omit<UseQueryOptions<TData>, 'queryKey' | 'queryFn'>
|
|
519
|
-
) {
|
|
520
|
-
return useBaseQuery<TData>('/', options);
|
|
521
|
-
}
|
|
522
|
-
`,
|
|
523
|
-
});
|
|
524
|
+
new ApiServiceFiles(project, { srcdir: options.srcdir });
|
|
524
525
|
// Create App.css
|
|
525
526
|
new projen_1.SampleFile(project, `${options.srcdir}/App.css`, {
|
|
526
527
|
contents: `#root {
|
|
@@ -576,8 +577,15 @@ import { useConfig } from './config'
|
|
|
576
577
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
|
|
577
578
|
|
|
578
579
|
function AppWrapper() {
|
|
579
|
-
const { config, isLoading } = useConfig();
|
|
580
|
+
const { config, isLoading, error } = useConfig();
|
|
580
581
|
const queryClient = new QueryClient()
|
|
582
|
+
if (error) {
|
|
583
|
+
return (
|
|
584
|
+
<div className="loading-screen">
|
|
585
|
+
Could not load the app configuration.
|
|
586
|
+
</div>
|
|
587
|
+
);
|
|
588
|
+
}
|
|
581
589
|
if (isLoading || !config) {
|
|
582
590
|
return (
|
|
583
591
|
<div className="loading-screen">
|
|
@@ -673,6 +681,395 @@ html, body, #root {
|
|
|
673
681
|
});
|
|
674
682
|
}
|
|
675
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Bootstraps the web client's API layer: `services/ApiService.ts` (query and mutation hooks
|
|
686
|
+
* keyed per path) and the `helpers/` it is built on. Written once, then owned by the consumer.
|
|
687
|
+
*/
|
|
688
|
+
class ApiServiceFiles extends projen_1.Component {
|
|
689
|
+
constructor(project, options) {
|
|
690
|
+
super(project);
|
|
691
|
+
new projen_1.SampleFile(project, `${options.srcdir}/services/ApiService.ts`, {
|
|
692
|
+
contents: `import { useAuth } from '@clerk/clerk-react';
|
|
693
|
+
import { QueryClient, useMutation, UseMutationOptions, useQuery, UseQueryOptions } from '@tanstack/react-query';
|
|
694
|
+
import { useEffect, useMemo, useRef } from 'react';
|
|
695
|
+
import { loadConfig, useConfig } from '../config';
|
|
696
|
+
import { RequestCancelledError } from '../helpers/HttpError';
|
|
697
|
+
import { get, post, put, RequestOptions, TokenGetter } from '../helpers/requests';
|
|
698
|
+
|
|
699
|
+
/** The React Query key for an API path: its segments, so a prefix's key covers every path under it. */
|
|
700
|
+
export function apiQueryKey(path: string): string[] {
|
|
701
|
+
return path.split('/').filter(Boolean);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
export function invalidateApiQueries(queryClient: QueryClient, prefix: string): Promise<void> {
|
|
705
|
+
return queryClient.invalidateQueries({ queryKey: apiQueryKey(prefix), exact: false });
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
export function useApiQuery<TData = unknown>(
|
|
709
|
+
path: string,
|
|
710
|
+
options?: Omit<UseQueryOptions<TData>, 'queryKey' | 'queryFn'>,
|
|
711
|
+
) {
|
|
712
|
+
const { config } = useConfig();
|
|
713
|
+
const { getToken } = useAuth();
|
|
714
|
+
const { enabled, ...restOptions } = options ?? {};
|
|
715
|
+
|
|
716
|
+
return useQuery<TData>({
|
|
717
|
+
queryKey: apiQueryKey(path),
|
|
718
|
+
queryFn: ({ signal }) => get<TData>(config!.apiBaseUrl, path, getToken as TokenGetter, { signal }),
|
|
719
|
+
...restOptions,
|
|
720
|
+
// A caller's \`enabled\` narrows the config gate rather than replacing it: \`queryFn\` needs the config.
|
|
721
|
+
enabled: (enabled ?? true) && !!config?.apiBaseUrl,
|
|
722
|
+
});
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
export interface ApiClient {
|
|
726
|
+
get<TData = unknown>(path: string, options?: RequestOptions): Promise<TData>;
|
|
727
|
+
post<TData = unknown>(path: string, body: unknown, options?: RequestOptions): Promise<TData>;
|
|
728
|
+
put<TData = unknown>(path: string, body: unknown, options?: RequestOptions): Promise<TData>;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Calls the API imperatively, reading the runtime config and the token getter at the moment of
|
|
733
|
+
* each call. A call made before the config has arrived waits for the shared load, and fails
|
|
734
|
+
* when that load fails.
|
|
735
|
+
*/
|
|
736
|
+
export function useApiClient(): ApiClient {
|
|
737
|
+
const { config } = useConfig();
|
|
738
|
+
const { getToken } = useAuth();
|
|
739
|
+
const latest = useRef({ config, getToken });
|
|
740
|
+
useEffect(() => {
|
|
741
|
+
latest.current = { config, getToken };
|
|
742
|
+
}, [config, getToken]);
|
|
743
|
+
|
|
744
|
+
return useMemo(() => {
|
|
745
|
+
const untilCancelled = (signal: AbortSignal | undefined) => new Promise<never>((_, reject) => {
|
|
746
|
+
if (signal?.aborted) {
|
|
747
|
+
reject(new RequestCancelledError());
|
|
748
|
+
}
|
|
749
|
+
signal?.addEventListener('abort', () => reject(new RequestCancelledError()), { once: true });
|
|
750
|
+
});
|
|
751
|
+
const apiBaseUrl = async (signal: AbortSignal | undefined): Promise<string> => {
|
|
752
|
+
const config = latest.current.config
|
|
753
|
+
?? await Promise.race([loadConfig().catch(() => undefined), untilCancelled(signal)]);
|
|
754
|
+
if (!config?.apiBaseUrl) {
|
|
755
|
+
throw new Error('API base URL not configured');
|
|
756
|
+
}
|
|
757
|
+
return config.apiBaseUrl;
|
|
758
|
+
};
|
|
759
|
+
const token: TokenGetter = () => (latest.current.getToken as TokenGetter)();
|
|
760
|
+
return {
|
|
761
|
+
get: async <TData>(path: string, options?: RequestOptions) =>
|
|
762
|
+
get<TData>(await apiBaseUrl(options?.signal), path, token, options),
|
|
763
|
+
post: async <TData>(path: string, body: unknown, options?: RequestOptions) =>
|
|
764
|
+
post<TData>(await apiBaseUrl(options?.signal), path, body, token, options),
|
|
765
|
+
put: async <TData>(path: string, body: unknown, options?: RequestOptions) =>
|
|
766
|
+
put<TData>(await apiBaseUrl(options?.signal), path, body, token, options),
|
|
767
|
+
};
|
|
768
|
+
}, []);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
type ApiMutationVariables = { path: string; body: unknown; signal?: AbortSignal };
|
|
772
|
+
|
|
773
|
+
export function useApiMutation<TData = unknown>(
|
|
774
|
+
method: 'POST' | 'PUT',
|
|
775
|
+
options?: Omit<UseMutationOptions<TData, unknown, ApiMutationVariables>, 'mutationFn'>,
|
|
776
|
+
) {
|
|
777
|
+
const client = useApiClient();
|
|
778
|
+
|
|
779
|
+
return useMutation<TData, unknown, ApiMutationVariables>({
|
|
780
|
+
mutationFn: ({ path, body, signal }) =>
|
|
781
|
+
method === 'POST' ? client.post<TData>(path, body, { signal }) : client.put<TData>(path, body, { signal }),
|
|
782
|
+
...options,
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
`,
|
|
786
|
+
});
|
|
787
|
+
new projen_1.SampleFile(project, `${options.srcdir}/helpers/requests.ts`, {
|
|
788
|
+
contents: `import { HttpError, RequestCancelledError, RequestTimeoutError, type HttpErrorDetails } from './HttpError';
|
|
789
|
+
|
|
790
|
+
export type TokenGetter = () => Promise<string | null | undefined>;
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* How long a request may go unanswered before it fails. It stays above the longest CloudFront
|
|
794
|
+
* can take to give any answer: three 10 s connection attempts to the API origin plus its 30 s
|
|
795
|
+
* response timeout. The local dev server has no limit of its own, so there this is the only one.
|
|
796
|
+
*/
|
|
797
|
+
export const API_REQUEST_TIMEOUT_MS = 65 * 1000;
|
|
798
|
+
|
|
799
|
+
export interface RequestOptions {
|
|
800
|
+
readonly signal?: AbortSignal;
|
|
801
|
+
/** Called when the API rejects the caller's session (a 401), before the error is thrown. */
|
|
802
|
+
readonly onSessionRejected?: () => void;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
interface Deadline {
|
|
806
|
+
readonly signal: AbortSignal;
|
|
807
|
+
/** Settles with \`promise\`, or rejects as soon as the request is abandoned. */
|
|
808
|
+
race<T>(promise: Promise<T>): Promise<T>;
|
|
809
|
+
/** Why the request was abandoned, or \`undefined\` while it is still live. */
|
|
810
|
+
readonly abandonment: HttpError | undefined;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
async function withDeadline<T>(callerSignal: AbortSignal | undefined, run: (deadline: Deadline) => Promise<T>): Promise<T> {
|
|
814
|
+
const controller = new AbortController();
|
|
815
|
+
let abandonment: HttpError | undefined;
|
|
816
|
+
const abandoned = new Promise<never>((_, reject) => {
|
|
817
|
+
controller.signal.addEventListener('abort', () => reject(abandonment), { once: true });
|
|
818
|
+
});
|
|
819
|
+
abandoned.catch(() => undefined);
|
|
820
|
+
|
|
821
|
+
const abandon = (error: HttpError) => {
|
|
822
|
+
if (!abandonment) {
|
|
823
|
+
abandonment = error;
|
|
824
|
+
controller.abort();
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
const timer = setTimeout(() => abandon(new RequestTimeoutError()), API_REQUEST_TIMEOUT_MS);
|
|
828
|
+
const cancel = () => abandon(new RequestCancelledError());
|
|
829
|
+
if (callerSignal?.aborted) {
|
|
830
|
+
cancel();
|
|
831
|
+
} else {
|
|
832
|
+
callerSignal?.addEventListener('abort', cancel, { once: true });
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
try {
|
|
836
|
+
return await run({
|
|
837
|
+
signal: controller.signal,
|
|
838
|
+
race: (promise) => Promise.race([promise, abandoned]),
|
|
839
|
+
get abandonment() {
|
|
840
|
+
return abandonment;
|
|
841
|
+
},
|
|
842
|
+
});
|
|
843
|
+
} finally {
|
|
844
|
+
clearTimeout(timer);
|
|
845
|
+
callerSignal?.removeEventListener('abort', cancel);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function buildUrl(apiBaseUrl: string, path: string): string {
|
|
850
|
+
const baseUrl = apiBaseUrl.replace(/\\/+$/, '');
|
|
851
|
+
const normalizedPath = path.startsWith('/') ? path : \`/\${path}\`;
|
|
852
|
+
return \`\${baseUrl}\${normalizedPath}\`;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
async function request(
|
|
856
|
+
method: 'GET' | 'POST' | 'PUT',
|
|
857
|
+
apiBaseUrl: string,
|
|
858
|
+
path: string,
|
|
859
|
+
getToken: TokenGetter,
|
|
860
|
+
deadline: Deadline,
|
|
861
|
+
body: unknown,
|
|
862
|
+
onSessionRejected: (() => void) | undefined,
|
|
863
|
+
): Promise<Response> {
|
|
864
|
+
let response: Response;
|
|
865
|
+
try {
|
|
866
|
+
const token = await deadline.race(getToken());
|
|
867
|
+
response = await fetch(buildUrl(apiBaseUrl, path), {
|
|
868
|
+
method,
|
|
869
|
+
headers: {
|
|
870
|
+
Authorization: \`Bearer \${token ?? ''}\`,
|
|
871
|
+
...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
|
|
872
|
+
},
|
|
873
|
+
...(body !== undefined ? { body: JSON.stringify(body) } : {}),
|
|
874
|
+
signal: deadline.signal,
|
|
875
|
+
});
|
|
876
|
+
} catch (error) {
|
|
877
|
+
throw incomplete(method, path, deadline, error);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
if (!response.ok) {
|
|
881
|
+
const parsed = await deadline.race(parseErrorBody(response)).catch(() => undefined);
|
|
882
|
+
if (!parsed) {
|
|
883
|
+
throw incomplete(method, path, deadline, undefined);
|
|
884
|
+
}
|
|
885
|
+
const { error, message, details } = parsed;
|
|
886
|
+
console.error(\`[api] \${method} \${path} responded \${response.status}: \${message}\`);
|
|
887
|
+
if (response.status === 401) {
|
|
888
|
+
onSessionRejected?.();
|
|
889
|
+
}
|
|
890
|
+
throw new HttpError(response.status, error, message, details);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
return response;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* The error for a request that got no usable answer, logged before it is thrown so a caller
|
|
898
|
+
* that swallows it still leaves a trace. A caller's own cancellation is not logged.
|
|
899
|
+
*/
|
|
900
|
+
function incomplete(method: string, path: string, deadline: Deadline, cause: unknown): HttpError {
|
|
901
|
+
const abandonment = deadline.abandonment;
|
|
902
|
+
if (abandonment instanceof RequestCancelledError) {
|
|
903
|
+
return abandonment;
|
|
904
|
+
}
|
|
905
|
+
if (abandonment) {
|
|
906
|
+
console.error(\`[api] \${method} \${path} timed out after \${API_REQUEST_TIMEOUT_MS} ms\`);
|
|
907
|
+
return abandonment;
|
|
908
|
+
}
|
|
909
|
+
const message = cause instanceof Error ? cause.message : 'Failed to reach the API';
|
|
910
|
+
console.error(\`[api] \${method} \${path} failed to reach the API: \${message}\`);
|
|
911
|
+
return new HttpError(0, 'Network Error', message);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
function send<TData = unknown>(
|
|
915
|
+
method: 'GET' | 'POST' | 'PUT',
|
|
916
|
+
apiBaseUrl: string,
|
|
917
|
+
path: string,
|
|
918
|
+
getToken: TokenGetter,
|
|
919
|
+
body: unknown,
|
|
920
|
+
{ signal, onSessionRejected }: RequestOptions = {},
|
|
921
|
+
): Promise<TData> {
|
|
922
|
+
return withDeadline(signal, async (deadline) => {
|
|
923
|
+
const response = await request(method, apiBaseUrl, path, getToken, deadline, body, onSessionRejected);
|
|
924
|
+
try {
|
|
925
|
+
return await deadline.race(response.json());
|
|
926
|
+
} catch (error) {
|
|
927
|
+
if (deadline.abandonment) {
|
|
928
|
+
throw incomplete(method, path, deadline, error);
|
|
929
|
+
}
|
|
930
|
+
throw error;
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
/** Every field of an error body other than \`error\` and \`message\`. */
|
|
936
|
+
function detailsOf(body: Record<string, unknown>): HttpErrorDetails {
|
|
937
|
+
return Object.fromEntries(Object.entries(body).filter(([key]) => key !== 'error' && key !== 'message'));
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
async function parseErrorBody(response: Response): Promise<{ error: string; message: string; details: HttpErrorDetails }> {
|
|
941
|
+
try {
|
|
942
|
+
const body = await response.json();
|
|
943
|
+
if (body && typeof body.message === 'string') {
|
|
944
|
+
return {
|
|
945
|
+
error: typeof body.error === 'string' ? body.error : response.statusText,
|
|
946
|
+
message: body.message,
|
|
947
|
+
details: detailsOf(body),
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
} catch {
|
|
951
|
+
// Not JSON (e.g. a proxy's error page): fall through to the generic error below.
|
|
952
|
+
}
|
|
953
|
+
return { error: response.statusText || 'Error', message: \`HTTP error! status: \${response.status}\`, details: {} };
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
export function get<TData = unknown>(
|
|
957
|
+
apiBaseUrl: string,
|
|
958
|
+
path: string,
|
|
959
|
+
getToken: TokenGetter,
|
|
960
|
+
options?: RequestOptions,
|
|
961
|
+
): Promise<TData> {
|
|
962
|
+
return send<TData>('GET', apiBaseUrl, path, getToken, undefined, options);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
export function post<TData = unknown>(
|
|
966
|
+
apiBaseUrl: string,
|
|
967
|
+
path: string,
|
|
968
|
+
body: unknown,
|
|
969
|
+
getToken: TokenGetter,
|
|
970
|
+
options?: RequestOptions,
|
|
971
|
+
): Promise<TData> {
|
|
972
|
+
return send<TData>('POST', apiBaseUrl, path, getToken, body, options);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
export function put<TData = unknown>(
|
|
976
|
+
apiBaseUrl: string,
|
|
977
|
+
path: string,
|
|
978
|
+
body: unknown,
|
|
979
|
+
getToken: TokenGetter,
|
|
980
|
+
options?: RequestOptions,
|
|
981
|
+
): Promise<TData> {
|
|
982
|
+
return send<TData>('PUT', apiBaseUrl, path, getToken, body, options);
|
|
983
|
+
}
|
|
984
|
+
`,
|
|
985
|
+
});
|
|
986
|
+
new projen_1.SampleFile(project, `${options.srcdir}/helpers/HttpError.ts`, {
|
|
987
|
+
contents: `/** The fields an error body carries beyond \`error\` and \`message\`. */
|
|
988
|
+
export type HttpErrorDetails = Readonly<Record<string, unknown>>;
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* A failed API request: the HTTP status (0 when the API gave no answer) and the error body's
|
|
992
|
+
* \`error\` and \`message\`, with any other fields it carries as \`details\`.
|
|
993
|
+
*/
|
|
994
|
+
export class HttpError extends Error {
|
|
995
|
+
status: number;
|
|
996
|
+
error: string;
|
|
997
|
+
details: HttpErrorDetails;
|
|
998
|
+
|
|
999
|
+
constructor(status: number, error: string, message: string, details: HttpErrorDetails = {}) {
|
|
1000
|
+
super(message);
|
|
1001
|
+
this.name = 'HttpError';
|
|
1002
|
+
this.status = status;
|
|
1003
|
+
this.error = error;
|
|
1004
|
+
this.details = details;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/** The API did not answer within the client's bound. */
|
|
1009
|
+
export class RequestTimeoutError extends HttpError {
|
|
1010
|
+
constructor() {
|
|
1011
|
+
super(0, 'Timeout', 'The server took too long to respond. Please try again.');
|
|
1012
|
+
this.name = 'RequestTimeoutError';
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/** The caller cancelled the request before the API answered. */
|
|
1017
|
+
export class RequestCancelledError extends HttpError {
|
|
1018
|
+
constructor() {
|
|
1019
|
+
super(0, 'Aborted', 'The request was cancelled.');
|
|
1020
|
+
this.name = 'RequestCancelledError';
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
/** Whether \`error\`'s message was written for the person using the app: a refusal (4xx) or a timeout. */
|
|
1025
|
+
export function isUserFacing(error: unknown): error is HttpError {
|
|
1026
|
+
return error instanceof RequestTimeoutError || (error instanceof HttpError && error.status >= 400 && error.status < 500);
|
|
1027
|
+
}
|
|
1028
|
+
`,
|
|
1029
|
+
});
|
|
1030
|
+
new projen_1.SampleFile(project, `${options.srcdir}/helpers/errors.ts`, {
|
|
1031
|
+
contents: `import { HttpError } from './HttpError';
|
|
1032
|
+
|
|
1033
|
+
/** A 5xx's message is the server's, not written for the person using the app, so it gets the default. */
|
|
1034
|
+
export function getErrorMessage(error: unknown, defaultMessage: string): string {
|
|
1035
|
+
if (error instanceof HttpError && error.status >= 500) {
|
|
1036
|
+
return defaultMessage;
|
|
1037
|
+
}
|
|
1038
|
+
if (error instanceof Error && error.message) {
|
|
1039
|
+
return error.message;
|
|
1040
|
+
}
|
|
1041
|
+
return defaultMessage;
|
|
1042
|
+
}
|
|
1043
|
+
`,
|
|
1044
|
+
});
|
|
1045
|
+
new projen_1.SampleFile(project, `${options.srcdir}/helpers/retry.ts`, {
|
|
1046
|
+
contents: `import { HttpError, RequestCancelledError } from './HttpError';
|
|
1047
|
+
|
|
1048
|
+
/** React Query's own default: three retries after the first failure. */
|
|
1049
|
+
const MAX_RETRIES = 3;
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* A query \`retry\` that never retries a 401, because the API will reject the same token again.
|
|
1053
|
+
* Everything else gets React Query's default.
|
|
1054
|
+
*/
|
|
1055
|
+
export function retryUnlessRejected(failureCount: number, error: unknown): boolean {
|
|
1056
|
+
if (error instanceof HttpError && error.status === 401) {
|
|
1057
|
+
return false;
|
|
1058
|
+
}
|
|
1059
|
+
return failureCount < MAX_RETRIES;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* A failure worth trying again unchanged: the API answered 5xx, or was not reached or did not
|
|
1064
|
+
* answer in time (status 0). A cancellation is not one: whoever cancelled wants it stopped.
|
|
1065
|
+
*/
|
|
1066
|
+
export function isTransientFailure(error: unknown): boolean {
|
|
1067
|
+
return error instanceof HttpError && !(error instanceof RequestCancelledError) && (error.status === 0 || error.status >= 500);
|
|
1068
|
+
}
|
|
1069
|
+
`,
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
676
1073
|
/**
|
|
677
1074
|
* Adds Playwright e2e testing support: devDeps, a `test:e2e` task, e2e-related
|
|
678
1075
|
* .gitignore entries, and a scaffolded (one-time, not regenerated on synth)
|
|
@@ -959,4 +1356,4 @@ gh secret set E2E_CLERK_USER_ID
|
|
|
959
1356
|
});
|
|
960
1357
|
}
|
|
961
1358
|
}
|
|
962
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVml0ZVJlYWN0UHJvamVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9WaXRlUmVhY3RQcm9qZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtCQUEwQztBQUMxQyxtQ0FBc0Y7QUFDdEYsc0RBQXVGO0FBRXZGLG1DQUEyQztBQW1DM0M7O0dBRUc7QUFDSCxNQUFhLGdCQUFpQixTQUFRLGlDQUFvQjtJQUN4QyxNQUFNLENBQVM7SUFDZixTQUFTLENBQVM7SUFDbEIsVUFBVSxDQUFTO0lBQ2xCLFlBQVksQ0FBc0I7SUFFbkQsWUFBWSxPQUFnQztRQUMxQyxNQUFNLEVBQ0osVUFBVSxHQUFHLElBQUksRUFDakIsTUFBTSxHQUFHLEtBQUssRUFDZCxTQUFTLEdBQUcsUUFBUSxFQUNwQixLQUFLLEVBQ0wsVUFBVSxHQUFHLElBQUksRUFDakIsR0FBRyxXQUFXLEVBQ2YsR0FBRyxPQUFPLENBQUM7UUFDWixLQUFLLENBQUM7WUFDSixHQUFHLFdBQVc7WUFDZCxVQUFVLEVBQUUsS0FBSyxFQUFFLHFDQUFxQztZQUN4RCxNQUFNLEVBQUUsS0FBSyxFQUFFLG1DQUFtQztZQUNsRCxJQUFJLEVBQUUsS0FBSyxFQUFFLDZCQUE2QjtZQUMxQyxPQUFPLEVBQUUsSUFBSTtZQUNiLGVBQWUsRUFBRSxJQUFJLEVBQUUsa0NBQWtDO1lBQ3pELGNBQWMsRUFBRyxXQUFXLENBQUMsTUFBd0IsQ0FBQyxPQUFPLENBQUMsY0FBYztZQUM1RSxXQUFXLEVBQUU7Z0JBQ1gsb0JBQW9CLEVBQUU7b0JBQ3BCLHVFQUF1RTtvQkFDdkUsc0VBQXNFO29CQUN0RSxvRUFBb0U7b0JBQ3BFLCtEQUErRDtvQkFDL0QsV0FBVyxFQUFFO3dCQUNYLFNBQVMsRUFBRSxJQUFJO3dCQUNmLGVBQWUsRUFBRSxJQUFJO3FCQUN0QjtvQkFDRCxHQUFHLFdBQVcsQ0FBQyxXQUFXLEVBQUUsb0JBQW9CO2lCQUNqRDthQUNGO1lBQ0QsSUFBSSxFQUFFO2dCQUNKLG9CQUFvQjtnQkFDcEIsdUJBQXVCO2dCQUN2QixzQkFBc0I7Z0JBQ3RCLGNBQWM7Z0JBQ2QsU0FBUztnQkFDVCxhQUFhO2dCQUNiLFFBQVE7Z0JBQ1IsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQzthQUN0QztTQUNGLENBQUMsQ0FBQztRQUVILG1DQUFtQztRQUNuQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1FBRTlDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBRTNCLHFCQUFxQjtRQUNyQixJQUFJLGFBQWEsQ0FBQyxJQUFJLEVBQUU7WUFDdEIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1NBQ3BCLENBQUMsQ0FBQztRQUVILDJCQUEyQjtRQUMzQixJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTNCLGlCQUFpQjtRQUNqQixJQUFJLFNBQVMsQ0FBQyxJQUFJLEVBQUU7WUFDbEIsS0FBSyxFQUFFLEtBQUssSUFBSSxJQUFJLENBQUMsSUFBSTtZQUN6QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07U0FDcEIsQ0FBQyxDQUFDO1FBRUgseUJBQXlCO1FBQ3pCLElBQUksYUFBYSxDQUFDLElBQUksRUFBRTtZQUN0QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07U0FDcEIsQ0FBQyxDQUFDO1FBRUgseUJBQXlCO1FBQ3pCLElBQUksQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFFM0QsMENBQTBDO1FBQzFDLElBQUksVUFBVSxDQUFDLElBQUksRUFBRTtZQUNuQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07U0FDcEIsQ0FBQyxDQUFDO1FBRUgsa0NBQWtDO1FBQ2xDLElBQUksaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFNUIsMENBQTBDO1FBQzFDLElBQUksVUFBVSxDQUFDLElBQUksRUFBRTtZQUNuQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07U0FDcEIsQ0FBQyxDQUFDO1FBRUgseUJBQXlCO1FBQ3pCLElBQUksY0FBYyxDQUFDLElBQUksRUFBRSxFQUFHLENBQUMsQ0FBQztRQUc5QiwrQkFBK0I7UUFDL0IsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLElBQUksY0FBYyxDQUFDLElBQUksRUFBRTtnQkFDdkIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO2dCQUNuQixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7YUFDMUIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHFDQUFxQztRQUNyQyxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsSUFBSSxzQkFBc0IsQ0FBQyxJQUFJLEVBQUU7Z0JBQy9CLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUzthQUMxQixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsbUNBQW1DO1FBQ25DLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxNQUFNO1lBQ2hDLENBQUMsQ0FBQyxJQUFBLGVBQVEsRUFBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQzNDLENBQUMsQ0FBQyxJQUFBLGVBQVEsRUFBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLGNBQWMsT0FBTyxJQUFBLHdCQUFnQixFQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDdEcsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsY0FBYyxDQUFDLFNBQWlCLEVBQUUsU0FBaUI7UUFDakQsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzVDLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7T0FHRztJQUNILGVBQWU7UUFDYixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUM7SUFDM0IsQ0FBQztDQUNGO0FBcklELDRDQXFJQztBQU1EOztHQUVHO0FBQ0gsTUFBTSxhQUFjLFNBQVEsa0JBQVM7SUFDbkMsWUFBWSxPQUE2QixFQUFFLFFBQThCO1FBQ3ZFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVmLE1BQU0sU0FBUyxHQUFHLE9BQStCLENBQUM7UUFFbEQsNkNBQTZDO1FBQzdDLFNBQVMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztRQUU3Qyx5QkFBeUI7UUFDekIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxlQUFlLEVBQUUsbUJBQW1CLENBQUMsQ0FBQztRQUV4RCx1QkFBdUI7UUFDdkIsU0FBUyxDQUFDLFVBQVUsQ0FDbEIsc0JBQXNCLEVBQ3RCLDBCQUEwQixFQUMxQiw2QkFBNkIsRUFDN0IsYUFBYSxFQUNiLG1CQUFtQixFQUNuQixvQkFBb0IsRUFDcEIsZ0JBQWdCLEVBQ2hCLGtDQUFrQyxFQUNsQyxxQ0FBcUMsRUFDckMsaUJBQWlCLEVBQ2pCLDJCQUEyQixDQUM1QixDQUFDO1FBRUYsMENBQTBDO1FBQzFDLElBQUksY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRTVCLGNBQWM7UUFDZCxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRTtZQUN2QixXQUFXLEVBQUUsMEJBQTBCO1lBQ3ZDLElBQUksRUFBRSxNQUFNO1NBQ2IsQ0FBQyxDQUFDO1FBRUgsMERBQTBEO1FBQzFELFNBQVMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDOUIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUU7WUFDekIsV0FBVyxFQUFFLHNCQUFzQjtZQUNuQyxJQUFJLEVBQUUsc0JBQXNCO1NBQzdCLENBQUMsQ0FBQztRQUVILFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFO1lBQzNCLFdBQVcsRUFBRSwwQkFBMEI7WUFDdkMsSUFBSSxFQUFFLGNBQWM7U0FDckIsQ0FBQyxDQUFDO1FBRUgsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUU7WUFDeEIsV0FBVyxFQUFFLFdBQVc7WUFDeEIsSUFBSSxFQUFFLFVBQVU7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLGdCQUFpQixTQUFRLGlCQUFRO0lBQ3JDLFlBQVksT0FBZ0I7UUFDMUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRTtZQUNqQyxNQUFNLEVBQUUsSUFBSTtZQUNaLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGlCQUFpQjtRQUNmLE9BQU87Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBNkJWLENBQUM7SUFDQSxDQUFDO0NBQ0Y7QUFFRDs7R0FFRztBQUNILE1BQU0sY0FBZSxTQUFRLGlCQUFRO0lBQ25DLFlBQVksT0FBZ0I7UUFDMUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRTtZQUMvQixNQUFNLEVBQUUsSUFBSTtZQUNaLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGlCQUFpQjtRQUNmLE9BQU87Ozs7Ozs7Q0FPVixDQUFDO0lBQ0EsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLGlCQUFrQixTQUFRLGlCQUFRO0lBQ3RDLFlBQVksT0FBZ0I7UUFDMUIsS0FBSyxDQUFDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRTtZQUNsQyxNQUFNLEVBQUUsSUFBSTtZQUNaLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGlCQUFpQjtRQUNmLE9BQU87Ozs7OztDQU1WLENBQUM7SUFDQSxDQUFDO0NBQ0Y7QUFNRDs7R0FFRztBQUNILE1BQU0sVUFBVyxTQUFRLGlCQUFRO0lBQy9CLFlBQVksT0FBZ0IsRUFBRSxPQUEwQjtRQUN0RCxLQUFLLENBQUMsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sZ0JBQWdCLEVBQUU7WUFDaEQsTUFBTSxFQUFFLElBQUk7WUFDWixRQUFRLEVBQUUsSUFBSTtTQUNmLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxpQkFBaUI7UUFDZixPQUFPO0NBQ1YsQ0FBQztJQUNBLENBQUM7Q0FDRjtBQU1EOztHQUVHO0FBQ0gsTUFBTSxVQUFXLFNBQVEsaUJBQVE7SUFDL0IsWUFBWSxPQUFnQixFQUFFLE9BQTBCO1FBQ3RELEtBQUssQ0FBQyxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUMsTUFBTSxZQUFZLEVBQUU7WUFDNUMsTUFBTSxFQUFFLElBQUk7WUFDWixRQUFRLEVBQUUsSUFBSTtTQUNmLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxpQkFBaUI7UUFDZiwrQ0FBK0M7UUFDL0MsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLE9BQTJCLENBQUM7UUFDckQsTUFBTSxZQUFZLEdBQUcsV0FBVyxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBRW5ELDRCQUE0QjtRQUM1QixNQUFNLGNBQWMsR0FBRzs7OztFQUl6QixDQUFDO1FBRUMsMkNBQTJDO1FBQzNDLElBQUksb0JBQTRCLENBQUM7UUFDakMsSUFBSSxZQUFZLENBQUMsSUFBSSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzFCLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLENBQUM7aUJBQ3hELEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxLQUFLLElBQUksS0FBSyxJQUFJLEdBQUcsQ0FBQztpQkFDNUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRWQsTUFBTSxnQkFBZ0IsR0FBRztFQUM3QixnQkFBZ0I7RUFDaEIsQ0FBQztZQUVHLG9CQUFvQixHQUFHLEdBQUcsZ0JBQWdCOztnREFFQSxDQUFDO1FBQzdDLENBQUM7YUFBTSxDQUFDO1lBQ04sb0JBQW9CLEdBQUcsa0NBQWtDLENBQUM7UUFDNUQsQ0FBQztRQUVELE9BQU87O0VBRVQsY0FBYzs7RUFFZCxvQkFBb0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBb0JyQixDQUFDO0lBQ0EsQ0FBQztDQUNGO0FBSUQ7O0dBRUc7QUFDSCxNQUFNLGNBQWUsU0FBUSxtQkFBVTtJQUNyQyxJQUFJLENBQVM7SUFDYixZQUFZLE9BQXlCLEVBQUUsUUFBK0I7UUFDcEUsS0FBSyxDQUFDLE9BQU8sRUFBRSxHQUFHLE9BQU8sQ0FBQyxTQUFTLGNBQWMsRUFBRTtZQUNqRCxRQUFRLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDdkIsVUFBVSxFQUFFLDJCQUEyQjtnQkFDdkMsbUJBQW1CLEVBQUUsS0FBSzthQUMzQixFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7U0FDWixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsT0FBTyxDQUFDLFNBQVMsY0FBYyxDQUFDO0lBQ2pELENBQUM7Q0FDRjtBQU9EOztHQUVHO0FBQ0gsTUFBTSxTQUFVLFNBQVEsbUJBQVU7SUFDaEMsWUFBWSxPQUFnQixFQUFFLE9BQXlCO1FBQ3JELEtBQUssQ0FBQyxPQUFPLEVBQUUsWUFBWSxFQUFFO1lBQzNCLFFBQVEsRUFBRTs7Ozs7O2FBTUgsT0FBTyxDQUFDLEtBQUs7Ozs7a0NBSVEsT0FBTyxDQUFDLE1BQU07OztDQUcvQztTQUNJLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQU1EOztHQUVHO0FBQ0gsTUFBTSxhQUFjLFNBQVEsa0JBQVM7SUFDbkMsWUFBWSxPQUFnQixFQUFFLE9BQTZCO1FBQ3pELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVmLDBDQUEwQztRQUMxQyxJQUFJLGlCQUFRLENBQUMsT0FBTyxFQUFFLGVBQWUsRUFBRTtZQUNyQyxNQUFNLEVBQUUsSUFBSTtZQUNaLFFBQVEsRUFBRSxJQUFJO1lBQ2QsR0FBRyxFQUFFO2dCQUNILEtBQUssRUFBRSxFQUFFO2dCQUNULFVBQVUsRUFBRTtvQkFDVixFQUFFLElBQUksRUFBRSxxQkFBcUIsRUFBRTtvQkFDL0IsRUFBRSxJQUFJLEVBQUUsc0JBQXNCLEVBQUU7aUJBQ2pDO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCwyQ0FBMkM7UUFDM0MsSUFBSSxpQkFBUSxDQUFDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRTtZQUN6QyxNQUFNLEVBQUUsSUFBSTtZQUNaLFFBQVEsRUFBRSxJQUFJO1lBQ2QsR0FBRyxFQUFFO2dCQUNILGVBQWUsRUFBRTtvQkFDZixNQUFNLEVBQUUsUUFBUTtvQkFDaEIsdUJBQXVCLEVBQUUsSUFBSTtvQkFDN0IsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxjQUFjLENBQUM7b0JBQ3RDLE1BQU0sRUFBRSxRQUFRO29CQUNoQixZQUFZLEVBQUUsSUFBSTtvQkFFbEIsZUFBZTtvQkFDZixnQkFBZ0IsRUFBRSxTQUFTO29CQUMzQiwwQkFBMEIsRUFBRSxJQUFJO29CQUNoQyxlQUFlLEVBQUUsSUFBSTtvQkFDckIsZUFBZSxFQUFFLE9BQU87b0JBQ3hCLE1BQU0sRUFBRSxJQUFJO29CQUNaLEdBQUcsRUFBRSxXQUFXO29CQUVoQixVQUFVO29CQUNWLE1BQU0sRUFBRSxJQUFJO29CQUNaLGNBQWMsRUFBRSxJQUFJO29CQUNwQixrQkFBa0IsRUFBRSxJQUFJO29CQUN4QiwwQkFBMEIsRUFBRSxJQUFJO29CQUNoQyw0QkFBNEIsRUFBRSxJQUFJO2lCQUNuQztnQkFDRCxPQUFPLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO2FBQzFCO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsdUNBQXVDO1FBQ3ZDLElBQUksaUJBQVEsQ0FBQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUU7WUFDMUMsTUFBTSxFQUFFLElBQUk7WUFDWixRQUFRLEVBQUUsSUFBSTtZQUNkLEdBQUcsRUFBRTtnQkFDSCxlQUFlLEVBQUU7b0JBQ2YsTUFBTSxFQUFFLFFBQVE7b0JBQ2hCLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQztvQkFDZixNQUFNLEVBQUUsUUFBUTtvQkFDaEIsWUFBWSxFQUFFLElBQUk7b0JBRWxCLGVBQWU7b0JBQ2YsZ0JBQWdCLEVBQUUsU0FBUztvQkFDM0IsMEJBQTBCLEVBQUUsSUFBSTtvQkFDaEMsZUFBZSxFQUFFLElBQUk7b0JBQ3JCLGVBQWUsRUFBRSxPQUFPO29CQUN4QixNQUFNLEVBQUUsSUFBSTtvQkFFWixVQUFVO29CQUNWLE1BQU0sRUFBRSxJQUFJO29CQUNaLGNBQWMsRUFBRSxJQUFJO29CQUNwQixrQkFBa0IsRUFBRSxJQUFJO29CQUN4QiwwQkFBMEIsRUFBRSxJQUFJO2lCQUNqQztnQkFDRCxPQUFPLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQzthQUM1QjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQU9EOztHQUVHO0FBQ0gsTUFBTSxjQUFlLFNBQVEsa0JBQVM7SUFDcEMsWUFBWSxPQUFnQixFQUFFLE9BQThCO1FBQzFELEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVmLGlCQUFpQjtRQUNqQixJQUFJLG1CQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sVUFBVSxFQUFFO1lBQ25ELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXlCZjtTQUNJLENBQUMsQ0FBQztRQUVILHdCQUF3QjtRQUN4QixJQUFJLGlCQUFRLENBQUMsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sMEJBQTBCLEVBQUU7WUFDakUsTUFBTSxFQUFFLElBQUk7WUFDWixRQUFRLEVBQUUsSUFBSTtZQUNkLEtBQUssRUFBRTtnQkFDTCxzRUFBc0U7Z0JBQ3RFLGlEQUFpRDtnQkFDakQsMENBQTBDO2dCQUMxQyxFQUFFO2dCQUNGLGdEQUFnRDtnQkFDaEQsaUJBQWlCO2dCQUNqQixzRUFBc0U7Z0JBQ3RFLEtBQUs7Z0JBQ0wsbUNBQW1DO2dCQUNuQyxtQ0FBbUM7Z0JBQ25DLEVBQUU7Z0JBQ0YsNEJBQTRCO2dCQUM1QiwyQkFBMkI7Z0JBQzNCLDRCQUE0QjtnQkFDNUIsa0NBQWtDO2dCQUNsQywyREFBMkQ7Z0JBQzNELFNBQVM7Z0JBQ1QsRUFBRTtnQkFDRix1Q0FBdUM7Z0JBQ3ZDLEVBQUU7Z0JBQ0Ysb0dBQW9HO2dCQUNwRyxpRUFBaUU7Z0JBQ2pFLDBFQUEwRTtnQkFDMUUsUUFBUTtnQkFDUixxRUFBcUU7Z0JBQ3JFLG9CQUFvQjtnQkFDcEIsaURBQWlEO2dCQUNqRCxZQUFZO2dCQUNaLFdBQVc7Z0JBQ1gsRUFBRTtnQkFDRiwyQkFBMkI7Z0JBQzNCLG9FQUFvRTtnQkFDcEUsU0FBUztnQkFDVCxFQUFFO2dCQUNGLCtCQUErQjtnQkFDL0IsUUFBUTtnQkFDUixvQ0FBb0M7Z0JBQ3BDLGlCQUFpQjtnQkFDakIsT0FBTztnQkFDUCxHQUFHO2FBQ0o7U0FDRixDQUFDLENBQUM7UUFFSCx3QkFBd0I7UUFDeEIsSUFBSSxtQkFBVSxDQUFDLE9BQU8sRUFBRSxHQUFHLE9BQU8sQ0FBQyxNQUFNLDBCQUEwQixFQUFFO1lBQ25FLFFBQVEsRUFBRTs7Ozs7Ozs7Q0FRZjtTQUNJLENBQUMsQ0FBQztRQUVILGlCQUFpQjtRQUNqQixJQUFJLG1CQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sVUFBVSxFQUFFO1lBQ25ELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXdDZjtTQUNJLENBQUMsQ0FBQztRQUVILGtCQUFrQjtRQUNsQixJQUFJLG1CQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sV0FBVyxFQUFFO1lBQ3BELFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBMENmO1NBQ0ksQ0FBQyxDQUFDO1FBRUgsbUJBQW1CO1FBQ25CLElBQUksbUJBQVUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUMsTUFBTSxZQUFZLEVBQUU7WUFDckQsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXdEZjtTQUNJLENBQUMsQ0FBQztJQUVMLENBQUM7Q0FDRjtBQU1EOzs7Ozs7R0FNRztBQUNILE1BQU0sc0JBQXVCLFNBQVEsa0JBQVM7SUFDNUMsWUFBWSxPQUF5QixFQUFFLE9BQXNDO1FBQzNFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUVmLE9BQU8sQ0FBQyxVQUFVLENBQ2hCLDBCQUEwQixFQUMxQix3QkFBd0IsRUFDeEIsd0JBQXdCLEVBQ3hCLGdCQUFnQixDQUNqQixDQUFDO1FBRUYsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUU7WUFDMUIsV0FBVyxFQUFFLGtHQUFrRztZQUMvRyxJQUFJLEVBQUUsaUJBQWlCO1NBQ3hCLENBQUMsQ0FBQztRQUVILE9BQU8sQ0FBQyxZQUFZLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUMzQyxPQUFPLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3RDLE9BQU8sQ0FBQyxZQUFZLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDckMscUZBQXFGO1FBQ3JGLHNGQUFzRjtRQUN0RixPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTdCLElBQUksb0JBQW9CLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekMsSUFBSSxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNoQyxJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQy9CLElBQUksZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDOUIsSUFBSSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0IsQ0FBQztDQUNGO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sb0JBQXFCLFNBQVEsbUJBQVU7SUFDM0MsWUFBWSxPQUF5QjtRQUNuQyxLQUFLLENBQUMsT0FBTyxFQUFFLHNCQUFzQixFQUFFO1lBQ3JDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Z0JBbUNBLElBQUEsd0JBQWdCLEVBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDOzs7Ozs7Q0FNdEU7U0FDSSxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUFNRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLGtCQUFtQixTQUFRLG1CQUFVO0lBQ3pDLFlBQVksT0FBeUIsRUFBRSxPQUFrQztRQUN2RSxLQUFLLENBQUMsT0FBTyxFQUFFLDZCQUE2QixFQUFFO1lBQzVDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7O3NDQWVzQixPQUFPLENBQUMsU0FBUzs7Ozs7Q0FLdEQ7U0FDSSxDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sa0JBQW1CLFNBQVEsbUJBQVU7SUFDekMsWUFBWSxPQUF5QjtRQUNuQyxLQUFLLENBQUMsT0FBTyxFQUFFLDhCQUE4QixFQUFFO1lBQzdDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7OztDQWdCZjtTQUNJLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxpQkFBa0IsU0FBUSxtQkFBVTtJQUN4QyxZQUFZLE9BQXlCO1FBQ25DLEtBQUssQ0FBQyxPQUFPLEVBQUUscUJBQXFCLEVBQUU7WUFDcEMsUUFBUSxFQUFFOzs7Ozs7Ozs7Q0FTZjtTQUNJLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sZ0JBQWlCLFNBQVEsbUJBQVU7SUFDdkMsWUFBWSxPQUF5QjtRQUNuQyxLQUFLLENBQUMsT0FBTyxFQUFFLG1CQUFtQixFQUFFO1lBQ2xDLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0NBd0JmO1NBQ0ksQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxhQUFjLFNBQVEsbUJBQVU7SUFDcEMsWUFBWSxPQUF5QjtRQUNuQyxNQUFNLGNBQWMsR0FBRyxJQUFBLHdCQUFnQixFQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3BGLEtBQUssQ0FBQyxPQUFPLEVBQUUsZUFBZSxFQUFFO1lBQzlCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7MEVBdUIwRCxjQUFjOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7NkNBcUIzQyxjQUFjOzs7Ozs7Ozs7OztFQVd6RCxjQUFjOzs7Ozs7Ozs7Ozs7OztDQWNmO1NBQ0ksQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVsYXRpdmUsIGJhc2VuYW1lIH0gZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBDb21wb25lbnQsIEZpbGVCYXNlLCBKc29uRmlsZSwgUHJvamVjdCwgU2FtcGxlRmlsZSwgVGV4dEZpbGUgfSBmcm9tICdwcm9qZW4nO1xuaW1wb3J0IHsgVHlwZVNjcmlwdEFwcFByb2plY3QsIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyB9IGZyb20gJ3Byb2plbi9saWIvdHlwZXNjcmlwdCc7XG5pbXBvcnQgeyBCYXRtYW5Qcm9qZWN0IH0gZnJvbSAnLi9CYXRtYW5Qcm9qZWN0JztcbmltcG9ydCB7IHJ1blNjcmlwdENvbW1hbmQgfSBmcm9tICcuL3V0aWxzJztcblxuZXhwb3J0IGludGVyZmFjZSBWaXRlUmVhY3RQcm9qZWN0T3B0aW9ucyBleHRlbmRzIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGdlbmVyYXRlIHNhbXBsZSBjb2RlXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNhbXBsZUNvZGU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTb3VyY2UgZGlyZWN0b3J5XG4gICAqIEBkZWZhdWx0IFwic3JjXCJcbiAgICovXG4gIHJlYWRvbmx5IHNyY2Rpcj86IHN0cmluZztcblxuICAvKipcbiAgICogUHVibGljIGRpcmVjdG9yeSBmb3Igc3RhdGljIGFzc2V0c1xuICAgKiBAZGVmYXVsdCBcInB1YmxpY1wiXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNEaXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRpdGxlIGZvciB0aGUgSFRNTCBwYWdlXG4gICAqIEBkZWZhdWx0IHByb2plY3QgbmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgdGl0bGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYWRkIFBsYXl3cmlnaHQgZTJlIHRlc3Rpbmcgc3VwcG9ydCAoZGV2RGVwcywgYSBgdGVzdDplMmVgIHRhc2ssXG4gICAqIGFuZCBhIHNjYWZmb2xkZWQgYHBsYXl3cmlnaHQuY29uZmlnLnRzYCArIGBlMmUvYCBzdGFydGVyIHN1aXRlKS5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZTJlVGVzdGluZz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogVml0ZSArIFJlYWN0IFR5cGVTY3JpcHQgcHJvamVjdFxuICovXG5leHBvcnQgY2xhc3MgVml0ZVJlYWN0UHJvamVjdCBleHRlbmRzIFR5cGVTY3JpcHRBcHBQcm9qZWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IHNyY2Rpcjogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcHVibGljRGlyOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBkZXZDb21tYW5kOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnRmllbGRzOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFZpdGVSZWFjdFByb2plY3RPcHRpb25zKSB7XG4gICAgY29uc3Qge1xuICAgICAgc2FtcGxlQ29kZSA9IHRydWUsXG4gICAgICBzcmNkaXIgPSAnc3JjJyxcbiAgICAgIHB1YmxpY0RpciA9ICdwdWJsaWMnLFxuICAgICAgdGl0bGUsXG4gICAgICBlMmVUZXN0aW5nID0gdHJ1ZSxcbiAgICAgIC4uLnJlc3RPcHRpb25zXG4gICAgfSA9IG9wdGlvbnM7XG4gICAgc3VwZXIoe1xuICAgICAgLi4ucmVzdE9wdGlvbnMsXG4gICAgICBzYW1wbGVDb2RlOiBmYWxzZSwgLy8gV2UnbGwgaGFuZGxlIHNhbXBsZSBjb2RlIG91cnNlbHZlc1xuICAgICAgZXNsaW50OiBmYWxzZSwgLy8gV2UnbGwgY29uZmlndXJlIGVzbGludCBvdXJzZWx2ZXNcbiAgICAgIGplc3Q6IGZhbHNlLCAvLyBWaXRlIHVzZXMgdml0ZXN0IHR5cGljYWxseVxuICAgICAgcGFja2FnZTogdHJ1ZSxcbiAgICAgIGRpc2FibGVUc2NvbmZpZzogdHJ1ZSwgLy8gV2UnbGwgbWFuYWdlIHRzY29uZmlnIG91cnNlbHZlc1xuICAgICAgcGFja2FnZU1hbmFnZXI6IChyZXN0T3B0aW9ucy5wYXJlbnQgYXMgQmF0bWFuUHJvamVjdCkucGFja2FnZS5wYWNrYWdlTWFuYWdlcixcbiAgICAgIHBucG1PcHRpb25zOiB7XG4gICAgICAgIHdvcmtzcGFjZVlhbWxPcHRpb25zOiB7XG4gICAgICAgICAgLy8gVGhpcyBzdWJwcm9qZWN0IGhhcyBpdHMgb3duIHNlcGFyYXRlIGxvY2tmaWxlL3N0b3JlIGZyb20gaXRzIHBhcmVudCxcbiAgICAgICAgICAvLyBzbyBpdCBuZWVkcyBpdHMgb3duIGFwcHJvdmFsIGZvciB0aGUgbmF0aXZlIHBvc3RpbnN0YWxsIHNjcmlwdHMgaXRzXG4gICAgICAgICAgLy8gZml4ZWQgZGVwZW5kZW5jeSBzZXQgYWx3YXlzIG5lZWRzIChlc2J1aWxkJ3MgYmluYXJ5IGRvd25sb2FkLCBhbmRcbiAgICAgICAgICAvLyBAY2xlcmsvY2xlcmstcmVhY3QncyB0cmFuc2l0aXZlIEBjbGVyay9zaGFyZWQgc2V0dXAgc2NyaXB0KS5cbiAgICAgICAgICBhbGxvd0J1aWxkczoge1xuICAgICAgICAgICAgJ2VzYnVpbGQnOiB0cnVlLFxuICAgICAgICAgICAgJ0BjbGVyay9zaGFyZWQnOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLi4ucmVzdE9wdGlvbnMucG5wbU9wdGlvbnM/LndvcmtzcGFjZVlhbWxPcHRpb25zLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGRlcHM6IFtcbiAgICAgICAgJ0BjbGVyay9jbGVyay1yZWFjdCcsXG4gICAgICAgICdAdGFuc3RhY2svcmVhY3QtcXVlcnknLFxuICAgICAgICAnQHRhaWx3aW5kY3NzL3Bvc3Rjc3MnLFxuICAgICAgICAnYXV0b3ByZWZpeGVyJyxcbiAgICAgICAgJ3Bvc3Rjc3MnLFxuICAgICAgICAndGFpbHdpbmRjc3MnLFxuICAgICAgICAncm9sbHVwJyxcbiAgICAgICAgLi4uKG9wdGlvbnMuZGVwcyA/IG9wdGlvbnMuZGVwcyA6IFtdKSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBJbml0aWFsaXplIGNvbmZpZyBmaWVsZHMgc3RvcmFnZVxuICAgIHRoaXMuY29uZmlnRmllbGRzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcblxuICAgIHRoaXMuc3JjZGlyID0gc3JjZGlyO1xuICAgIHRoaXMucHVibGljRGlyID0gcHVibGljRGlyO1xuXG4gICAgLy8gQWRkIFZpdGUgY29tcG9uZW50XG4gICAgbmV3IFZpdGVDb21wb25lbnQodGhpcywge1xuICAgICAgc3JjZGlyOiB0aGlzLnNyY2RpcixcbiAgICB9KTtcblxuICAgIC8vIEFkZCBFU0xpbnQgY29uZmlndXJhdGlvblxuICAgIG5ldyBWaXRlRXNsaW50Q29uZmlnKHRoaXMpO1xuXG4gICAgLy8gQWRkIGluZGV4Lmh0bWxcbiAgICBuZXcgSW5kZXhIdG1sKHRoaXMsIHtcbiAgICAgIHRpdGxlOiB0aXRsZSA/PyB0aGlzLm5hbWUsXG4gICAgICBzcmNkaXI6IHRoaXMuc3JjZGlyLFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIFR5cGVTY3JpcHQgY29uZmlnc1xuICAgIG5ldyBWaXRlVHNDb25maWdzKHRoaXMsIHtcbiAgICAgIHNyY2RpcjogdGhpcy5zcmNkaXIsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgLmdpdGlnbm9yZSBlbnRyaWVzXG4gICAgdGhpcy5naXRpZ25vcmU/LmFkZFBhdHRlcm5zKCdkaXN0JywgJ2Rpc3Qtc3NyJywgJyoubG9jYWwnKTtcblxuICAgIC8vIEFkZCB2aXRlLWVudi5kLnRzIGZvciB0eXBlIGRlY2xhcmF0aW9uc1xuICAgIG5ldyBWaXRlRW52RHRzKHRoaXMsIHtcbiAgICAgIHNyY2RpcjogdGhpcy5zcmNkaXIsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgUG9zdENTUyBjb25maWcgZm9yIFRhaWx3aW5kXG4gICAgbmV3IFBvc3RDU1NDb25maWdGaWxlKHRoaXMpO1xuXG4gICAgLy8gQWRkIGNvbmZpZy50cyBmb3IgcnVudGltZSBjb25maWd1cmF0aW9uXG4gICAgbmV3IENvbmZpZ0ZpbGUodGhpcywge1xuICAgICAgc3JjZGlyOiB0aGlzLnNyY2RpcixcbiAgICB9KTtcblxuICAgIC8vIEFkZCBzYW1wbGUgY29uZmlnLmpzb25cbiAgICBuZXcgQ29uZmlnSnNvbkZpbGUodGhpcywgeyB9KTtcblxuXG4gICAgLy8gQWRkIHNhbXBsZSBjb2RlIGlmIHJlcXVlc3RlZFxuICAgIGlmIChzYW1wbGVDb2RlKSB7XG4gICAgICBuZXcgVml0ZVNhbXBsZUNvZGUodGhpcywge1xuICAgICAgICBzcmNkaXI6IHRoaXMuc3JjZGlyLFxuICAgICAgICBwdWJsaWNEaXI6IHRoaXMucHVibGljRGlyLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQWRkIFBsYXl3cmlnaHQgZTJlIHRlc3Rpbmcgc3VwcG9ydFxuICAgIGlmIChlMmVUZXN0aW5nKSB7XG4gICAgICBuZXcgUGxheXdyaWdodEUyRUNvbXBvbmVudCh0aGlzLCB7XG4gICAgICAgIHB1YmxpY0RpcjogdGhpcy5wdWJsaWNEaXIsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBVc2UgcmVsYXRpdmUgcGF0aCBmb3IgZGV2Q29tbWFuZFxuICAgIGNvbnN0IHJlbGF0aXZlT3V0ZGlyID0gdGhpcy5wYXJlbnRcbiAgICAgID8gcmVsYXRpdmUodGhpcy5wYXJlbnQub3V0ZGlyLCB0aGlzLm91dGRpcilcbiAgICAgIDogYmFzZW5hbWUodGhpcy5vdXRkaXIpO1xuICAgIHRoaXMuZGV2Q29tbWFuZCA9IGBjZCAke3JlbGF0aXZlT3V0ZGlyfSAmJiAke3J1blNjcmlwdENvbW1hbmQodGhpcy5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyLCAnZGV2Jyl9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBjdXN0b20gZmllbGQgdG8gdGhlIENvbmZpZyB0eXBlXG4gICAqIEBwYXJhbSBmaWVsZE5hbWUgVGhlIG5hbWUgb2YgdGhlIGZpZWxkXG4gICAqIEBwYXJhbSBmaWVsZFR5cGUgVGhlIFR5cGVTY3JpcHQgdHlwZSBvZiB0aGUgZmllbGQgKGUuZy4sICdzdHJpbmcnLCAnbnVtYmVyJywgJ2Jvb2xlYW4nLCAnc3RyaW5nW10nKVxuICAgKiBAcmV0dXJucyB0aGlzIHByb2plY3QgaW5zdGFuY2UgZm9yIGNoYWluaW5nXG4gICAqL1xuICBhZGRDb25maWdGaWVsZChmaWVsZE5hbWU6IHN0cmluZywgZmllbGRUeXBlOiBzdHJpbmcpOiB0aGlzIHtcbiAgICB0aGlzLmNvbmZpZ0ZpZWxkcy5zZXQoZmllbGROYW1lLCBmaWVsZFR5cGUpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY29uZmlnIGZpZWxkcyBtYXAgKGZvciBpbnRlcm5hbCB1c2UgYnkgQ29uZmlnRmlsZSlcbiAgICogQGludGVybmFsXG4gICAqL1xuICBnZXRDb25maWdGaWVsZHMoKTogTWFwPHN0cmluZywgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnRmllbGRzO1xuICB9XG59XG5cbmludGVyZmFjZSBWaXRlQ29tcG9uZW50T3B0aW9ucyB7XG4gIHJlYWRvbmx5IHNyY2Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyZXMgVml0ZSBkZXBlbmRlbmNpZXMgYW5kIHNjcmlwdHNcbiAqL1xuY2xhc3MgVml0ZUNvbXBvbmVudCBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFR5cGVTY3JpcHRBcHBQcm9qZWN0LCBfb3B0aW9uczogVml0ZUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIGNvbnN0IHRzUHJvamVjdCA9IHByb2plY3QgYXMgVHlwZVNjcmlwdEFwcFByb2plY3Q7XG5cbiAgICAvLyBTZXQgcGFja2FnZSB0eXBlIHRvIG1vZHVsZSBmb3IgRVNNIHN1cHBvcnRcbiAgICB0c1Byb2plY3QucGFja2FnZS5hZGRGaWVsZCgndHlwZScsICdtb2R1bGUnKTtcblxuICAgIC8vIEFkZCBSZWFjdCBkZXBlbmRlbmNpZXNcbiAgICB0c1Byb2plY3QuYWRkRGVwcygncmVhY3RAXjE5LjIuMCcsICdyZWFjdC1kb21AXjE5LjIuMCcpO1xuXG4gICAgLy8gQWRkIGRldiBkZXBlbmRlbmNpZXNcbiAgICB0c1Byb2plY3QuYWRkRGV2RGVwcyhcbiAgICAgICdAdHlwZXMvcmVhY3RAXjE5LjIuMicsXG4gICAgICAnQHR5cGVzL3JlYWN0LWRvbUBeMTkuMi4yJyxcbiAgICAgICdAdml0ZWpzL3BsdWdpbi1yZWFjdEBeNS4xLjAnLFxuICAgICAgJ3ZpdGVAXjUuNC4wJyxcbiAgICAgICd0eXBlc2NyaXB0QH41LjkuMycsXG4gICAgICAnQGVzbGludC9qc0BeOS4zOS4xJyxcbiAgICAgICdlc2xpbnRAXjkuMzkuMScsXG4gICAgICAnZXNsaW50LXBsdWdpbi1yZWFjdC1ob29rc0BeNS4yLjAnLFxuICAgICAgJ2VzbGludC1wbHVnaW4tcmVhY3QtcmVmcmVzaEBeMC40LjI0JyxcbiAgICAgICdnbG9iYWxzQF4xNi41LjAnLFxuICAgICAgJ3R5cGVzY3JpcHQtZXNsaW50QF44LjQ2LjMnLFxuICAgICk7XG5cbiAgICAvLyBDcmVhdGUgdml0ZS5jb25maWcudHMgYXMgYSBtYW5hZ2VkIGZpbGVcbiAgICBuZXcgVml0ZUNvbmZpZ0ZpbGUocHJvamVjdCk7XG5cbiAgICAvLyBBZGQgc2NyaXB0c1xuICAgIHRzUHJvamVjdC5hZGRUYXNrKCdkZXYnLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1N0YXJ0IGRldmVsb3BtZW50IHNlcnZlcicsXG4gICAgICBleGVjOiAndml0ZScsXG4gICAgfSk7XG5cbiAgICAvLyBSZW1vdmUgYW5kIHJlY3JlYXRlIGJ1aWxkIHRhc2sgdG8gY3VzdG9taXplIGl0IGZvciBWaXRlXG4gICAgdHNQcm9qZWN0LnJlbW92ZVRhc2soJ2J1aWxkJyk7XG4gICAgdHNQcm9qZWN0LmFkZFRhc2soJ2J1aWxkJywge1xuICAgICAgZGVzY3JpcHRpb246ICdCdWlsZCBmb3IgcHJvZHVjdGlvbicsXG4gICAgICBleGVjOiAndHNjIC1iICYmIHZpdGUgYnVpbGQnLFxuICAgIH0pO1xuXG4gICAgdHNQcm9qZWN0LmFkZFRhc2soJ3ByZXZpZXcnLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1ByZXZpZXcgcHJvZHVjdGlvbiBidWlsZCcsXG4gICAgICBleGVjOiAndml0ZSBwcmV2aWV3JyxcbiAgICB9KTtcblxuICAgIHRzUHJvamVjdC5hZGRUYXNrKCdsaW50Jywge1xuICAgICAgZGVzY3JpcHRpb246ICdMaW50IGNvZGUnLFxuICAgICAgZXhlYzogJ2VzbGludCAuJyxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIEVTTGludCBjb25maWd1cmF0aW9uIGZvciBWaXRlICsgUmVhY3RcbiAqL1xuY2xhc3MgVml0ZUVzbGludENvbmZpZyBleHRlbmRzIEZpbGVCYXNlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QsICdlc2xpbnQuY29uZmlnLmpzJywge1xuICAgICAgbWFya2VyOiB0cnVlLFxuICAgICAgcmVhZG9ubHk6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICBzeW50aGVzaXplQ29udGVudCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBgaW1wb3J0IGpzIGZyb20gJ0Blc2xpbnQvanMnXG5pbXBvcnQgZ2xvYmFscyBmcm9tICdnbG9iYWxzJ1xuaW1wb3J0IHJlYWN0SG9va3MgZnJvbSAnZXNsaW50LXBsdWdpbi1yZWFjdC1ob29rcydcbmltcG9ydCByZWFjdFJlZnJlc2ggZnJvbSAnZXNsaW50LXBsdWdpbi1yZWFjdC1yZWZyZXNoJ1xuaW1wb3J0IHRzZXNsaW50IGZyb20gJ3R5cGVzY3JpcHQtZXNsaW50J1xuXG5leHBvcnQgZGVmYXVsdCBbXG4gIHsgaWdub3JlczogWydkaXN0J10gfSxcbiAge1xuICAgIGZpbGVzOiBbJyoqLyoue3RzLHRzeH0nXSxcbiAgICBsYW5ndWFnZU9wdGlvbnM6IHtcbiAgICAgIGVjbWFWZXJzaW9uOiAyMDIwLFxuICAgICAgZ2xvYmFsczogZ2xvYmFscy5icm93c2VyLFxuICAgIH0sXG4gICAgcGx1Z2luczoge1xuICAgICAgJ3JlYWN0LWhvb2tzJzogcmVhY3RIb29rcyxcbiAgICAgICdyZWFjdC1yZWZyZXNoJzogcmVhY3RSZWZyZXNoLFxuICAgIH0sXG4gICAgcnVsZXM6IHtcbiAgICAgIC4uLnJlYWN0SG9va3MuY29uZmlncy5yZWNvbW1lbmRlZC5ydWxlcyxcbiAgICAgICdyZWFjdC1yZWZyZXNoL29ubHktZXhwb3J0LWNvbXBvbmVudHMnOiBbXG4gICAgICAgICd3YXJuJyxcbiAgICAgICAgeyBhbGxvd0NvbnN0YW50RXhwb3J0OiB0cnVlIH0sXG4gICAgICBdLFxuICAgIH0sXG4gIH0sXG4gIGpzLmNvbmZpZ3MucmVjb21tZW5kZWQsXG4gIC4uLnRzZXNsaW50LmNvbmZpZ3MucmVjb21tZW5kZWQsXG5dXG5gO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgdml0ZS5jb25maWcudHMgZmlsZVxuICovXG5jbGFzcyBWaXRlQ29uZmlnRmlsZSBleHRlbmRzIEZpbGVCYXNlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QsICd2aXRlLmNvbmZpZy50cycsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgc3ludGhlc2l6ZUNvbnRlbnQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gYGltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gJ3ZpdGUnXG5pbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3QnXG5cbi8vIGh0dHBzOi8vdml0ZS5kZXYvY29uZmlnL1xuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgcGx1Z2luczogW3JlYWN0KCldLFxufSlcbmA7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBwb3N0Y3NzLmNvbmZpZy5qcyBmaWxlIGZvciBUYWlsd2luZCBDU1MgdjRcbiAqL1xuY2xhc3MgUG9zdENTU0NvbmZpZ0ZpbGUgZXh0ZW5kcyBGaWxlQmFzZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QpIHtcbiAgICBzdXBlcihwcm9qZWN0LCAncG9zdGNzcy5jb25maWcuanMnLCB7XG4gICAgICBtYXJrZXI6IHRydWUsXG4gICAgICByZWFkb25seTogdHJ1ZSxcbiAgICB9KTtcbiAgfVxuXG4gIHN5bnRoZXNpemVDb250ZW50KCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGBleHBvcnQgZGVmYXVsdCB7XG4gIHBsdWdpbnM6IHtcbiAgICBcIkB0YWlsd2luZGNzcy9wb3N0Y3NzXCI6IHt9LFxuICAgIGF1dG9wcmVmaXhlcjoge30sXG4gIH0sXG59XG5gO1xuICB9XG59XG5cbmludGVyZmFjZSBWaXRlRW52RHRzT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHNyY2Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIHZpdGUtZW52LmQudHMgZmlsZSBmb3IgdHlwZSBkZWNsYXJhdGlvbnNcbiAqL1xuY2xhc3MgVml0ZUVudkR0cyBleHRlbmRzIEZpbGVCYXNlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgb3B0aW9uczogVml0ZUVudkR0c09wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vdml0ZS1lbnYuZC50c2AsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgc3ludGhlc2l6ZUNvbnRlbnQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gYC8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZS9jbGllbnRcIiAvPlxuYDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgQ29uZmlnRmlsZU9wdGlvbnMge1xuICByZWFkb25seSBzcmNkaXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBjb25maWcudHMgZmlsZSBmb3IgcnVudGltZSBjb25maWd1cmF0aW9uXG4gKi9cbmNsYXNzIENvbmZpZ0ZpbGUgZXh0ZW5kcyBGaWxlQmFzZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IENvbmZpZ0ZpbGVPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCwgYCR7b3B0aW9ucy5zcmNkaXJ9L2NvbmZpZy50c2AsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgc3ludGhlc2l6ZUNvbnRlbnQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAvLyBHZXQgY3VzdG9tIGNvbmZpZyBmaWVsZHMgZnJvbSBwYXJlbnQgcHJvamVjdFxuICAgIGNvbnN0IHZpdGVQcm9qZWN0ID0gdGhpcy5wcm9qZWN0IGFzIFZpdGVSZWFjdFByb2plY3Q7XG4gICAgY29uc3QgY3VzdG9tRmllbGRzID0gdml0ZVByb2plY3QuZ2V0Q29uZmlnRmllbGRzKCk7XG5cbiAgICAvLyBHZW5lcmF0ZSBiYXNlIGNvbmZpZyB0eXBlXG4gICAgY29uc3QgYmFzZUNvbmZpZ1R5cGUgPSBgdHlwZSBCYXNlQ29uZmlnID0ge1xuICBjbGVya1B1Ymxpc2hhYmxlS2V5OiBzdHJpbmc7XG4gIGFwaUJhc2VVcmw6IHN0cmluZztcbiAgdGltZW91dDogbnVtYmVyO1xufWA7XG5cbiAgICAvLyBHZW5lcmF0ZSBjdXN0b20gZmllbGRzIHR5cGUgaWYgYW55IGV4aXN0XG4gICAgbGV0IGNvbmZpZ1R5cGVEZWZpbml0aW9uOiBzdHJpbmc7XG4gICAgaWYgKGN1c3RvbUZpZWxkcy5zaXplID4gMCkge1xuICAgICAgY29uc3QgZmllbGREZWZpbml0aW9ucyA9IEFycmF5LmZyb20oY3VzdG9tRmllbGRzLmVudHJpZXMoKSlcbiAgICAgICAgLm1hcCgoW25hbWUsIHR5cGVdKSA9PiBgICAke25hbWV9OiAke3R5cGV9O2ApXG4gICAgICAgIC5qb2luKCdcXG4nKTtcblxuICAgICAgY29uc3QgY3VzdG9tRmllbGRzVHlwZSA9IGB0eXBlIEN1c3RvbUNvbmZpZyA9IHtcbiR7ZmllbGREZWZpbml0aW9uc31cbn1gO1xuXG4gICAgICBjb25maWdUeXBlRGVmaW5pdGlvbiA9IGAke2N1c3RvbUZpZWxkc1R5cGV9XG5cbmV4cG9ydCB0eXBlIENvbmZpZyA9IEJhc2VDb25maWcgJiBDdXN0b21Db25maWc7YDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uZmlnVHlwZURlZmluaXRpb24gPSAnZXhwb3J0IHR5cGUgQ29uZmlnID0gQmFzZUNvbmZpZzsnO1xuICAgIH1cblxuICAgIHJldHVybiBgaW1wb3J0IHsgdXNlRWZmZWN0LCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JztcblxuJHtiYXNlQ29uZmlnVHlwZX1cblxuJHtjb25maWdUeXBlRGVmaW5pdGlvbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVzZUNvbmZpZygpIHtcbiAgY29uc3QgW2xvYWRlZENvbmZpZywgc2V0TG9hZGVkQ29uZmlnXSA9IHVzZVN0YXRlPENvbmZpZ3x1bmRlZmluZWQ+KCk7XG4gIGNvbnN0IFtpc0xvYWRpbmcsIHNldElzTG9hZGluZ10gPSB1c2VTdGF0ZShmYWxzZSk7XG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIWxvYWRlZENvbmZpZykge1xuICAgICAgZmV0Y2goJy9jb25maWcuanNvbicsIHsgY2FjaGU6ICduby1zdG9yZScgfSkudGhlbihyZXNwb25zZT0+e1xuICAgICAgICByZXNwb25zZS5qc29uKCkudGhlbigoY29uZmlnKSA9PiB7XG4gICAgICAgICAgc2V0SXNMb2FkaW5nKGZhbHNlKVxuICAgICAgICAgIHNldExvYWRlZENvbmZpZyhjb25maWcpXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICB9XG4gIH0sIFtsb2FkZWRDb25maWddKTtcblxuICByZXR1cm4geyBjb25maWc6IGxvYWRlZENvbmZpZywgaXNMb2FkaW5nIH07XG59XG5gO1xuICB9XG59XG5cbmludGVyZmFjZSBDb25maWdKc29uRmlsZU9wdGlvbnMge31cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBjb25maWcuanNvbiBzYW1wbGUgZmlsZSBmb3IgcnVudGltZSBjb25maWd1cmF0aW9uXG4gKi9cbmNsYXNzIENvbmZpZ0pzb25GaWxlIGV4dGVuZHMgU2FtcGxlRmlsZSB7XG4gIHBhdGg6IHN0cmluZztcbiAgY29uc3RydWN0b3IocHJvamVjdDogVml0ZVJlYWN0UHJvamVjdCwgX29wdGlvbnM6IENvbmZpZ0pzb25GaWxlT3B0aW9ucykge1xuICAgIHN1cGVyKHByb2plY3QsIGAke3Byb2plY3QucHVibGljRGlyfS9jb25maWcuanNvbmAsIHtcbiAgICAgIGNvbnRlbnRzOiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGFwaUJhc2VVcmw6ICdodHRwOi8vbG9jYWxob3N0OjMwMDAvYXBpJyxcbiAgICAgICAgY2xlcmtQdWJsaXNoYWJsZUtleTogJ3RiZCcsXG4gICAgICB9LCBudWxsLCAyKSxcbiAgICB9KTtcbiAgICB0aGlzLnBhdGggPSBgJHtwcm9qZWN0LnB1YmxpY0Rpcn0vY29uZmlnLmpzb25gO1xuICB9XG59XG5cbmludGVyZmFjZSBJbmRleEh0bWxPcHRpb25zIHtcbiAgcmVhZG9ubHkgdGl0bGU6IHN0cmluZztcbiAgcmVhZG9ubHkgc3JjZGlyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgaW5kZXguaHRtbCBmaWxlXG4gKi9cbmNsYXNzIEluZGV4SHRtbCBleHRlbmRzIFNhbXBsZUZpbGUge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBQcm9qZWN0LCBvcHRpb25zOiBJbmRleEh0bWxPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCwgJ2luZGV4Lmh0bWwnLCB7XG4gICAgICBjb250ZW50czogYDwhZG9jdHlwZSBodG1sPlxuPGh0bWwgbGFuZz1cImVuXCI+XG4gIDxoZWFkPlxuICAgIDxtZXRhIGNoYXJzZXQ9XCJVVEYtOFwiIC8+XG4gICAgPGxpbmsgcmVsPVwiaWNvblwiIHR5cGU9XCJpbWFnZS9zdmcreG1sXCIgaHJlZj1cIi92aXRlLnN2Z1wiIC8+XG4gICAgPG1ldGEgbmFtZT1cInZpZXdwb3J0XCIgY29udGVudD1cIndpZHRoPWRldmljZS13aWR0aCwgaW5pdGlhbC1zY2FsZT0xLjBcIiAvPlxuICAgIDx0aXRsZT4ke29wdGlvbnMudGl0bGV9PC90aXRsZT5cbiAgPC9oZWFkPlxuICA8Ym9keT5cbiAgICA8ZGl2IGlkPVwicm9vdFwiPjwvZGl2PlxuICAgIDxzY3JpcHQgdHlwZT1cIm1vZHVsZVwiIHNyYz1cIi8ke29wdGlvbnMuc3JjZGlyfS9tYWluLnRzeFwiPjwvc2NyaXB0PlxuICA8L2JvZHk+XG48L2h0bWw+XG5gLFxuICAgIH0pO1xuICB9XG59XG5cbmludGVyZmFjZSBWaXRlVHNDb25maWdzT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHNyY2Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIFR5cGVTY3JpcHQgY29uZmlndXJhdGlvbiBmaWxlcyBmb3IgVml0ZVxuICovXG5jbGFzcyBWaXRlVHNDb25maWdzIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgb3B0aW9uczogVml0ZVRzQ29uZmlnc09wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIC8vIE1haW4gdHNjb25maWcuanNvbiAocHJvamVjdCByZWZlcmVuY2VzKVxuICAgIG5ldyBKc29uRmlsZShwcm9qZWN0LCAndHNjb25maWcuanNvbicsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgICAgb2JqOiB7XG4gICAgICAgIGZpbGVzOiBbXSxcbiAgICAgICAgcmVmZXJlbmNlczogW1xuICAgICAgICAgIHsgcGF0aDogJy4vdHNjb25maWcuYXBwLmpzb24nIH0sXG4gICAgICAgICAgeyBwYXRoOiAnLi90c2NvbmZpZy5ub2RlLmpzb24nIH0sXG4gICAgICAgIF0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gdHNjb25maWcuYXBwLmpzb24gKGZvciBhcHBsaWNhdGlvbiBjb2RlKVxuICAgIG5ldyBKc29uRmlsZShwcm9qZWN0LCAndHNjb25maWcuYXBwLmpzb24nLCB7XG4gICAgICBtYXJrZXI6IHRydWUsXG4gICAgICByZWFkb25seTogdHJ1ZSxcbiAgICAgIG9iajoge1xuICAgICAgICBjb21waWxlck9wdGlvbnM6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdFUzIwMjAnLFxuICAgICAgICAgIHVzZURlZmluZUZvckNsYXNzRmllbGRzOiB0cnVlLFxuICAgICAgICAgIGxpYjogWydFUzIwMjAnLCAnRE9NJywgJ0RPTS5JdGVyYWJsZSddLFxuICAgICAgICAgIG1vZHVsZTogJ0VTTmV4dCcsXG4gICAgICAgICAgc2tpcExpYkNoZWNrOiB0cnVlLFxuXG4gICAgICAgICAgLy8gQnVuZGxlciBtb2RlXG4gICAgICAgICAgbW9kdWxlUmVzb2x1dGlvbjogJ2J1bmRsZXInLFxuICAgICAgICAgIGFsbG93SW1wb3J0aW5nVHNFeHRlbnNpb25zOiB0cnVlLFxuICAgICAgICAgIGlzb2xhdGVkTW9kdWxlczogdHJ1ZSxcbiAgICAgICAgICBtb2R1bGVEZXRlY3Rpb246ICdmb3JjZScsXG4gICAgICAgICAgbm9FbWl0OiB0cnVlLFxuICAgICAgICAgIGpzeDogJ3JlYWN0LWpzeCcsXG5cbiAgICAgICAgICAvLyBMaW50aW5nXG4gICAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICAgIG5vVW51c2VkTG9jYWxzOiB0cnVlLFxuICAgICAgICAgIG5vVW51c2VkUGFyYW1ldGVyczogdHJ1ZSxcbiAgICAgICAgICBub0ZhbGx0aHJvdWdoQ2FzZXNJblN3aXRjaDogdHJ1ZSxcbiAgICAgICAgICBub1VuY2hlY2tlZFNpZGVFZmZlY3RJbXBvcnRzOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBpbmNsdWRlOiBbb3B0aW9ucy5zcmNkaXJdLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIHRzY29uZmlnLm5vZGUuanNvbiAoZm9yIFZpdGUgY29uZmlnKVxuICAgIG5ldyBKc29uRmlsZShwcm9qZWN0LCAndHNjb25maWcubm9kZS5qc29uJywge1xuICAgICAgbWFya2VyOiB0cnVlLFxuICAgICAgcmVhZG9ubHk6IHRydWUsXG4gICAgICBvYmo6IHtcbiAgICAgICAgY29tcGlsZXJPcHRpb25zOiB7XG4gICAgICAgICAgdGFyZ2V0OiAnRVMyMDIyJyxcbiAgICAgICAgICBsaWI6IFsnRVMyMDIzJ10sXG4gICAgICAgICAgbW9kdWxlOiAnRVNOZXh0JyxcbiAgICAgICAgICBza2lwTGliQ2hlY2s6IHRydWUsXG5cbiAgICAgICAgICAvLyBCdW5kbGVyIG1vZGVcbiAgICAgICAgICBtb2R1bGVSZXNvbHV0aW9uOiAnYnVuZGxlcicsXG4gICAgICAgICAgYWxsb3dJbXBvcnRpbmdUc0V4dGVuc2lvbnM6IHRydWUsXG4gICAgICAgICAgaXNvbGF0ZWRNb2R1bGVzOiB0cnVlLFxuICAgICAgICAgIG1vZHVsZURldGVjdGlvbjogJ2ZvcmNlJyxcbiAgICAgICAgICBub0VtaXQ6IHRydWUsXG5cbiAgICAgICAgICAvLyBMaW50aW5nXG4gICAgICAgICAgc3RyaWN0OiB0cnVlLFxuICAgICAgICAgIG5vVW51c2VkTG9jYWxzOiB0cnVlLFxuICAgICAgICAgIG5vVW51c2VkUGFyYW1ldGVyczogdHJ1ZSxcbiAgICAgICAgICBub0ZhbGx0aHJvdWdoQ2FzZXNJblN3aXRjaDogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICAgICAgaW5jbHVkZTogWyd2aXRlLmNvbmZpZy50cyddLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgVml0ZVNhbXBsZUNvZGVPcHRpb25zIHtcbiAgcmVhZG9ubHkgc3JjZGlyOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHB1YmxpY0Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBzYW1wbGUgY29kZSBmb3IgYSBWaXRlICsgUmVhY3QgcHJvamVjdFxuICovXG5jbGFzcyBWaXRlU2FtcGxlQ29kZSBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IFZpdGVTYW1wbGVDb2RlT3B0aW9ucykge1xuICAgIHN1cGVyKHByb2plY3QpO1xuXG4gICAgLy8gQ3JlYXRlIEFwcC50c3hcbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vQXBwLnRzeGAsIHtcbiAgICAgIGNvbnRlbnRzOiBgaW1wb3J0ICcuL0FwcC5jc3MnXG5pbXBvcnQgeyBTaWduZWRJbiwgVXNlckJ1dHRvbiB9IGZyb20gJ0BjbGVyay9jbGVyay1yZWFjdCc7XG5pbXBvcnQgeyB1c2VCYXNlUXVlcnkgfSBmcm9tIFwiLi9zZXJ2aWNlcy9CYXNlU2VydmljZS50c1wiO1xuXG5cbmZ1bmN0aW9uIEFwcCgpIHtcbiAgY29uc3Qge2RhdGEsIGlzTG9hZGluZ30gPSB1c2VCYXNlUXVlcnkoJy8nLCB7cmV0cnlPbk1vdW50OiB0cnVlfSk7XG5cblxuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICAgIDxoZWFkZXI+XG5cbiAgICAgICAgICA8U2lnbmVkSW4+XG4gICAgICAgICAgICA8VXNlckJ1dHRvbi8+XG4gICAgICAgICAgPC9TaWduZWRJbj5cbiAgICAgICAgPC9oZWFkZXI+XG4gICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiY2FyZFwiPlxuICAgICAgICAgIHsgaXNMb2FkaW5nID8gJ0xvYWRpbmcuLi4nIDogSlNPTi5zdHJpbmdpZnkoZGF0YSwgbnVsbCAsKX1cbiAgICAgICAgPC9kaXY+XG4gICAgPC8+XG4gIClcbn1cblxuZXhwb3J0IGRlZmF1bHQgQXBwXG5gLFxuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIEJhc2VTZXJ2aWNlLnRzXG4gICAgbmV3IFRleHRGaWxlKHByb2plY3QsIGAke29wdGlvbnMuc3JjZGlyfS9zZXJ2aWNlcy9CYXNlU2VydmljZS50c2AsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgICAgbGluZXM6IFtcbiAgICAgICAgJ2ltcG9ydCB7IHVzZVF1ZXJ5LCBVc2VRdWVyeU9wdGlvbnMgfSBmcm9tIFxcJ0B0YW5zdGFjay9yZWFjdC1xdWVyeVxcJzsnLFxuICAgICAgICAnaW1wb3J0IHsgdXNlQXV0aCB9IGZyb20gXFwnQGNsZXJrL2NsZXJrLXJlYWN0XFwnOycsXG4gICAgICAgICdpbXBvcnQgeyB1c2VDb25maWcgfSBmcm9tIFxcJy4uL2NvbmZpZ1xcJzsnLFxuICAgICAgICAnJyxcbiAgICAgICAgJ2V4cG9ydCBmdW5jdGlvbiB1c2VCYXNlUXVlcnk8VERhdGEgPSB1bmtub3duPignLFxuICAgICAgICAnICBwYXRoOiBzdHJpbmcsJyxcbiAgICAgICAgJyAgb3B0aW9ucz86IE9taXQ8VXNlUXVlcnlPcHRpb25zPFREYXRhPiwgXFwncXVlcnlLZXlcXCcgfCBcXCdxdWVyeUZuXFwnPicsXG4gICAgICAgICcpIHsnLFxuICAgICAgICAnICBjb25zdCB7IGNvbmZpZyB9ID0gdXNlQ29uZmlnKCk7JyxcbiAgICAgICAgJyAgY29uc3QgeyBnZXRUb2tlbiB9ID0gdXNlQXV0aCgpOycsXG4gICAgICAgICcnLFxuICAgICAgICAnICByZXR1cm4gdXNlUXVlcnk8VERhdGE+KHsnLFxuICAgICAgICAnICAgIHF1ZXJ5S2V5OiBbXFwnYmFzZVxcJ10sJyxcbiAgICAgICAgJyAgICBxdWVyeUZuOiBhc3luYyAoKSA9PiB7JyxcbiAgICAgICAgJyAgICAgIGlmICghY29uZmlnPy5hcGlCYXNlVXJsKSB7JyxcbiAgICAgICAgJyAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxcJ0FQSSBiYXNlIFVSTCBub3QgY29uZmlndXJlZFxcJyk7JyxcbiAgICAgICAgJyAgICAgIH0nLFxuICAgICAgICAnJyxcbiAgICAgICAgJyAgICAgIGNvbnN0IHRva2VuID0gYXdhaXQgZ2V0VG9rZW4oKTsnLFxuICAgICAgICAnJyxcbiAgICAgICAgJyAgICAgIC8vIE5vcm1hbGl6ZSBVUkwgYnkgcmVtb3ZpbmcgdHJhaWxpbmcgc2xhc2ggZnJvbSBiYXNlVXJsIGFuZCBlbnN1cmluZyBwYXRoIHN0YXJ0cyB3aXRoIHNsYXNoJyxcbiAgICAgICAgJyAgICAgIGNvbnN0IGJhc2VVcmwgPSBjb25maWcuYXBpQmFzZVVybC5yZXBsYWNlKC9cXFxcLyskLywgXFwnXFwnKTsnLFxuICAgICAgICAnICAgICAgY29uc3Qgbm9ybWFsaXplZFBhdGggPSBwYXRoLnN0YXJ0c1dpdGgoXFwnL1xcJykgPyBwYXRoIDogYC8ke3BhdGh9YDsnLFxuICAgICAgICAnICAgICAgJyxcbiAgICAgICAgJyAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYCR7YmFzZVVybH0ke25vcm1hbGl6ZWRQYXRofWAsIHsnLFxuICAgICAgICAnICAgICAgICBoZWFkZXJzOiB7JyxcbiAgICAgICAgJyAgICAgICAgICBcXCdBdXRob3JpemF0aW9uXFwnOiBgQmVhcmVyICR7dG9rZW59YCwnLFxuICAgICAgICAnICAgICAgICB9LCcsXG4gICAgICAgICcgICAgICB9KTsnLFxuICAgICAgICAnJyxcbiAgICAgICAgJyAgICAgIGlmICghcmVzcG9uc2Uub2spIHsnLFxuICAgICAgICAnICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEhUVFAgZXJyb3IhIHN0YXR1czogJHtyZXNwb25zZS5zdGF0dXN9YCk7JyxcbiAgICAgICAgJyAgICAgIH0nLFxuICAgICAgICAnJyxcbiAgICAgICAgJyAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7JyxcbiAgICAgICAgJyAgICB9LCcsXG4gICAgICAgICcgICAgZW5hYmxlZDogISFjb25maWc/LmFwaUJhc2VVcmwsJyxcbiAgICAgICAgJyAgICAuLi5vcHRpb25zLCcsXG4gICAgICAgICcgIH0pOycsXG4gICAgICAgICd9JyxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgUm9vdFNlcnZpY2UudHNcbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vc2VydmljZXMvUm9vdFNlcnZpY2UudHNgLCB7XG4gICAgICBjb250ZW50czogYGltcG9ydCB7IFVzZVF1ZXJ5T3B0aW9ucyB9IGZyb20gJ0B0YW5zdGFjay9yZWFjdC1xdWVyeSc7XG5pbXBvcnQgeyB1c2VCYXNlUXVlcnkgfSBmcm9tICcuL0Jhc2VTZXJ2aWNlJztcblxuZXhwb3J0IGZ1bmN0aW9uIHVzZVJvb3RRdWVyeTxURGF0YSA9IHVua25vd24+KFxuICBvcHRpb25zPzogT21pdDxVc2VRdWVyeU9wdGlvbnM8VERhdGE+LCAncXVlcnlLZXknIHwgJ3F1ZXJ5Rm4nPlxuKSB7XG4gIHJldHVybiB1c2VCYXNlUXVlcnk8VERhdGE+KCcvJywgb3B0aW9ucyk7XG59XG5gLFxuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIEFwcC5jc3NcbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vQXBwLmNzc2AsIHtcbiAgICAgIGNvbnRlbnRzOiBgI3Jvb3Qge1xuICB3aWR0aDogMTAwJTtcbiAgaGVpZ2h0OiAxMDAlO1xufVxuXG4ubG9nbyB7XG4gIGhlaWdodDogNmVtO1xuICBwYWRkaW5nOiAxLjVlbTtcbiAgd2lsbC1jaGFuZ2U6IGZpbHRlcjtcbiAgdHJhbnNpdGlvbjogZmlsdGVyIDMwMG1zO1xufVxuLmxvZ286aG92ZXIge1xuICBmaWx0ZXI6IGRyb3Atc2hhZG93KDAgMCAyZW0gIzY0NmNmZmFhKTtcbn1cbi5sb2dvLnJlYWN0OmhvdmVyIHtcbiAgZmlsdGVyOiBkcm9wLXNoYWRvdygwIDAgMmVtICM2MWRhZmJhYSk7XG59XG5cbkBrZXlmcmFtZXMgbG9nby1zcGluIHtcbiAgZnJvbSB7XG4gICAgdHJhbnNmb3JtOiByb3RhdGUoMGRlZyk7XG4gIH1cbiAgdG8ge1xuICAgIHRyYW5zZm9ybTogcm90YXRlKDM2MGRlZyk7XG4gIH1cbn1cblxuQG1lZGlhIChwcmVmZXJzLXJlZHVjZWQtbW90aW9uOiBuby1wcmVmZXJlbmNlKSB7XG4gIGE6bnRoLW9mLXR5cGUoMikgLmxvZ28ge1xuICAgIGFuaW1hdGlvbjogbG9nby1zcGluIGluZmluaXRlIDIwcyBsaW5lYXI7XG4gIH1cbn1cblxuLmNhcmQge1xuICBwYWRkaW5nOiAyZW07XG59XG5cbi5yZWFkLXRoZS1kb2NzIHtcbiAgY29sb3I6ICM4ODg7XG59XG5gLFxuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIG1haW4udHN4XG4gICAgbmV3IFNhbXBsZUZpbGUocHJvamVjdCwgYCR7b3B0aW9ucy5zcmNkaXJ9L21haW4udHN4YCwge1xuICAgICAgY29udGVudHM6IGBpbXBvcnQgeyBTdHJpY3RNb2RlIH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBjcmVhdGVSb290IH0gZnJvbSAncmVhY3QtZG9tL2NsaWVudCdcbmltcG9ydCAnLi9pbmRleC5jc3MnXG5pbXBvcnQgQXBwIGZyb20gJy4vQXBwLnRzeCdcbmltcG9ydCB7IENsZXJrUHJvdmlkZXIsIFNpZ25lZEluLCBTaWduZWRPdXQsIFNpZ25JbkJ1dHRvbiB9IGZyb20gJ0BjbGVyay9jbGVyay1yZWFjdCdcbmltcG9ydCB7IHVzZUNvbmZpZyB9IGZyb20gJy4vY29uZmlnJ1xuaW1wb3J0IHsgUXVlcnlDbGllbnQsIFF1ZXJ5Q2xpZW50UHJvdmlkZXIgfSBmcm9tIFwiQHRhbnN0YWNrL3JlYWN0LXF1ZXJ5XCJcblxuZnVuY3Rpb24gQXBwV3JhcHBlcigpIHtcbiAgY29uc3QgeyBjb25maWcsIGlzTG9hZGluZyB9ID0gdXNlQ29uZmlnKCk7XG4gIGNvbnN0IHF1ZXJ5Q2xpZW50ID0gbmV3IFF1ZXJ5Q2xpZW50KClcbiAgaWYgKGlzTG9hZGluZyB8fCAhY29uZmlnKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXYgY2xhc3NOYW1lPVwibG9hZGluZy1zY3JlZW5cIj5cbiAgICAgICAgTG9hZGluZy4uLlxuICAgICAgPC9kaXY+XG4gICAgKTtcbiAgfVxuXG4gIHJldHVybiAoXG4gICAgPENsZXJrUHJvdmlkZXIgcHVibGlzaGFibGVLZXk9e2NvbmZpZy5jbGVya1B1Ymxpc2hhYmxlS2V5fT5cbiAgICAgIDxRdWVyeUNsaWVudFByb3ZpZGVyIGNsaWVudD17cXVlcnlDbGllbnR9PlxuICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cInctZnVsbCBoLWZ1bGxcIj5cbiAgICAgICAgICA8U2lnbmVkT3V0PlxuICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBtaW4taC1zY3JlZW5cIj5cbiAgICAgICAgICAgICAgPFNpZ25JbkJ1dHRvbi8+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L1NpZ25lZE91dD5cbiAgICAgICAgICA8U2lnbmVkSW4+XG4gICAgICAgICAgICA8QXBwLz5cbiAgICAgICAgICA8L1NpZ25lZEluPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvUXVlcnlDbGllbnRQcm92aWRlcj5cbiAgICA8L0NsZXJrUHJvdmlkZXI+XG4gICk7XG59XG5cbmNyZWF0ZVJvb3QoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Jvb3QnKSEpLnJlbmRlcihcbiAgPFN0cmljdE1vZGU+XG4gICAgPEFwcFdyYXBwZXIvPlxuICA8L1N0cmljdE1vZGU+XG4pXG5gLFxuICAgIH0pO1xuXG4gICAgLy8gQ3JlYXRlIGluZGV4LmNzc1xuICAgIG5ldyBTYW1wbGVGaWxlKHByb2plY3QsIGAke29wdGlvbnMuc3JjZGlyfS9pbmRleC5jc3NgLCB7XG4gICAgICBjb250ZW50czogYEBpbXBvcnQgXCJ0YWlsd2luZGNzc1wiO1xuXG5AdGhlbWUge1xuICAtLWNvbG9yLXNjaGVtZTogbGlnaHQgZGFyaztcbn1cblxuOnJvb3Qge1xuICBmb250LWZhbWlseTogSW50ZXIsIHN5c3RlbS11aSwgQXZlbmlyLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlmO1xuICBsaW5lLWhlaWdodDogMS41O1xuICBmb250LXdlaWdodDogNDAwO1xuXG4gIGNvbG9yLXNjaGVtZTogbGlnaHQgZGFyaztcblxuICBmb250LXN5bnRoZXNpczogbm9uZTtcbiAgdGV4dC1yZW5kZXJpbmc6IG9wdGltaXplTGVnaWJpbGl0eTtcbiAgLXdlYmtpdC1mb250LXNtb290aGluZzogYW50aWFsaWFzZWQ7XG4gIC1tb3otb3N4LWZvbnQtc21vb3RoaW5nOiBncmF5c2NhbGU7XG59XG5cbmEge1xuICBmb250LXdlaWdodDogNTAwO1xuICBjb2xvcjogIzY0NmNmZjtcbiAgdGV4dC1kZWNvcmF0aW9uOiBpbmhlcml0O1xufVxuYTpob3ZlciB7XG4gIGNvbG9yOiAjNTM1YmYyO1xufVxuXG5ib2R5IHtcbiAgbWFyZ2luOiAwO1xuICBtaW4td2lkdGg6IDMyMHB4O1xuICBtaW4taGVpZ2h0OiAxMDB2aDtcbn1cblxuaDEge1xuICBmb250LXNpemU6IDMuMmVtO1xuICBsaW5lLWhlaWdodDogMS4xO1xufVxuXG5idXR0b24ge1xuICBmb250LWZhbWlseTogaW5oZXJpdDtcbiAgY3Vyc29yOiBwb2ludGVyO1xufVxuXG4ubG9hZGluZy1zY3JlZW4ge1xuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgaGVpZ2h0OiAxMDB2aDtcbiAgZm9udC1zaXplOiAxLjVyZW07XG59XG5cbmh0bWwsIGJvZHksICNyb290IHtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogMTAwJTtcbn1cbmAsXG4gICAgfSk7XG5cbiAgfVxufVxuXG5pbnRlcmZhY2UgUGxheXdyaWdodEUyRUNvbXBvbmVudE9wdGlvbnMge1xuICByZWFkb25seSBwdWJsaWNEaXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBBZGRzIFBsYXl3cmlnaHQgZTJlIHRlc3Rpbmcgc3VwcG9ydDogZGV2RGVwcywgYSBgdGVzdDplMmVgIHRhc2ssIGUyZS1yZWxhdGVkXG4gKiAuZ2l0aWdub3JlIGVudHJpZXMsIGFuZCBhIHNjYWZmb2xkZWQgKG9uZS10aW1lLCBub3QgcmVnZW5lcmF0ZWQgb24gc3ludGgpXG4gKiBgcGxheXdyaWdodC5jb25maWcudHNgICsgYGUyZS9gIHN0YXJ0ZXIgc3VpdGUuIEdlbmVyYWxpemVzIHRoZSBoYW5kLWF1dGhvcmVkXG4gKiBzdWl0ZSBhZGRlZCBpbiBtYWNlZG9uLXRlY2hub2xvZ2llcy9leG1hbiMxMTIgc28gZXZlcnkgVml0ZVJlYWN0UHJvamVjdFxuICogY29uc3VtZXIgZ2V0cyBpdCBmb3IgZnJlZSAobWFjZWRvbi10ZWNobm9sb2dpZXMvcGxhdGZvcm0tY29tbW9uIzk4KS5cbiAqL1xuY2xhc3MgUGxheXdyaWdodEUyRUNvbXBvbmVudCBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFZpdGVSZWFjdFByb2plY3QsIG9wdGlvbnM6IFBsYXl3cmlnaHRFMkVDb21wb25lbnRPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG5cbiAgICBwcm9qZWN0LmFkZERldkRlcHMoXG4gICAgICAnQHBsYXl3cmlnaHQvdGVzdEBeMS42My4wJyxcbiAgICAgICdAY2xlcmsvdGVzdGluZ0BeMi4yLjM0JyxcbiAgICAgICdAY2xlcmsvYmFja2VuZEBeMy4xNy4yJyxcbiAgICAgICdkb3RlbnZAXjE3LjQuMicsXG4gICAgKTtcblxuICAgIHByb2plY3QuYWRkVGFzaygndGVzdDplMmUnLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1J1biB0aGUgUGxheXdyaWdodCBlMmUgc3VpdGUgKG5lZWRzIENMRVJLX1NFQ1JFVF9LRVkgYW5kIEUyRV9DTEVSS19VU0VSX0lEIC0tIHNlZSBlMmUvUkVBRE1FLm1kKScsXG4gICAgICBleGVjOiAncGxheXdyaWdodCB0ZXN0JyxcbiAgICB9KTtcblxuICAgIHByb2plY3QuYWRkR2l0SWdub3JlKCdwbGF5d3JpZ2h0LXJlcG9ydC8nKTtcbiAgICBwcm9qZWN0LmFkZEdpdElnbm9yZSgndGVzdC1yZXN1bHRzLycpO1xuICAgIHByb2plY3QuYWRkR2l0SWdub3JlKCdibG9iLXJlcG9ydC8nKTtcbiAgICAvLyBgKi5sb2NhbGAgKGFkZGVkIGVsc2V3aGVyZSkgYWxyZWFkeSBjb3ZlcnMgYC5lbnYubG9jYWxgLCBidXQgbm90IGEgcGxhaW4gYC5lbnZgIC0tXG4gICAgLy8gZXhhY3RseSB3aGVyZSBDTEVSS19TRUNSRVRfS0VZIChhIHJlYWwgc2VjcmV0KSBpcyBkb2N1bWVudGVkIHRvIGdvIChlMmUvUkVBRE1FLm1kKS5cbiAgICBwcm9qZWN0LmFkZEdpdElnbm9yZSgnLmVudicpO1xuXG4gICAgbmV3IFBsYXl3cmlnaHRDb25maWdGaWxlKHByb2plY3QpO1xuICAgIG5ldyBFMkVHbG9iYWxTZXR1cEZpbGUocHJvamVjdCwgb3B0aW9ucyk7XG4gICAgbmV3IEUyRUNsZXJrU2lnbkluRmlsZShwcm9qZWN0KTtcbiAgICBuZXcgRTJFTGl2ZUhlbHBlckZpbGUocHJvamVjdCk7XG4gICAgbmV3IEUyRVNtb2tlU3BlY0ZpbGUocHJvamVjdCk7XG4gICAgbmV3IEUyRVJlYWRtZUZpbGUocHJvamVjdCk7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBwbGF5d3JpZ2h0LmNvbmZpZy50cyBmaWxlLiBBIGBTYW1wbGVGaWxlYCwgbm90IGEgbWFuYWdlZCBgRmlsZUJhc2VgIC0tXG4gKiBjb25zdW1lcnMgbmVlZCB0byBjdXN0b21pemUgdGhpcyAoZS5nLiBleG1hbidzIG93biBjb25maWcgbmVlZGVkIGEgbGl2ZS9zdHViXG4gKiBicmFuY2gpLCB0aGUgc2FtZSByZWFzb24gVml0ZVJlYWN0UHJvamVjdCdzIEFwcC50c3gvbWFpbi50c3ggYXJlIFNhbXBsZUZpbGVzIHRvby5cbiAqL1xuY2xhc3MgUGxheXdyaWdodENvbmZpZ0ZpbGUgZXh0ZW5kcyBTYW1wbGVGaWxlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogVml0ZVJlYWN0UHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QsICdwbGF5d3JpZ2h0LmNvbmZpZy50cycsIHtcbiAgICAgIGNvbnRlbnRzOiBgaW1wb3J0IHsgY29uZmlnIGFzIGxvYWREb3RlbnYgfSBmcm9tICdkb3RlbnYnXG5pbXBvcnQgeyBkZWZpbmVDb25maWcsIGRldmljZXMgfSBmcm9tICdAcGxheXdyaWdodC90ZXN0J1xuaW1wb3J0IHsgaXNMaXZlUnVuIH0gZnJvbSAnLi9lMmUvc3VwcG9ydC9saXZlJ1xuXG4vLyBMb2FkZWQgaGVyZSwgZmlyc3QsIHJhdGhlciB0aGFuIGxlZnQgdG8gQGNsZXJrL3Rlc3RpbmcncyBvd24gaW50ZXJuYWwgZG90ZW52IGNhbGxcbi8vIGluc2lkZSBnbG9iYWwtc2V0dXAudHM6IHRoYXQgY2FsbCBydW5zIGluc2lkZSBnbG9iYWxTZXR1cCwgd2hpY2ggZXhlY3V0ZXMgQUZURVJcbi8vIFBsYXl3cmlnaHQgaGFzIGFscmVhZHkgY29sbGVjdGVkIGV2ZXJ5IHNwZWMgZmlsZSBhbmQgcnVuIHRoZWlyIG1vZHVsZS1sZXZlbCBjb2RlIC0tXG4vLyBzbyBhbnl0aGluZyByZWFkaW5nIHByb2Nlc3MuZW52IGJlZm9yZSB0aGVuIHdvdWxkIG9ubHkgZXZlciBzZWUgYSAuZW52IGZpbGUncyB2YWx1ZXNcbi8vIGFzIHVuc2V0LiBMb2FkaW5nIGl0IGhlcmUsIGF0IHRoZSB0b3Agb2YgdGhlIGNvbmZpZyBmaWxlIFBsYXl3cmlnaHQgcmVhZHMgYmVmb3JlXG4vLyBhbnl0aGluZyBlbHNlLCBtZWFucyBpdCdzIHBvcHVsYXRlZCBmb3IgY29sbGVjdGlvbiwgZ2xvYmFsU2V0dXAsIGFuZCBldmVyeSB0ZXN0LlxubG9hZERvdGVudigpXG5cbi8vIFNldCBFMkVfQkFTRV9VUkwgdG8gcnVuIGFnYWluc3QgYSByZWFsIGRlcGxveW1lbnQgKGUuZy4gYSBQUidzIHByLWRlcGxveSBXZWJzaXRlVXJsKVxuLy8gaW5zdGVhZCBvZiBhIGxvY2FsIGRldiBzZXJ2ZXIgLS0gc2VlIGUyZS9zdXBwb3J0L2xpdmUudHMgYW5kIGUyZS9SRUFETUUubWQuXG4vLyBcXGB8fCB1bmRlZmluZWRcXGAsIG5vdCBcXGA/P1xcYDogYW4gZW1wdHkgc3RyaW5nIChlLmcuIGFuIHVuc2V0IEdpdEh1YiBBY3Rpb25zIG91dHB1dCkgaXNcbi8vIG5vdCBudWxsL3VuZGVmaW5lZCwgc28gPz8gd291bGQgbGVhdmUgYmFzZVVSTCBhcyAnJyB3aGlsZSBpc0xpdmVSdW4oKSdzIHBsYWluICEhXG4vLyBjaGVjayBzdGlsbCByZWFkIHRoZSBydW4gYXMgbm9uLWxpdmUgLS0gYW4gaW52YWxpZCwgc2lsZW50bHktbWlzbWF0Y2hlZCBjb25maWcuXG5jb25zdCBsaXZlQmFzZVVybCA9IHByb2Nlc3MuZW52LkUyRV9CQVNFX1VSTCB8fCB1bmRlZmluZWRcblxuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgdGVzdERpcjogJy4vZTJlJyxcbiAgZnVsbHlQYXJhbGxlbDogZmFsc2UsXG4gIGZvcmJpZE9ubHk6ICEhcHJvY2Vzcy5lbnYuQ0ksXG4gIHJldHJpZXM6IHByb2Nlc3MuZW52LkNJID8gMSA6IDAsXG4gIHJlcG9ydGVyOiBwcm9jZXNzLmVudi5DSSA/IFtbJ2h0bWwnLCB7IG9wZW46ICduZXZlcicgfV1dIDogJ2xpc3QnLFxuICBnbG9iYWxTZXR1cDogJy4vZTJlL3N1cHBvcnQvZ2xvYmFsLXNldHVwLnRzJyxcbiAgdXNlOiB7XG4gICAgYmFzZVVSTDogbGl2ZUJhc2VVcmwgPz8gJ2h0dHA6Ly9sb2NhbGhvc3Q6NTE3MycsXG4gICAgdHJhY2U6ICdvbi1maXJzdC1yZXRyeScsXG4gIH0sXG4gIHByb2plY3RzOiBbXG4gICAgeyBuYW1lOiAnY2hyb21pdW0nLCB1c2U6IHsgLi4uZGV2aWNlc1snRGVza3RvcCBDaHJvbWUnXSB9IH0sXG4gIF0sXG4gIC8vIE5vIGxvY2FsIHNlcnZlciB0byBtYW5hZ2Ugd2hlbiBwb2ludGVkIGF0IGEgbGl2ZSBkZXBsb3ltZW50LlxuICB3ZWJTZXJ2ZXI6IGlzTGl2ZVJ1bigpID8gdW5kZWZpbmVkIDoge1xuICAgIGNvbW1hbmQ6ICcke3J1blNjcmlwdENvbW1hbmQocHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyLCAnZGV2Jyl9JyxcbiAgICB1cmw6ICdodHRwOi8vbG9jYWxob3N0OjUxNzMnLFxuICAgIHJldXNlRXhpc3RpbmdTZXJ2ZXI6ICFwcm9jZXNzLmVudi5DSSxcbiAgICB0aW1lb3V0OiA2MF8wMDAsXG4gIH0sXG59KVxuYCxcbiAgICB9KTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgRTJFR2xvYmFsU2V0dXBGaWxlT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHB1YmxpY0Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgZTJlL3N1cHBvcnQvZ2xvYmFsLXNldHVwLnRzLCB3aGljaCBwcmltZXMgQGNsZXJrL3Rlc3RpbmcgZm9yIHRoZSBzaWduLWluXG4gKiBmbG93IGluIGNsZXJrLXNpZ24taW4udHMuIFJlYWRzIHRoZSBDbGVyayBwdWJsaXNoYWJsZSBrZXkgZnJvbSB0aGUgc2NhZmZvbGRlZFxuICogcHVibGljL2NvbmZpZy5qc29uIChDb25maWdKc29uRmlsZSkgcmF0aGVyIHRoYW4gaGFyZGNvZGluZyBvbmUgLS0gVml0ZVJlYWN0UHJvamVjdCdzXG4gKiBvd24gYXBwIGZldGNoZXMgdGhhdCBrZXkgYXQgcnVudGltZSB0aGUgc2FtZSB3YXkgKHNlZSBjb25maWcudHMpLCBzbyB0aGVyZSdzIG5vXG4gKiBidWlsZC10aW1lIGNvbnN0YW50IHRoaXMgY29uc3RydWN0IGNvdWxkIGVtYmVkIGluc3RlYWQuXG4gKi9cbmNsYXNzIEUyRUdsb2JhbFNldHVwRmlsZSBleHRlbmRzIFNhbXBsZUZpbGUge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBWaXRlUmVhY3RQcm9qZWN0LCBvcHRpb25zOiBFMkVHbG9iYWxTZXR1cEZpbGVPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCwgJ2UyZS9zdXBwb3J0L2dsb2JhbC1zZXR1cC50cycsIHtcbiAgICAgIGNvbnRlbnRzOiBgaW1wb3J0IHsgcmVhZEZpbGVTeW5jIH0gZnJvbSAnZnMnXG5pbXBvcnQgeyBjbGVya1NldHVwIH0gZnJvbSAnQGNsZXJrL3Rlc3RpbmcvcGxheXdyaWdodCdcblxuLy8gQSBuby1vcCAobm90IGEgdGhyb3cpIHdoZW4gQ0xFUktfU0VDUkVUX0tFWSBpcyBtaXNzaW5nOiBldmVyeSBzcGVjIHRoYXQgbmVlZHMgYVxuLy8gc2lnbmVkLWluIHVzZXIgYWxyZWFkeSBza2lwcyBpdHNlbGYgaW4gdGhhdCBjYXNlIChzZWUgLi4vc21va2Uuc3BlYy50cyksIHNvIHJ1bm5pbmdcbi8vIHRoZSBzdWl0ZSB3aXRob3V0IHNlY3JldHMgY29uZmlndXJlZCB5ZXQgcmVwb3J0cyBcInNraXBwZWRcIiwgbm90IGEgY3Jhc2hlZCBnbG9iYWxcbi8vIHNldHVwLiBTZWUgZTJlL1JFQURNRS5tZCBmb3IgaG93IHRvIGdldCBhIHNlY3JldCBrZXkuXG5leHBvcnQgZGVmYXVsdCBhc3luYyBmdW5jdGlvbiBnbG9iYWxTZXR1cCgpIHtcbiAgaWYgKCFwcm9jZXNzLmVudi5DTEVSS19TRUNSRVRfS0VZKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICAvLyBpbXBvcnQubWV0YS51cmwsIG5vdCBfX2Rpcm5hbWU6IHRoZSB3ZWIgcGFja2FnZSBzZXRzIFwidHlwZVwiOiBcIm1vZHVsZVwiIChWaXRlQ29tcG9uZW50KSxcbiAgLy8gc28gdGhpcyBmaWxlIHJ1bnMgYXMgRVNNLCB3aGVyZSBfX2Rpcm5hbWUgaXNuJ3QgZGVmaW5lZC4gZnMucmVhZEZpbGVTeW5jIGFjY2VwdHMgYSBVUkxcbiAgLy8gZGlyZWN0bHksIHNvIG5vIG5lZWQgdG8gY29udmVydCBpdCB0byBhIHBhdGggZmlyc3QuXG4gIGNvbnN0IGNvbmZpZ1BhdGggPSBuZXcgVVJMKCcuLi8uLi8ke29wdGlvbnMucHVibGljRGlyfS9jb25maWcuanNvbicsIGltcG9ydC5tZXRhLnVybClcbiAgY29uc3QgeyBjbGVya1B1Ymxpc2hhYmxlS2V5IH0gPSBKU09OLnBhcnNlKHJlYWRGaWxlU3luYyhjb25maWdQYXRoLCAndXRmLTgnKSlcblxuICBhd2FpdCBjbGVya1NldHVwKHsgcHVibGlzaGFibGVLZXk6IGNsZXJrUHVibGlzaGFibGVLZXkgfSlcbn1cbmAsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGUyZS9zdXBwb3J0L2NsZXJrLXNpZ24taW4udHMuIFNpZ25zIGluIGFzIGEgc3BlY2lmaWMgQ2xlcmsgdXNlciBieSBpZCB2aWEgYVxuICogYmFja2VuZC1pc3N1ZWQgc2lnbi1pbiB0b2tlbiAodGlja2V0IHN0cmF0ZWd5KSwgYnlwYXNzaW5nIHRoZSBhcHAncyBhY3R1YWwgc2lnbi1pblxuICogVUkgLS0gd2hpY2ggdHlwaWNhbGx5IG9ubHkgZXhwb3NlcyBhbiBPQXV0aCBwcm92aWRlciBidXR0b24gdGhhdCBjYW4ndCBiZSBkcml2ZW5cbiAqIHJlbGlhYmx5IGZyb20gYSB0ZXN0LiBAY2xlcmsvdGVzdGluZy9wbGF5d3JpZ2h0J3Mgb3duIGBjbGVyay5zaWduSW4oeyBlbWFpbEFkZHJlc3MgfSlgXG4gKiBkb2VzIHRoZSBzYW1lIHRpY2tldCBleGNoYW5nZSBpbnRlcm5hbGx5IGFmdGVyIGFuIGV4dHJhIGVtYWlsLT51c2VyIGxvb2t1cDsgZ29pbmdcbiAqIGZyb20gYSB1c2VyIGlkIGRpcmVjdGx5IChFMkVfQ0xFUktfVVNFUl9JRCkgc2tpcHMgdGhhdCBsb29rdXAgYW5kIGl0cyBmYWlsdXJlIG1vZGVcbiAqIChhbiBleGlzdGluZyB1c2VyIHdpdGhvdXQgYSB2ZXJpZmllZCBlbWFpbCBhdHRhY2hlZCkuXG4gKi9cbmNsYXNzIEUyRUNsZXJrU2lnbkluRmlsZSBleHRlbmRzIFNhbXBsZUZpbGUge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBWaXRlUmVhY3RQcm9qZWN0KSB7XG4gICAgc3VwZXIocHJvamVjdCwgJ2UyZS9zdXBwb3J0L2NsZXJrLXNpZ24taW4udHMnLCB7XG4gICAgICBjb250ZW50czogYGltcG9ydCB7IGNyZWF0ZUNsZXJrQ2xpZW50IH0gZnJvbSAnQGNsZXJrL2JhY2tlbmQnXG5pbXBvcnQgeyBjbGVyayB9IGZyb20gJ0BjbGVyay90ZXN0aW5nL3BsYXl3cmlnaHQnXG5pbXBvcnQgdHlwZSB7IFBhZ2UgfSBmcm9tICdAcGxheXdyaWdodC90ZXN0J1xuXG4vKipcbiAqIFNpZ25zIGluIGFzIGEgc3BlY2lmaWMgQ2xlcmsgdXNlciBieSBpZC4gUmVxdWlyZXMgQ0xFUktfU0VDUkVUX0tFWSAoYWxzbyB1c2VkIGJ5XG4gKiBnbG9iYWwtc2V0dXAudHMpIGFuZCBhIHByaW9yIHBhZ2UuZ290bygpIHRvIGEgcGFnZSB0aGF0IGxvYWRzIENsZXJrLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc2lnbkluQXNVc2VyKHBhZ2U6IFBhZ2UsIHVzZXJJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IGNsZXJrQ2xpZW50ID0gY3JlYXRlQ2xlcmtDbGllbnQoeyBzZWNyZXRLZXk6IHByb2Nlc3MuZW52LkNMRVJLX1NFQ1JFVF9LRVkgfSlcbiAgY29uc3QgeyB0b2tlbiB9ID0gYXdhaXQgY2xlcmtDbGllbnQuc2lnbkluVG9rZW5zLmNyZWF0ZVNpZ25JblRva2VuKHtcbiAgICB1c2VySWQsXG4gICAgZXhwaXJlc0luU2Vjb25kczogMzAwLFxuICB9KVxuICBhd2FpdCBjbGVyay5zaWduSW4oeyBwYWdlLCBzaWduSW5QYXJhbXM6IHsgc3RyYXRlZ3k6ICd0aWNrZXQnLCB0aWNrZXQ6IHRva2VuIH0gfSlcbn1cbmAsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGUyZS9zdXBwb3J0L2xpdmUudHMuXG4gKi9cbmNsYXNzIEUyRUxpdmVIZWxwZXJGaWxlIGV4dGVuZHMgU2FtcGxlRmlsZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFZpdGVSZWFjdFByb2plY3QpIHtcbiAgICBzdXBlcihwcm9qZWN0LCAnZTJlL3N1cHBvcnQvbGl2ZS50cycsIHtcbiAgICAgIGNvbnRlbnRzOiBgLyoqXG4gKiBUcnVlIHdoZW4gdGhpcyBydW4gdGFyZ2V0cyBhIHJlYWwgZGVwbG95bWVudCAoRTJFX0JBU0VfVVJMIHNldCAtLSBzZWVcbiAqIHBsYXl3cmlnaHQuY29uZmlnLnRzKSByYXRoZXIgdGhhbiBhIGxvY2FsIGRldiBzZXJ2ZXIuIFNwZWNzIHJlYWQgdGhpcyB0byBkZWNpZGVcbiAqIHdoZXRoZXIgdG8gc3R1YiB0aGUgYmFja2VuZDogYSBsaXZlIHJ1biBtdXN0IGhpdCB0aGUgcmVhbCBBUEkgdG8gcHJvdmUgYW55dGhpbmcsXG4gKiBhbmQgc3R1YmJpbmcgaXQgd291bGQganVzdCBiZSB0ZXN0aW5nIHRoZSBzdHViLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNMaXZlUnVuKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gISFwcm9jZXNzLmVudi5FMkVfQkFTRV9VUkxcbn1cbmAsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGUyZS9zbW9rZS5zcGVjLnRzIC0tIGEgZ2VuZXJpYyBzdGFydGVyIHRlc3QgdGhhdCBvbmx5IHJlbGllcyBvbiBtYXJrdXBcbiAqIFZpdGVSZWFjdFByb2plY3QncyBvd24gc2NhZmZvbGRlZCBtYWluLnRzeC9BcHAudHN4IGFsd2F5cyByZW5kZXIgKFNpZ25lZEluL1xuICogVXNlckJ1dHRvbiksIHNvIGl0IHdvcmtzIGJlZm9yZSBhIGNvbnN1bWVyIGhhcyB3cml0dGVuIGFueSByZWFsIHBhZ2VzLiBDb25zdW1lcnNcbiAqIGFyZSBleHBlY3RlZCB0byBleHRlbmQvcmVwbGFjZSB0aGlzIHdpdGggcmVhbCBmbG93cywgdGhlIHNhbWUgd2F5IHRoZXkgYWxyZWFkeVxuICogY3VzdG9taXplIEFwcC50c3guXG4gKi9cbmNsYXNzIEUyRVNtb2tlU3BlY0ZpbGUgZXh0ZW5kcyBTYW1wbGVGaWxlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogVml0ZVJlYWN0UHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QsICdlMmUvc21va2Uuc3BlYy50cycsIHtcbiAgICAgIGNvbnRlbnRzOiBgaW1wb3J0IHsgdGVzdCwgZXhwZWN0IH0gZnJvbSAnQHBsYXl3cmlnaHQvdGVzdCdcbmltcG9ydCB7IHNpZ25JbkFzVXNlciB9IGZyb20gJy4vc3VwcG9ydC9jbGVyay1zaWduLWluJ1xuXG50ZXN0KCdzaWducyBpbiBhbmQgc2hvd3MgdGhlIGF1dGhlbnRpY2F0ZWQgVXNlckJ1dHRvbicsIGFzeW5jICh7IHBhZ2UgfSkgPT4ge1xuICAvLyBSZWFkIGZyb20gaW5zaWRlIHRoZSB0ZXN0IGJvZHksIG5vdCBtb2R1bGUgc2NvcGU6IFBsYXl3cmlnaHQgY29sbGVjdHMgKHJlcXVpcmVzKVxuICAvLyB0aGlzIGZpbGUgYmVmb3JlIHJ1bm5pbmcgZ2xvYmFsU2V0dXAsIHNvIGEgbW9kdWxlLWxldmVsIGNoZWNrIHdvdWxkIGFsd2F5cyBzZWUgYVxuICAvLyAuZW52LXNvdXJjZWQgdmFsdWUgYXMgdW5zZXQuIEV4cG9ydGluZyB0aGUgdmFyIGluIHRoZSBzaGVsbCB3b3JrcyBlaXRoZXIgd2F5LlxuICBjb25zdCB0ZXN0VXNlcklkID0gcHJvY2Vzcy5lbnYuRTJFX0NMRVJLX1VTRVJfSURcbiAgdGVzdC5za2lwKFxuICAgICF0ZXN0VXNlcklkIHx8ICFwcm9jZXNzLmVudi5DTEVSS19TRUNSRVRfS0VZLFxuICAgICdFMkVfQ0xFUktfVVNFUl9JRCBhbmQgQ0xFUktfU0VDUkVUX0tFWSBtdXN0IGJvdGggYmUgc2V0IC0tIHNlZSBlMmUvUkVBRE1FLm1kJyxcbiAgKVxuXG4gIC8vIHNpZ25JbkFzVXNlciByZXF1aXJlcyBhIHByaW9yIHBhZ2UuZ290bygpIHRvIGEgcGFnZSB0aGF0IGxvYWRzIENsZXJrLlxuICBhd2FpdCBwYWdlLmdvdG8oJy8nKVxuICBhd2FpdCBzaWduSW5Bc1VzZXIocGFnZSwgdGVzdFVzZXJJZCEpXG4gIGF3YWl0IHBhZ2UuZ290bygnLycpXG5cbiAgLy8gJy5jbC11c2VyQnV0dG9uVHJpZ2dlcicgaXMgb25lIG9mIENsZXJrJ3Mgb3duIGRvY3VtZW50ZWQsIHN0YWJsZSBcXGBjbC1cXGAtcHJlZml4ZWRcbiAgLy8gY2xhc3MgaG9va3MgKHBhcnQgb2YgaXRzIHRoZW1pbmcvYXBwZWFyYW5jZSBBUEkpLCBub3QgYW4gaW5jaWRlbnRhbCBET00gZGV0YWlsIC0tXG4gIC8vIHNhZmVyIHRvIGRlcGVuZCBvbiBhY3Jvc3MgQ2xlcmsgdmVyc2lvbnMgdGhhbiBhcHAtc3BlY2lmaWMgbWFya3VwIHRoaXMgY29uc3RydWN0XG4gIC8vIGRvZXNuJ3QgY29udHJvbC5cbiAgYXdhaXQgZXhwZWN0KHBhZ2UubG9jYXRvcignLmNsLXVzZXJCdXR0b25UcmlnZ2VyJykpLnRvQmVWaXNpYmxlKClcbn0pXG5gLFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyBlMmUvUkVBRE1FLm1kIGRvY3VtZW50aW5nIHRoZSBvbmUtdGltZSBzZXR1cCBhbmQgZW52IHZhciBjb252ZW50aW9uIGV2ZXJ5XG4gKiBjb25zdW1lciBuZWVkcywgc28gaXQgZG9lc24ndCBoYXZlIHRvIGJlIHJlLWRlcml2ZWQgYnkgaGFuZCBwZXIgcmVwby5cbiAqL1xuY2xhc3MgRTJFUmVhZG1lRmlsZSBleHRlbmRzIFNhbXBsZUZpbGUge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBWaXRlUmVhY3RQcm9qZWN0KSB7XG4gICAgY29uc3QgdGVzdEUyZUNvbW1hbmQgPSBydW5TY3JpcHRDb21tYW5kKHByb2plY3QucGFja2FnZS5wYWNrYWdlTWFuYWdlciwgJ3Rlc3Q6ZTJlJyk7XG4gICAgc3VwZXIocHJvamVjdCwgJ2UyZS9SRUFETUUubWQnLCB7XG4gICAgICBjb250ZW50czogYCMgUGxheXdyaWdodCBlMmUgc3VpdGVcblxuUnVucyBhZ2FpbnN0IGEgcmVhbCBkZXYgc2VydmVyIChvciBhIGxpdmUgZGVwbG95bWVudCwgdmlhIFxcYEUyRV9CQVNFX1VSTFxcYCkgYW5kIHJlYWxcbkNsZXJrIGF1dGhlbnRpY2F0aW9uLlxuXG4jIyBPbmUtdGltZSBzZXR1cFxuXG4xLiBJbnN0YWxsIFBsYXl3cmlnaHQncyBicm93c2VyIGJpbmFyeSAobm90IGNvdmVyZWQgYnkgYSBwbGFpbiBkZXBlbmRlbmN5IGluc3RhbGwpOlxuXG4gICBcXGBcXGBcXGBiYXNoXG4gICBucHggcGxheXdyaWdodCBpbnN0YWxsIGNocm9taXVtXG4gICBcXGBcXGBcXGBcblxuMi4gR2V0IHR3byB2YWx1ZXMgZnJvbSB5b3VyIENsZXJrIGRhc2hib2FyZCdzIGRldiBpbnN0YW5jZTpcblxuICAgLSBcXGBDTEVSS19TRUNSRVRfS0VZXFxgIC0tIHRoZSAqKnNlY3JldCoqIGtleSAoQVBJIEtleXMpLiBOZXZlciBjb21taXQgdGhpczsgZXhwb3J0IGl0XG4gICAgIGluIHlvdXIgc2hlbGwgb3IgcHV0IGl0IGluIGEgbG9jYWwsIGdpdGlnbm9yZWQgXFxgLmVudlxcYC5cbiAgIC0gXFxgRTJFX0NMRVJLX1VTRVJfSURcXGAgLS0gdGhlIGlkIChcXGB1c2VyXy4uLlxcYCkgb2YgYW4gZXhpc3RpbmcgdGVzdCB1c2VyIChVc2VycyAtPiBjbGlja1xuICAgICBhIHVzZXIsIHRoZSBpZCBpcyBzaG93biBhdCB0aGUgdG9wKS4gVGhlIHVzZXIgbmVlZHMgYSB2ZXJpZmllZCBlbWFpbCBhZGRyZXNzLCBub3RcbiAgICAganVzdCBhbiBPQXV0aCBjb25uZWN0aW9uIC0tIGEgc2lnbi1pbiB0b2tlbiBoYXMgdG8gYmluZCB0byBhIHZlcmlmaWVkXG4gICAgIGlkZW50aWZpY2F0aW9uLiBDcmVhdGluZyBhIGRlZGljYXRlZCB0ZXN0IHVzZXIgd2l0aCBhbiBlbWFpbCBzZXQgZXhwbGljaXRseSBpcyB0aGVcbiAgICAgc2FmZXIgZGVmYXVsdC5cblxuICAgQSBydW4gd2l0aCBlaXRoZXIgdmFyaWFibGUgdW5zZXQgKipza2lwcyoqIHJhdGhlciB0aGFuIGZhaWxpbmcsIHNvIFxcYCR7dGVzdEUyZUNvbW1hbmR9XFxgXG4gICBpcyBhbHdheXMgc2FmZSB0byBydW4gd2l0aG91dCB0aGVtLlxuXG4zLiBUaGlzIGNvbnN0cnVjdCBkb2Vzbid0IG1hbmFnZSBcXGB2aXRlc3QuY29uZmlnLnRzXFxgIChpdCdzIGEgaGFuZC1hdXRob3JlZCxcbiAgIHBlci1jb25zdW1lciBmaWxlKS4gQWRkIGFuIFxcYGV4Y2x1ZGVcXGAgZW50cnkgc28gdml0ZXN0J3MgZGVmYXVsdCB0ZXN0IGdsb2IgZG9lc24ndFxuICAgYWxzbyB0cnkgdG8gcGljayB1cCB0aGVzZSBQbGF5d3JpZ2h0IHNwZWMgZmlsZXM6XG5cbiAgIFxcYFxcYFxcYHRzXG4gICBpbXBvcnQgeyBkZWZpbmVDb25maWcsIGNvbmZpZ0RlZmF1bHRzIH0gZnJvbSAndml0ZXN0L2NvbmZpZydcblxuICAgZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgICAgdGVzdDoge1xuICAgICAgIGV4Y2x1ZGU6IFsuLi5jb25maWdEZWZhdWx0cy5leGNsdWRlLCAnZTJlLyoqJ10sXG4gICAgICAgLy8gLi4ueW91ciBleGlzdGluZyBjb25maWdcbiAgICAgfSxcbiAgIH0pXG4gICBcXGBcXGBcXGBcblxuIyMgUnVubmluZ1xuXG5cXGBcXGBcXGBiYXNoXG5DTEVSS19TRUNSRVRfS0VZPS4uLiBFMkVfQ0xFUktfVVNFUl9JRD0uLi4gJHt0ZXN0RTJlQ29tbWFuZH1cblxcYFxcYFxcYFxuXG4jIyBSdW5uaW5nIGFnYWluc3QgYSBsaXZlIGVudmlyb25tZW50XG5cblNldCBcXGBFMkVfQkFTRV9VUkxcXGAgdG8gcG9pbnQgdGhlIHN1aXRlIGF0IGEgcmVhbCBkZXBsb3ltZW50IChhIHBlcnNvbmFsIGRldiBzdGFjaywgb3IgYVxuUFIncyBwci1kZXBsb3kgXFxgV2Vic2l0ZVVybFxcYCwgcG9zdGVkIGFzIGEgUFIgY29tbWVudCkgaW5zdGVhZCBvZiBhIGxvY2FsIGRldiBzZXJ2ZXI6XG5cblxcYFxcYFxcYGJhc2hcbkUyRV9CQVNFX1VSTD1odHRwczovLzx5b3VyLXN0YWNrPi5leGFtcGxlLmNvbSBcXFxcXG5DTEVSS19TRUNSRVRfS0VZPS4uLiBFMkVfQ0xFUktfVVNFUl9JRD0uLi4gXFxcXFxuJHt0ZXN0RTJlQ29tbWFuZH1cblxcYFxcYFxcYFxuXG4jIyBDSVxuXG5UaGUgZ2VuZXJhdGVkIFxcYHByLWRlcGxveS55bWxcXGAgd29ya2Zsb3cgKHNlZSBcXGBQckRlcGxveVdvcmtmbG93XFxgKSBhbHJlYWR5IHJ1bnMgdGhpc1xuc3VpdGUgYWdhaW5zdCBlYWNoIFBSJ3MgZGVwbG95ZWQgXFxgV2Vic2l0ZVVybFxcYCBhbmQgdXBsb2FkcyB0aGUgSFRNTCByZXBvcnQgYXMgYSBidWlsZFxuYXJ0aWZhY3Qgb24gZmFpbHVyZS4gSXQgc2VsZi1za2lwcyBleGFjdGx5IGxpa2UgYSBsb2NhbCBydW4gdW50aWwgYm90aCBzZWNyZXRzIGV4aXN0XG5pbiB0aGUgcmVwbzpcblxuXFxgXFxgXFxgYmFzaFxuZ2ggc2VjcmV0IHNldCBDTEVSS19TRUNSRVRfS0VZXG5naCBzZWNyZXQgc2V0IEUyRV9DTEVSS19VU0VSX0lEXG5cXGBcXGBcXGBcbmAsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
|
|
1359
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVml0ZVJlYWN0UHJvamVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9WaXRlUmVhY3RQcm9qZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtCQUEwQztBQUMxQyxtQ0FBNEU7QUFDNUUsc0RBQXVGO0FBRXZGLG1DQUEyQztBQW1DM0M7O0dBRUc7QUFDSCxNQUFhLGdCQUFpQixTQUFRLGlDQUFvQjtJQUN4QyxNQUFNLENBQVM7SUFDZixTQUFTLENBQVM7SUFDbEIsVUFBVSxDQUFTO0lBQ2xCLFlBQVksQ0FBc0I7SUFFbkQsWUFBWSxPQUFnQztRQUMxQyxNQUFNLEVBQ0osVUFBVSxHQUFHLElBQUksRUFDakIsTUFBTSxHQUFHLEtBQUssRUFDZCxTQUFTLEdBQUcsUUFBUSxFQUNwQixLQUFLLEVBQ0wsVUFBVSxHQUFHLElBQUksRUFDakIsR0FBRyxXQUFXLEVBQ2YsR0FBRyxPQUFPLENBQUM7UUFDWixLQUFLLENBQUM7WUFDSixHQUFHLFdBQVc7WUFDZCxVQUFVLEVBQUUsS0FBSyxFQUFFLHFDQUFxQztZQUN4RCxNQUFNLEVBQUUsS0FBSyxFQUFFLG1DQUFtQztZQUNsRCxJQUFJLEVBQUUsS0FBSyxFQUFFLDZCQUE2QjtZQUMxQyxPQUFPLEVBQUUsSUFBSTtZQUNiLGVBQWUsRUFBRSxJQUFJLEVBQUUsa0NBQWtDO1lBQ3pELGNBQWMsRUFBRyxXQUFXLENBQUMsTUFBd0IsQ0FBQyxPQUFPLENBQUMsY0FBYztZQUM1RSxXQUFXLEVBQUU7Z0JBQ1gsb0JBQW9CLEVBQUU7b0JBQ3BCLHVFQUF1RTtvQkFDdkUsc0VBQXNFO29CQUN0RSxvRUFBb0U7b0JBQ3BFLCtEQUErRDtvQkFDL0QsV0FBVyxFQUFFO3dCQUNYLFNBQVMsRUFBRSxJQUFJO3dCQUNmLGVBQWUsRUFBRSxJQUFJO3FCQUN0QjtvQkFDRCxHQUFHLFdBQVcsQ0FBQyxXQUFXLEVBQUUsb0JBQW9CO2lCQUNqRDthQUNGO1lBQ0QsSUFBSSxFQUFFO2dCQUNKLG9C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Q0Y7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLGdCQUFpQixTQUFRLG1CQUFVO0lBQ3ZDLFlBQVksT0FBeUI7UUFDbkMsS0FBSyxDQUFDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRTtZQUNsQyxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztDQXdCZjtTQUNJLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQUVEOzs7R0FHRztBQUNILE1BQU0sYUFBYyxTQUFRLG1CQUFVO0lBQ3BDLFlBQVksT0FBeUI7UUFDbkMsTUFBTSxjQUFjLEdBQUcsSUFBQSx3QkFBZ0IsRUFBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGNBQWMsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUNwRixLQUFLLENBQUMsT0FBTyxFQUFFLGVBQWUsRUFBRTtZQUM5QixRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzBFQXVCMEQsY0FBYzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OzZDQXFCM0MsY0FBYzs7Ozs7Ozs7Ozs7RUFXekQsY0FBYzs7Ozs7Ozs7Ozs7Ozs7Q0FjZjtTQUNJLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHJlbGF0aXZlLCBiYXNlbmFtZSB9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQ29tcG9uZW50LCBGaWxlQmFzZSwgSnNvbkZpbGUsIFByb2plY3QsIFNhbXBsZUZpbGUgfSBmcm9tICdwcm9qZW4nO1xuaW1wb3J0IHsgVHlwZVNjcmlwdEFwcFByb2plY3QsIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyB9IGZyb20gJ3Byb2plbi9saWIvdHlwZXNjcmlwdCc7XG5pbXBvcnQgeyBCYXRtYW5Qcm9qZWN0IH0gZnJvbSAnLi9CYXRtYW5Qcm9qZWN0JztcbmltcG9ydCB7IHJ1blNjcmlwdENvbW1hbmQgfSBmcm9tICcuL3V0aWxzJztcblxuZXhwb3J0IGludGVyZmFjZSBWaXRlUmVhY3RQcm9qZWN0T3B0aW9ucyBleHRlbmRzIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGdlbmVyYXRlIHNhbXBsZSBjb2RlXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNhbXBsZUNvZGU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBTb3VyY2UgZGlyZWN0b3J5XG4gICAqIEBkZWZhdWx0IFwic3JjXCJcbiAgICovXG4gIHJlYWRvbmx5IHNyY2Rpcj86IHN0cmluZztcblxuICAvKipcbiAgICogUHVibGljIGRpcmVjdG9yeSBmb3Igc3RhdGljIGFzc2V0c1xuICAgKiBAZGVmYXVsdCBcInB1YmxpY1wiXG4gICAqL1xuICByZWFkb25seSBwdWJsaWNEaXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRpdGxlIGZvciB0aGUgSFRNTCBwYWdlXG4gICAqIEBkZWZhdWx0IHByb2plY3QgbmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgdGl0bGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYWRkIFBsYXl3cmlnaHQgZTJlIHRlc3Rpbmcgc3VwcG9ydCAoZGV2RGVwcywgYSBgdGVzdDplMmVgIHRhc2ssXG4gICAqIGFuZCBhIHNjYWZmb2xkZWQgYHBsYXl3cmlnaHQuY29uZmlnLnRzYCArIGBlMmUvYCBzdGFydGVyIHN1aXRlKS5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZTJlVGVzdGluZz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogVml0ZSArIFJlYWN0IFR5cGVTY3JpcHQgcHJvamVjdFxuICovXG5leHBvcnQgY2xhc3MgVml0ZVJlYWN0UHJvamVjdCBleHRlbmRzIFR5cGVTY3JpcHRBcHBQcm9qZWN0IHtcbiAgcHVibGljIHJlYWRvbmx5IHNyY2Rpcjogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcHVibGljRGlyOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBkZXZDb21tYW5kOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnRmllbGRzOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFZpdGVSZWFjdFByb2plY3RPcHRpb25zKSB7XG4gICAgY29uc3Qge1xuICAgICAgc2FtcGxlQ29kZSA9IHRydWUsXG4gICAgICBzcmNkaXIgPSAnc3JjJyxcbiAgICAgIHB1YmxpY0RpciA9ICdwdWJsaWMnLFxuICAgICAgdGl0bGUsXG4gICAgICBlMmVUZXN0aW5nID0gdHJ1ZSxcbiAgICAgIC4uLnJlc3RPcHRpb25zXG4gICAgfSA9IG9wdGlvbnM7XG4gICAgc3VwZXIoe1xuICAgICAgLi4ucmVzdE9wdGlvbnMsXG4gICAgICBzYW1wbGVDb2RlOiBmYWxzZSwgLy8gV2UnbGwgaGFuZGxlIHNhbXBsZSBjb2RlIG91cnNlbHZlc1xuICAgICAgZXNsaW50OiBmYWxzZSwgLy8gV2UnbGwgY29uZmlndXJlIGVzbGludCBvdXJzZWx2ZXNcbiAgICAgIGplc3Q6IGZhbHNlLCAvLyBWaXRlIHVzZXMgdml0ZXN0IHR5cGljYWxseVxuICAgICAgcGFja2FnZTogdHJ1ZSxcbiAgICAgIGRpc2FibGVUc2NvbmZpZzogdHJ1ZSwgLy8gV2UnbGwgbWFuYWdlIHRzY29uZmlnIG91cnNlbHZlc1xuICAgICAgcGFja2FnZU1hbmFnZXI6IChyZXN0T3B0aW9ucy5wYXJlbnQgYXMgQmF0bWFuUHJvamVjdCkucGFja2FnZS5wYWNrYWdlTWFuYWdlcixcbiAgICAgIHBucG1PcHRpb25zOiB7XG4gICAgICAgIHdvcmtzcGFjZVlhbWxPcHRpb25zOiB7XG4gICAgICAgICAgLy8gVGhpcyBzdWJwcm9qZWN0IGhhcyBpdHMgb3duIHNlcGFyYXRlIGxvY2tmaWxlL3N0b3JlIGZyb20gaXRzIHBhcmVudCxcbiAgICAgICAgICAvLyBzbyBpdCBuZWVkcyBpdHMgb3duIGFwcHJvdmFsIGZvciB0aGUgbmF0aXZlIHBvc3RpbnN0YWxsIHNjcmlwdHMgaXRzXG4gICAgICAgICAgLy8gZml4ZWQgZGVwZW5kZW5jeSBzZXQgYWx3YXlzIG5lZWRzIChlc2J1aWxkJ3MgYmluYXJ5IGRvd25sb2FkLCBhbmRcbiAgICAgICAgICAvLyBAY2xlcmsvY2xlcmstcmVhY3QncyB0cmFuc2l0aXZlIEBjbGVyay9zaGFyZWQgc2V0dXAgc2NyaXB0KS5cbiAgICAgICAgICBhbGxvd0J1aWxkczoge1xuICAgICAgICAgICAgJ2VzYnVpbGQnOiB0cnVlLFxuICAgICAgICAgICAgJ0BjbGVyay9zaGFyZWQnOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLi4ucmVzdE9wdGlvbnMucG5wbU9wdGlvbnM/LndvcmtzcGFjZVlhbWxPcHRpb25zLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGRlcHM6IFtcbiAgICAgICAgJ0BjbGVyay9jbGVyay1yZWFjdCcsXG4gICAgICAgICdAdGFuc3RhY2svcmVhY3QtcXVlcnknLFxuICAgICAgICAnQHRhaWx3aW5kY3NzL3Bvc3Rjc3MnLFxuICAgICAgICAnYXV0b3ByZWZpeGVyJyxcbiAgICAgICAgJ3Bvc3Rjc3MnLFxuICAgICAgICAndGFpbHdpbmRjc3MnLFxuICAgICAgICAncm9sbHVwJyxcbiAgICAgICAgLi4uKG9wdGlvbnMuZGVwcyA/IG9wdGlvbnMuZGVwcyA6IFtdKSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBJbml0aWFsaXplIGNvbmZpZyBmaWVsZHMgc3RvcmFnZVxuICAgIHRoaXMuY29uZmlnRmllbGRzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcblxuICAgIHRoaXMuc3JjZGlyID0gc3JjZGlyO1xuICAgIHRoaXMucHVibGljRGlyID0gcHVibGljRGlyO1xuXG4gICAgLy8gQWRkIFZpdGUgY29tcG9uZW50XG4gICAgbmV3IFZpdGVDb21wb25lbnQodGhpcywge1xuICAgICAgc3JjZGlyOiB0aGlzLnNyY2RpcixcbiAgICB9KTtcblxuICAgIC8vIEFkZCBFU0xpbnQgY29uZmlndXJhdGlvblxuICAgIG5ldyBWaXRlRXNsaW50Q29uZmlnKHRoaXMpO1xuXG4gICAgLy8gQWRkIGluZGV4Lmh0bWxcbiAgICBuZXcgSW5kZXhIdG1sKHRoaXMsIHtcbiAgICAgIHRpdGxlOiB0aXRsZSA/PyB0aGlzLm5hbWUsXG4gICAgICBzcmNkaXI6IHRoaXMuc3JjZGlyLFxuICAgIH0pO1xuXG4gICAgLy8gQWRkIFR5cGVTY3JpcHQgY29uZmlnc1xuICAgIG5ldyBWaXRlVHNDb25maWdzKHRoaXMsIHtcbiAgICAgIHNyY2RpcjogdGhpcy5zcmNkaXIsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgLmdpdGlnbm9yZSBlbnRyaWVzXG4gICAgdGhpcy5naXRpZ25vcmU/LmFkZFBhdHRlcm5zKCdkaXN0JywgJ2Rpc3Qtc3NyJywgJyoubG9jYWwnKTtcblxuICAgIC8vIEFkZCB2aXRlLWVudi5kLnRzIGZvciB0eXBlIGRlY2xhcmF0aW9uc1xuICAgIG5ldyBWaXRlRW52RHRzKHRoaXMsIHtcbiAgICAgIHNyY2RpcjogdGhpcy5zcmNkaXIsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgUG9zdENTUyBjb25maWcgZm9yIFRhaWx3aW5kXG4gICAgbmV3IFBvc3RDU1NDb25maWdGaWxlKHRoaXMpO1xuXG4gICAgLy8gQWRkIGNvbmZpZy50cyBmb3IgcnVudGltZSBjb25maWd1cmF0aW9uXG4gICAgbmV3IENvbmZpZ0ZpbGUodGhpcywge1xuICAgICAgc3JjZGlyOiB0aGlzLnNyY2RpcixcbiAgICB9KTtcblxuICAgIC8vIEFkZCBzYW1wbGUgY29uZmlnLmpzb25cbiAgICBuZXcgQ29uZmlnSnNvbkZpbGUodGhpcywgeyB9KTtcblxuXG4gICAgLy8gQWRkIHNhbXBsZSBjb2RlIGlmIHJlcXVlc3RlZFxuICAgIGlmIChzYW1wbGVDb2RlKSB7XG4gICAgICBuZXcgVml0ZVNhbXBsZUNvZGUodGhpcywge1xuICAgICAgICBzcmNkaXI6IHRoaXMuc3JjZGlyLFxuICAgICAgICBwdWJsaWNEaXI6IHRoaXMucHVibGljRGlyLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQWRkIFBsYXl3cmlnaHQgZTJlIHRlc3Rpbmcgc3VwcG9ydFxuICAgIGlmIChlMmVUZXN0aW5nKSB7XG4gICAgICBuZXcgUGxheXdyaWdodEUyRUNvbXBvbmVudCh0aGlzLCB7XG4gICAgICAgIHB1YmxpY0RpcjogdGhpcy5wdWJsaWNEaXIsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBVc2UgcmVsYXRpdmUgcGF0aCBmb3IgZGV2Q29tbWFuZFxuICAgIGNvbnN0IHJlbGF0aXZlT3V0ZGlyID0gdGhpcy5wYXJlbnRcbiAgICAgID8gcmVsYXRpdmUodGhpcy5wYXJlbnQub3V0ZGlyLCB0aGlzLm91dGRpcilcbiAgICAgIDogYmFzZW5hbWUodGhpcy5vdXRkaXIpO1xuICAgIHRoaXMuZGV2Q29tbWFuZCA9IGBjZCAke3JlbGF0aXZlT3V0ZGlyfSAmJiAke3J1blNjcmlwdENvbW1hbmQodGhpcy5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyLCAnZGV2Jyl9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBjdXN0b20gZmllbGQgdG8gdGhlIENvbmZpZyB0eXBlXG4gICAqIEBwYXJhbSBmaWVsZE5hbWUgVGhlIG5hbWUgb2YgdGhlIGZpZWxkXG4gICAqIEBwYXJhbSBmaWVsZFR5cGUgVGhlIFR5cGVTY3JpcHQgdHlwZSBvZiB0aGUgZmllbGQgKGUuZy4sICdzdHJpbmcnLCAnbnVtYmVyJywgJ2Jvb2xlYW4nLCAnc3RyaW5nW10nKVxuICAgKiBAcmV0dXJucyB0aGlzIHByb2plY3QgaW5zdGFuY2UgZm9yIGNoYWluaW5nXG4gICAqL1xuICBhZGRDb25maWdGaWVsZChmaWVsZE5hbWU6IHN0cmluZywgZmllbGRUeXBlOiBzdHJpbmcpOiB0aGlzIHtcbiAgICB0aGlzLmNvbmZpZ0ZpZWxkcy5zZXQoZmllbGROYW1lLCBmaWVsZFR5cGUpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY29uZmlnIGZpZWxkcyBtYXAgKGZvciBpbnRlcm5hbCB1c2UgYnkgQ29uZmlnRmlsZSlcbiAgICogQGludGVybmFsXG4gICAqL1xuICBnZXRDb25maWdGaWVsZHMoKTogTWFwPHN0cmluZywgc3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnRmllbGRzO1xuICB9XG59XG5cbmludGVyZmFjZSBWaXRlQ29tcG9uZW50T3B0aW9ucyB7XG4gIHJlYWRvbmx5IHNyY2Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyZXMgVml0ZSBkZXBlbmRlbmNpZXMgYW5kIHNjcmlwdHNcbiAqL1xuY2xhc3MgVml0ZUNvbXBvbmVudCBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFR5cGVTY3JpcHRBcHBQcm9qZWN0LCBfb3B0aW9uczogVml0ZUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIGNvbnN0IHRzUHJvamVjdCA9IHByb2plY3QgYXMgVHlwZVNjcmlwdEFwcFByb2plY3Q7XG5cbiAgICAvLyBTZXQgcGFja2FnZSB0eXBlIHRvIG1vZHVsZSBmb3IgRVNNIHN1cHBvcnRcbiAgICB0c1Byb2plY3QucGFja2FnZS5hZGRGaWVsZCgndHlwZScsICdtb2R1bGUnKTtcblxuICAgIC8vIEFkZCBSZWFjdCBkZXBlbmRlbmNpZXNcbiAgICB0c1Byb2plY3QuYWRkRGVwcygncmVhY3RAXjE5LjIuMCcsICdyZWFjdC1kb21AXjE5LjIuMCcpO1xuXG4gICAgLy8gQWRkIGRldiBkZXBlbmRlbmNpZXNcbiAgICB0c1Byb2plY3QuYWRkRGV2RGVwcyhcbiAgICAgICdAdHlwZXMvcmVhY3RAXjE5LjIuMicsXG4gICAgICAnQHR5cGVzL3JlYWN0LWRvbUBeMTkuMi4yJyxcbiAgICAgICdAdml0ZWpzL3BsdWdpbi1yZWFjdEBeNS4xLjAnLFxuICAgICAgJ3ZpdGVAXjUuNC4wJyxcbiAgICAgICd0eXBlc2NyaXB0QH41LjkuMycsXG4gICAgICAnQGVzbGludC9qc0BeOS4zOS4xJyxcbiAgICAgICdlc2xpbnRAXjkuMzkuMScsXG4gICAgICAnZXNsaW50LXBsdWdpbi1yZWFjdC1ob29rc0BeNS4yLjAnLFxuICAgICAgJ2VzbGludC1wbHVnaW4tcmVhY3QtcmVmcmVzaEBeMC40LjI0JyxcbiAgICAgICdnbG9iYWxzQF4xNi41LjAnLFxuICAgICAgJ3R5cGVzY3JpcHQtZXNsaW50QF44LjQ2LjMnLFxuICAgICk7XG5cbiAgICAvLyBDcmVhdGUgdml0ZS5jb25maWcudHMgYXMgYSBtYW5hZ2VkIGZpbGVcbiAgICBuZXcgVml0ZUNvbmZpZ0ZpbGUocHJvamVjdCk7XG5cbiAgICAvLyBBZGQgc2NyaXB0c1xuICAgIHRzUHJvamVjdC5hZGRUYXNrKCdkZXYnLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1N0YXJ0IGRldmVsb3BtZW50IHNlcnZlcicsXG4gICAgICBleGVjOiAndml0ZScsXG4gICAgfSk7XG5cbiAgICAvLyBSZW1vdmUgYW5kIHJlY3JlYXRlIGJ1aWxkIHRhc2sgdG8gY3VzdG9taXplIGl0IGZvciBWaXRlXG4gICAgdHNQcm9qZWN0LnJlbW92ZVRhc2soJ2J1aWxkJyk7XG4gICAgdHNQcm9qZWN0LmFkZFRhc2soJ2J1aWxkJywge1xuICAgICAgZGVzY3JpcHRpb246ICdCdWlsZCBmb3IgcHJvZHVjdGlvbicsXG4gICAgICBleGVjOiAndHNjIC1iICYmIHZpdGUgYnVpbGQnLFxuICAgIH0pO1xuXG4gICAgdHNQcm9qZWN0LmFkZFRhc2soJ3ByZXZpZXcnLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1ByZXZpZXcgcHJvZHVjdGlvbiBidWlsZCcsXG4gICAgICBleGVjOiAndml0ZSBwcmV2aWV3JyxcbiAgICB9KTtcblxuICAgIHRzUHJvamVjdC5hZGRUYXNrKCdsaW50Jywge1xuICAgICAgZGVzY3JpcHRpb246ICdMaW50IGNvZGUnLFxuICAgICAgZXhlYzogJ2VzbGludCAuJyxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIEVTTGludCBjb25maWd1cmF0aW9uIGZvciBWaXRlICsgUmVhY3RcbiAqL1xuY2xhc3MgVml0ZUVzbGludENvbmZpZyBleHRlbmRzIEZpbGVCYXNlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QsICdlc2xpbnQuY29uZmlnLmpzJywge1xuICAgICAgbWFya2VyOiB0cnVlLFxuICAgICAgcmVhZG9ubHk6IHRydWUsXG4gICAgfSk7XG4gIH1cblxuICBzeW50aGVzaXplQ29udGVudCgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBgaW1wb3J0IGpzIGZyb20gJ0Blc2xpbnQvanMnXG5pbXBvcnQgZ2xvYmFscyBmcm9tICdnbG9iYWxzJ1xuaW1wb3J0IHJlYWN0SG9va3MgZnJvbSAnZXNsaW50LXBsdWdpbi1yZWFjdC1ob29rcydcbmltcG9ydCByZWFjdFJlZnJlc2ggZnJvbSAnZXNsaW50LXBsdWdpbi1yZWFjdC1yZWZyZXNoJ1xuaW1wb3J0IHRzZXNsaW50IGZyb20gJ3R5cGVzY3JpcHQtZXNsaW50J1xuXG5leHBvcnQgZGVmYXVsdCBbXG4gIHsgaWdub3JlczogWydkaXN0J10gfSxcbiAge1xuICAgIGZpbGVzOiBbJyoqLyoue3RzLHRzeH0nXSxcbiAgICBsYW5ndWFnZU9wdGlvbnM6IHtcbiAgICAgIGVjbWFWZXJzaW9uOiAyMDIwLFxuICAgICAgZ2xvYmFsczogZ2xvYmFscy5icm93c2VyLFxuICAgIH0sXG4gICAgcGx1Z2luczoge1xuICAgICAgJ3JlYWN0LWhvb2tzJzogcmVhY3RIb29rcyxcbiAgICAgICdyZWFjdC1yZWZyZXNoJzogcmVhY3RSZWZyZXNoLFxuICAgIH0sXG4gICAgcnVsZXM6IHtcbiAgICAgIC4uLnJlYWN0SG9va3MuY29uZmlncy5yZWNvbW1lbmRlZC5ydWxlcyxcbiAgICAgICdyZWFjdC1yZWZyZXNoL29ubHktZXhwb3J0LWNvbXBvbmVudHMnOiBbXG4gICAgICAgICd3YXJuJyxcbiAgICAgICAgeyBhbGxvd0NvbnN0YW50RXhwb3J0OiB0cnVlIH0sXG4gICAgICBdLFxuICAgIH0sXG4gIH0sXG4gIGpzLmNvbmZpZ3MucmVjb21tZW5kZWQsXG4gIC4uLnRzZXNsaW50LmNvbmZpZ3MucmVjb21tZW5kZWQsXG5dXG5gO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgdml0ZS5jb25maWcudHMgZmlsZVxuICovXG5jbGFzcyBWaXRlQ29uZmlnRmlsZSBleHRlbmRzIEZpbGVCYXNlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QsICd2aXRlLmNvbmZpZy50cycsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgc3ludGhlc2l6ZUNvbnRlbnQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gYGltcG9ydCB7IGRlZmluZUNvbmZpZyB9IGZyb20gJ3ZpdGUnXG5pbXBvcnQgcmVhY3QgZnJvbSAnQHZpdGVqcy9wbHVnaW4tcmVhY3QnXG5cbi8vIGh0dHBzOi8vdml0ZS5kZXYvY29uZmlnL1xuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgcGx1Z2luczogW3JlYWN0KCldLFxufSlcbmA7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBwb3N0Y3NzLmNvbmZpZy5qcyBmaWxlIGZvciBUYWlsd2luZCBDU1MgdjRcbiAqL1xuY2xhc3MgUG9zdENTU0NvbmZpZ0ZpbGUgZXh0ZW5kcyBGaWxlQmFzZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QpIHtcbiAgICBzdXBlcihwcm9qZWN0LCAncG9zdGNzcy5jb25maWcuanMnLCB7XG4gICAgICBtYXJrZXI6IHRydWUsXG4gICAgICByZWFkb25seTogdHJ1ZSxcbiAgICB9KTtcbiAgfVxuXG4gIHN5bnRoZXNpemVDb250ZW50KCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGBleHBvcnQgZGVmYXVsdCB7XG4gIHBsdWdpbnM6IHtcbiAgICBcIkB0YWlsd2luZGNzcy9wb3N0Y3NzXCI6IHt9LFxuICAgIGF1dG9wcmVmaXhlcjoge30sXG4gIH0sXG59XG5gO1xuICB9XG59XG5cbmludGVyZmFjZSBWaXRlRW52RHRzT3B0aW9ucyB7XG4gIHJlYWRvbmx5IHNyY2Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIHZpdGUtZW52LmQudHMgZmlsZSBmb3IgdHlwZSBkZWNsYXJhdGlvbnNcbiAqL1xuY2xhc3MgVml0ZUVudkR0cyBleHRlbmRzIEZpbGVCYXNlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgb3B0aW9uczogVml0ZUVudkR0c09wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vdml0ZS1lbnYuZC50c2AsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgc3ludGhlc2l6ZUNvbnRlbnQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gYC8vLyA8cmVmZXJlbmNlIHR5cGVzPVwidml0ZS9jbGllbnRcIiAvPlxuYDtcbiAgfVxufVxuXG5pbnRlcmZhY2UgQ29uZmlnRmlsZU9wdGlvbnMge1xuICByZWFkb25seSBzcmNkaXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBjb25maWcudHMgZmlsZSBmb3IgcnVudGltZSBjb25maWd1cmF0aW9uXG4gKi9cbmNsYXNzIENvbmZpZ0ZpbGUgZXh0ZW5kcyBGaWxlQmFzZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IENvbmZpZ0ZpbGVPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCwgYCR7b3B0aW9ucy5zcmNkaXJ9L2NvbmZpZy50c2AsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgc3ludGhlc2l6ZUNvbnRlbnQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICAvLyBHZXQgY3VzdG9tIGNvbmZpZyBmaWVsZHMgZnJvbSBwYXJlbnQgcHJvamVjdFxuICAgIGNvbnN0IHZpdGVQcm9qZWN0ID0gdGhpcy5wcm9qZWN0IGFzIFZpdGVSZWFjdFByb2plY3Q7XG4gICAgY29uc3QgY3VzdG9tRmllbGRzID0gdml0ZVByb2plY3QuZ2V0Q29uZmlnRmllbGRzKCk7XG5cbiAgICAvLyBHZW5lcmF0ZSBiYXNlIGNvbmZpZyB0eXBlXG4gICAgY29uc3QgYmFzZUNvbmZpZ1R5cGUgPSBgdHlwZSBCYXNlQ29uZmlnID0ge1xuICBjbGVya1B1Ymxpc2hhYmxlS2V5OiBzdHJpbmc7XG4gIGFwaUJhc2VVcmw6IHN0cmluZztcbiAgdGltZW91dDogbnVtYmVyO1xufWA7XG5cbiAgICAvLyBHZW5lcmF0ZSBjdXN0b20gZmllbGRzIHR5cGUgaWYgYW55IGV4aXN0XG4gICAgbGV0IGNvbmZpZ1R5cGVEZWZpbml0aW9uOiBzdHJpbmc7XG4gICAgaWYgKGN1c3RvbUZpZWxkcy5zaXplID4gMCkge1xuICAgICAgY29uc3QgZmllbGREZWZpbml0aW9ucyA9IEFycmF5LmZyb20oY3VzdG9tRmllbGRzLmVudHJpZXMoKSlcbiAgICAgICAgLm1hcCgoW25hbWUsIHR5cGVdKSA9PiBgICAke25hbWV9OiAke3R5cGV9O2ApXG4gICAgICAgIC5qb2luKCdcXG4nKTtcblxuICAgICAgY29uc3QgY3VzdG9tRmllbGRzVHlwZSA9IGB0eXBlIEN1c3RvbUNvbmZpZyA9IHtcbiR7ZmllbGREZWZpbml0aW9uc31cbn1gO1xuXG4gICAgICBjb25maWdUeXBlRGVmaW5pdGlvbiA9IGAke2N1c3RvbUZpZWxkc1R5cGV9XG5cbmV4cG9ydCB0eXBlIENvbmZpZyA9IEJhc2VDb25maWcgJiBDdXN0b21Db25maWc7YDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uZmlnVHlwZURlZmluaXRpb24gPSAnZXhwb3J0IHR5cGUgQ29uZmlnID0gQmFzZUNvbmZpZzsnO1xuICAgIH1cblxuICAgIHJldHVybiBgaW1wb3J0IHsgdXNlRWZmZWN0LCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JztcblxuJHtiYXNlQ29uZmlnVHlwZX1cblxuJHtjb25maWdUeXBlRGVmaW5pdGlvbn1cblxubGV0IHNoYXJlZDogUHJvbWlzZTxDb25maWc+IHwgdW5kZWZpbmVkO1xubGV0IGxvYWRlZDogQ29uZmlnIHwgdW5kZWZpbmVkO1xuXG4vKiogSG93IGxvbmcgdGhlIHNoYXJlZCBsb2FkIG9mIC9jb25maWcuanNvbiBtYXkgdGFrZSBiZWZvcmUgaXQgaXMgYWJhbmRvbmVkIGFuZCBmYWlscy4gKi9cbmV4cG9ydCBjb25zdCBDT05GSUdfTE9BRF9USU1FT1VUX01TID0gMTUgKiAxMDAwO1xuXG4vKipcbiAqIFRoZSBydW50aW1lIGNvbmZpZywgbG9hZGVkIG9uY2UgYW5kIHNoYXJlZCBieSBldmVyeSB1c2VDb25maWcoKTsgYSBmYWlsZWQgbG9hZCwgaW5jbHVkaW5nIG9uZVxuICogYWJhbmRvbmVkIGFmdGVyIENPTkZJR19MT0FEX1RJTUVPVVRfTVMsIGlzIHRyaWVkIGFnYWluIGJ5IHRoZSBuZXh0IGNhbGxlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvYWRDb25maWcoKTogUHJvbWlzZTxDb25maWc+IHtcbiAgaWYgKCFzaGFyZWQpIHtcbiAgICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIGNvbnN0IHRpbWVyID0gc2V0VGltZW91dCgoKSA9PiBjb250cm9sbGVyLmFib3J0KCksIENPTkZJR19MT0FEX1RJTUVPVVRfTVMpO1xuICAgIGNvbnN0IGxvYWQ6IFByb21pc2U8Q29uZmlnPiA9IGZldGNoKCcvY29uZmlnLmpzb24nLCB7IGNhY2hlOiAnbm8tc3RvcmUnLCBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsIH0pXG4gICAgICAudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcXGBMb2FkaW5nIC9jb25maWcuanNvbiBmYWlsZWQgd2l0aCBzdGF0dXMgXFwke3Jlc3BvbnNlLnN0YXR1c31cXGApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCkgYXMgUHJvbWlzZTxDb25maWc+O1xuICAgICAgfSlcbiAgICAgIC5maW5hbGx5KCgpID0+IGNsZWFyVGltZW91dCh0aW1lcikpXG4gICAgICAudGhlbigoY29uZmlnKSA9PiB7XG4gICAgICAgIGlmIChzaGFyZWQgPT09IGxvYWQpIHtcbiAgICAgICAgICBsb2FkZWQgPSBjb25maWc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICAgIH0pO1xuICAgIGxvYWQuY2F0Y2goKCkgPT4ge1xuICAgICAgaWYgKHNoYXJlZCA9PT0gbG9hZCkge1xuICAgICAgICBzaGFyZWQgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfSk7XG4gICAgc2hhcmVkID0gbG9hZDtcbiAgfVxuICByZXR1cm4gc2hhcmVkO1xufVxuXG4vKiogRm9yZ2V0cyB0aGUgc2hhcmVkIGNvbmZpZywgc28gZWFjaCB0ZXN0IGxvYWRzIGl0cyBvd24uICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXRDb25maWdGb3JUZXN0cygpOiB2b2lkIHtcbiAgc2hhcmVkID0gdW5kZWZpbmVkO1xuICBsb2FkZWQgPSB1bmRlZmluZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VDb25maWcoKSB7XG4gIGNvbnN0IFtsb2FkZWRDb25maWcsIHNldExvYWRlZENvbmZpZ10gPSB1c2VTdGF0ZTxDb25maWcgfCB1bmRlZmluZWQ+KGxvYWRlZCk7XG4gIGNvbnN0IFtpc0xvYWRpbmcsIHNldElzTG9hZGluZ10gPSB1c2VTdGF0ZSghbG9hZGVkKTtcbiAgY29uc3QgW2Vycm9yLCBzZXRFcnJvcl0gPSB1c2VTdGF0ZTx1bmtub3duPigpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKGxvYWRlZENvbmZpZykge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgbGV0IGxpdmUgPSB0cnVlO1xuICAgIHNldElzTG9hZGluZyh0cnVlKTtcbiAgICBzZXRFcnJvcih1bmRlZmluZWQpO1xuICAgIGxvYWRDb25maWcoKS50aGVuKFxuICAgICAgKGNvbmZpZykgPT4ge1xuICAgICAgICBpZiAobGl2ZSkge1xuICAgICAgICAgIHNldExvYWRlZENvbmZpZyhjb25maWcpO1xuICAgICAgICAgIHNldElzTG9hZGluZyhmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAoZXJyKSA9PiB7XG4gICAgICAgIGlmIChsaXZlKSB7XG4gICAgICAgICAgc2V0RXJyb3IoZXJyKTtcbiAgICAgICAgICBzZXRJc0xvYWRpbmcoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICk7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGxpdmUgPSBmYWxzZTtcbiAgICB9O1xuICB9LCBbbG9hZGVkQ29uZmlnXSk7XG5cbiAgcmV0dXJuIHsgY29uZmlnOiBsb2FkZWRDb25maWcsIGlzTG9hZGluZywgZXJyb3IgfTtcbn1cbmA7XG4gIH1cbn1cblxuaW50ZXJmYWNlIENvbmZpZ0pzb25GaWxlT3B0aW9ucyB7fVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIGNvbmZpZy5qc29uIHNhbXBsZSBmaWxlIGZvciBydW50aW1lIGNvbmZpZ3VyYXRpb25cbiAqL1xuY2xhc3MgQ29uZmlnSnNvbkZpbGUgZXh0ZW5kcyBTYW1wbGVGaWxlIHtcbiAgcGF0aDogc3RyaW5nO1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBWaXRlUmVhY3RQcm9qZWN0LCBfb3B0aW9uczogQ29uZmlnSnNvbkZpbGVPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCwgYCR7cHJvamVjdC5wdWJsaWNEaXJ9L2NvbmZpZy5qc29uYCwge1xuICAgICAgY29udGVudHM6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgYXBpQmFzZVVybDogJ2h0dHA6Ly9sb2NhbGhvc3Q6MzAwMC9hcGknLFxuICAgICAgICBjbGVya1B1Ymxpc2hhYmxlS2V5OiAndGJkJyxcbiAgICAgIH0sIG51bGwsIDIpLFxuICAgIH0pO1xuICAgIHRoaXMucGF0aCA9IGAke3Byb2plY3QucHVibGljRGlyfS9jb25maWcuanNvbmA7XG4gIH1cbn1cblxuaW50ZXJmYWNlIEluZGV4SHRtbE9wdGlvbnMge1xuICByZWFkb25seSB0aXRsZTogc3RyaW5nO1xuICByZWFkb25seSBzcmNkaXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIHRoZSBpbmRleC5odG1sIGZpbGVcbiAqL1xuY2xhc3MgSW5kZXhIdG1sIGV4dGVuZHMgU2FtcGxlRmlsZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFByb2plY3QsIG9wdGlvbnM6IEluZGV4SHRtbE9wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0LCAnaW5kZXguaHRtbCcsIHtcbiAgICAgIGNvbnRlbnRzOiBgPCFkb2N0eXBlIGh0bWw+XG48aHRtbCBsYW5nPVwiZW5cIj5cbiAgPGhlYWQ+XG4gICAgPG1ldGEgY2hhcnNldD1cIlVURi04XCIgLz5cbiAgICA8bGluayByZWw9XCJpY29uXCIgdHlwZT1cImltYWdlL3N2Zyt4bWxcIiBocmVmPVwiL3ZpdGUuc3ZnXCIgLz5cbiAgICA8bWV0YSBuYW1lPVwidmlld3BvcnRcIiBjb250ZW50PVwid2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMFwiIC8+XG4gICAgPHRpdGxlPiR7b3B0aW9ucy50aXRsZX08L3RpdGxlPlxuICA8L2hlYWQ+XG4gIDxib2R5PlxuICAgIDxkaXYgaWQ9XCJyb290XCI+PC9kaXY+XG4gICAgPHNjcmlwdCB0eXBlPVwibW9kdWxlXCIgc3JjPVwiLyR7b3B0aW9ucy5zcmNkaXJ9L21haW4udHN4XCI+PC9zY3JpcHQ+XG4gIDwvYm9keT5cbjwvaHRtbD5cbmAsXG4gICAgfSk7XG4gIH1cbn1cblxuaW50ZXJmYWNlIFZpdGVUc0NvbmZpZ3NPcHRpb25zIHtcbiAgcmVhZG9ubHkgc3JjZGlyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ3JlYXRlcyB0aGUgVHlwZVNjcmlwdCBjb25maWd1cmF0aW9uIGZpbGVzIGZvciBWaXRlXG4gKi9cbmNsYXNzIFZpdGVUc0NvbmZpZ3MgZXh0ZW5kcyBDb21wb25lbnQge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBQcm9qZWN0LCBvcHRpb25zOiBWaXRlVHNDb25maWdzT3B0aW9ucykge1xuICAgIHN1cGVyKHByb2plY3QpO1xuXG4gICAgLy8gTWFpbiB0c2NvbmZpZy5qc29uIChwcm9qZWN0IHJlZmVyZW5jZXMpXG4gICAgbmV3IEpzb25GaWxlKHByb2plY3QsICd0c2NvbmZpZy5qc29uJywge1xuICAgICAgbWFya2VyOiB0cnVlLFxuICAgICAgcmVhZG9ubHk6IHRydWUsXG4gICAgICBvYmo6IHtcbiAgICAgICAgZmlsZXM6IFtdLFxuICAgICAgICByZWZlcmVuY2VzOiBbXG4gICAgICAgICAgeyBwYXRoOiAnLi90c2NvbmZpZy5hcHAuanNvbicgfSxcbiAgICAgICAgICB7IHBhdGg6ICcuL3RzY29uZmlnLm5vZGUuanNvbicgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyB0c2NvbmZpZy5hcHAuanNvbiAoZm9yIGFwcGxpY2F0aW9uIGNvZGUpXG4gICAgbmV3IEpzb25GaWxlKHByb2plY3QsICd0c2NvbmZpZy5hcHAuanNvbicsIHtcbiAgICAgIG1hcmtlcjogdHJ1ZSxcbiAgICAgIHJlYWRvbmx5OiB0cnVlLFxuICAgICAgb2JqOiB7XG4gICAgICAgIGNvbXBpbGVyT3B0aW9uczoge1xuICAgICAgICAgIHRhcmdldDogJ0VTMjAyMCcsXG4gICAgICAgICAgdXNlRGVmaW5lRm9yQ2xhc3NGaWVsZHM6IHRydWUsXG4gICAgICAgICAgbGliOiBbJ0VTMjAyMCcsICdET00nLCAnRE9NLkl0ZXJhYmxlJ10sXG4gICAgICAgICAgbW9kdWxlOiAnRVNOZXh0JyxcbiAgICAgICAgICBza2lwTGliQ2hlY2s6IHRydWUsXG5cbiAgICAgICAgICAvLyBCdW5kbGVyIG1vZGVcbiAgICAgICAgICBtb2R1bGVSZXNvbHV0aW9uOiAnYnVuZGxlcicsXG4gICAgICAgICAgYWxsb3dJbXBvcnRpbmdUc0V4dGVuc2lvbnM6IHRydWUsXG4gICAgICAgICAgaXNvbGF0ZWRNb2R1bGVzOiB0cnVlLFxuICAgICAgICAgIG1vZHVsZURldGVjdGlvbjogJ2ZvcmNlJyxcbiAgICAgICAgICBub0VtaXQ6IHRydWUsXG4gICAgICAgICAganN4OiAncmVhY3QtanN4JyxcblxuICAgICAgICAgIC8vIExpbnRpbmdcbiAgICAgICAgICBzdHJpY3Q6IHRydWUsXG4gICAgICAgICAgbm9VbnVzZWRMb2NhbHM6IHRydWUsXG4gICAgICAgICAgbm9VbnVzZWRQYXJhbWV0ZXJzOiB0cnVlLFxuICAgICAgICAgIG5vRmFsbHRocm91Z2hDYXNlc0luU3dpdGNoOiB0cnVlLFxuICAgICAgICAgIG5vVW5jaGVja2VkU2lkZUVmZmVjdEltcG9ydHM6IHRydWUsXG4gICAgICAgIH0sXG4gICAgICAgIGluY2x1ZGU6IFtvcHRpb25zLnNyY2Rpcl0sXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gdHNjb25maWcubm9kZS5qc29uIChmb3IgVml0ZSBjb25maWcpXG4gICAgbmV3IEpzb25GaWxlKHByb2plY3QsICd0c2NvbmZpZy5ub2RlLmpzb24nLCB7XG4gICAgICBtYXJrZXI6IHRydWUsXG4gICAgICByZWFkb25seTogdHJ1ZSxcbiAgICAgIG9iajoge1xuICAgICAgICBjb21waWxlck9wdGlvbnM6IHtcbiAgICAgICAgICB0YXJnZXQ6ICdFUzIwMjInLFxuICAgICAgICAgIGxpYjogWydFUzIwMjMnXSxcbiAgICAgICAgICBtb2R1bGU6ICdFU05leHQnLFxuICAgICAgICAgIHNraXBMaWJDaGVjazogdHJ1ZSxcblxuICAgICAgICAgIC8vIEJ1bmRsZXIgbW9kZVxuICAgICAgICAgIG1vZHVsZVJlc29sdXRpb246ICdidW5kbGVyJyxcbiAgICAgICAgICBhbGxvd0ltcG9ydGluZ1RzRXh0ZW5zaW9uczogdHJ1ZSxcbiAgICAgICAgICBpc29sYXRlZE1vZHVsZXM6IHRydWUsXG4gICAgICAgICAgbW9kdWxlRGV0ZWN0aW9uOiAnZm9yY2UnLFxuICAgICAgICAgIG5vRW1pdDogdHJ1ZSxcblxuICAgICAgICAgIC8vIExpbnRpbmdcbiAgICAgICAgICBzdHJpY3Q6IHRydWUsXG4gICAgICAgICAgbm9VbnVzZWRMb2NhbHM6IHRydWUsXG4gICAgICAgICAgbm9VbnVzZWRQYXJhbWV0ZXJzOiB0cnVlLFxuICAgICAgICAgIG5vRmFsbHRocm91Z2hDYXNlc0luU3dpdGNoOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICBpbmNsdWRlOiBbJ3ZpdGUuY29uZmlnLnRzJ10sXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG59XG5cbmludGVyZmFjZSBWaXRlU2FtcGxlQ29kZU9wdGlvbnMge1xuICByZWFkb25seSBzcmNkaXI6IHN0cmluZztcbiAgcmVhZG9ubHkgcHVibGljRGlyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogR2VuZXJhdGVzIHNhbXBsZSBjb2RlIGZvciBhIFZpdGUgKyBSZWFjdCBwcm9qZWN0XG4gKi9cbmNsYXNzIFZpdGVTYW1wbGVDb2RlIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgb3B0aW9uczogVml0ZVNhbXBsZUNvZGVPcHRpb25zKSB7XG4gICAgc3VwZXIocHJvamVjdCk7XG5cbiAgICAvLyBDcmVhdGUgQXBwLnRzeFxuICAgIG5ldyBTYW1wbGVGaWxlKHByb2plY3QsIGAke29wdGlvbnMuc3JjZGlyfS9BcHAudHN4YCwge1xuICAgICAgY29udGVudHM6IGBpbXBvcnQgJy4vQXBwLmNzcydcbmltcG9ydCB7IFNpZ25lZEluLCBVc2VyQnV0dG9uIH0gZnJvbSAnQGNsZXJrL2NsZXJrLXJlYWN0JztcbmltcG9ydCB7IHVzZUFwaVF1ZXJ5IH0gZnJvbSBcIi4vc2VydmljZXMvQXBpU2VydmljZS50c1wiO1xuXG5cbmZ1bmN0aW9uIEFwcCgpIHtcbiAgY29uc3Qge2RhdGEsIGlzTG9hZGluZ30gPSB1c2VBcGlRdWVyeSgnLycsIHtyZXRyeU9uTW91bnQ6IHRydWV9KTtcblxuXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgICAgPGhlYWRlcj5cblxuICAgICAgICAgIDxTaWduZWRJbj5cbiAgICAgICAgICAgIDxVc2VyQnV0dG9uLz5cbiAgICAgICAgICA8L1NpZ25lZEluPlxuICAgICAgICA8L2hlYWRlcj5cbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJjYXJkXCI+XG4gICAgICAgICAgeyBpc0xvYWRpbmcgPyAnTG9hZGluZy4uLicgOiBKU09OLnN0cmluZ2lmeShkYXRhLCBudWxsICwpfVxuICAgICAgICA8L2Rpdj5cbiAgICA8Lz5cbiAgKVxufVxuXG5leHBvcnQgZGVmYXVsdCBBcHBcbmAsXG4gICAgfSk7XG5cbiAgICBuZXcgQXBpU2VydmljZUZpbGVzKHByb2plY3QsIHsgc3JjZGlyOiBvcHRpb25zLnNyY2RpciB9KTtcblxuICAgIC8vIENyZWF0ZSBBcHAuY3NzXG4gICAgbmV3IFNhbXBsZUZpbGUocHJvamVjdCwgYCR7b3B0aW9ucy5zcmNkaXJ9L0FwcC5jc3NgLCB7XG4gICAgICBjb250ZW50czogYCNyb290IHtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogMTAwJTtcbn1cblxuLmxvZ28ge1xuICBoZWlnaHQ6IDZlbTtcbiAgcGFkZGluZzogMS41ZW07XG4gIHdpbGwtY2hhbmdlOiBmaWx0ZXI7XG4gIHRyYW5zaXRpb246IGZpbHRlciAzMDBtcztcbn1cbi5sb2dvOmhvdmVyIHtcbiAgZmlsdGVyOiBkcm9wLXNoYWRvdygwIDAgMmVtICM2NDZjZmZhYSk7XG59XG4ubG9nby5yZWFjdDpob3ZlciB7XG4gIGZpbHRlcjogZHJvcC1zaGFkb3coMCAwIDJlbSAjNjFkYWZiYWEpO1xufVxuXG5Aa2V5ZnJhbWVzIGxvZ28tc3BpbiB7XG4gIGZyb20ge1xuICAgIHRyYW5zZm9ybTogcm90YXRlKDBkZWcpO1xuICB9XG4gIHRvIHtcbiAgICB0cmFuc2Zvcm06IHJvdGF0ZSgzNjBkZWcpO1xuICB9XG59XG5cbkBtZWRpYSAocHJlZmVycy1yZWR1Y2VkLW1vdGlvbjogbm8tcHJlZmVyZW5jZSkge1xuICBhOm50aC1vZi10eXBlKDIpIC5sb2dvIHtcbiAgICBhbmltYXRpb246IGxvZ28tc3BpbiBpbmZpbml0ZSAyMHMgbGluZWFyO1xuICB9XG59XG5cbi5jYXJkIHtcbiAgcGFkZGluZzogMmVtO1xufVxuXG4ucmVhZC10aGUtZG9jcyB7XG4gIGNvbG9yOiAjODg4O1xufVxuYCxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBtYWluLnRzeFxuICAgIG5ldyBTYW1wbGVGaWxlKHByb2plY3QsIGAke29wdGlvbnMuc3JjZGlyfS9tYWluLnRzeGAsIHtcbiAgICAgIGNvbnRlbnRzOiBgaW1wb3J0IHsgU3RyaWN0TW9kZSB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgY3JlYXRlUm9vdCB9IGZyb20gJ3JlYWN0LWRvbS9jbGllbnQnXG5pbXBvcnQgJy4vaW5kZXguY3NzJ1xuaW1wb3J0IEFwcCBmcm9tICcuL0FwcC50c3gnXG5pbXBvcnQgeyBDbGVya1Byb3ZpZGVyLCBTaWduZWRJbiwgU2lnbmVkT3V0LCBTaWduSW5CdXR0b24gfSBmcm9tICdAY2xlcmsvY2xlcmstcmVhY3QnXG5pbXBvcnQgeyB1c2VDb25maWcgfSBmcm9tICcuL2NvbmZpZydcbmltcG9ydCB7IFF1ZXJ5Q2xpZW50LCBRdWVyeUNsaWVudFByb3ZpZGVyIH0gZnJvbSBcIkB0YW5zdGFjay9yZWFjdC1xdWVyeVwiXG5cbmZ1bmN0aW9uIEFwcFdyYXBwZXIoKSB7XG4gIGNvbnN0IHsgY29uZmlnLCBpc0xvYWRpbmcsIGVycm9yIH0gPSB1c2VDb25maWcoKTtcbiAgY29uc3QgcXVlcnlDbGllbnQgPSBuZXcgUXVlcnlDbGllbnQoKVxuICBpZiAoZXJyb3IpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPGRpdiBjbGFzc05hbWU9XCJsb2FkaW5nLXNjcmVlblwiPlxuICAgICAgICBDb3VsZCBub3QgbG9hZCB0aGUgYXBwIGNvbmZpZ3VyYXRpb24uXG4gICAgICA8L2Rpdj5cbiAgICApO1xuICB9XG4gIGlmIChpc0xvYWRpbmcgfHwgIWNvbmZpZykge1xuICAgIHJldHVybiAoXG4gICAgICA8ZGl2IGNsYXNzTmFtZT1cImxvYWRpbmctc2NyZWVuXCI+XG4gICAgICAgIExvYWRpbmcuLi5cbiAgICAgIDwvZGl2PlxuICAgICk7XG4gIH1cblxuICByZXR1cm4gKFxuICAgIDxDbGVya1Byb3ZpZGVyIHB1Ymxpc2hhYmxlS2V5PXtjb25maWcuY2xlcmtQdWJsaXNoYWJsZUtleX0+XG4gICAgICA8UXVlcnlDbGllbnRQcm92aWRlciBjbGllbnQ9e3F1ZXJ5Q2xpZW50fT5cbiAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJ3LWZ1bGwgaC1mdWxsXCI+XG4gICAgICAgICAgPFNpZ25lZE91dD5cbiAgICAgICAgICAgIDxkaXYgY2xhc3NOYW1lPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgbWluLWgtc2NyZWVuXCI+XG4gICAgICAgICAgICAgIDxTaWduSW5CdXR0b24vPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9TaWduZWRPdXQ+XG4gICAgICAgICAgPFNpZ25lZEluPlxuICAgICAgICAgICAgPEFwcC8+XG4gICAgICAgICAgPC9TaWduZWRJbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L1F1ZXJ5Q2xpZW50UHJvdmlkZXI+XG4gICAgPC9DbGVya1Byb3ZpZGVyPlxuICApO1xufVxuXG5jcmVhdGVSb290KGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdyb290JykhKS5yZW5kZXIoXG4gIDxTdHJpY3RNb2RlPlxuICAgIDxBcHBXcmFwcGVyLz5cbiAgPC9TdHJpY3RNb2RlPlxuKVxuYCxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBpbmRleC5jc3NcbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vaW5kZXguY3NzYCwge1xuICAgICAgY29udGVudHM6IGBAaW1wb3J0IFwidGFpbHdpbmRjc3NcIjtcblxuQHRoZW1lIHtcbiAgLS1jb2xvci1zY2hlbWU6IGxpZ2h0IGRhcms7XG59XG5cbjpyb290IHtcbiAgZm9udC1mYW1pbHk6IEludGVyLCBzeXN0ZW0tdWksIEF2ZW5pciwgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjtcbiAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgZm9udC13ZWlnaHQ6IDQwMDtcblxuICBjb2xvci1zY2hlbWU6IGxpZ2h0IGRhcms7XG5cbiAgZm9udC1zeW50aGVzaXM6IG5vbmU7XG4gIHRleHQtcmVuZGVyaW5nOiBvcHRpbWl6ZUxlZ2liaWxpdHk7XG4gIC13ZWJraXQtZm9udC1zbW9vdGhpbmc6IGFudGlhbGlhc2VkO1xuICAtbW96LW9zeC1mb250LXNtb290aGluZzogZ3JheXNjYWxlO1xufVxuXG5hIHtcbiAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgY29sb3I6ICM2NDZjZmY7XG4gIHRleHQtZGVjb3JhdGlvbjogaW5oZXJpdDtcbn1cbmE6aG92ZXIge1xuICBjb2xvcjogIzUzNWJmMjtcbn1cblxuYm9keSB7XG4gIG1hcmdpbjogMDtcbiAgbWluLXdpZHRoOiAzMjBweDtcbiAgbWluLWhlaWdodDogMTAwdmg7XG59XG5cbmgxIHtcbiAgZm9udC1zaXplOiAzLjJlbTtcbiAgbGluZS1oZWlnaHQ6IDEuMTtcbn1cblxuYnV0dG9uIHtcbiAgZm9udC1mYW1pbHk6IGluaGVyaXQ7XG4gIGN1cnNvcjogcG9pbnRlcjtcbn1cblxuLmxvYWRpbmctc2NyZWVuIHtcbiAgZGlzcGxheTogZmxleDtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGhlaWdodDogMTAwdmg7XG4gIGZvbnQtc2l6ZTogMS41cmVtO1xufVxuXG5odG1sLCBib2R5LCAjcm9vdCB7XG4gIHdpZHRoOiAxMDAlO1xuICBoZWlnaHQ6IDEwMCU7XG59XG5gLFxuICAgIH0pO1xuXG4gIH1cbn1cblxuaW50ZXJmYWNlIEFwaVNlcnZpY2VGaWxlc09wdGlvbnMge1xuICByZWFkb25seSBzcmNkaXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBCb290c3RyYXBzIHRoZSB3ZWIgY2xpZW50J3MgQVBJIGxheWVyOiBgc2VydmljZXMvQXBpU2VydmljZS50c2AgKHF1ZXJ5IGFuZCBtdXRhdGlvbiBob29rc1xuICoga2V5ZWQgcGVyIHBhdGgpIGFuZCB0aGUgYGhlbHBlcnMvYCBpdCBpcyBidWlsdCBvbi4gV3JpdHRlbiBvbmNlLCB0aGVuIG93bmVkIGJ5IHRoZSBjb25zdW1lci5cbiAqL1xuY2xhc3MgQXBpU2VydmljZUZpbGVzIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogUHJvamVjdCwgb3B0aW9uczogQXBpU2VydmljZUZpbGVzT3B0aW9ucykge1xuICAgIHN1cGVyKHByb2plY3QpO1xuXG4gICAgbmV3IFNhbXBsZUZpbGUocHJvamVjdCwgYCR7b3B0aW9ucy5zcmNkaXJ9L3NlcnZpY2VzL0FwaVNlcnZpY2UudHNgLCB7XG4gICAgICBjb250ZW50czogYGltcG9ydCB7IHVzZUF1dGggfSBmcm9tICdAY2xlcmsvY2xlcmstcmVhY3QnO1xuaW1wb3J0IHsgUXVlcnlDbGllbnQsIHVzZU11dGF0aW9uLCBVc2VNdXRhdGlvbk9wdGlvbnMsIHVzZVF1ZXJ5LCBVc2VRdWVyeU9wdGlvbnMgfSBmcm9tICdAdGFuc3RhY2svcmVhY3QtcXVlcnknO1xuaW1wb3J0IHsgdXNlRWZmZWN0LCB1c2VNZW1vLCB1c2VSZWYgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBsb2FkQ29uZmlnLCB1c2VDb25maWcgfSBmcm9tICcuLi9jb25maWcnO1xuaW1wb3J0IHsgUmVxdWVzdENhbmNlbGxlZEVycm9yIH0gZnJvbSAnLi4vaGVscGVycy9IdHRwRXJyb3InO1xuaW1wb3J0IHsgZ2V0LCBwb3N0LCBwdXQsIFJlcXVlc3RPcHRpb25zLCBUb2tlbkdldHRlciB9IGZyb20gJy4uL2hlbHBlcnMvcmVxdWVzdHMnO1xuXG4vKiogVGhlIFJlYWN0IFF1ZXJ5IGtleSBmb3IgYW4gQVBJIHBhdGg6IGl0cyBzZWdtZW50cywgc28gYSBwcmVmaXgncyBrZXkgY292ZXJzIGV2ZXJ5IHBhdGggdW5kZXIgaXQuICovXG5leHBvcnQgZnVuY3Rpb24gYXBpUXVlcnlLZXkocGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gcGF0aC5zcGxpdCgnLycpLmZpbHRlcihCb29sZWFuKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGludmFsaWRhdGVBcGlRdWVyaWVzKHF1ZXJ5Q2xpZW50OiBRdWVyeUNsaWVudCwgcHJlZml4OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgcmV0dXJuIHF1ZXJ5Q2xpZW50LmludmFsaWRhdGVRdWVyaWVzKHsgcXVlcnlLZXk6IGFwaVF1ZXJ5S2V5KHByZWZpeCksIGV4YWN0OiBmYWxzZSB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVzZUFwaVF1ZXJ5PFREYXRhID0gdW5rbm93bj4oXG4gIHBhdGg6IHN0cmluZyxcbiAgb3B0aW9ucz86IE9taXQ8VXNlUXVlcnlPcHRpb25zPFREYXRhPiwgJ3F1ZXJ5S2V5JyB8ICdxdWVyeUZuJz4sXG4pIHtcbiAgY29uc3QgeyBjb25maWcgfSA9IHVzZUNvbmZpZygpO1xuICBjb25zdCB7IGdldFRva2VuIH0gPSB1c2VBdXRoKCk7XG4gIGNvbnN0IHsgZW5hYmxlZCwgLi4ucmVzdE9wdGlvbnMgfSA9IG9wdGlvbnMgPz8ge307XG5cbiAgcmV0dXJuIHVzZVF1ZXJ5PFREYXRhPih7XG4gICAgcXVlcnlLZXk6IGFwaVF1ZXJ5S2V5KHBhdGgpLFxuICAgIHF1ZXJ5Rm46ICh7IHNpZ25hbCB9KSA9PiBnZXQ8VERhdGE+KGNvbmZpZyEuYXBpQmFzZVVybCwgcGF0aCwgZ2V0VG9rZW4gYXMgVG9rZW5HZXR0ZXIsIHsgc2lnbmFsIH0pLFxuICAgIC4uLnJlc3RPcHRpb25zLFxuICAgIC8vIEEgY2FsbGVyJ3MgXFxgZW5hYmxlZFxcYCBuYXJyb3dzIHRoZSBjb25maWcgZ2F0ZSByYXRoZXIgdGhhbiByZXBsYWNpbmcgaXQ6IFxcYHF1ZXJ5Rm5cXGAgbmVlZHMgdGhlIGNvbmZpZy5cbiAgICBlbmFibGVkOiAoZW5hYmxlZCA/PyB0cnVlKSAmJiAhIWNvbmZpZz8uYXBpQmFzZVVybCxcbiAgfSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXBpQ2xpZW50IHtcbiAgZ2V0PFREYXRhID0gdW5rbm93bj4ocGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVxdWVzdE9wdGlvbnMpOiBQcm9taXNlPFREYXRhPjtcbiAgcG9zdDxURGF0YSA9IHVua25vd24+KHBhdGg6IHN0cmluZywgYm9keTogdW5rbm93biwgb3B0aW9ucz86IFJlcXVlc3RPcHRpb25zKTogUHJvbWlzZTxURGF0YT47XG4gIHB1dDxURGF0YSA9IHVua25vd24+KHBhdGg6IHN0cmluZywgYm9keTogdW5rbm93biwgb3B0aW9ucz86IFJlcXVlc3RPcHRpb25zKTogUHJvbWlzZTxURGF0YT47XG59XG5cbi8qKlxuICogQ2FsbHMgdGhlIEFQSSBpbXBlcmF0aXZlbHksIHJlYWRpbmcgdGhlIHJ1bnRpbWUgY29uZmlnIGFuZCB0aGUgdG9rZW4gZ2V0dGVyIGF0IHRoZSBtb21lbnQgb2ZcbiAqIGVhY2ggY2FsbC4gQSBjYWxsIG1hZGUgYmVmb3JlIHRoZSBjb25maWcgaGFzIGFycml2ZWQgd2FpdHMgZm9yIHRoZSBzaGFyZWQgbG9hZCwgYW5kIGZhaWxzXG4gKiB3aGVuIHRoYXQgbG9hZCBmYWlscy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZUFwaUNsaWVudCgpOiBBcGlDbGllbnQge1xuICBjb25zdCB7IGNvbmZpZyB9ID0gdXNlQ29uZmlnKCk7XG4gIGNvbnN0IHsgZ2V0VG9rZW4gfSA9IHVzZUF1dGgoKTtcbiAgY29uc3QgbGF0ZXN0ID0gdXNlUmVmKHsgY29uZmlnLCBnZXRUb2tlbiB9KTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBsYXRlc3QuY3VycmVudCA9IHsgY29uZmlnLCBnZXRUb2tlbiB9O1xuICB9LCBbY29uZmlnLCBnZXRUb2tlbl0pO1xuXG4gIHJldHVybiB1c2VNZW1vKCgpID0+IHtcbiAgICBjb25zdCB1bnRpbENhbmNlbGxlZCA9IChzaWduYWw6IEFib3J0U2lnbmFsIHwgdW5kZWZpbmVkKSA9PiBuZXcgUHJvbWlzZTxuZXZlcj4oKF8sIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKHNpZ25hbD8uYWJvcnRlZCkge1xuICAgICAgICByZWplY3QobmV3IFJlcXVlc3RDYW5jZWxsZWRFcnJvcigpKTtcbiAgICAgIH1cbiAgICAgIHNpZ25hbD8uYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCAoKSA9PiByZWplY3QobmV3IFJlcXVlc3RDYW5jZWxsZWRFcnJvcigpKSwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIH0pO1xuICAgIGNvbnN0IGFwaUJhc2VVcmwgPSBhc3luYyAoc2lnbmFsOiBBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZCk6IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gICAgICBjb25zdCBjb25maWcgPSBsYXRlc3QuY3VycmVudC5jb25maWdcbiAgICAgICAgPz8gYXdhaXQgUHJvbWlzZS5yYWNlKFtsb2FkQ29uZmlnKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKSwgdW50aWxDYW5jZWxsZWQoc2lnbmFsKV0pO1xuICAgICAgaWYgKCFjb25maWc/LmFwaUJhc2VVcmwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdBUEkgYmFzZSBVUkwgbm90IGNvbmZpZ3VyZWQnKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBjb25maWcuYXBpQmFzZVVybDtcbiAgICB9O1xuICAgIGNvbnN0IHRva2VuOiBUb2tlbkdldHRlciA9ICgpID0+IChsYXRlc3QuY3VycmVudC5nZXRUb2tlbiBhcyBUb2tlbkdldHRlcikoKTtcbiAgICByZXR1cm4ge1xuICAgICAgZ2V0OiBhc3luYyA8VERhdGE+KHBhdGg6IHN0cmluZywgb3B0aW9ucz86IFJlcXVlc3RPcHRpb25zKSA9PlxuICAgICAgICBnZXQ8VERhdGE+KGF3YWl0IGFwaUJhc2VVcmwob3B0aW9ucz8uc2lnbmFsKSwgcGF0aCwgdG9rZW4sIG9wdGlvbnMpLFxuICAgICAgcG9zdDogYXN5bmMgPFREYXRhPihwYXRoOiBzdHJpbmcsIGJvZHk6IHVua25vd24sIG9wdGlvbnM/OiBSZXF1ZXN0T3B0aW9ucykgPT5cbiAgICAgICAgcG9zdDxURGF0YT4oYXdhaXQgYXBpQmFzZVVybChvcHRpb25zPy5zaWduYWwpLCBwYXRoLCBib2R5LCB0b2tlbiwgb3B0aW9ucyksXG4gICAgICBwdXQ6IGFzeW5jIDxURGF0YT4ocGF0aDogc3RyaW5nLCBib2R5OiB1bmtub3duLCBvcHRpb25zPzogUmVxdWVzdE9wdGlvbnMpID0+XG4gICAgICAgIHB1dDxURGF0YT4oYXdhaXQgYXBpQmFzZVVybChvcHRpb25zPy5zaWduYWwpLCBwYXRoLCBib2R5LCB0b2tlbiwgb3B0aW9ucyksXG4gICAgfTtcbiAgfSwgW10pO1xufVxuXG50eXBlIEFwaU11dGF0aW9uVmFyaWFibGVzID0geyBwYXRoOiBzdHJpbmc7IGJvZHk6IHVua25vd247IHNpZ25hbD86IEFib3J0U2lnbmFsIH07XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VBcGlNdXRhdGlvbjxURGF0YSA9IHVua25vd24+KFxuICBtZXRob2Q6ICdQT1NUJyB8ICdQVVQnLFxuICBvcHRpb25zPzogT21pdDxVc2VNdXRhdGlvbk9wdGlvbnM8VERhdGEsIHVua25vd24sIEFwaU11dGF0aW9uVmFyaWFibGVzPiwgJ211dGF0aW9uRm4nPixcbikge1xuICBjb25zdCBjbGllbnQgPSB1c2VBcGlDbGllbnQoKTtcblxuICByZXR1cm4gdXNlTXV0YXRpb248VERhdGEsIHVua25vd24sIEFwaU11dGF0aW9uVmFyaWFibGVzPih7XG4gICAgbXV0YXRpb25GbjogKHsgcGF0aCwgYm9keSwgc2lnbmFsIH0pID0+XG4gICAgICBtZXRob2QgPT09ICdQT1NUJyA/IGNsaWVudC5wb3N0PFREYXRhPihwYXRoLCBib2R5LCB7IHNpZ25hbCB9KSA6IGNsaWVudC5wdXQ8VERhdGE+KHBhdGgsIGJvZHksIHsgc2lnbmFsIH0pLFxuICAgIC4uLm9wdGlvbnMsXG4gIH0pO1xufVxuYCxcbiAgICB9KTtcblxuICAgIG5ldyBTYW1wbGVGaWxlKHByb2plY3QsIGAke29wdGlvbnMuc3JjZGlyfS9oZWxwZXJzL3JlcXVlc3RzLnRzYCwge1xuICAgICAgY29udGVudHM6IGBpbXBvcnQgeyBIdHRwRXJyb3IsIFJlcXVlc3RDYW5jZWxsZWRFcnJvciwgUmVxdWVzdFRpbWVvdXRFcnJvciwgdHlwZSBIdHRwRXJyb3JEZXRhaWxzIH0gZnJvbSAnLi9IdHRwRXJyb3InO1xuXG5leHBvcnQgdHlwZSBUb2tlbkdldHRlciA9ICgpID0+IFByb21pc2U8c3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZD47XG5cbi8qKlxuICogSG93IGxvbmcgYSByZXF1ZXN0IG1heSBnbyB1bmFuc3dlcmVkIGJlZm9yZSBpdCBmYWlscy4gSXQgc3RheXMgYWJvdmUgdGhlIGxvbmdlc3QgQ2xvdWRGcm9udFxuICogY2FuIHRha2UgdG8gZ2l2ZSBhbnkgYW5zd2VyOiB0aHJlZSAxMCBzIGNvbm5lY3Rpb24gYXR0ZW1wdHMgdG8gdGhlIEFQSSBvcmlnaW4gcGx1cyBpdHMgMzAgc1xuICogcmVzcG9uc2UgdGltZW91dC4gVGhlIGxvY2FsIGRldiBzZXJ2ZXIgaGFzIG5vIGxpbWl0IG9mIGl0cyBvd24sIHNvIHRoZXJlIHRoaXMgaXMgdGhlIG9ubHkgb25lLlxuICovXG5leHBvcnQgY29uc3QgQVBJX1JFUVVFU1RfVElNRU9VVF9NUyA9IDY1ICogMTAwMDtcblxuZXhwb3J0IGludGVyZmFjZSBSZXF1ZXN0T3B0aW9ucyB7XG4gIHJlYWRvbmx5IHNpZ25hbD86IEFib3J0U2lnbmFsO1xuICAvKiogQ2FsbGVkIHdoZW4gdGhlIEFQSSByZWplY3RzIHRoZSBjYWxsZXIncyBzZXNzaW9uIChhIDQwMSksIGJlZm9yZSB0aGUgZXJyb3IgaXMgdGhyb3duLiAqL1xuICByZWFkb25seSBvblNlc3Npb25SZWplY3RlZD86ICgpID0+IHZvaWQ7XG59XG5cbmludGVyZmFjZSBEZWFkbGluZSB7XG4gIHJlYWRvbmx5IHNpZ25hbDogQWJvcnRTaWduYWw7XG4gIC8qKiBTZXR0bGVzIHdpdGggXFxgcHJvbWlzZVxcYCwgb3IgcmVqZWN0cyBhcyBzb29uIGFzIHRoZSByZXF1ZXN0IGlzIGFiYW5kb25lZC4gKi9cbiAgcmFjZTxUPihwcm9taXNlOiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPjtcbiAgLyoqIFdoeSB0aGUgcmVxdWVzdCB3YXMgYWJhbmRvbmVkLCBvciBcXGB1bmRlZmluZWRcXGAgd2hpbGUgaXQgaXMgc3RpbGwgbGl2ZS4gKi9cbiAgcmVhZG9ubHkgYWJhbmRvbm1lbnQ6IEh0dHBFcnJvciB8IHVuZGVmaW5lZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gd2l0aERlYWRsaW5lPFQ+KGNhbGxlclNpZ25hbDogQWJvcnRTaWduYWwgfCB1bmRlZmluZWQsIHJ1bjogKGRlYWRsaW5lOiBEZWFkbGluZSkgPT4gUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICBsZXQgYWJhbmRvbm1lbnQ6IEh0dHBFcnJvciB8IHVuZGVmaW5lZDtcbiAgY29uc3QgYWJhbmRvbmVkID0gbmV3IFByb21pc2U8bmV2ZXI+KChfLCByZWplY3QpID0+IHtcbiAgICBjb250cm9sbGVyLnNpZ25hbC5hZGRFdmVudExpc3RlbmVyKCdhYm9ydCcsICgpID0+IHJlamVjdChhYmFuZG9ubWVudCksIHsgb25jZTogdHJ1ZSB9KTtcbiAgfSk7XG4gIGFiYW5kb25lZC5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuXG4gIGNvbnN0IGFiYW5kb24gPSAoZXJyb3I6IEh0dHBFcnJvcikgPT4ge1xuICAgIGlmICghYWJhbmRvbm1lbnQpIHtcbiAgICAgIGFiYW5kb25tZW50ID0gZXJyb3I7XG4gICAgICBjb250cm9sbGVyLmFib3J0KCk7XG4gICAgfVxuICB9O1xuICBjb25zdCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4gYWJhbmRvbihuZXcgUmVxdWVzdFRpbWVvdXRFcnJvcigpKSwgQVBJX1JFUVVFU1RfVElNRU9VVF9NUyk7XG4gIGNvbnN0IGNhbmNlbCA9ICgpID0+IGFiYW5kb24obmV3IFJlcXVlc3RDYW5jZWxsZWRFcnJvcigpKTtcbiAgaWYgKGNhbGxlclNpZ25hbD8uYWJvcnRlZCkge1xuICAgIGNhbmNlbCgpO1xuICB9IGVsc2Uge1xuICAgIGNhbGxlclNpZ25hbD8uYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCBjYW5jZWwsIHsgb25jZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHJ1bih7XG4gICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgcmFjZTogKHByb21pc2UpID0+IFByb21pc2UucmFjZShbcHJvbWlzZSwgYWJhbmRvbmVkXSksXG4gICAgICBnZXQgYWJhbmRvbm1lbnQoKSB7XG4gICAgICAgIHJldHVybiBhYmFuZG9ubWVudDtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH0gZmluYWxseSB7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICBjYWxsZXJTaWduYWw/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Fib3J0JywgY2FuY2VsKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBidWlsZFVybChhcGlCYXNlVXJsOiBzdHJpbmcsIHBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGJhc2VVcmwgPSBhcGlCYXNlVXJsLnJlcGxhY2UoL1xcXFwvKyQvLCAnJyk7XG4gIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gcGF0aC5zdGFydHNXaXRoKCcvJykgPyBwYXRoIDogXFxgL1xcJHtwYXRofVxcYDtcbiAgcmV0dXJuIFxcYFxcJHtiYXNlVXJsfVxcJHtub3JtYWxpemVkUGF0aH1cXGA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlcXVlc3QoXG4gIG1ldGhvZDogJ0dFVCcgfCAnUE9TVCcgfCAnUFVUJyxcbiAgYXBpQmFzZVVybDogc3RyaW5nLFxuICBwYXRoOiBzdHJpbmcsXG4gIGdldFRva2VuOiBUb2tlbkdldHRlcixcbiAgZGVhZGxpbmU6IERlYWRsaW5lLFxuICBib2R5OiB1bmtub3duLFxuICBvblNlc3Npb25SZWplY3RlZDogKCgpID0+IHZvaWQpIHwgdW5kZWZpbmVkLFxuKTogUHJvbWlzZTxSZXNwb25zZT4ge1xuICBsZXQgcmVzcG9uc2U6IFJlc3BvbnNlO1xuICB0cnkge1xuICAgIGNvbnN0IHRva2VuID0gYXdhaXQgZGVhZGxpbmUucmFjZShnZXRUb2tlbigpKTtcbiAgICByZXNwb25zZSA9IGF3YWl0IGZldGNoKGJ1aWxkVXJsKGFwaUJhc2VVcmwsIHBhdGgpLCB7XG4gICAgICBtZXRob2QsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIEF1dGhvcml6YXRpb246IFxcYEJlYXJlciBcXCR7dG9rZW4gPz8gJyd9XFxgLFxuICAgICAgICAuLi4oYm9keSAhPT0gdW5kZWZpbmVkID8geyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH0gOiB7fSksXG4gICAgICB9LFxuICAgICAgLi4uKGJvZHkgIT09IHVuZGVmaW5lZCA/IHsgYm9keTogSlNPTi5zdHJpbmdpZnkoYm9keSkgfSA6IHt9KSxcbiAgICAgIHNpZ25hbDogZGVhZGxpbmUuc2lnbmFsLFxuICAgIH0pO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHRocm93IGluY29tcGxldGUobWV0aG9kLCBwYXRoLCBkZWFkbGluZSwgZXJyb3IpO1xuICB9XG5cbiAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgIGNvbnN0IHBhcnNlZCA9IGF3YWl0IGRlYWRsaW5lLnJhY2UocGFyc2VFcnJvckJvZHkocmVzcG9uc2UpKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIGlmICghcGFyc2VkKSB7XG4gICAgICB0aHJvdyBpbmNvbXBsZXRlKG1ldGhvZCwgcGF0aCwgZGVhZGxpbmUsIHVuZGVmaW5lZCk7XG4gICAgfVxuICAgIGNvbnN0IHsgZXJyb3IsIG1lc3NhZ2UsIGRldGFpbHMgfSA9IHBhcnNlZDtcbiAgICBjb25zb2xlLmVycm9yKFxcYFthcGldIFxcJHttZXRob2R9IFxcJHtwYXRofSByZXNwb25kZWQgXFwke3Jlc3BvbnNlLnN0YXR1c306IFxcJHttZXNzYWdlfVxcYCk7XG4gICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDAxKSB7XG4gICAgICBvblNlc3Npb25SZWplY3RlZD8uKCk7XG4gICAgfVxuICAgIHRocm93IG5ldyBIdHRwRXJyb3IocmVzcG9uc2Uuc3RhdHVzLCBlcnJvciwgbWVzc2FnZSwgZGV0YWlscyk7XG4gIH1cblxuICByZXR1cm4gcmVzcG9uc2U7XG59XG5cbi8qKlxuICogVGhlIGVycm9yIGZvciBhIHJlcXVlc3QgdGhhdCBnb3Qgbm8gdXNhYmxlIGFuc3dlciwgbG9nZ2VkIGJlZm9yZSBpdCBpcyB0aHJvd24gc28gYSBjYWxsZXJcbiAqIHRoYXQgc3dhbGxvd3MgaXQgc3RpbGwgbGVhdmVzIGEgdHJhY2UuIEEgY2FsbGVyJ3Mgb3duIGNhbmNlbGxhdGlvbiBpcyBub3QgbG9nZ2VkLlxuICovXG5mdW5jdGlvbiBpbmNvbXBsZXRlKG1ldGhvZDogc3RyaW5nLCBwYXRoOiBzdHJpbmcsIGRlYWRsaW5lOiBEZWFkbGluZSwgY2F1c2U6IHVua25vd24pOiBIdHRwRXJyb3Ige1xuICBjb25zdCBhYmFuZG9ubWVudCA9IGRlYWRsaW5lLmFiYW5kb25tZW50O1xuICBpZiAoYWJhbmRvbm1lbnQgaW5zdGFuY2VvZiBSZXF1ZXN0Q2FuY2VsbGVkRXJyb3IpIHtcbiAgICByZXR1cm4gYWJhbmRvbm1lbnQ7XG4gIH1cbiAgaWYgKGFiYW5kb25tZW50KSB7XG4gICAgY29uc29sZS5lcnJvcihcXGBbYXBpXSBcXCR7bWV0aG9kfSBcXCR7cGF0aH0gdGltZWQgb3V0IGFmdGVyIFxcJHtBUElfUkVRVUVTVF9USU1FT1VUX01TfSBtc1xcYCk7XG4gICAgcmV0dXJuIGFiYW5kb25tZW50O1xuICB9XG4gIGNvbnN0IG1lc3NhZ2UgPSBjYXVzZSBpbnN0YW5jZW9mIEVycm9yID8gY2F1c2UubWVzc2FnZSA6ICdGYWlsZWQgdG8gcmVhY2ggdGhlIEFQSSc7XG4gIGNvbnNvbGUuZXJyb3IoXFxgW2FwaV0gXFwke21ldGhvZH0gXFwke3BhdGh9IGZhaWxlZCB0byByZWFjaCB0aGUgQVBJOiBcXCR7bWVzc2FnZX1cXGApO1xuICByZXR1cm4gbmV3IEh0dHBFcnJvcigwLCAnTmV0d29yayBFcnJvcicsIG1lc3NhZ2UpO1xufVxuXG5mdW5jdGlvbiBzZW5kPFREYXRhID0gdW5rbm93bj4oXG4gIG1ldGhvZDogJ0dFVCcgfCAnUE9TVCcgfCAnUFVUJyxcbiAgYXBpQmFzZVVybDogc3RyaW5nLFxuICBwYXRoOiBzdHJpbmcsXG4gIGdldFRva2VuOiBUb2tlbkdldHRlcixcbiAgYm9keTogdW5rbm93bixcbiAgeyBzaWduYWwsIG9uU2Vzc2lvblJlamVjdGVkIH06IFJlcXVlc3RPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPFREYXRhPiB7XG4gIHJldHVybiB3aXRoRGVhZGxpbmUoc2lnbmFsLCBhc3luYyAoZGVhZGxpbmUpID0+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHJlcXVlc3QobWV0aG9kLCBhcGlCYXNlVXJsLCBwYXRoLCBnZXRUb2tlbiwgZGVhZGxpbmUsIGJvZHksIG9uU2Vzc2lvblJlamVjdGVkKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGRlYWRsaW5lLnJhY2UocmVzcG9uc2UuanNvbigpKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGRlYWRsaW5lLmFiYW5kb25tZW50KSB7XG4gICAgICAgIHRocm93IGluY29tcGxldGUobWV0aG9kLCBwYXRoLCBkZWFkbGluZSwgZXJyb3IpO1xuICAgICAgfVxuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9KTtcbn1cblxuLyoqIEV2ZXJ5IGZpZWxkIG9mIGFuIGVycm9yIGJvZHkgb3RoZXIgdGhhbiBcXGBlcnJvclxcYCBhbmQgXFxgbWVzc2FnZVxcYC4gKi9cbmZ1bmN0aW9uIGRldGFpbHNPZihib2R5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEh0dHBFcnJvckRldGFpbHMge1xuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKE9iamVjdC5lbnRyaWVzKGJvZHkpLmZpbHRlcigoW2tleV0pID0+IGtleSAhPT0gJ2Vycm9yJyAmJiBrZXkgIT09ICdtZXNzYWdlJykpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwYXJzZUVycm9yQm9keShyZXNwb25zZTogUmVzcG9uc2UpOiBQcm9taXNlPHsgZXJyb3I6IHN0cmluZzsgbWVzc2FnZTogc3RyaW5nOyBkZXRhaWxzOiBIdHRwRXJyb3JEZXRhaWxzIH0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCBib2R5ID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIGlmIChib2R5ICYmIHR5cGVvZiBib2R5Lm1lc3NhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBlcnJvcjogdHlwZW9mIGJvZHkuZXJyb3IgPT09ICdzdHJpbmcnID8gYm9keS5lcnJvciA6IHJlc3BvbnNlLnN0YXR1c1RleHQsXG4gICAgICAgIG1lc3NhZ2U6IGJvZHkubWVzc2FnZSxcbiAgICAgICAgZGV0YWlsczogZGV0YWlsc09mKGJvZHkpLFxuICAgICAgfTtcbiAgICB9XG4gIH0gY2F0Y2gge1xuICAgIC8vIE5vdCBKU09OIChlLmcuIGEgcHJveHkncyBlcnJvciBwYWdlKTogZmFsbCB0aHJvdWdoIHRvIHRoZSBnZW5lcmljIGVycm9yIGJlbG93LlxuICB9XG4gIHJldHVybiB7IGVycm9yOiByZXNwb25zZS5zdGF0dXNUZXh0IHx8ICdFcnJvcicsIG1lc3NhZ2U6IFxcYEhUVFAgZXJyb3IhIHN0YXR1czogXFwke3Jlc3BvbnNlLnN0YXR1c31cXGAsIGRldGFpbHM6IHt9IH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXQ8VERhdGEgPSB1bmtub3duPihcbiAgYXBpQmFzZVVybDogc3RyaW5nLFxuICBwYXRoOiBzdHJpbmcsXG4gIGdldFRva2VuOiBUb2tlbkdldHRlcixcbiAgb3B0aW9ucz86IFJlcXVlc3RPcHRpb25zLFxuKTogUHJvbWlzZTxURGF0YT4ge1xuICByZXR1cm4gc2VuZDxURGF0YT4oJ0dFVCcsIGFwaUJhc2VVcmwsIHBhdGgsIGdldFRva2VuLCB1bmRlZmluZWQsIG9wdGlvbnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcG9zdDxURGF0YSA9IHVua25vd24+KFxuICBhcGlCYXNlVXJsOiBzdHJpbmcsXG4gIHBhdGg6IHN0cmluZyxcbiAgYm9keTogdW5rbm93bixcbiAgZ2V0VG9rZW46IFRva2VuR2V0dGVyLFxuICBvcHRpb25zPzogUmVxdWVzdE9wdGlvbnMsXG4pOiBQcm9taXNlPFREYXRhPiB7XG4gIHJldHVybiBzZW5kPFREYXRhPignUE9TVCcsIGFwaUJhc2VVcmwsIHBhdGgsIGdldFRva2VuLCBib2R5LCBvcHRpb25zKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHB1dDxURGF0YSA9IHVua25vd24+KFxuICBhcGlCYXNlVXJsOiBzdHJpbmcsXG4gIHBhdGg6IHN0cmluZyxcbiAgYm9keTogdW5rbm93bixcbiAgZ2V0VG9rZW46IFRva2VuR2V0dGVyLFxuICBvcHRpb25zPzogUmVxdWVzdE9wdGlvbnMsXG4pOiBQcm9taXNlPFREYXRhPiB7XG4gIHJldHVybiBzZW5kPFREYXRhPignUFVUJywgYXBpQmFzZVVybCwgcGF0aCwgZ2V0VG9rZW4sIGJvZHksIG9wdGlvbnMpO1xufVxuYCxcbiAgICB9KTtcblxuICAgIG5ldyBTYW1wbGVGaWxlKHByb2plY3QsIGAke29wdGlvbnMuc3JjZGlyfS9oZWxwZXJzL0h0dHBFcnJvci50c2AsIHtcbiAgICAgIGNvbnRlbnRzOiBgLyoqIFRoZSBmaWVsZHMgYW4gZXJyb3IgYm9keSBjYXJyaWVzIGJleW9uZCBcXGBlcnJvclxcYCBhbmQgXFxgbWVzc2FnZVxcYC4gKi9cbmV4cG9ydCB0eXBlIEh0dHBFcnJvckRldGFpbHMgPSBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG5cbi8qKlxuICogQSBmYWlsZWQgQVBJIHJlcXVlc3Q6IHRoZSBIVFRQIHN0YXR1cyAoMCB3aGVuIHRoZSBBUEkgZ2F2ZSBubyBhbnN3ZXIpIGFuZCB0aGUgZXJyb3IgYm9keSdzXG4gKiBcXGBlcnJvclxcYCBhbmQgXFxgbWVzc2FnZVxcYCwgd2l0aCBhbnkgb3RoZXIgZmllbGRzIGl0IGNhcnJpZXMgYXMgXFxgZGV0YWlsc1xcYC5cbiAqL1xuZXhwb3J0IGNsYXNzIEh0dHBFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgc3RhdHVzOiBudW1iZXI7XG4gIGVycm9yOiBzdHJpbmc7XG4gIGRldGFpbHM6IEh0dHBFcnJvckRldGFpbHM7XG5cbiAgY29uc3RydWN0b3Ioc3RhdHVzOiBudW1iZXIsIGVycm9yOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgZGV0YWlsczogSHR0cEVycm9yRGV0YWlscyA9IHt9KSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgdGhpcy5uYW1lID0gJ0h0dHBFcnJvcic7XG4gICAgdGhpcy5zdGF0dXMgPSBzdGF0dXM7XG4gICAgdGhpcy5lcnJvciA9IGVycm9yO1xuICAgIHRoaXMuZGV0YWlscyA9IGRldGFpbHM7XG4gIH1cbn1cblxuLyoqIFRoZSBBUEkgZGlkIG5vdCBhbnN3ZXIgd2l0aGluIHRoZSBjbGllbnQncyBib3VuZC4gKi9cbmV4cG9ydCBjbGFzcyBSZXF1ZXN0VGltZW91dEVycm9yIGV4dGVuZHMgSHR0cEVycm9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoMCwgJ1RpbWVvdXQnLCAnVGhlIHNlcnZlciB0b29rIHRvbyBsb25nIHRvIHJlc3BvbmQuIFBsZWFzZSB0cnkgYWdhaW4uJyk7XG4gICAgdGhpcy5uYW1lID0gJ1JlcXVlc3RUaW1lb3V0RXJyb3InO1xuICB9XG59XG5cbi8qKiBUaGUgY2FsbGVyIGNhbmNlbGxlZCB0aGUgcmVxdWVzdCBiZWZvcmUgdGhlIEFQSSBhbnN3ZXJlZC4gKi9cbmV4cG9ydCBjbGFzcyBSZXF1ZXN0Q2FuY2VsbGVkRXJyb3IgZXh0ZW5kcyBIdHRwRXJyb3Ige1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigwLCAnQWJvcnRlZCcsICdUaGUgcmVxdWVzdCB3YXMgY2FuY2VsbGVkLicpO1xuICAgIHRoaXMubmFtZSA9ICdSZXF1ZXN0Q2FuY2VsbGVkRXJyb3InO1xuICB9XG59XG5cbi8qKiBXaGV0aGVyIFxcYGVycm9yXFxgJ3MgbWVzc2FnZSB3YXMgd3JpdHRlbiBmb3IgdGhlIHBlcnNvbiB1c2luZyB0aGUgYXBwOiBhIHJlZnVzYWwgKDR4eCkgb3IgYSB0aW1lb3V0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVXNlckZhY2luZyhlcnJvcjogdW5rbm93bik6IGVycm9yIGlzIEh0dHBFcnJvciB7XG4gIHJldHVybiBlcnJvciBpbnN0YW5jZW9mIFJlcXVlc3RUaW1lb3V0RXJyb3IgfHwgKGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yICYmIGVycm9yLnN0YXR1cyA+PSA0MDAgJiYgZXJyb3Iuc3RhdHVzIDwgNTAwKTtcbn1cbmAsXG4gICAgfSk7XG5cbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vaGVscGVycy9lcnJvcnMudHNgLCB7XG4gICAgICBjb250ZW50czogYGltcG9ydCB7IEh0dHBFcnJvciB9IGZyb20gJy4vSHR0cEVycm9yJztcblxuLyoqIEEgNXh4J3MgbWVzc2FnZSBpcyB0aGUgc2VydmVyJ3MsIG5vdCB3cml0dGVuIGZvciB0aGUgcGVyc29uIHVzaW5nIHRoZSBhcHAsIHNvIGl0IGdldHMgdGhlIGRlZmF1bHQuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RXJyb3JNZXNzYWdlKGVycm9yOiB1bmtub3duLCBkZWZhdWx0TWVzc2FnZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yICYmIGVycm9yLnN0YXR1cyA+PSA1MDApIHtcbiAgICByZXR1cm4gZGVmYXVsdE1lc3NhZ2U7XG4gIH1cbiAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyb3IubWVzc2FnZSkge1xuICAgIHJldHVybiBlcnJvci5tZXNzYWdlO1xuICB9XG4gIHJldHVybiBkZWZhdWx0TWVzc2FnZTtcbn1cbmAsXG4gICAgfSk7XG5cbiAgICBuZXcgU2FtcGxlRmlsZShwcm9qZWN0LCBgJHtvcHRpb25zLnNyY2Rpcn0vaGVscGVycy9yZXRyeS50c2AsIHtcbiAgICAgIGNvbnRlbnRzOiBgaW1wb3J0IHsgSHR0cEVycm9yLCBSZXF1ZXN0Q2FuY2VsbGVkRXJyb3IgfSBmcm9tICcuL0h0dHBFcnJvcic7XG5cbi8qKiBSZWFjdCBRdWVyeSdzIG93biBkZWZhdWx0OiB0aHJlZSByZXRyaWVzIGFmdGVyIHRoZSBmaXJzdCBmYWlsdXJlLiAqL1xuY29uc3QgTUFYX1JFVFJJRVMgPSAzO1xuXG4vKipcbiAqIEEgcXVlcnkgXFxgcmV0cnlcXGAgdGhhdCBuZXZlciByZXRyaWVzIGEgNDAxLCBiZWNhdXNlIHRoZSBBUEkgd2lsbCByZWplY3QgdGhlIHNhbWUgdG9rZW4gYWdhaW4uXG4gKiBFdmVyeXRoaW5nIGVsc2UgZ2V0cyBSZWFjdCBRdWVyeSdzIGRlZmF1bHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXRyeVVubGVzc1JlamVjdGVkKGZhaWx1cmVDb3VudDogbnVtYmVyLCBlcnJvcjogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBIdHRwRXJyb3IgJiYgZXJyb3Iuc3RhdHVzID09PSA0MDEpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIGZhaWx1cmVDb3VudCA8IE1BWF9SRVRSSUVTO1xufVxuXG4vKipcbiAqIEEgZmFpbHVyZSB3b3J0aCB0cnlpbmcgYWdhaW4gdW5jaGFuZ2VkOiB0aGUgQVBJIGFuc3dlcmVkIDV4eCwgb3Igd2FzIG5vdCByZWFjaGVkIG9yIGRpZCBub3RcbiAqIGFuc3dlciBpbiB0aW1lIChzdGF0dXMgMCkuIEEgY2FuY2VsbGF0aW9uIGlzIG5vdCBvbmU6IHdob2V2ZXIgY2FuY2VsbGVkIHdhbnRzIGl0IHN0b3BwZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1RyYW5zaWVudEZhaWx1cmUoZXJyb3I6IHVua25vd24pOiBib29sZWFuIHtcbiAgcmV0dXJuIGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yICYmICEoZXJyb3IgaW5zdGFuY2VvZiBSZXF1ZXN0Q2FuY2VsbGVkRXJyb3IpICYmIChlcnJvci5zdGF0dXMgPT09IDAgfHwgZXJyb3Iuc3RhdHVzID49IDUwMCk7XG59XG5gLFxuICAgIH0pO1xuICB9XG59XG5cbmludGVyZmFjZSBQbGF5d3JpZ2h0RTJFQ29tcG9uZW50T3B0aW9ucyB7XG4gIHJlYWRvbmx5IHB1YmxpY0Rpcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIEFkZHMgUGxheXdyaWdodCBlMmUgdGVzdGluZyBzdXBwb3J0OiBkZXZEZXBzLCBhIGB0ZXN0OmUyZWAgdGFzaywgZTJlLXJlbGF0ZWRcbiAqIC5naXRpZ25vcmUgZW50cmllcywgYW5kIGEgc2NhZmZvbGRlZCAob25lLXRpbWUsIG5vdCByZWdlbmVyYXRlZCBvbiBzeW50aClcbiAqIGBwbGF5d3JpZ2h0LmNvbmZpZy50c2AgKyBgZTJlL2Agc3RhcnRlciBzdWl0ZS4gR2VuZXJhbGl6ZXMgdGhlIGhhbmQtYXV0aG9yZWRcbiAqIHN1aXRlIGFkZGVkIGluIG1hY2Vkb24tdGVjaG5vbG9naWVzL2V4bWFuIzExMiBzbyBldmVyeSBWaXRlUmVhY3RQcm9qZWN0XG4gKiBjb25zdW1lciBnZXRzIGl0IGZvciBmcmVlIChtYWNlZG9uLXRlY2hub2xvZ2llcy9wbGF0Zm9ybS1jb21tb24jOTgpLlxuICovXG5jbGFzcyBQbGF5d3JpZ2h0RTJFQ29tcG9uZW50IGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogVml0ZVJlYWN0UHJvamVjdCwgb3B0aW9uczogUGxheXdyaWdodEUyRUNvbXBvbmVudE9wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0KTtcblxuICAgIHByb2plY3QuYWRkRGV2RGVwcyhcbiAgICAgICdAcGxheXdyaWdodC90ZXN0QF4xLjYzLjAnLFxuICAgICAgJ0BjbGVyay90ZXN0aW5nQF4yLjIuMzQnLFxuICAgICAgJ0BjbGVyay9iYWNrZW5kQF4zLjE3LjInLFxuICAgICAgJ2RvdGVudkBeMTcuNC4yJyxcbiAgICApO1xuXG4gICAgcHJvamVjdC5hZGRUYXNrKCd0ZXN0OmUyZScsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnUnVuIHRoZSBQbGF5d3JpZ2h0IGUyZSBzdWl0ZSAobmVlZHMgQ0xFUktfU0VDUkVUX0tFWSBhbmQgRTJFX0NMRVJLX1VTRVJfSUQgLS0gc2VlIGUyZS9SRUFETUUubWQpJyxcbiAgICAgIGV4ZWM6ICdwbGF5d3JpZ2h0IHRlc3QnLFxuICAgIH0pO1xuXG4gICAgcHJvamVjdC5hZGRHaXRJZ25vcmUoJ3BsYXl3cmlnaHQtcmVwb3J0LycpO1xuICAgIHByb2plY3QuYWRkR2l0SWdub3JlKCd0ZXN0LXJlc3VsdHMvJyk7XG4gICAgcHJvamVjdC5hZGRHaXRJZ25vcmUoJ2Jsb2ItcmVwb3J0LycpO1xuICAgIC8vIGAqLmxvY2FsYCAoYWRkZWQgZWxzZXdoZXJlKSBhbHJlYWR5IGNvdmVycyBgLmVudi5sb2NhbGAsIGJ1dCBub3QgYSBwbGFpbiBgLmVudmAgLS1cbiAgICAvLyBleGFjdGx5IHdoZXJlIENMRVJLX1NFQ1JFVF9LRVkgKGEgcmVhbCBzZWNyZXQpIGlzIGRvY3VtZW50ZWQgdG8gZ28gKGUyZS9SRUFETUUubWQpLlxuICAgIHByb2plY3QuYWRkR2l0SWdub3JlKCcuZW52Jyk7XG5cbiAgICBuZXcgUGxheXdyaWdodENvbmZpZ0ZpbGUocHJvamVjdCk7XG4gICAgbmV3IEUyRUdsb2JhbFNldHVwRmlsZShwcm9qZWN0LCBvcHRpb25zKTtcbiAgICBuZXcgRTJFQ2xlcmtTaWduSW5GaWxlKHByb2plY3QpO1xuICAgIG5ldyBFMkVMaXZlSGVscGVyRmlsZShwcm9qZWN0KTtcbiAgICBuZXcgRTJFU21va2VTcGVjRmlsZShwcm9qZWN0KTtcbiAgICBuZXcgRTJFUmVhZG1lRmlsZShwcm9qZWN0KTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgdGhlIHBsYXl3cmlnaHQuY29uZmlnLnRzIGZpbGUuIEEgYFNhbXBsZUZpbGVgLCBub3QgYSBtYW5hZ2VkIGBGaWxlQmFzZWAgLS1cbiAqIGNvbnN1bWVycyBuZWVkIHRvIGN1c3RvbWl6ZSB0aGlzIChlLmcuIGV4bWFuJ3Mgb3duIGNvbmZpZyBuZWVkZWQgYSBsaXZlL3N0dWJcbiAqIGJyYW5jaCksIHRoZSBzYW1lIHJlYXNvbiBWaXRlUmVhY3RQcm9qZWN0J3MgQXBwLnRzeC9tYWluLnRzeCBhcmUgU2FtcGxlRmlsZXMgdG9vLlxuICovXG5jbGFzcyBQbGF5d3JpZ2h0Q29uZmlnRmlsZSBleHRlbmRzIFNhbXBsZUZpbGUge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBWaXRlUmVhY3RQcm9qZWN0KSB7XG4gICAgc3VwZXIocHJvamVjdCwgJ3BsYXl3cmlnaHQuY29uZmlnLnRzJywge1xuICAgICAgY29udGVudHM6IGBpbXBvcnQgeyBjb25maWcgYXMgbG9hZERvdGVudiB9IGZyb20gJ2RvdGVudidcbmltcG9ydCB7IGRlZmluZUNvbmZpZywgZGV2aWNlcyB9IGZyb20gJ0BwbGF5d3JpZ2h0L3Rlc3QnXG5pbXBvcnQgeyBpc0xpdmVSdW4gfSBmcm9tICcuL2UyZS9zdXBwb3J0L2xpdmUnXG5cbi8vIExvYWRlZCBoZXJlLCBmaXJzdCwgcmF0aGVyIHRoYW4gbGVmdCB0byBAY2xlcmsvdGVzdGluZydzIG93biBpbnRlcm5hbCBkb3RlbnYgY2FsbFxuLy8gaW5zaWRlIGdsb2JhbC1zZXR1cC50czogdGhhdCBjYWxsIHJ1bnMgaW5zaWRlIGdsb2JhbFNldHVwLCB3aGljaCBleGVjdXRlcyBBRlRFUlxuLy8gUGxheXdyaWdodCBoYXMgYWxyZWFkeSBjb2xsZWN0ZWQgZXZlcnkgc3BlYyBmaWxlIGFuZCBydW4gdGhlaXIgbW9kdWxlLWxldmVsIGNvZGUgLS1cbi8vIHNvIGFueXRoaW5nIHJlYWRpbmcgcHJvY2Vzcy5lbnYgYmVmb3JlIHRoZW4gd291bGQgb25seSBldmVyIHNlZSBhIC5lbnYgZmlsZSdzIHZhbHVlc1xuLy8gYXMgdW5zZXQuIExvYWRpbmcgaXQgaGVyZSwgYXQgdGhlIHRvcCBvZiB0aGUgY29uZmlnIGZpbGUgUGxheXdyaWdodCByZWFkcyBiZWZvcmVcbi8vIGFueXRoaW5nIGVsc2UsIG1lYW5zIGl0J3MgcG9wdWxhdGVkIGZvciBjb2xsZWN0aW9uLCBnbG9iYWxTZXR1cCwgYW5kIGV2ZXJ5IHRlc3QuXG5sb2FkRG90ZW52KClcblxuLy8gU2V0IEUyRV9CQVNFX1VSTCB0byBydW4gYWdhaW5zdCBhIHJlYWwgZGVwbG95bWVudCAoZS5nLiBhIFBSJ3MgcHItZGVwbG95IFdlYnNpdGVVcmwpXG4vLyBpbnN0ZWFkIG9mIGEgbG9jYWwgZGV2IHNlcnZlciAtLSBzZWUgZTJlL3N1cHBvcnQvbGl2ZS50cyBhbmQgZTJlL1JFQURNRS5tZC5cbi8vIFxcYHx8IHVuZGVmaW5lZFxcYCwgbm90IFxcYD8/XFxgOiBhbiBlbXB0eSBzdHJpbmcgKGUuZy4gYW4gdW5zZXQgR2l0SHViIEFjdGlvbnMgb3V0cHV0KSBpc1xuLy8gbm90IG51bGwvdW5kZWZpbmVkLCBzbyA/PyB3b3VsZCBsZWF2ZSBiYXNlVVJMIGFzICcnIHdoaWxlIGlzTGl2ZVJ1bigpJ3MgcGxhaW4gISFcbi8vIGNoZWNrIHN0aWxsIHJlYWQgdGhlIHJ1biBhcyBub24tbGl2ZSAtLSBhbiBpbnZhbGlkLCBzaWxlbnRseS1taXNtYXRjaGVkIGNvbmZpZy5cbmNvbnN0IGxpdmVCYXNlVXJsID0gcHJvY2Vzcy5lbnYuRTJFX0JBU0VfVVJMIHx8IHVuZGVmaW5lZFxuXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xuICB0ZXN0RGlyOiAnLi9lMmUnLFxuICBmdWxseVBhcmFsbGVsOiBmYWxzZSxcbiAgZm9yYmlkT25seTogISFwcm9jZXNzLmVudi5DSSxcbiAgcmV0cmllczogcHJvY2Vzcy5lbnYuQ0kgPyAxIDogMCxcbiAgcmVwb3J0ZXI6IHByb2Nlc3MuZW52LkNJID8gW1snaHRtbCcsIHsgb3BlbjogJ25ldmVyJyB9XV0gOiAnbGlzdCcsXG4gIGdsb2JhbFNldHVwOiAnLi9lMmUvc3VwcG9ydC9nbG9iYWwtc2V0dXAudHMnLFxuICB1c2U6IHtcbiAgICBiYXNlVVJMOiBsaXZlQmFzZVVybCA/PyAnaHR0cDovL2xvY2FsaG9zdDo1MTczJyxcbiAgICB0cmFjZTogJ29uLWZpcnN0LXJldHJ5JyxcbiAgfSxcbiAgcHJvamVjdHM6IFtcbiAgICB7IG5hbWU6ICdjaHJvbWl1bScsIHVzZTogeyAuLi5kZXZpY2VzWydEZXNrdG9wIENocm9tZSddIH0gfSxcbiAgXSxcbiAgLy8gTm8gbG9jYWwgc2VydmVyIHRvIG1hbmFnZSB3aGVuIHBvaW50ZWQgYXQgYSBsaXZlIGRlcGxveW1lbnQuXG4gIHdlYlNlcnZlcjogaXNMaXZlUnVuKCkgPyB1bmRlZmluZWQgOiB7XG4gICAgY29tbWFuZDogJyR7cnVuU2NyaXB0Q29tbWFuZChwcm9qZWN0LnBhY2thZ2UucGFja2FnZU1hbmFnZXIsICdkZXYnKX0nLFxuICAgIHVybDogJ2h0dHA6Ly9sb2NhbGhvc3Q6NTE3MycsXG4gICAgcmV1c2VFeGlzdGluZ1NlcnZlcjogIXByb2Nlc3MuZW52LkNJLFxuICAgIHRpbWVvdXQ6IDYwXzAwMCxcbiAgfSxcbn0pXG5gLFxuICAgIH0pO1xuICB9XG59XG5cbmludGVyZmFjZSBFMkVHbG9iYWxTZXR1cEZpbGVPcHRpb25zIHtcbiAgcmVhZG9ubHkgcHVibGljRGlyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBlMmUvc3VwcG9ydC9nbG9iYWwtc2V0dXAudHMsIHdoaWNoIHByaW1lcyBAY2xlcmsvdGVzdGluZyBmb3IgdGhlIHNpZ24taW5cbiAqIGZsb3cgaW4gY2xlcmstc2lnbi1pbi50cy4gUmVhZHMgdGhlIENsZXJrIHB1Ymxpc2hhYmxlIGtleSBmcm9tIHRoZSBzY2FmZm9sZGVkXG4gKiBwdWJsaWMvY29uZmlnLmpzb24gKENvbmZpZ0pzb25GaWxlKSByYXRoZXIgdGhhbiBoYXJkY29kaW5nIG9uZSAtLSBWaXRlUmVhY3RQcm9qZWN0J3NcbiAqIG93biBhcHAgZmV0Y2hlcyB0aGF0IGtleSBhdCBydW50aW1lIHRoZSBzYW1lIHdheSAoc2VlIGNvbmZpZy50cyksIHNvIHRoZXJlJ3Mgbm9cbiAqIGJ1aWxkLXRpbWUgY29uc3RhbnQgdGhpcyBjb25zdHJ1Y3QgY291bGQgZW1iZWQgaW5zdGVhZC5cbiAqL1xuY2xhc3MgRTJFR2xvYmFsU2V0dXBGaWxlIGV4dGVuZHMgU2FtcGxlRmlsZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFZpdGVSZWFjdFByb2plY3QsIG9wdGlvbnM6IEUyRUdsb2JhbFNldHVwRmlsZU9wdGlvbnMpIHtcbiAgICBzdXBlcihwcm9qZWN0LCAnZTJlL3N1cHBvcnQvZ2xvYmFsLXNldHVwLnRzJywge1xuICAgICAgY29udGVudHM6IGBpbXBvcnQgeyByZWFkRmlsZVN5bmMgfSBmcm9tICdmcydcbmltcG9ydCB7IGNsZXJrU2V0dXAgfSBmcm9tICdAY2xlcmsvdGVzdGluZy9wbGF5d3JpZ2h0J1xuXG4vLyBBIG5vLW9wIChub3QgYSB0aHJvdykgd2hlbiBDTEVSS19TRUNSRVRfS0VZIGlzIG1pc3Npbmc6IGV2ZXJ5IHNwZWMgdGhhdCBuZWVkcyBhXG4vLyBzaWduZWQtaW4gdXNlciBhbHJlYWR5IHNraXBzIGl0c2VsZiBpbiB0aGF0IGNhc2UgKHNlZSAuLi9zbW9rZS5zcGVjLnRzKSwgc28gcnVubmluZ1xuLy8gdGhlIHN1aXRlIHdpdGhvdXQgc2VjcmV0cyBjb25maWd1cmVkIHlldCByZXBvcnRzIFwic2tpcHBlZFwiLCBub3QgYSBjcmFzaGVkIGdsb2JhbFxuLy8gc2V0dXAuIFNlZSBlMmUvUkVBRE1FLm1kIGZvciBob3cgdG8gZ2V0IGEgc2VjcmV0IGtleS5cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIGdsb2JhbFNldHVwKCkge1xuICBpZiAoIXByb2Nlc3MuZW52LkNMRVJLX1NFQ1JFVF9LRVkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIC8vIGltcG9ydC5tZXRhLnVybCwgbm90IF9fZGlybmFtZTogdGhlIHdlYiBwYWNrYWdlIHNldHMgXCJ0eXBlXCI6IFwibW9kdWxlXCIgKFZpdGVDb21wb25lbnQpLFxuICAvLyBzbyB0aGlzIGZpbGUgcnVucyBhcyBFU00sIHdoZXJlIF9fZGlybmFtZSBpc24ndCBkZWZpbmVkLiBmcy5yZWFkRmlsZVN5bmMgYWNjZXB0cyBhIFVSTFxuICAvLyBkaXJlY3RseSwgc28gbm8gbmVlZCB0byBjb252ZXJ0IGl0IHRvIGEgcGF0aCBmaXJzdC5cbiAgY29uc3QgY29uZmlnUGF0aCA9IG5ldyBVUkwoJy4uLy4uLyR7b3B0aW9ucy5wdWJsaWNEaXJ9L2NvbmZpZy5qc29uJywgaW1wb3J0Lm1ldGEudXJsKVxuICBjb25zdCB7IGNsZXJrUHVibGlzaGFibGVLZXkgfSA9IEpTT04ucGFyc2UocmVhZEZpbGVTeW5jKGNvbmZpZ1BhdGgsICd1dGYtOCcpKVxuXG4gIGF3YWl0IGNsZXJrU2V0dXAoeyBwdWJsaXNoYWJsZUtleTogY2xlcmtQdWJsaXNoYWJsZUtleSB9KVxufVxuYCxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgZTJlL3N1cHBvcnQvY2xlcmstc2lnbi1pbi50cy4gU2lnbnMgaW4gYXMgYSBzcGVjaWZpYyBDbGVyayB1c2VyIGJ5IGlkIHZpYSBhXG4gKiBiYWNrZW5kLWlzc3VlZCBzaWduLWluIHRva2VuICh0aWNrZXQgc3RyYXRlZ3kpLCBieXBhc3NpbmcgdGhlIGFwcCdzIGFjdHVhbCBzaWduLWluXG4gKiBVSSAtLSB3aGljaCB0eXBpY2FsbHkgb25seSBleHBvc2VzIGFuIE9BdXRoIHByb3ZpZGVyIGJ1dHRvbiB0aGF0IGNhbid0IGJlIGRyaXZlblxuICogcmVsaWFibHkgZnJvbSBhIHRlc3QuIEBjbGVyay90ZXN0aW5nL3BsYXl3cmlnaHQncyBvd24gYGNsZXJrLnNpZ25Jbih7IGVtYWlsQWRkcmVzcyB9KWBcbiAqIGRvZXMgdGhlIHNhbWUgdGlja2V0IGV4Y2hhbmdlIGludGVybmFsbHkgYWZ0ZXIgYW4gZXh0cmEgZW1haWwtPnVzZXIgbG9va3VwOyBnb2luZ1xuICogZnJvbSBhIHVzZXIgaWQgZGlyZWN0bHkgKEUyRV9DTEVSS19VU0VSX0lEKSBza2lwcyB0aGF0IGxvb2t1cCBhbmQgaXRzIGZhaWx1cmUgbW9kZVxuICogKGFuIGV4aXN0aW5nIHVzZXIgd2l0aG91dCBhIHZlcmlmaWVkIGVtYWlsIGF0dGFjaGVkKS5cbiAqL1xuY2xhc3MgRTJFQ2xlcmtTaWduSW5GaWxlIGV4dGVuZHMgU2FtcGxlRmlsZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFZpdGVSZWFjdFByb2plY3QpIHtcbiAgICBzdXBlcihwcm9qZWN0LCAnZTJlL3N1cHBvcnQvY2xlcmstc2lnbi1pbi50cycsIHtcbiAgICAgIGNvbnRlbnRzOiBgaW1wb3J0IHsgY3JlYXRlQ2xlcmtDbGllbnQgfSBmcm9tICdAY2xlcmsvYmFja2VuZCdcbmltcG9ydCB7IGNsZXJrIH0gZnJvbSAnQGNsZXJrL3Rlc3RpbmcvcGxheXdyaWdodCdcbmltcG9ydCB0eXBlIHsgUGFnZSB9IGZyb20gJ0BwbGF5d3JpZ2h0L3Rlc3QnXG5cbi8qKlxuICogU2lnbnMgaW4gYXMgYSBzcGVjaWZpYyBDbGVyayB1c2VyIGJ5IGlkLiBSZXF1aXJlcyBDTEVSS19TRUNSRVRfS0VZIChhbHNvIHVzZWQgYnlcbiAqIGdsb2JhbC1zZXR1cC50cykgYW5kIGEgcHJpb3IgcGFnZS5nb3RvKCkgdG8gYSBwYWdlIHRoYXQgbG9hZHMgQ2xlcmsuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzaWduSW5Bc1VzZXIocGFnZTogUGFnZSwgdXNlcklkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY2xlcmtDbGllbnQgPSBjcmVhdGVDbGVya0NsaWVudCh7IHNlY3JldEtleTogcHJvY2Vzcy5lbnYuQ0xFUktfU0VDUkVUX0tFWSB9KVxuICBjb25zdCB7IHRva2VuIH0gPSBhd2FpdCBjbGVya0NsaWVudC5zaWduSW5Ub2tlbnMuY3JlYXRlU2lnbkluVG9rZW4oe1xuICAgIHVzZXJJZCxcbiAgICBleHBpcmVzSW5TZWNvbmRzOiAzMDAsXG4gIH0pXG4gIGF3YWl0IGNsZXJrLnNpZ25Jbih7IHBhZ2UsIHNpZ25JblBhcmFtczogeyBzdHJhdGVneTogJ3RpY2tldCcsIHRpY2tldDogdG9rZW4gfSB9KVxufVxuYCxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgZTJlL3N1cHBvcnQvbGl2ZS50cy5cbiAqL1xuY2xhc3MgRTJFTGl2ZUhlbHBlckZpbGUgZXh0ZW5kcyBTYW1wbGVGaWxlIHtcbiAgY29uc3RydWN0b3IocHJvamVjdDogVml0ZVJlYWN0UHJvamVjdCkge1xuICAgIHN1cGVyKHByb2plY3QsICdlMmUvc3VwcG9ydC9saXZlLnRzJywge1xuICAgICAgY29udGVudHM6IGAvKipcbiAqIFRydWUgd2hlbiB0aGlzIHJ1biB0YXJnZXRzIGEgcmVhbCBkZXBsb3ltZW50IChFMkVfQkFTRV9VUkwgc2V0IC0tIHNlZVxuICogcGxheXdyaWdodC5jb25maWcudHMpIHJhdGhlciB0aGFuIGEgbG9jYWwgZGV2IHNlcnZlci4gU3BlY3MgcmVhZCB0aGlzIHRvIGRlY2lkZVxuICogd2hldGhlciB0byBzdHViIHRoZSBiYWNrZW5kOiBhIGxpdmUgcnVuIG11c3QgaGl0IHRoZSByZWFsIEFQSSB0byBwcm92ZSBhbnl0aGluZyxcbiAqIGFuZCBzdHViYmluZyBpdCB3b3VsZCBqdXN0IGJlIHRlc3RpbmcgdGhlIHN0dWIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0xpdmVSdW4oKTogYm9vbGVhbiB7XG4gIHJldHVybiAhIXByb2Nlc3MuZW52LkUyRV9CQVNFX1VSTFxufVxuYCxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIENyZWF0ZXMgZTJlL3Ntb2tlLnNwZWMudHMgLS0gYSBnZW5lcmljIHN0YXJ0ZXIgdGVzdCB0aGF0IG9ubHkgcmVsaWVzIG9uIG1hcmt1cFxuICogVml0ZVJlYWN0UHJvamVjdCdzIG93biBzY2FmZm9sZGVkIG1haW4udHN4L0FwcC50c3ggYWx3YXlzIHJlbmRlciAoU2lnbmVkSW4vXG4gKiBVc2VyQnV0dG9uKSwgc28gaXQgd29ya3MgYmVmb3JlIGEgY29uc3VtZXIgaGFzIHdyaXR0ZW4gYW55IHJlYWwgcGFnZXMuIENvbnN1bWVyc1xuICogYXJlIGV4cGVjdGVkIHRvIGV4dGVuZC9yZXBsYWNlIHRoaXMgd2l0aCByZWFsIGZsb3dzLCB0aGUgc2FtZSB3YXkgdGhleSBhbHJlYWR5XG4gKiBjdXN0b21pemUgQXBwLnRzeC5cbiAqL1xuY2xhc3MgRTJFU21va2VTcGVjRmlsZSBleHRlbmRzIFNhbXBsZUZpbGUge1xuICBjb25zdHJ1Y3Rvcihwcm9qZWN0OiBWaXRlUmVhY3RQcm9qZWN0KSB7XG4gICAgc3VwZXIocHJvamVjdCwgJ2UyZS9zbW9rZS5zcGVjLnRzJywge1xuICAgICAgY29udGVudHM6IGBpbXBvcnQgeyB0ZXN0LCBleHBlY3QgfSBmcm9tICdAcGxheXdyaWdodC90ZXN0J1xuaW1wb3J0IHsgc2lnbkluQXNVc2VyIH0gZnJvbSAnLi9zdXBwb3J0L2NsZXJrLXNpZ24taW4nXG5cbnRlc3QoJ3NpZ25zIGluIGFuZCBzaG93cyB0aGUgYXV0aGVudGljYXRlZCBVc2VyQnV0dG9uJywgYXN5bmMgKHsgcGFnZSB9KSA9PiB7XG4gIC8vIFJlYWQgZnJvbSBpbnNpZGUgdGhlIHRlc3QgYm9keSwgbm90IG1vZHVsZSBzY29wZTogUGxheXdyaWdodCBjb2xsZWN0cyAocmVxdWlyZXMpXG4gIC8vIHRoaXMgZmlsZSBiZWZvcmUgcnVubmluZyBnbG9iYWxTZXR1cCwgc28gYSBtb2R1bGUtbGV2ZWwgY2hlY2sgd291bGQgYWx3YXlzIHNlZSBhXG4gIC8vIC5lbnYtc291cmNlZCB2YWx1ZSBhcyB1bnNldC4gRXhwb3J0aW5nIHRoZSB2YXIgaW4gdGhlIHNoZWxsIHdvcmtzIGVpdGhlciB3YXkuXG4gIGNvbnN0IHRlc3RVc2VySWQgPSBwcm9jZXNzLmVudi5FMkVfQ0xFUktfVVNFUl9JRFxuICB0ZXN0LnNraXAoXG4gICAgIXRlc3RVc2VySWQgfHwgIXByb2Nlc3MuZW52LkNMRVJLX1NFQ1JFVF9LRVksXG4gICAgJ0UyRV9DTEVSS19VU0VSX0lEIGFuZCBDTEVSS19TRUNSRVRfS0VZIG11c3QgYm90aCBiZSBzZXQgLS0gc2VlIGUyZS9SRUFETUUubWQnLFxuICApXG5cbiAgLy8gc2lnbkluQXNVc2VyIHJlcXVpcmVzIGEgcHJpb3IgcGFnZS5nb3RvKCkgdG8gYSBwYWdlIHRoYXQgbG9hZHMgQ2xlcmsuXG4gIGF3YWl0IHBhZ2UuZ290bygnLycpXG4gIGF3YWl0IHNpZ25JbkFzVXNlcihwYWdlLCB0ZXN0VXNlcklkISlcbiAgYXdhaXQgcGFnZS5nb3RvKCcvJylcblxuICAvLyAnLmNsLXVzZXJCdXR0b25UcmlnZ2VyJyBpcyBvbmUgb2YgQ2xlcmsncyBvd24gZG9jdW1lbnRlZCwgc3RhYmxlIFxcYGNsLVxcYC1wcmVmaXhlZFxuICAvLyBjbGFzcyBob29rcyAocGFydCBvZiBpdHMgdGhlbWluZy9hcHBlYXJhbmNlIEFQSSksIG5vdCBhbiBpbmNpZGVudGFsIERPTSBkZXRhaWwgLS1cbiAgLy8gc2FmZXIgdG8gZGVwZW5kIG9uIGFjcm9zcyBDbGVyayB2ZXJzaW9ucyB0aGFuIGFwcC1zcGVjaWZpYyBtYXJrdXAgdGhpcyBjb25zdHJ1Y3RcbiAgLy8gZG9lc24ndCBjb250cm9sLlxuICBhd2FpdCBleHBlY3QocGFnZS5sb2NhdG9yKCcuY2wtdXNlckJ1dHRvblRyaWdnZXInKSkudG9CZVZpc2libGUoKVxufSlcbmAsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBDcmVhdGVzIGUyZS9SRUFETUUubWQgZG9jdW1lbnRpbmcgdGhlIG9uZS10aW1lIHNldHVwIGFuZCBlbnYgdmFyIGNvbnZlbnRpb24gZXZlcnlcbiAqIGNvbnN1bWVyIG5lZWRzLCBzbyBpdCBkb2Vzbid0IGhhdmUgdG8gYmUgcmUtZGVyaXZlZCBieSBoYW5kIHBlciByZXBvLlxuICovXG5jbGFzcyBFMkVSZWFkbWVGaWxlIGV4dGVuZHMgU2FtcGxlRmlsZSB7XG4gIGNvbnN0cnVjdG9yKHByb2plY3Q6IFZpdGVSZWFjdFByb2plY3QpIHtcbiAgICBjb25zdCB0ZXN0RTJlQ29tbWFuZCA9IHJ1blNjcmlwdENvbW1hbmQocHJvamVjdC5wYWNrYWdlLnBhY2thZ2VNYW5hZ2VyLCAndGVzdDplMmUnKTtcbiAgICBzdXBlcihwcm9qZWN0LCAnZTJlL1JFQURNRS5tZCcsIHtcbiAgICAgIGNvbnRlbnRzOiBgIyBQbGF5d3JpZ2h0IGUyZSBzdWl0ZVxuXG5SdW5zIGFnYWluc3QgYSByZWFsIGRldiBzZXJ2ZXIgKG9yIGEgbGl2ZSBkZXBsb3ltZW50LCB2aWEgXFxgRTJFX0JBU0VfVVJMXFxgKSBhbmQgcmVhbFxuQ2xlcmsgYXV0aGVudGljYXRpb24uXG5cbiMjIE9uZS10aW1lIHNldHVwXG5cbjEuIEluc3RhbGwgUGxheXdyaWdodCdzIGJyb3dzZXIgYmluYXJ5IChub3QgY292ZXJlZCBieSBhIHBsYWluIGRlcGVuZGVuY3kgaW5zdGFsbCk6XG5cbiAgIFxcYFxcYFxcYGJhc2hcbiAgIG5weCBwbGF5d3JpZ2h0IGluc3RhbGwgY2hyb21pdW1cbiAgIFxcYFxcYFxcYFxuXG4yLiBHZXQgdHdvIHZhbHVlcyBmcm9tIHlvdXIgQ2xlcmsgZGFzaGJvYXJkJ3MgZGV2IGluc3RhbmNlOlxuXG4gICAtIFxcYENMRVJLX1NFQ1JFVF9LRVlcXGAgLS0gdGhlICoqc2VjcmV0Kioga2V5IChBUEkgS2V5cykuIE5ldmVyIGNvbW1pdCB0aGlzOyBleHBvcnQgaXRcbiAgICAgaW4geW91ciBzaGVsbCBvciBwdXQgaXQgaW4gYSBsb2NhbCwgZ2l0aWdub3JlZCBcXGAuZW52XFxgLlxuICAgLSBcXGBFMkVfQ0xFUktfVVNFUl9JRFxcYCAtLSB0aGUgaWQgKFxcYHVzZXJfLi4uXFxgKSBvZiBhbiBleGlzdGluZyB0ZXN0IHVzZXIgKFVzZXJzIC0+IGNsaWNrXG4gICAgIGEgdXNlciwgdGhlIGlkIGlzIHNob3duIGF0IHRoZSB0b3ApLiBUaGUgdXNlciBuZWVkcyBhIHZlcmlmaWVkIGVtYWlsIGFkZHJlc3MsIG5vdFxuICAgICBqdXN0IGFuIE9BdXRoIGNvbm5lY3Rpb24gLS0gYSBzaWduLWluIHRva2VuIGhhcyB0byBiaW5kIHRvIGEgdmVyaWZpZWRcbiAgICAgaWRlbnRpZmljYXRpb24uIENyZWF0aW5nIGEgZGVkaWNhdGVkIHRlc3QgdXNlciB3aXRoIGFuIGVtYWlsIHNldCBleHBsaWNpdGx5IGlzIHRoZVxuICAgICBzYWZlciBkZWZhdWx0LlxuXG4gICBBIHJ1biB3aXRoIGVpdGhlciB2YXJpYWJsZSB1bnNldCAqKnNraXBzKiogcmF0aGVyIHRoYW4gZmFpbGluZywgc28gXFxgJHt0ZXN0RTJlQ29tbWFuZH1cXGBcbiAgIGlzIGFsd2F5cyBzYWZlIHRvIHJ1biB3aXRob3V0IHRoZW0uXG5cbjMuIFRoaXMgY29uc3RydWN0IGRvZXNuJ3QgbWFuYWdlIFxcYHZpdGVzdC5jb25maWcudHNcXGAgKGl0J3MgYSBoYW5kLWF1dGhvcmVkLFxuICAgcGVyLWNvbnN1bWVyIGZpbGUpLiBBZGQgYW4gXFxgZXhjbHVkZVxcYCBlbnRyeSBzbyB2aXRlc3QncyBkZWZhdWx0IHRlc3QgZ2xvYiBkb2Vzbid0XG4gICBhbHNvIHRyeSB0byBwaWNrIHVwIHRoZXNlIFBsYXl3cmlnaHQgc3BlYyBmaWxlczpcblxuICAgXFxgXFxgXFxgdHNcbiAgIGltcG9ydCB7IGRlZmluZUNvbmZpZywgY29uZmlnRGVmYXVsdHMgfSBmcm9tICd2aXRlc3QvY29uZmlnJ1xuXG4gICBleHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoe1xuICAgICB0ZXN0OiB7XG4gICAgICAgZXhjbHVkZTogWy4uLmNvbmZpZ0RlZmF1bHRzLmV4Y2x1ZGUsICdlMmUvKionXSxcbiAgICAgICAvLyAuLi55b3VyIGV4aXN0aW5nIGNvbmZpZ1xuICAgICB9LFxuICAgfSlcbiAgIFxcYFxcYFxcYFxuXG4jIyBSdW5uaW5nXG5cblxcYFxcYFxcYGJhc2hcbkNMRVJLX1NFQ1JFVF9LRVk9Li4uIEUyRV9DTEVSS19VU0VSX0lEPS4uLiAke3Rlc3RFMmVDb21tYW5kfVxuXFxgXFxgXFxgXG5cbiMjIFJ1bm5pbmcgYWdhaW5zdCBhIGxpdmUgZW52aXJvbm1lbnRcblxuU2V0IFxcYEUyRV9CQVNFX1VSTFxcYCB0byBwb2ludCB0aGUgc3VpdGUgYXQgYSByZWFsIGRlcGxveW1lbnQgKGEgcGVyc29uYWwgZGV2IHN0YWNrLCBvciBhXG5QUidzIHByLWRlcGxveSBcXGBXZWJzaXRlVXJsXFxgLCBwb3N0ZWQgYXMgYSBQUiBjb21tZW50KSBpbnN0ZWFkIG9mIGEgbG9jYWwgZGV2IHNlcnZlcjpcblxuXFxgXFxgXFxgYmFzaFxuRTJFX0JBU0VfVVJMPWh0dHBzOi8vPHlvdXItc3RhY2s+LmV4YW1wbGUuY29tIFxcXFxcbkNMRVJLX1NFQ1JFVF9LRVk9Li4uIEUyRV9DTEVSS19VU0VSX0lEPS4uLiBcXFxcXG4ke3Rlc3RFMmVDb21tYW5kfVxuXFxgXFxgXFxgXG5cbiMjIENJXG5cblRoZSBnZW5lcmF0ZWQgXFxgcHItZGVwbG95LnltbFxcYCB3b3JrZmxvdyAoc2VlIFxcYFByRGVwbG95V29ya2Zsb3dcXGApIGFscmVhZHkgcnVucyB0aGlzXG5zdWl0ZSBhZ2FpbnN0IGVhY2ggUFIncyBkZXBsb3llZCBcXGBXZWJzaXRlVXJsXFxgIGFuZCB1cGxvYWRzIHRoZSBIVE1MIHJlcG9ydCBhcyBhIGJ1aWxkXG5hcnRpZmFjdCBvbiBmYWlsdXJlLiBJdCBzZWxmLXNraXBzIGV4YWN0bHkgbGlrZSBhIGxvY2FsIHJ1biB1bnRpbCBib3RoIHNlY3JldHMgZXhpc3RcbmluIHRoZSByZXBvOlxuXG5cXGBcXGBcXGBiYXNoXG5naCBzZWNyZXQgc2V0IENMRVJLX1NFQ1JFVF9LRVlcbmdoIHNlY3JldCBzZXQgRTJFX0NMRVJLX1VTRVJfSURcblxcYFxcYFxcYFxuYCxcbiAgICB9KTtcbiAgfVxufVxuIl19
|