@macedon-technologies/batman 1.27.0 → 1.29.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.
@@ -295,23 +295,82 @@ ${baseConfigType}
295
295
 
296
296
  ${configTypeDefinition}
297
297
 
298
- export function useConfig() {
299
- const [loadedConfig, setLoadedConfig] = useState<Config|undefined>();
300
- const [isLoading, setIsLoading] = useState(false);
298
+ let shared: Promise<Config> | undefined;
299
+ let loaded: Config | undefined;
301
300
 
302
- useEffect(() => {
303
- if (!loadedConfig) {
304
- fetch('/config.json', { cache: 'no-store' }).then(response=>{
305
- response.json().then((config) => {
306
- setIsLoading(false)
307
- setLoadedConfig(config)
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 { useBaseQuery } from "./services/BaseService.ts";
499
+ import { useApiQuery } from "./services/ApiService.ts";
441
500
 
442
501
 
443
502
  function App() {
444
- const {data, isLoading} = useBaseQuery('/', {retryOnMount: true});
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
- // Create BaseService.ts
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVml0ZVJlYWN0UHJvamVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9WaXRlUmVhY3RQcm9qZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtCQUEwQztBQUMxQyxtQ0FBc0Y7QUFDdEYsc0RBQXVGO0FBRXZGLG1DQUEyQztBQW1DM0M7O0dBRUc7QUFDSCxNQUFhLGdCQUFpQixTQUFRLGlDQUFvQjtJQUN4QyxNQUFNLENBQVM7SUFDZixTQUFTLENBQVM7SUFDbEIsVUFBVSxDQUFTO0lBQ2xCLFlBQVksQ0FBc0I7SUFFbkQsWUFBWSxPQUFnQztRQUMxQyxNQUFNLEVBQ0osVUFBVSxHQUFHLElBQUksRUFDakIsTUFBTSxHQUFHLEtBQUssRUFDZCxTQUFTLEdBQUcsUUFBUSxFQUNwQixLQUFLLEVBQ0wsVUFBVSxHQUFHLElBQUksRUFDakIsR0FBRyxXQUFXLEVBQ2YsR0FBRyxPQUFPLENBQUM7UUFDWixLQUFLLENBQUM7WUFDSixHQUFHLFdBQVc7WUFDZCxVQUFVLEVBQUUsS0FBSyxFQUFFLHFDQUFxQztZQUN4RCxNQUFNLEVBQUUsS0FBSyxFQUFFLG1DQUFtQztZQUNsRCxJQUFJLEVBQUUsS0FBSyxFQUFFLDZCQUE2QjtZQUMxQyxPQUFPLEVBQUUsSUFBSTtZQUNiLGVBQWUsRUFBRSxJQUFJLEVBQUUsa0NBQWtDO1lBQ3pELGNBQWMsRUFBRyxXQUFXLENBQUMsTUFBd0IsQ0FBQyxPQUFPLENBQUMsY0FBYztZQUM1RSxXQUFXLEVBQUU7Z0JBQ1gsb0JBQW9CLEVBQUU7b0JBQ3BCLHVFQUF1RTtvQkFDdkUsc0VBQXNFO29CQUN0RSxvRUFBb0U7b0JBQ3BFLCtEQUErRDtvQkFDL0QsV0FBVyxFQUFFO3dCQUNYLFNBQVMsRUFBRSxJQUFJO3dCQUNmLGVBQWUsRUFBRSxJQUFJO3FCQUN0QjtvQkFDRCxHQUFHLFdBQVcsQ0FBQyxXQUFXLEVBQUUsb0JBQW9CO2lCQUNqRDthQUNGO1lBQ0QsSUFBSSxFQUFFO2dCQUNKLG9C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QyxPQUFPLEVBQUUsZUFBZSxFQUFFO1lBQzlCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7MEVBdUIwRCxjQUFjOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7NkNBcUIzQyxjQUFjOzs7Ozs7Ozs7OztFQVd6RCxjQUFjOzs7Ozs7Ozs7Ozs7OztDQWNmO1NBQ0ksQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmVsYXRpdmUsIGJhc2VuYW1lIH0gZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBDb21wb25lbnQsIEZpbGVCYXNlLCBKc29uRmlsZSwgUHJvamVjdCwgU2FtcGxlRmlsZSwgVGV4dEZpbGUgfSBmcm9tICdwcm9qZW4nO1xuaW1wb3J0IHsgVHlwZVNjcmlwdEFwcFByb2plY3QsIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyB9IGZyb20gJ3Byb2plbi9saWIvdHlwZXNjcmlwdCc7XG5pbXBvcnQgeyBCYXRtYW5Qcm9qZWN0IH0gZnJvbSAnLi9CYXRtYW5Qcm9qZWN0JztcbmltcG9ydCB7IHJ1blNjcmlwdENvbW1hbmQgfSBmcm9tICcuL3V0aWxzJztcblxuZXhwb3J0IGludGVyZmFjZSBWaXRlUmVhY3RQcm9qZWN0T3B0aW9ucyBleHRlbmRzIFR5cGVTY3JpcHRQcm9qZWN0T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGdlbmVyYXRlIHNhbXBsZSBjb2RlXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHNhbXBsZUNvZGU/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