Files
speckle-server/scratch/edge-debug-selection/Default/Cache/Cache_Data/f_000045
T

452 lines
48 KiB
Plaintext

import { buildManualPromise, ensureError, throwUncoveredError } from "/_nuxt/@fs/D:/speckle-server/packages/shared/dist/esm/index.js";
import { useServerFileUploadLimit } from "/_nuxt/lib/common/composables/serverInfo.ts";
import { importFileLegacy } from "/_nuxt/lib/core/api/fileImport.ts";
import { useAuthCookie } from "/_nuxt/lib/auth/composables/auth.ts";
import { BlobUploadStatus } from "/_nuxt/lib/core/api/blobStorage.ts";
import { useMixpanel } from "/_nuxt/lib/core/composables/mp.ts";
import { graphql } from "/_nuxt/lib/common/generated/gql/index.ts";
import {
useIsNextGenFileImporterEnabled,
useIsRhinoFileImporterEnabled
} from "/_nuxt/composables/globals.ts";
import {
rhinoImporterSupportedFileExtensions,
FileUploadConvertedStatus
} from "/_nuxt/@fs/D:/speckle-server/packages/shared/dist/esm/blobs/index.js";
import { useApolloClient } from "/_nuxt/node_modules/@vue/apollo-composable/dist/index.mjs?v=e4f18c29";
import {
FileTooLargeError,
ForbiddenFileTypeError,
generateFileId,
MissingFileExtensionError,
prettyFileSize,
resolveFileExtension
} from "/_nuxt/@fs/D:/speckle-server/packages/ui-components/dist/lib.js";
import __vite__cjsImport11_dayjs from "/_nuxt/node_modules/.cache/vite/client/deps/dayjs.js?v=e4f18c29"; const dayjs = __vite__cjsImport11_dayjs.__esModule ? __vite__cjsImport11_dayjs.default : __vite__cjsImport11_dayjs;
import { trimEnd, uniqBy } from "/_nuxt/node_modules/.cache/vite/client/deps/lodash-es.js?v=e4f18c29";
import { useState } from "/_nuxt/node_modules/nuxt/dist/app/composables/state.js?v=e4f18c29";
import { computed, ref, unref } from "/_nuxt/node_modules/vue/dist/vue.runtime.esm-bundler.js?v=e4f18c29";
import { useRuntimeConfig } from "/_nuxt/node_modules/nuxt/dist/app/nuxt.js?v=e4f18c29";
import { getFirstGqlErrorMessage } from "/_nuxt/utils/globals.ts";
import { useLogger } from "/_nuxt/composables/logging.ts";
import { useApiOrigin } from "/_nuxt/composables/env.ts";
export const FailedFileImportJobError = {
InvalidFileType: "InvalidFileType",
MissingFileExtensionError: "MissingFileExtensionError",
FileTooLarge: "FileTooLarge",
UploadFailed: "UploadFailed",
ImportFailed: "ImportFailed"
};
graphql(`
fragment UseFailedFileImportJobUtils_FileUpload on FileUpload {
id
fileName
projectId
modelId
updatedAt
convertedStatus
convertedMessage
}
`);
export const useFailedFileImportJobUtils = () => {
const { maxSizeInBytes, accept } = useFileImportBaseSettings();
const convertUploadToFailedJob = (upload) => {
if (upload.convertedStatus !== FileUploadConvertedStatus.Error) {
throw new Error("Cannot convert upload to failed job if it is not in error state");
}
return {
id: upload.id,
projectId: upload.projectId,
modelId: upload.modelId || null,
fileName: upload.fileName,
date: dayjs(upload.updatedAt).toDate(),
error: {
type: FailedFileImportJobError.ImportFailed,
message: upload.convertedMessage || "An unknown error occurred during file import"
}
};
};
const getErrorMessage = (job) => {
switch (job.error.type) {
case FailedFileImportJobError.FileTooLarge: {
let base = `The file is too large to be uploaded. The maximum file size is ${prettyFileSize(
maxSizeInBytes.value
)}`;
if (job.file) {
base += ` while the file you tried to upload is ${prettyFileSize(
job.file.size
)}.`;
} else {
base += ".";
}
return base;
}
case FailedFileImportJobError.MissingFileExtensionError:
return `The file you tried to upload does not have a valid file extension.`;
case FailedFileImportJobError.InvalidFileType: {
const fileExtension = resolveFileExtension(job.fileName);
return `The file you tried to upload (${fileExtension}) is not a supported file type. Only ${accept.value} are supported by this server.`;
}
case FailedFileImportJobError.ImportFailed:
return trimEnd(job.error.message, ".") + ".";
case FailedFileImportJobError.UploadFailed: {
const base = `The file upload failed unexpectedly.`;
return base;
}
default:
throwUncoveredError(job.error.type);
}
};
return {
convertUploadToFailedJob,
getErrorMessage
};
};
export const useGlobalFileImportManager = () => {
const state = useState(
"global_file_import_manager",
() => ({
failedJobs: [],
activeUploads: []
})
);
const addFailedJob = (job) => {
state.value.failedJobs = uniqBy([...state.value.failedJobs, job], (job2) => job2.id);
};
const clearFailedJobs = () => {
state.value.failedJobs = [];
};
const registerActiveUpload = (uploadId) => {
if (!state.value.activeUploads.includes(uploadId)) {
state.value.activeUploads = [...state.value.activeUploads, uploadId];
}
};
const unregisterActiveUpload = (uploadId) => {
state.value.activeUploads = state.value.activeUploads.filter(
(id) => id !== uploadId
);
};
const unregisterAllActiveUploads = () => {
state.value.activeUploads = [];
};
const hasActiveUploads = computed(() => {
return state.value.activeUploads.length > 0;
});
const failedJobs = computed(() => state.value.failedJobs);
return {
registerActiveUpload,
unregisterActiveUpload,
unregisterAllActiveUploads,
hasActiveUploads,
addFailedJob,
clearFailedJobs,
failedJobs
};
};
const generateUploadUrlMutation = graphql(`
mutation GenerateUploadUrl($input: GenerateFileUploadUrlInput!) {
fileUploadMutations {
generateUploadUrl(input: $input) {
url
fileId
}
}
}
`);
const startFileImportMutation = graphql(`
mutation StartFileImport($input: StartFileImportInput!) {
fileUploadMutations {
startFileImport(input: $input) {
id
}
}
}
`);
export const useFileImportApi = () => {
const {
public: { FF_LEGACY_FILE_IMPORTS_ENABLED }
} = useRuntimeConfig();
const apollo = useApolloClient().client;
const { registerActiveUpload, unregisterActiveUpload } = useGlobalFileImportManager();
const importFileV2 = async (params, callbacks) => {
const { file, projectId, modelId } = params;
const { onProgress } = callbacks || {};
const generateUploadUrlResponse = await apollo.mutate({
mutation: generateUploadUrlMutation,
variables: {
input: {
projectId,
fileName: file.name
}
}
});
const generateUploadUrl = generateUploadUrlResponse.data?.fileUploadMutations.generateUploadUrl;
if (!generateUploadUrl) {
const errMsg = getFirstGqlErrorMessage(
generateUploadUrlResponse.errors,
"Couldn't generate upload URL"
);
throw new Error(errMsg);
}
const { url: uploadUrl, fileId } = generateUploadUrl;
const request = new XMLHttpRequest();
const uploadPromise = buildManualPromise();
request.open("PUT", uploadUrl);
request.setRequestHeader("Content-Type", file.type);
request.upload.addEventListener("progress", (e) => {
const percentage = e.loaded / e.total * 100;
onProgress?.(percentage);
});
const handleResponse = () => {
const statusCode = request.status;
if (statusCode >= 200 && statusCode < 300) {
const etag2 = request.getResponseHeader("ETag");
if (!etag2) {
return uploadPromise.reject(new Error("No ETag in upload response"));
}
return uploadPromise.resolve({ etag: etag2 });
} else {
const errorMessage = request.responseText.match(
/<Message>(.*?)<\/Message>/
)?.[1];
return uploadPromise.reject(
new Error(errorMessage || `Upload failed unexpectedly`)
);
}
};
request.addEventListener("load", () => handleResponse());
request.addEventListener("error", () => handleResponse());
request.send(file);
const { etag } = await uploadPromise.promise;
const startFileImportResponse = await apollo.mutate({
mutation: startFileImportMutation,
variables: {
input: {
projectId,
fileId,
etag,
modelId
}
}
});
const fileImportStarted = startFileImportResponse.data?.fileUploadMutations.startFileImport.id;
if (!fileImportStarted) {
const errMsg = getFirstGqlErrorMessage(
startFileImportResponse.errors,
"Couldn't start file import"
);
throw new Error(errMsg);
}
const res = {
fileName: file.name,
fileSize: file.size,
formKey: "file",
uploadStatus: BlobUploadStatus.Completed,
uploadError: ""
};
return res;
};
const importFile = async (...args) => {
const resolveUploadId = () => {
const params = args[0];
const fileId = generateFileId(params.file);
return JSON.stringify({
fileId,
projectId: params.projectId,
modelId: params.modelId,
modelName: params.modelName
});
};
const uploadId = resolveUploadId();
try {
registerActiveUpload(uploadId);
return await (FF_LEGACY_FILE_IMPORTS_ENABLED ? importFileLegacy : importFileV2)(
...args
);
} finally {
unregisterActiveUpload(uploadId);
}
};
return {
importFile
};
};
graphql(`
fragment UseFileImport_Project on Project {
id
}
`);
graphql(`
fragment UseFileImport_Model on Model {
id
name
}
`);
export const useFileImportBaseSettings = () => {
const { maxSizeInBytes } = useServerFileUploadLimit();
const isNextGenFileImporterEnabled = useIsNextGenFileImporterEnabled();
const isRhinoFileImportEnabled = useIsRhinoFileImporterEnabled();
const legacyFileImportService = ".ifc,.obj,.stl";
const nextGenBackgroundJobs = `.ifc,${isRhinoFileImportEnabled.value ? [...rhinoImporterSupportedFileExtensions].map((ext) => `.${ext}`).join(",") : ""}`;
const accept = computed(
() => isNextGenFileImporterEnabled.value ? nextGenBackgroundJobs : legacyFileImportService
);
return { maxSizeInBytes, accept };
};
export function useFileImport(params) {
const {
project,
model,
manuallyTriggerUpload,
fileUploadedCallback,
fileSelectedCallback,
errorCallback
} = params;
const { maxSizeInBytes, accept } = useFileImportBaseSettings();
const logger = useLogger();
const { importFile } = useFileImportApi();
const authToken = useAuthCookie();
const apiOrigin = useApiOrigin();
const upload = ref(
null
);
const isUploading = ref(false);
const isUploadable = computed(() => {
if (!upload.value) return false;
if (upload.value.error) return false;
if (upload.value.result) return false;
if (isUploading.value) return false;
if (!authToken.value) return false;
if (!upload.value.file) return false;
return true;
});
const mp = useMixpanel();
const handleError = () => {
if (!errorCallback || !upload.value) return;
let error = void 0;
if (upload.value.error) {
if (upload.value.error instanceof FileTooLargeError) {
error = {
type: FailedFileImportJobError.FileTooLarge,
message: upload.value.error.message
};
} else if (upload.value.error instanceof MissingFileExtensionError) {
error = {
type: FailedFileImportJobError.MissingFileExtensionError,
message: upload.value.error.message
};
} else if (upload.value.error instanceof ForbiddenFileTypeError) {
error = {
type: FailedFileImportJobError.InvalidFileType,
message: upload.value.error.message
};
}
} else if (upload.value.result?.uploadError) {
error = {
type: FailedFileImportJobError.UploadFailed,
message: upload.value.result.uploadError
};
}
if (!error) {
error = {
type: FailedFileImportJobError.UploadFailed,
message: "An unknown error occurred during file upload"
};
}
const failedJob = {
id: upload.value.id,
fileName: upload.value.file.name,
projectId: unref(project).id,
modelId: upload.value.model?.id || null,
error,
date: /* @__PURE__ */ new Date()
};
logger[upload.value.result?.uploadError ? "error" : "warn"](
{
failedJob
},
"File import failed"
);
errorCallback({ failedJob });
};
const uploadSelected = async (params2) => {
if (!isUploadable.value || !upload.value || !authToken.value) return;
if (params2?.model) {
upload.value.model = params2.model;
}
isUploading.value = true;
try {
if (!upload.value.model) {
throw new Error("No model provided for file import");
}
const res = await importFile(
{
file: upload.value.file,
projectId: unref(project).id,
modelName: upload.value.model.name,
modelId: upload.value.model.id,
authToken: authToken.value,
apiOrigin
},
{
onProgress: (percentage) => {
if (upload.value) upload.value.progress = percentage;
}
}
);
upload.value.result = res;
mp.track("Upload Action", {
type: "action",
name: "create",
source: "model card"
});
fileUploadedCallback?.(upload.value);
} catch (e) {
upload.value.result = {
uploadStatus: BlobUploadStatus.Error,
uploadError: ensureError(e).message,
formKey: "file"
};
handleError();
} finally {
upload.value.progress = 100;
isUploading.value = false;
}
};
const resetSelected = () => {
if (isUploading.value) return;
upload.value = null;
};
const onFilesSelected = async (params2) => {
if (isUploading.value || !authToken.value) return;
const file = params2.files[0];
if (!file) return;
upload.value = {
...file,
result: void 0,
progress: 0,
model: unref(model) || null
};
if (file.error) {
handleError();
return;
}
fileSelectedCallback?.();
if (!manuallyTriggerUpload) {
await uploadSelected();
}
};
return {
maxSizeInBytes,
onFilesSelected,
accept,
upload,
isUploading,
uploadSelected,
resetSelected,
isUploadable
};
}
//# sourceMappingURL=data:application/json;base64,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XSwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsiZmlsZUltcG9ydC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IE1heWJlUmVmIH0gZnJvbSAnQHZ1ZXVzZS9jb3JlJ1xyXG5pbXBvcnQgeyBidWlsZE1hbnVhbFByb21pc2UsIGVuc3VyZUVycm9yLCB0aHJvd1VuY292ZXJlZEVycm9yIH0gZnJvbSAnQHNwZWNrbGUvc2hhcmVkJ1xyXG5pbXBvcnQgdHlwZSB7IE1heWJlTnVsbE9yVW5kZWZpbmVkLCBOdWxsYWJsZSwgT3B0aW9uYWwgfSBmcm9tICdAc3BlY2tsZS9zaGFyZWQnXHJcbmltcG9ydCB7IHVzZVNlcnZlckZpbGVVcGxvYWRMaW1pdCB9IGZyb20gJ35+L2xpYi9jb21tb24vY29tcG9zYWJsZXMvc2VydmVySW5mbydcclxuaW1wb3J0IHR5cGUge1xyXG4gIFVwbG9hZGFibGVGaWxlSXRlbSxcclxuICBVcGxvYWRGaWxlSXRlbVxyXG59IGZyb20gJ35+L2xpYi9mb3JtL2NvbXBvc2FibGVzL2ZpbGVVcGxvYWQnXHJcbmltcG9ydCB7IGltcG9ydEZpbGVMZWdhY3ksIHR5cGUgSW1wb3J0RmlsZSB9IGZyb20gJ35+L2xpYi9jb3JlL2FwaS9maWxlSW1wb3J0J1xyXG5pbXBvcnQgeyB1c2VBdXRoQ29va2llIH0gZnJvbSAnfn4vbGliL2F1dGgvY29tcG9zYWJsZXMvYXV0aCdcclxuaW1wb3J0IHsgQmxvYlVwbG9hZFN0YXR1cywgdHlwZSBCbG9iUG9zdFJlc3VsdEl0ZW0gfSBmcm9tICd+fi9saWIvY29yZS9hcGkvYmxvYlN0b3JhZ2UnXHJcbmltcG9ydCB7IHVzZU1peHBhbmVsIH0gZnJvbSAnfn4vbGliL2NvcmUvY29tcG9zYWJsZXMvbXAnXHJcbmltcG9ydCB7IGdyYXBocWwgfSBmcm9tICd+L2xpYi9jb21tb24vZ2VuZXJhdGVkL2dxbCdcclxuaW1wb3J0IHtcclxuICB1c2VJc05leHRHZW5GaWxlSW1wb3J0ZXJFbmFibGVkLFxyXG4gIHVzZUlzUmhpbm9GaWxlSW1wb3J0ZXJFbmFibGVkXHJcbn0gZnJvbSAnfi9jb21wb3NhYmxlcy9nbG9iYWxzJ1xyXG5pbXBvcnQge1xyXG4gIHJoaW5vSW1wb3J0ZXJTdXBwb3J0ZWRGaWxlRXh0ZW5zaW9ucyxcclxuICBGaWxlVXBsb2FkQ29udmVydGVkU3RhdHVzXHJcbn0gZnJvbSAnQHNwZWNrbGUvc2hhcmVkL2Jsb2JzJ1xyXG5pbXBvcnQgdHlwZSB7XHJcbiAgVXNlRmFpbGVkRmlsZUltcG9ydEpvYlV0aWxzX0ZpbGVVcGxvYWRGcmFnbWVudCxcclxuICBVc2VGaWxlSW1wb3J0X01vZGVsRnJhZ21lbnQsXHJcbiAgVXNlRmlsZUltcG9ydF9Qcm9qZWN0RnJhZ21lbnRcclxufSBmcm9tICd+L2xpYi9jb21tb24vZ2VuZXJhdGVkL2dxbC9ncmFwaHFsJ1xyXG5pbXBvcnQgeyB1c2VBcG9sbG9DbGllbnQgfSBmcm9tICdAdnVlL2Fwb2xsby1jb21wb3NhYmxlJ1xyXG5pbXBvcnQge1xyXG4gIEZpbGVUb29MYXJnZUVycm9yLFxyXG4gIEZvcmJpZGRlbkZpbGVUeXBlRXJyb3IsXHJcbiAgZ2VuZXJhdGVGaWxlSWQsXHJcbiAgTWlzc2luZ0ZpbGVFeHRlbnNpb25FcnJvcixcclxuICBwcmV0dHlGaWxlU2l6ZSxcclxuICByZXNvbHZlRmlsZUV4dGVuc2lvblxyXG59IGZyb20gJ0BzcGVja2xlL3VpLWNvbXBvbmVudHMnXHJcbmltcG9ydCBkYXlqcyBmcm9tICdkYXlqcydcclxuaW1wb3J0IHsgdHJpbUVuZCwgdW5pcUJ5IH0gZnJvbSAnbG9kYXNoLWVzJ1xyXG5cclxuZXhwb3J0IGNvbnN0IEZhaWxlZEZpbGVJbXBvcnRKb2JFcnJvciA9IDxjb25zdD57XHJcbiAgSW52YWxpZEZpbGVUeXBlOiAnSW52YWxpZEZpbGVUeXBlJyxcclxuICBNaXNzaW5nRmlsZUV4dGVuc2lvbkVycm9yOiAnTWlzc2luZ0ZpbGVFeHRlbnNpb25FcnJvcicsXHJcbiAgRmlsZVRvb0xhcmdlOiAnRmlsZVRvb0xhcmdlJyxcclxuICBVcGxvYWRGYWlsZWQ6ICdVcGxvYWRGYWlsZWQnLFxyXG4gIEltcG9ydEZhaWxlZDogJ0ltcG9ydEZhaWxlZCdcclxufVxyXG5cclxuZXhwb3J0IHR5cGUgRmFpbGVkRmlsZUltcG9ydEpvYkVycm9yID1cclxuICAodHlwZW9mIEZhaWxlZEZpbGVJbXBvcnRKb2JFcnJvcilba2V5b2YgdHlwZW9mIEZhaWxlZEZpbGVJbXBvcnRKb2JFcnJvcl1cclxuXHJcbmV4cG9ydCB0eXBlIEZhaWxlZEZpbGVJbXBvcnRKb2IgPSB7XHJcbiAgaWQ6IHN0cmluZ1xyXG4gIGZpbGVOYW1lOiBzdHJpbmdcclxuICBwcm9qZWN0SWQ6IHN0cmluZ1xyXG4gIGZpbGU/OiBGaWxlIC8vIG9ubHkgYXZhaWxhYmxlIGlmIGpvYiBmYWlsZWQgYmVmb3JlIHVwbG9hZCBzdGFydGVkXHJcbiAgbW9kZWxJZDogc3RyaW5nIHwgbnVsbCAvLyBudWxsIGlmIGVycm9yIG9jY3VycmVkIGJlZm9yZSBtb2RlbCB3YXMgY3JlYXRlZFxyXG4gIGVycm9yOiB7IHR5cGU6IEZhaWxlZEZpbGVJbXBvcnRKb2JFcnJvcjsgbWVzc2FnZTogc3RyaW5nIH1cclxuICBkYXRlOiBEYXRlXHJcbn1cclxuXHJcbnR5cGUgR2xvYmFsRmlsZUltcG9ydE1hbmFnZXJTdGF0ZSA9IHtcclxuICBmYWlsZWRKb2JzOiBGYWlsZWRGaWxlSW1wb3J0Sm9iW11cclxuICBhY3RpdmVVcGxvYWRzOiBzdHJpbmdbXVxyXG59XHJcblxyXG5ncmFwaHFsKGBcclxuICBmcmFnbWVudCBVc2VGYWlsZWRGaWxlSW1wb3J0Sm9iVXRpbHNfRmlsZVVwbG9hZCBvbiBGaWxlVXBsb2FkIHtcclxuICAgIGlkXHJcbiAgICBmaWxlTmFtZVxyXG4gICAgcHJvamVjdElkXHJcbiAgICBtb2RlbElkXHJcbiAgICB1cGRhdGVkQXRcclxuICAgIGNvbnZlcnRlZFN0YXR1c1xyXG4gICAgY29udmVydGVkTWVzc2FnZVxyXG4gIH1cclxuYClcclxuXHJcbmV4cG9ydCBjb25zdCB1c2VGYWlsZWRGaWxlSW1wb3J0Sm9iVXRpbHMgPSAoKSA9PiB7XHJcbiAgY29uc3QgeyBtYXhTaXplSW5CeXRlcywgYWNjZXB0IH0gPSB1c2VGaWxlSW1wb3J0QmFzZVNldHRpbmdzKClcclxuXHJcbiAgY29uc3QgY29udmVydFVwbG9hZFRvRmFpbGVkSm9iID0gKFxyXG4gICAgdXBsb2FkOiBVc2VGYWlsZWRGaWxlSW1wb3J0Sm9iVXRpbHNfRmlsZVVwbG9hZEZyYWdtZW50XHJcbiAgKTogRmFpbGVkRmlsZUltcG9ydEpvYiA9PiB7XHJcbiAgICBpZiAodXBsb2FkLmNvbnZlcnRlZFN0YXR1cyAhPT0gRmlsZVVwbG9hZENvbnZlcnRlZFN0YXR1cy5FcnJvcikge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IHVwbG9hZCB0byBmYWlsZWQgam9iIGlmIGl0IGlzIG5vdCBpbiBlcnJvciBzdGF0ZScpXHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHtcclxuICAgICAgaWQ6IHVwbG9hZC5pZCxcclxuICAgICAgcHJvamVjdElkOiB1cGxvYWQucHJvamVjdElkLFxyXG4gICAgICBtb2RlbElkOiB1cGxvYWQubW9kZWxJZCB8fCBudWxsLFxyXG4gICAgICBmaWxlTmFtZTogdXBsb2FkLmZpbGVOYW1lLFxyXG4gICAgICBkYXRlOiBkYXlqcyh1cGxvYWQudXBkYXRlZEF0KS50b0RhdGUoKSxcclxuICAgICAgZXJyb3I6IHtcclxuICAgICAgICB0eXBlOiBGYWlsZWRGaWxlSW1wb3J0Sm9iRXJyb3IuSW1wb3J0RmFpbGVkLFxyXG4gICAgICAgIG1lc3NhZ2U6XHJcbiAgICAgICAgICB1cGxvYWQuY29udmVydGVkTWVzc2FnZSB8fCAnQW4gdW5rbm93biBlcnJvciBvY2N1cnJlZCBkdXJpbmcgZmlsZSBpbXBvcnQnXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IGdldEVycm9yTWVzc2FnZSA9IChqb2I6IEZhaWxlZEZpbGVJbXBvcnRKb2IpID0+IHtcclxuICAgIHN3aXRjaCAoam9iLmVycm9yLnR5cGUpIHtcclxuICAgICAgY2FzZSBGYWlsZWRGaWxlSW1wb3J0Sm9iRXJyb3IuRmlsZVRvb0xhcmdlOiB7XHJcbiAgICAgICAgbGV0IGJhc2UgPSBgVGhlIGZpbGUgaXMgdG9vIGxhcmdlIHRvIGJlIHVwbG9hZGVkLiBUaGUgbWF4aW11bSBmaWxlIHNpemUgaXMgJHtwcmV0dHlGaWxlU2l6ZShcclxuICAgICAgICAgIG1heFNpemVJbkJ5dGVzLnZhbHVlXHJcbiAgICAgICAgKX1gXHJcblxyXG4gICAgICAgIGlmIChqb2IuZmlsZSkge1xyXG4gICAgICAgICAgYmFzZSArPSBgIHdoaWxlIHRoZSBmaWxlIHlvdSB0cmllZCB0byB1cGxvYWQgaXMgJHtwcmV0dHlGaWxlU2l6ZShcclxuICAgICAgICAgICAgam9iLmZpbGUuc2l6ZVxyXG4gICAgICAgICAgKX0uYFxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBiYXNlICs9ICcuJ1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYmFzZVxyXG4gICAgICB9XHJcbiAgICAgIGNhc2UgRmFpbGVkRmlsZUltcG9ydEpvYkVycm9yLk1pc3NpbmdGaWxlRXh0ZW5zaW9uRXJyb3I6XHJcbiAgICAgICAgcmV0dXJuIGBUaGUgZmlsZSB5b3UgdHJpZWQgdG8gdXBsb2FkIGRvZXMgbm90IGhhdmUgYSB2YWxpZCBmaWxlIGV4dGVuc2lvbi5gXHJcbiAgICAgIGNhc2UgRmFpbGVkRmlsZUltcG9ydEpvYkVycm9yLkludmFsaWRGaWxlVHlwZToge1xyXG4gICAgICAgIGNvbnN0IGZpbGVFeHRlbnNpb24gPSByZXNvbHZlRmlsZUV4dGVuc2lvbihqb2IuZmlsZU5hbWUpXHJcbiAgICAgICAgcmV0dXJuIGBUaGUgZmlsZSB5b3UgdHJpZWQgdG8gdXBsb2FkICgke2ZpbGVFeHRlbnNpb259KSBpcyBub3QgYSBzdXBwb3J0ZWQgZmlsZSB0eXBlLiBPbmx5ICR7YWNjZXB0LnZhbHVlfSBhcmUgc3VwcG9ydGVkIGJ5IHRoaXMgc2VydmVyLmBcclxuICAgICAgfVxyXG4gICAgICBjYXNlIEZhaWxlZEZpbGVJbXBvcnRKb2JFcnJvci5JbXBvcnRGYWlsZWQ6XHJcbiAgICAgICAgcmV0dXJuIHRyaW1FbmQoam9iLmVycm9yLm1lc3NhZ2UsICcuJykgKyAnLidcclxuICAgICAgY2FzZSBGYWlsZWRGaWxlSW1wb3J0Sm9iRXJyb3IuVXBsb2FkRmFpbGVkOiB7XHJcbiAgICAgICAgY29uc3QgYmFzZSA9IGBUaGUgZmlsZSB1cGxvYWQgZmFpbGVkIHVuZXhwZWN0ZWRseS5gXHJcbiAgICAgICAgcmV0dXJuIGJhc2VcclxuICAgICAgfVxyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHRocm93VW5jb3ZlcmVkRXJyb3Ioam9iLmVycm9yLnR5cGUpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgY29udmVydFVwbG9hZFRvRmFpbGVkSm9iLFxyXG4gICAgZ2V0RXJyb3JNZXNzYWdlXHJcbiAgfVxyXG59XHJcblxyXG5leHBvcnQgY29uc3QgdXNlR2xvYmFsRmlsZUltcG9ydE1hbmFnZXIgPSAoKSA9PiB7XHJcbiAgY29uc3Qgc3RhdGUgPSB1c2VTdGF0ZTxHbG9iYWxGaWxlSW1wb3J0TWFuYWdlclN0YXRlPihcclxuICAgICdnbG9iYWxfZmlsZV9pbXBvcnRfbWFuYWdlcicsXHJcbiAgICAoKSA9PiAoe1xyXG4gICAgICBmYWlsZWRKb2JzOiBbXSxcclxuICAgICAgYWN0aXZlVXBsb2FkczogW11cclxuICAgIH0pXHJcbiAgKVxyXG5cclxuICBjb25zdCBhZGRGYWlsZWRKb2IgPSAoam9iOiBGYWlsZWRGaWxlSW1wb3J0Sm9iKSA9PiB7XHJcbiAgICBzdGF0ZS52YWx1ZS5mYWlsZWRKb2JzID0gdW5pcUJ5KFsuLi5zdGF0ZS52YWx1ZS5mYWlsZWRKb2JzLCBqb2JdLCAoam9iKSA9PiBqb2IuaWQpXHJcbiAgfVxyXG5cclxuICBjb25zdCBjbGVhckZhaWxlZEpvYnMgPSAoKSA9PiB7XHJcbiAgICBzdGF0ZS52YWx1ZS5mYWlsZWRKb2JzID0gW11cclxuICB9XHJcblxyXG4gIGNvbnN0IHJlZ2lzdGVyQWN0aXZlVXBsb2FkID0gKHVwbG9hZElkOiBzdHJpbmcpID0+IHtcclxuICAgIGlmICghc3RhdGUudmFsdWUuYWN0aXZlVXBsb2Fkcy5pbmNsdWRlcyh1cGxvYWRJZCkpIHtcclxuICAgICAgc3RhdGUudmFsdWUuYWN0aXZlVXBsb2FkcyA9IFsuLi5zdGF0ZS52YWx1ZS5hY3RpdmVVcGxvYWRzLCB1cGxvYWRJZF1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IHVucmVnaXN0ZXJBY3RpdmVVcGxvYWQgPSAodXBsb2FkSWQ6IHN0cmluZykgPT4ge1xyXG4gICAgc3RhdGUudmFsdWUuYWN0aXZlVXBsb2FkcyA9IHN0YXRlLnZhbHVlLmFjdGl2ZVVwbG9hZHMuZmlsdGVyKFxyXG4gICAgICAoaWQpID0+IGlkICE9PSB1cGxvYWRJZFxyXG4gICAgKVxyXG4gIH1cclxuXHJcbiAgY29uc3QgdW5yZWdpc3RlckFsbEFjdGl2ZVVwbG9hZHMgPSAoKSA9PiB7XHJcbiAgICBzdGF0ZS52YWx1ZS5hY3RpdmVVcGxvYWRzID0gW11cclxuICB9XHJcblxyXG4gIGNvbnN0IGhhc0FjdGl2ZVVwbG9hZHMgPSBjb21wdXRlZCgoKSA9PiB7XHJcbiAgICByZXR1cm4gc3RhdGUudmFsdWUuYWN0aXZlVXBsb2Fkcy5sZW5ndGggPiAwXHJcbiAgfSlcclxuXHJcbiAgY29uc3QgZmFpbGVkSm9icyA9IGNvbXB1dGVkKCgpID0+IHN0YXRlLnZhbHVlLmZhaWxlZEpvYnMpXHJcblxyXG4gIHJldHVybiB7XHJcbiAgICByZWdpc3RlckFjdGl2ZVVwbG9hZCxcclxuICAgIHVucmVnaXN0ZXJBY3RpdmVVcGxvYWQsXHJcbiAgICB1bnJlZ2lzdGVyQWxsQWN0aXZlVXBsb2FkcyxcclxuICAgIGhhc0FjdGl2ZVVwbG9hZHMsXHJcbiAgICBhZGRGYWlsZWRKb2IsXHJcbiAgICBjbGVhckZhaWxlZEpvYnMsXHJcbiAgICBmYWlsZWRKb2JzXHJcbiAgfVxyXG59XHJcblxyXG5jb25zdCBnZW5lcmF0ZVVwbG9hZFVybE11dGF0aW9uID0gZ3JhcGhxbChgXHJcbiAgbXV0YXRpb24gR2VuZXJhdGVVcGxvYWRVcmwoJGlucHV0OiBHZW5lcmF0ZUZpbGVVcGxvYWRVcmxJbnB1dCEpIHtcclxuICAgIGZpbGVVcGxvYWRNdXRhdGlvbnMge1xyXG4gICAgICBnZW5lcmF0ZVVwbG9hZFVybChpbnB1dDogJGlucHV0KSB7XHJcbiAgICAgICAgdXJsXHJcbiAgICAgICAgZmlsZUlkXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbmApXHJcblxyXG5jb25zdCBzdGFydEZpbGVJbXBvcnRNdXRhdGlvbiA9IGdyYXBocWwoYFxyXG4gIG11dGF0aW9uIFN0YXJ0RmlsZUltcG9ydCgkaW5wdXQ6IFN0YXJ0RmlsZUltcG9ydElucHV0ISkge1xyXG4gICAgZmlsZVVwbG9hZE11dGF0aW9ucyB7XHJcbiAgICAgIHN0YXJ0RmlsZUltcG9ydChpbnB1dDogJGlucHV0KSB7XHJcbiAgICAgICAgaWRcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuYClcclxuXHJcbmV4cG9ydCBjb25zdCB1c2VGaWxlSW1wb3J0QXBpID0gKCkgPT4ge1xyXG4gIGNvbnN0IHtcclxuICAgIHB1YmxpYzogeyBGRl9MRUdBQ1lfRklMRV9JTVBPUlRTX0VOQUJMRUQgfVxyXG4gIH0gPSB1c2VSdW50aW1lQ29uZmlnKClcclxuICBjb25zdCBhcG9sbG8gPSB1c2VBcG9sbG9DbGllbnQoKS5jbGllbnRcclxuICBjb25zdCB7IHJlZ2lzdGVyQWN0aXZlVXBsb2FkLCB1bnJlZ2lzdGVyQWN0aXZlVXBsb2FkIH0gPSB1c2VHbG9iYWxGaWxlSW1wb3J0TWFuYWdlcigpXHJcblxyXG4gIGNvbnN0IGltcG9ydEZpbGVWMjogSW1wb3J0RmlsZSA9IGFzeW5jIChwYXJhbXMsIGNhbGxiYWNrcykgPT4ge1xyXG4gICAgY29uc3QgeyBmaWxlLCBwcm9qZWN0SWQsIG1vZGVsSWQgfSA9IHBhcmFtc1xyXG4gICAgY29uc3QgeyBvblByb2dyZXNzIH0gPSBjYWxsYmFja3MgfHwge31cclxuXHJcbiAgICAvLyBHZW5lcmF0ZSB1cGxvYWQgVVJMXHJcbiAgICBjb25zdCBnZW5lcmF0ZVVwbG9hZFVybFJlc3BvbnNlID0gYXdhaXQgYXBvbGxvLm11dGF0ZSh7XHJcbiAgICAgIG11dGF0aW9uOiBnZW5lcmF0ZVVwbG9hZFVybE11dGF0aW9uLFxyXG4gICAgICB2YXJpYWJsZXM6IHtcclxuICAgICAgICBpbnB1dDoge1xyXG4gICAgICAgICAgcHJvamVjdElkLFxyXG4gICAgICAgICAgZmlsZU5hbWU6IGZpbGUubmFtZVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSlcclxuXHJcbiAgICBjb25zdCBnZW5lcmF0ZVVwbG9hZFVybCA9XHJcbiAgICAgIGdlbmVyYXRlVXBsb2FkVXJsUmVzcG9uc2UuZGF0YT8uZmlsZVVwbG9hZE11dGF0aW9ucy5nZW5lcmF0ZVVwbG9hZFVybFxyXG4gICAgaWYgKCFnZW5lcmF0ZVVwbG9hZFVybCkge1xyXG4gICAgICBjb25zdCBlcnJNc2cgPSBnZXRGaXJzdEdxbEVycm9yTWVzc2FnZShcclxuICAgICAgICBnZW5lcmF0ZVVwbG9hZFVybFJlc3BvbnNlLmVycm9ycyxcclxuICAgICAgICBcIkNvdWxkbid0IGdlbmVyYXRlIHVwbG9hZCBVUkxcIlxyXG4gICAgICApXHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihlcnJNc2cpXHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgeyB1cmw6IHVwbG9hZFVybCwgZmlsZUlkIH0gPSBnZW5lcmF0ZVVwbG9hZFVybFxyXG5cclxuICAgIC8vIFVwbG9hZCB0byBTMyBjb21wYXRpYmxlIGVuZHBvaW50XHJcbiAgICBjb25zdCByZXF1ZXN0ID0gbmV3IFhNTEh0dHBSZXF1ZXN0KClcclxuICAgIGNvbnN0IHVwbG9hZFByb21pc2UgPSBidWlsZE1hbnVhbFByb21pc2U8eyBldGFnOiBzdHJpbmcgfT4oKVxyXG4gICAgcmVxdWVzdC5vcGVuKCdQVVQnLCB1cGxvYWRVcmwpXHJcbiAgICByZXF1ZXN0LnNldFJlcXVlc3RIZWFkZXIoJ0NvbnRlbnQtVHlwZScsIGZpbGUudHlwZSlcclxuXHJcbiAgICByZXF1ZXN0LnVwbG9hZC5hZGRFdmVudExpc3RlbmVyKCdwcm9ncmVzcycsIChlKSA9PiB7XHJcbiAgICAgIGNvbnN0IHBlcmNlbnRhZ2UgPSAoZS5sb2FkZWQgLyBlLnRvdGFsKSAqIDEwMFxyXG4gICAgICBvblByb2dyZXNzPy4ocGVyY2VudGFnZSlcclxuICAgIH0pXHJcblxyXG4gICAgY29uc3QgaGFuZGxlUmVzcG9uc2UgPSAoKSA9PiB7XHJcbiAgICAgIGNvbnN0IHN0YXR1c0NvZGUgPSByZXF1ZXN0LnN0YXR1c1xyXG4gICAgICBpZiAoc3RhdHVzQ29kZSA+PSAyMDAgJiYgc3RhdHVzQ29kZSA8IDMwMCkge1xyXG4gICAgICAgIC8vIENvbGxlY3QgZXRhZ1xyXG4gICAgICAgIGNvbnN0IGV0YWcgPSByZXF1ZXN0LmdldFJlc3BvbnNlSGVhZGVyKCdFVGFnJylcclxuICAgICAgICBpZiAoIWV0YWcpIHtcclxuICAgICAgICAgIHJldHVybiB1cGxvYWRQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ05vIEVUYWcgaW4gdXBsb2FkIHJlc3BvbnNlJykpXHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB1cGxvYWRQcm9taXNlLnJlc29sdmUoeyBldGFnIH0pXHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gVHJ5IHRvIHJlc29sdmUgZXJyb3IgbWVzc2FnZSBmcm9tIFhNTCByZXNwb25zZSB3LyByZWdleCAoZG9udCB3YW50IHRvIHBhcnNlIFhNTClcclxuICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPSByZXF1ZXN0LnJlc3BvbnNlVGV4dC5tYXRjaChcclxuICAgICAgICAgIC88TWVzc2FnZT4oLio/KTxcXC9NZXNzYWdlPi9cclxuICAgICAgICApPy5bMV1cclxuICAgICAgICByZXR1cm4gdXBsb2FkUHJvbWlzZS5yZWplY3QoXHJcbiAgICAgICAgICBuZXcgRXJyb3IoZXJyb3JNZXNzYWdlIHx8IGBVcGxvYWQgZmFpbGVkIHVuZXhwZWN0ZWRseWApXHJcbiAgICAgICAgKVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmVxdWVzdC5hZGRFdmVudExpc3RlbmVyKCdsb2FkJywgKCkgPT4gaGFuZGxlUmVzcG9uc2UoKSlcclxuICAgIHJlcXVlc3QuYWRkRXZlbnRMaXN0ZW5lcignZXJyb3InLCAoKSA9PiBoYW5kbGVSZXNwb25zZSgpKVxyXG4gICAgcmVxdWVzdC5zZW5kKGZpbGUpXHJcbiAgICBjb25zdCB7IGV0YWcgfSA9IGF3YWl0IHVwbG9hZFByb21pc2UucHJvbWlzZVxyXG5cclxuICAgIC8vIE5vdyBsZXRzIHN0YXJ0IHRoZSBmaWxlIGltcG9ydFxyXG4gICAgY29uc3Qgc3RhcnRGaWxlSW1wb3J0UmVzcG9uc2UgPSBhd2FpdCBhcG9sbG8ubXV0YXRlKHtcclxuICAgICAgbXV0YXRpb246IHN0YXJ0RmlsZUltcG9ydE11dGF0aW9uLFxyXG4gICAgICB2YXJpYWJsZXM6IHtcclxuICAgICAgICBpbnB1dDoge1xyXG4gICAgICAgICAgcHJvamVjdElkLFxyXG4gICAgICAgICAgZmlsZUlkLFxyXG4gICAgICAgICAgZXRhZyxcclxuICAgICAgICAgIG1vZGVsSWRcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pXHJcbiAgICBjb25zdCBmaWxlSW1wb3J0U3RhcnRlZCA9XHJcbiAgICAgIHN0YXJ0RmlsZUltcG9ydFJlc3BvbnNlLmRhdGE/LmZpbGVVcGxvYWRNdXRhdGlvbnMuc3RhcnRGaWxlSW1wb3J0LmlkXHJcbiAgICBpZiAoIWZpbGVJbXBvcnRTdGFydGVkKSB7XHJcbiAgICAgIGNvbnN0IGVyck1zZyA9IGdldEZpcnN0R3FsRXJyb3JNZXNzYWdlKFxyXG4gICAgICAgIHN0YXJ0RmlsZUltcG9ydFJlc3BvbnNlLmVycm9ycyxcclxuICAgICAgICBcIkNvdWxkbid0IHN0YXJ0IGZpbGUgaW1wb3J0XCJcclxuICAgICAgKVxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyTXNnKVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHJlczogQmxvYlBvc3RSZXN1bHRJdGVtID0ge1xyXG4gICAgICBmaWxlTmFtZTogZmlsZS5uYW1lLFxyXG4gICAgICBmaWxlU2l6ZTogZmlsZS5zaXplLFxyXG4gICAgICBmb3JtS2V5OiAnZmlsZScsXHJcbiAgICAgIHVwbG9hZFN0YXR1czogQmxvYlVwbG9hZFN0YXR1cy5Db21wbGV0ZWQsXHJcbiAgICAgIHVwbG9hZEVycm9yOiAnJ1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByZXNcclxuICB9XHJcblxyXG4gIGNvbnN0IGltcG9ydEZpbGU6IEltcG9ydEZpbGUgPSBhc3luYyAoLi4uYXJncykgPT4ge1xyXG4gICAgY29uc3QgcmVzb2x2ZVVwbG9hZElkID0gKCkgPT4ge1xyXG4gICAgICBjb25zdCBwYXJhbXMgPSBhcmdzWzBdXHJcblxyXG4gICAgICBjb25zdCBmaWxlSWQgPSBnZW5lcmF0ZUZpbGVJZChwYXJhbXMuZmlsZSlcclxuICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHtcclxuICAgICAgICBmaWxlSWQsXHJcbiAgICAgICAgcHJvamVjdElkOiBwYXJhbXMucHJvamVjdElkLFxyXG4gICAgICAgIG1vZGVsSWQ6IHBhcmFtcy5tb2RlbElkLFxyXG4gICAgICAgIG1vZGVsTmFtZTogcGFyYW1zLm1vZGVsTmFtZVxyXG4gICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHVwbG9hZElkID0gcmVzb2x2ZVVwbG9hZElkKClcclxuICAgIHRyeSB7XHJcbiAgICAgIHJlZ2lzdGVyQWN0aXZlVXBsb2FkKHVwbG9hZElkKVxyXG4gICAgICByZXR1cm4gYXdhaXQgKEZGX0xFR0FDWV9GSUxFX0lNUE9SVFNfRU5BQkxFRCA/IGltcG9ydEZpbGVMZWdhY3kgOiBpbXBvcnRGaWxlVjIpKFxyXG4gICAgICAgIC4uLmFyZ3NcclxuICAgICAgKVxyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgdW5yZWdpc3RlckFjdGl2ZVVwbG9hZCh1cGxvYWRJZClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBpbXBvcnRGaWxlXHJcbiAgfVxyXG59XHJcblxyXG5ncmFwaHFsKGBcclxuICBmcmFnbWVudCBVc2VGaWxlSW1wb3J0X1Byb2plY3Qgb24gUHJvamVjdCB7XHJcbiAgICBpZFxyXG4gIH1cclxuYClcclxuXHJcbmdyYXBocWwoYFxyXG4gIGZyYWdtZW50IFVzZUZpbGVJbXBvcnRfTW9kZWwgb24gTW9kZWwge1xyXG4gICAgaWRcclxuICAgIG5hbWVcclxuICB9XHJcbmApXHJcblxyXG5leHBvcnQgY29uc3QgdXNlRmlsZUltcG9ydEJhc2VTZXR0aW5ncyA9ICgpID0+IHtcclxuICBjb25zdCB7IG1heFNpemVJbkJ5dGVzIH0gPSB1c2VTZXJ2ZXJGaWxlVXBsb2FkTGltaXQoKVxyXG4gIGNvbnN0IGlzTmV4dEdlbkZpbGVJbXBvcnRlckVuYWJsZWQgPSB1c2VJc05leHRHZW5GaWxlSW1wb3J0ZXJFbmFibGVkKClcclxuICBjb25zdCBpc1JoaW5vRmlsZUltcG9ydEVuYWJsZWQgPSB1c2VJc1JoaW5vRmlsZUltcG9ydGVyRW5hYmxlZCgpXHJcblxyXG4gIGNvbnN0IGxlZ2FjeUZpbGVJbXBvcnRTZXJ2aWNlID0gJy5pZmMsLm9iaiwuc3RsJ1xyXG4gIGNvbnN0IG5leHRHZW5CYWNrZ3JvdW5kSm9icyA9IGAuaWZjLCR7XHJcbiAgICBpc1JoaW5vRmlsZUltcG9ydEVuYWJsZWQudmFsdWVcclxuICAgICAgPyBbLi4ucmhpbm9JbXBvcnRlclN1cHBvcnRlZEZpbGVFeHRlbnNpb25zXVxyXG4gICAgICAgICAgLm1hcCgoZXh0OiBzdHJpbmcpID0+IGAuJHtleHR9YClcclxuICAgICAgICAgIC5qb2luKCcsJylcclxuICAgICAgOiAnJ1xyXG4gIH1gXHJcblxyXG4gIGNvbnN0IGFjY2VwdCA9IGNvbXB1dGVkKCgpID0+XHJcbiAgICBpc05leHRHZW5GaWxlSW1wb3J0ZXJFbmFibGVkLnZhbHVlID8gbmV4dEdlbkJhY2tncm91bmRKb2JzIDogbGVnYWN5RmlsZUltcG9ydFNlcnZpY2VcclxuICApXHJcblxyXG4gIHJldHVybiB7IG1heFNpemVJbkJ5dGVzLCBhY2NlcHQgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gdXNlRmlsZUltcG9ydChwYXJhbXM6IHtcclxuICBwcm9qZWN0OiBNYXliZVJlZjxVc2VGaWxlSW1wb3J0X1Byb2plY3RGcmFnbWVudD5cclxuICAvKipcclxuICAgKiBNb2RlbCBzaG91bGQgZXhpc3QgaWYgdXBsb2FkIGlzIGF1dG9tYXRpY2FsbHkgdHJpZ2dlcmVkLiBPdGhlcndpc2UgeW91IG11c3Qgc3RpbGwgZmVlZCBpdCBpbiwgYnV0XHJcbiAgICogYXQgdGhlIHBvaW50IHdoZW4geW91IGNhbGwgdXBsb2FkU2VsZWN0ZWQoKS5cclxuICAgKi9cclxuICBtb2RlbD86IE1heWJlUmVmPE1heWJlTnVsbE9yVW5kZWZpbmVkPFVzZUZpbGVJbXBvcnRfTW9kZWxGcmFnbWVudD4+XHJcbiAgLyoqXHJcbiAgICogSWYgdHJ1ZSwgdGhlIHVwbG9hZCB3aWxsIGJlIHByZXBhcmVkIGFuZCB2YWxpZGF0ZWQsIGJ1dCBmb3IgaXQgdG8gc3RhcnQgeW91IG11c3QgaW52b2tlIHVwbG9hZFNlbGVjdGVkKCkgbWFudWFsbHlcclxuICAgKi9cclxuICBtYW51YWxseVRyaWdnZXJVcGxvYWQ/OiBib29sZWFuXHJcbiAgLyoqXHJcbiAgICogT3B0aW9uYWxseSBoYW5kbGUgdGhlIGZpbGUgdXBsb2FkIGNvbXBsZXRpb24gZXZlbnQuXHJcbiAgICovXHJcbiAgZmlsZVVwbG9hZGVkQ2FsbGJhY2s/OiBPcHRpb25hbDwoZmlsZTogVXBsb2FkRmlsZUl0ZW0pID0+IHZvaWQ+XHJcbiAgLyoqXHJcbiAgICogT3B0aW9uYWxseSBoYW5kbGUgdGhlIGZpbGUgc2VsZWN0aW9uIGV2ZW50LlxyXG4gICAqL1xyXG4gIGZpbGVTZWxlY3RlZENhbGxiYWNrPzogT3B0aW9uYWw8KCkgPT4gdm9pZD5cclxuICAvKipcclxuICAgKiBPcHRpb25hbGx5IGhhbmRsZSBlcnJvcnMgdGhhdCBvY2N1ciBlaXRoZXIgb24gZmlsZSBzZWxlY3Rpb24gb3IgZHVyaW5nIHVwbG9hZCAoTk9UIGR1cmluZyB0aGUgYXN5bmMgaW1wb3J0IGpvYilcclxuICAgKi9cclxuICBlcnJvckNhbGxiYWNrPzogT3B0aW9uYWw8KHBhcmFtczogeyBmYWlsZWRKb2I6IEZhaWxlZEZpbGVJbXBvcnRKb2IgfSkgPT4gdm9pZD5cclxufSkge1xyXG4gIGNvbnN0IHtcclxuICAgIHByb2plY3QsXHJcbiAgICBtb2RlbCxcclxuICAgIG1hbnVhbGx5VHJpZ2dlclVwbG9hZCxcclxuICAgIGZpbGVVcGxvYWRlZENhbGxiYWNrLFxyXG4gICAgZmlsZVNlbGVjdGVkQ2FsbGJhY2ssXHJcbiAgICBlcnJvckNhbGxiYWNrXHJcbiAgfSA9IHBhcmFtc1xyXG5cclxuICBjb25zdCB7IG1heFNpemVJbkJ5dGVzLCBhY2NlcHQgfSA9IHVzZUZpbGVJbXBvcnRCYXNlU2V0dGluZ3MoKVxyXG4gIGNvbnN0IGxvZ2dlciA9IHVzZUxvZ2dlcigpXHJcbiAgY29uc3QgeyBpbXBvcnRGaWxlIH0gPSB1c2VGaWxlSW1wb3J0QXBpKClcclxuICBjb25zdCBhdXRoVG9rZW4gPSB1c2VBdXRoQ29va2llKClcclxuICBjb25zdCBhcGlPcmlnaW4gPSB1c2VBcGlPcmlnaW4oKVxyXG5cclxuICBjb25zdCB1cGxvYWQgPSByZWYoXHJcbiAgICBudWxsIGFzIE51bGxhYmxlPFVwbG9hZEZpbGVJdGVtICYgeyBtb2RlbDogTnVsbGFibGU8VXNlRmlsZUltcG9ydF9Nb2RlbEZyYWdtZW50PiB9PlxyXG4gIClcclxuICBjb25zdCBpc1VwbG9hZGluZyA9IHJlZihmYWxzZSlcclxuXHJcbiAgY29uc3QgaXNVcGxvYWRhYmxlID0gY29tcHV0ZWQoKCkgPT4ge1xyXG4gICAgaWYgKCF1cGxvYWQudmFsdWUpIHJldHVybiBmYWxzZVxyXG4gICAgaWYgKHVwbG9hZC52YWx1ZS5lcnJvcikgcmV0dXJuIGZhbHNlXHJcbiAgICBpZiAodXBsb2FkLnZhbHVlLnJlc3VsdCkgcmV0dXJuIGZhbHNlXHJcbiAgICBpZiAoaXNVcGxvYWRpbmcudmFsdWUpIHJldHVybiBmYWxzZVxyXG4gICAgaWYgKCFhdXRoVG9rZW4udmFsdWUpIHJldHVybiBmYWxzZVxyXG4gICAgaWYgKCF1cGxvYWQudmFsdWUuZmlsZSkgcmV0dXJuIGZhbHNlXHJcbiAgICByZXR1cm4gdHJ1ZVxyXG4gIH0pXHJcblxyXG4gIGNvbnN0IG1wID0gdXNlTWl4cGFuZWwoKVxyXG5cclxuICBjb25zdCBoYW5kbGVFcnJvciA9ICgpID0+IHtcclxuICAgIGlmICghZXJyb3JDYWxsYmFjayB8fCAhdXBsb2FkLnZhbHVlKSByZXR1cm5cclxuXHJcbiAgICAvLyBGaWd1cmUgb3V0IHdoYXQgaGFwcGVuZWQgYW5kIHJlcG9ydCB0byBjYWxsYmFja1xyXG4gICAgbGV0IGVycm9yOiBPcHRpb25hbDxGYWlsZWRGaWxlSW1wb3J0Sm9iWydlcnJvciddPiA9IHVuZGVmaW5lZFxyXG5cclxuICAgIGlmICh1cGxvYWQudmFsdWUuZXJyb3IpIHtcclxuICAgICAgLy8gUHJlLXVwbG9hZCB2YWxpZGF0aW9uIGVycm9yXHJcbiAgICAgIGlmICh1cGxvYWQudmFsdWUuZXJyb3IgaW5zdGFuY2VvZiBGaWxlVG9vTGFyZ2VFcnJvcikge1xyXG4gICAgICAgIGVycm9yID0ge1xyXG4gICAgICAgICAgdHlwZTogRmFpbGVkRmlsZUltcG9ydEpvYkVycm9yLkZpbGVUb29MYXJnZSxcclxuICAgICAgICAgIG1lc3NhZ2U6IHVwbG9hZC52YWx1ZS5lcnJvci5tZXNzYWdlXHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2UgaWYgKHVwbG9hZC52YWx1ZS5lcnJvciBpbnN0YW5jZW9mIE1pc3NpbmdGaWxlRXh0ZW5zaW9uRXJyb3IpIHtcclxuICAgICAgICBlcnJvciA9IHtcclxuICAgICAgICAgIHR5cGU6IEZhaWxlZEZpbGVJbXBvcnRKb2JFcnJvci5NaXNzaW5nRmlsZUV4dGVuc2lvbkVycm9yLFxyXG4gICAgICAgICAgbWVzc2FnZTogdXBsb2FkLnZhbHVlLmVycm9yLm1lc3NhZ2VcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSBpZiAodXBsb2FkLnZhbHVlLmVycm9yIGluc3RhbmNlb2YgRm9yYmlkZGVuRmlsZVR5cGVFcnJvcikge1xyXG4gICAgICAgIGVycm9yID0ge1xyXG4gICAgICAgICAgdHlwZTogRmFpbGVkRmlsZUltcG9ydEpvYkVycm9yLkludmFsaWRGaWxlVHlwZSxcclxuICAgICAgICAgIG1lc3NhZ2U6IHVwbG9hZC52YWx1ZS5lcnJvci5tZXNzYWdlXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2UgaWYgKHVwbG9hZC52YWx1ZS5yZXN1bHQ/LnVwbG9hZEVycm9yKSB7XHJcbiAgICAgIC8vIFBvc3QtdXBsb2FkIGVycm9yXHJcbiAgICAgIGVycm9yID0ge1xyXG4gICAgICAgIHR5cGU6IEZhaWxlZEZpbGVJbXBvcnRKb2JFcnJvci5VcGxvYWRGYWlsZWQsXHJcbiAgICAgICAgbWVzc2FnZTogdXBsb2FkLnZhbHVlLnJlc3VsdC51cGxvYWRFcnJvclxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFlcnJvcikge1xyXG4gICAgICBlcnJvciA9IHtcclxuICAgICAgICB0eXBlOiBGYWlsZWRGaWxlSW1wb3J0Sm9iRXJyb3IuVXBsb2FkRmFpbGVkLFxyXG4gICAgICAgIG1lc3NhZ2U6ICdBbiB1bmtub3duIGVycm9yIG9jY3VycmVkIGR1cmluZyBmaWxlIHVwbG9hZCdcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZhaWxlZEpvYjogRmFpbGVkRmlsZUltcG9ydEpvYiA9IHtcclxuICAgICAgaWQ6IHVwbG9hZC52YWx1ZS5pZCxcclxuICAgICAgZmlsZU5hbWU6IHVwbG9hZC52YWx1ZS5maWxlLm5hbWUsXHJcbiAgICAgIHByb2plY3RJZDogdW5yZWYocHJvamVjdCkuaWQsXHJcbiAgICAgIG1vZGVsSWQ6IHVwbG9hZC52YWx1ZS5tb2RlbD8uaWQgfHwgbnVsbCxcclxuICAgICAgZXJyb3IsXHJcbiAgICAgIGRhdGU6IG5ldyBEYXRlKClcclxuICAgIH1cclxuXHJcbiAgICAvLyBMb2cgZXJyb3IgdG8gY29uc29sZS9zZXFcclxuICAgIGxvZ2dlclt1cGxvYWQudmFsdWUucmVzdWx0Py51cGxvYWRFcnJvciA/ICdlcnJvcicgOiAnd2FybiddKFxyXG4gICAgICB7XHJcbiAgICAgICAgZmFpbGVkSm9iXHJcbiAgICAgIH0sXHJcbiAgICAgICdGaWxlIGltcG9ydCBmYWlsZWQnXHJcbiAgICApXHJcblxyXG4gICAgZXJyb3JDYWxsYmFjayh7IGZhaWxlZEpvYiB9KVxyXG4gIH1cclxuXHJcbiAgY29uc3QgdXBsb2FkU2VsZWN0ZWQgPSBhc3luYyAocGFyYW1zPzoge1xyXG4gICAgLyoqXHJcbiAgICAgKiBPcHRpb25hbGx5IG92ZXJyaWRlIG1vZGVsIHRhcmdldCBmb3IgdGhlIHVwbG9hZFxyXG4gICAgICovXHJcbiAgICBtb2RlbDogVXNlRmlsZUltcG9ydF9Nb2RlbEZyYWdtZW50XHJcbiAgfSkgPT4ge1xyXG4gICAgaWYgKCFpc1VwbG9hZGFibGUudmFsdWUgfHwgIXVwbG9hZC52YWx1ZSB8fCAhYXV0aFRva2VuLnZhbHVlKSByZXR1cm5cclxuXHJcbiAgICBpZiAocGFyYW1zPy5tb2RlbCkge1xyXG4gICAgICB1cGxvYWQudmFsdWUubW9kZWwgPSBwYXJhbXMubW9kZWxcclxuICAgIH1cclxuXHJcbiAgICBpc1VwbG9hZGluZy52YWx1ZSA9IHRydWVcclxuICAgIHRyeSB7XHJcbiAgICAgIGlmICghdXBsb2FkLnZhbHVlLm1vZGVsKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBtb2RlbCBwcm92aWRlZCBmb3IgZmlsZSBpbXBvcnQnKVxyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCByZXMgPSBhd2FpdCBpbXBvcnRGaWxlKFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIGZpbGU6IHVwbG9hZC52YWx1ZS5maWxlLFxyXG4gICAgICAgICAgcHJvamVjdElkOiB1bnJlZihwcm9qZWN0KS5pZCxcclxuICAgICAgICAgIG1vZGVsTmFtZTogdXBsb2FkLnZhbHVlLm1vZGVsLm5hbWUsXHJcbiAgICAgICAgICBtb2RlbElkOiB1cGxvYWQudmFsdWUubW9kZWwuaWQsXHJcbiAgICAgICAgICBhdXRoVG9rZW46IGF1dGhUb2tlbi52YWx1ZSxcclxuICAgICAgICAgIGFwaU9yaWdpblxyXG4gICAgICAgIH0sXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgb25Qcm9ncmVzczogKHBlcmNlbnRhZ2UpID0+IHtcclxuICAgICAgICAgICAgaWYgKHVwbG9hZC52YWx1ZSkgdXBsb2FkLnZhbHVlLnByb2dyZXNzID0gcGVyY2VudGFnZVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgKVxyXG4gICAgICB1cGxvYWQudmFsdWUucmVzdWx0ID0gcmVzXHJcblxyXG4gICAgICBtcC50cmFjaygnVXBsb2FkIEFjdGlvbicsIHtcclxuICAgICAgICB0eXBlOiAnYWN0aW9uJyxcclxuICAgICAgICBuYW1lOiAnY3JlYXRlJyxcclxuICAgICAgICBzb3VyY2U6ICdtb2RlbCBjYXJkJ1xyXG4gICAgICB9KVxyXG5cclxuICAgICAgZmlsZVVwbG9hZGVkQ2FsbGJhY2s/Lih1cGxvYWQudmFsdWUpXHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgIHVwbG9hZC52YWx1ZS5yZXN1bHQgPSB7XHJcbiAgICAgICAgdXBsb2FkU3RhdHVzOiBCbG9iVXBsb2FkU3RhdHVzLkVycm9yLFxyXG4gICAgICAgIHVwbG9hZEVycm9yOiBlbnN1cmVFcnJvcihlKS5tZXNzYWdlLFxyXG4gICAgICAgIGZvcm1LZXk6ICdmaWxlJ1xyXG4gICAgICB9XHJcbiAgICAgIGhhbmRsZUVycm9yKClcclxuICAgIH0gZmluYWxseSB7XHJcbiAgICAgIHVwbG9hZC52YWx1ZS5wcm9ncmVzcyA9IDEwMFxyXG4gICAgICBpc1VwbG9hZGluZy52YWx1ZSA9IGZhbHNlXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25zdCByZXNldFNlbGVjdGVkID0gKCkgPT4ge1xyXG4gICAgaWYgKGlzVXBsb2FkaW5nLnZhbHVlKSByZXR1cm5cclxuICAgIHVwbG9hZC52YWx1ZSA9IG51bGxcclxuICB9XHJcblxyXG4gIGNvbnN0IG9uRmlsZXNTZWxlY3RlZCA9IGFzeW5jIChwYXJhbXM6IHsgZmlsZXM6IFVwbG9hZGFibGVGaWxlSXRlbVtdIH0pID0+IHtcclxuICAgIGlmIChpc1VwbG9hZGluZy52YWx1ZSB8fCAhYXV0aFRva2VuLnZhbHVlKSByZXR1cm5cclxuXHJcbiAgICBjb25zdCBmaWxlID0gcGFyYW1zLmZpbGVzWzBdXHJcbiAgICBpZiAoIWZpbGUpIHJldHVyblxyXG5cclxuICAgIHVwbG9hZC52YWx1ZSA9IHtcclxuICAgICAgLi4uZmlsZSxcclxuICAgICAgcmVzdWx0OiB1bmRlZmluZWQsXHJcbiAgICAgIHByb2dyZXNzOiAwLFxyXG4gICAgICBtb2RlbDogdW5yZWYobW9kZWwpIHx8IG51bGxcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZmlsZS5lcnJvcikge1xyXG4gICAgICBoYW5kbGVFcnJvcigpXHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG5cclxuICAgIGZpbGVTZWxlY3RlZENhbGxiYWNrPy4oKVxyXG4gICAgaWYgKCFtYW51YWxseVRyaWdnZXJVcGxvYWQpIHtcclxuICAgICAgYXdhaXQgdXBsb2FkU2VsZWN0ZWQoKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIG1heFNpemVJbkJ5dGVzLFxyXG4gICAgb25GaWxlc1NlbGVjdGVkLFxyXG4gICAgYWNjZXB0LFxyXG4gICAgdXBsb2FkLFxyXG4gICAgaXNVcGxvYWRpbmcsXHJcbiAgICB1cGxvYWRTZWxlY3RlZCxcclxuICAgIHJlc2V0U2VsZWN0ZWQsXHJcbiAgICBpc1VwbG9hZGFibGVcclxuICB9XHJcbn1cclxuIl0sImZpbGUiOiJEOi9zcGVja2xlLXNlcnZlci9wYWNrYWdlcy9mcm9udGVuZC0yL2xpYi9jb3JlL2NvbXBvc2FibGVzL2ZpbGVJbXBvcnQudHMifQ==