1import { createHotContext as __vite__createHotContext } from "/@vite/client";import.meta.hot = __vite__createHotContext("/src/components/Documents/DocumentUpload.tsx");const useState = __vite__cjsImport0_react["useState"]; const useEffect = __vite__cjsImport0_react["useEffect"]; const useCallback = __vite__cjsImport0_react["useCallback"]; const useRef = __vite__cjsImport0_react["useRef"];const _jsxDEV = __vite__cjsImport13_react_jsxDevRuntime["jsxDEV"]; const _Fragment = __vite__cjsImport13_react_jsxDevRuntime["Fragment"];import __vite__cjsImport0_react from "/node_modules/.vite/deps/react.js?v=ae253003"; 2import axios from "/node_modules/.vite/deps/axios.js?v=ae253003"; 3import { App as AntdApp, Modal, Upload, Select, Space, Typography, Progress, Switch, Button } from "/node_modules/.vite/deps/antd.js?v=ae253003"; 4import { InboxOutlined } from "/node_modules/.vite/deps/@ant-design_icons.js?v=ae253003"; 5import { uploadDocument } from "/src/api/documents.ts"; 6import { watchVectorization } from "/src/store/vectorizationWatchStore.ts"; 7import { useDocumentStore } from "/src/store/documentStore.ts"; 8import { flattenCategories } from "/src/utils/categoryUtils.ts"; 9import { extractErrorMessage } from "/src/utils/errorUtils.ts"; 10import { FILE_UPLOAD, MODAL_WIDTH, STORAGE_KEYS } from "/src/constants.ts"; 11import { getFileExtension } from "/src/utils/fileUtils.ts"; 12import { formatFileSize } from "/src/utils/formatters.ts"; 13import { safeGetItem, safeSetItem } from "/src/utils/storageUtils.ts"; 14var _jsxFileName = "/home/bang/datatek_rag/frontend/src/components/Documents/DocumentUpload.tsx"; 15import __vite__cjsImport13_react_jsxDevRuntime from "/node_modules/.vite/deps/react_jsx-dev-runtime.js?v=ae253003"; 16var _s = $RefreshSig$(); 17const { Dragger } = Upload; 18const { Text } = Typography; 19// axios ì·¨ì ìë¬ì¸ì§ ê²¬ê³ íê² íë³íë¤. axios.isCancel ì¸ì íê²½ì ë°ë¼ name ë§ ë¤ë¥¸ 20// CanceledError / AbortError ë í¨ê» ì¸ì íë¤. 21function isAbortError(err) { 22 if (axios.isCancel(err)) return true; 23 const name = err?.name; 24 return name === "CanceledError" || name === "AbortError"; 25} 26export default function DocumentUpload({ open, onClose, onSuccess, defaultCategoryId }) { 27 _s(); 28 const { message: messageApi } = AntdApp.useApp(); 29 // Why: useDocumentStore() ì ì²´ 구ë â 100MB ì ë¡ë progress ì´ë²¤í¸ ëì¤ store ì 모ë 30 // mutation ì´ dragger + per-file Progress ì¬ë ë storm. R167/R168/R175 í¨í´ì¼ë¡ categories 31 // slice ë§ êµ¬ë . 32 const categories = useDocumentStore((s) => s.categories); 33 const [uploading, setUploading] = useState(false); 34 const [fileList, setFileList] = useState([]); 35 const [selectedCategory, setSelectedCategory] = useState(undefined); 36 const [uploadStatuses, setUploadStatuses] = useState({}); 37 // Why: R180 ì "preserve autoUpload across reopen" ìëê° useState lazy init ì´ë¼ 38 // DocumentUpload component ê° unmount ëë©´ (parent ì open=false ê° modal ë«ê³ component ë 39 // unmount) ë¤ì mount ì default true ë¡ reset ëì´ ì¬ì©ì preference silent ìì¤. localStorage 40 // ë¡ ì구 ë³´ì¡´. 'true' / 'false' ëª ì 문ìì´ ì¬ì©. 41 const [autoUpload, setAutoUpload] = useState(() => { 42 const stored = safeGetItem(STORAGE_KEYS.DOCUMENT_UPLOAD_AUTO); 43 if (stored === "false") return false; 44 return true; 45 }); 46 // Why: ì´ê¸° mount ì useState init ì¼ë¡ ì½ì ê°ì ì¦ì ë¤ì setItem íë©´ cross-tab ìëë¦¬ì¤ 47 // ìì ë¤ë¥¸ íì´ ë ìµì ê°ì¼ë¡ ë°ê¾¼ ì§í 본 íì´ mount íë©´ stale ê°ì¼ë¡ ë®ì´ì°ê¸° ê°ë¥. 48 // (storage event listener ê° ìì´ ë¤ë¥¸ íì ë³ê²½ì ì ë³´ë ìí© + 본 íì mount ê° ê·¸ ì´íë¼ë 49 // useState init ì´ cache hit ì¼ë¡ ì ê° ì½ì.) 첫 mount ì redundant write 를 skip. 50 const autoUploadDidMountRef = useRef(false); 51 // Why: ì§í ì¤ì¸ ì ë¡ë run ì ì¤ë¨í기 ìí AbortController. 모ë in-flight axios ìì²ì 52 // ê°ì signal ì ë겨 í ë²ì abort() ë¡ íì¬ íì¼ì ì·¨ìíê³ ë£¨í를 ë¹ ì ¸ëê°ë¤. 53 const abortRef = useRef(null); 54 useEffect(() => { 55 if (!autoUploadDidMountRef.current) { 56 autoUploadDidMountRef.current = true; 57 return; 58 } 59 safeSetItem(STORAGE_KEYS.DOCUMENT_UPLOAD_AUTO, autoUpload ? "true" : "false"); 60 }, [autoUpload]); 61 // Why: ì´ì ì lazy- 62 // init ì¼ë¡ë§ ì½ì´ Tab A ê° auto-upload OFF ë¡ ë°ê¿ë ì´ë¯¸ mount ë Tab B ëë 63 // ì¦ì reopen ì stale true ì ì§ â ì¬ì©ìê° Tab B ìì íì¼ ëëê·¸ ì ìëì¹ 64 // ìì ìë ì ë¡ë ë°ì¬ (Tab A ì preference 무ì). storage event ë¡ cross-tab 65 // sync â ë¤ë¥¸ íì ë³ê²½ ì¦ì ë°ì. 66 useEffect(() => { 67 const onStorage = (e) => { 68 if (e.key === STORAGE_KEYS.DOCUMENT_UPLOAD_AUTO && e.newValue !== null) { 69 const next = e.newValue === "true"; 70 setAutoUpload(next); 71 } 72 }; 73 window.addEventListener("storage", onStorage); 74 return () => window.removeEventListener("storage", onStorage); 75 }, []); 76 // Why: ì ë¡ë ì§í ì¤ì ì»´í¬ëí¸ê° unmount ëë©´(ë¶ëª¨ê° 모ë¬ì ì ê±°) in-flight ìì²ì´ ë¨ì 77 // ìë£ ì setUploadStatuses ê° ì¬ë¼ì§ ì»´í¬ëí¸ì setState 를 ìëíë¤. unmount ì ë¨ì 78 // 컨í¸ë¡¤ë¬ë¥¼ abort í´ ìì²ì ëê³ setState-after-unmount 를 ë°©ì§íë¤. 79 useEffect(() => { 80 return () => { 81 abortRef.current?.abort(); 82 }; 83 }, []); 84 // 모ë¬ì´ ë«íë¤ ë¤ì ì´ë¦¬ë©´ ì´ì ì¸ì ì fileList / uploadStatuses / selectedCategory ê° 85 // ê·¸ëë¡ ë¨ì ìì´ ì¬ì©ì í¼ë ì ë°. open === true ë¡ ë°ë ë ì´ê¸°í. 86 // Why: autoUpload ë ì¬ì©ìê° ëª ìì ì¼ë¡ ë íê²½ (ëë ê²í í ëª ìì Upload í´ë¦) ìì 87 // ëª¨ë¬ ë«ê³ ë¤ì ì´ë©´ silent ë¡ ë¤ì ì¼ì ¸, ë¤ì ëëê·¸ ì ìëì¹ ìì ìë ì ë¡ë ë°ì. ë¤ë¥¸ 88 // session-state (fileList ë±) ì ë¬ë¦¬ ì¬ì©ì preference ë¼ reset ëììì ì ì¸í´ ë³´ì¡´. 89 // queueMicrotask: setState ê° effect body ì ì§ì ìì¼ë©´ React 19 set-state-in-effect ê° 90 // ì¡ëë¤. microtask ë¡ ì®ê¸°ë©´ commit ì§í ê°ì tick ì ì¤íëì´ ì¬ì©ì ì²´ê° ëì¼. 91 useEffect(() => { 92 if (!open) return; 93 queueMicrotask(() => { 94 setFileList([]); 95 // Why: undefined ë¡ ë¦¬ì íë©´ ì¹´í ê³ ë¦¬ íí°ê° 걸린 목ë¡ìì ì° ëª¨ë¬ì´ 문맥ì ìëë¤ 96 // (ë¥ë§í¬ ì ì + ì±ê³µ í ìë ë«í â ì¬ì¤í 모ë). íì´ì§ê° ëê²¨ì¤ ê¸°ë³¸ê°ì¼ë¡ ë³µì. 97 setSelectedCategory(defaultCategoryId); 98 setUploadStatuses({}); 99 }); 100 }, [open, defaultCategoryId]); 101 const categoryOptions = flattenCategories(categories); 102 const uploadProps = { 103 name: "file", 104 multiple: true, 105 fileList, 106 disabled: uploading, 107 beforeUpload: (file) => { 108 // Clear old status traces when user selects new files after a previous upload run 109 if (!uploading && Object.keys(uploadStatuses).length > 0) { 110 setUploadStatuses({}); 111 } 112 // Check file type 113 const fileExt = getFileExtension(file.name); 114 if (!fileExt || !FILE_UPLOAD.SUPPORTED_TYPES.includes(fileExt)) { 115 messageApi.error(`ì§ìíì§ ìë íì¼ íì: ${fileExt || "ì ì ìì"}. ì§ì íì: ${FILE_UPLOAD.SUPPORTED_TYPES.join(", ")}`); 116 return Upload.LIST_IGNORE; 117 } 118 // Check file size 119 if (file.size > FILE_UPLOAD.MAX_SIZE) { 120 messageApi.error(`"${file.name}" íì¼ì´ ë무 í½ëë¤. ìµë í¬ê¸°: ${formatFileSize(FILE_UPLOAD.MAX_SIZE)}`); 121 return Upload.LIST_IGNORE; 122 } 123 let canAdd = true; 124 let duplicate = false;
125 // Check file count (use latest state inside updater to avoid stale length with multi-select) 126 setFileList((prev) => { 127 // ê°ì name+size+lastModified ì¡°í©ì´ ì´ë¯¸ 리ì¤í¸ì ìì¼ë©´ ì¤ë³µ ì¶ê° ë§ê¸°. 128 // Antd ì uid ë ë§¤ë² ìë¡ ì겨 dedup ìí ì 못íë¯ë¡ ë³ë í¤ë¡ ë¹êµ. 129 const fileKey = `${file.name}:${file.size}:${file.lastModified ?? ""}`; 130 const alreadyPresent = prev.some((f) => `${f.name}:${f.size ?? ""}:${f.lastModified ?? ""}` === fileKey); 131 if (alreadyPresent) { 132 duplicate = true; 133 return prev; 134 } 135 const activeCount = prev.filter((f) => uploadStatuses[f.uid]?.status !== "success").length; 136 if (activeCount >= FILE_UPLOAD.MAX_FILES) { 137 canAdd = false; 138 return prev; 139 } 140 // Why: RcFile(ì§ì§ File)ì fileList ì ê·¸ëë¡ ë´ì¼ë©´, ì´í ì§íë¥ /ìí ê°±ì ì´ 141 // `{ ...f, status: 'uploading' }` ë¡ ì¤íë ëíë ìê° File ì´ ìë íë²í ê°ì²´ê° 142 // ëë¤. File ì name/size/ë°ì´í°ë íë¡í íì getter ë¼ ì¤íë ëê° ë³µì¬íì§ ëª»íë¤ 143 // (own enumerable ì´ ë¹ì´ ìë¤). ê·¸ ê°ì²´ë¥¼ FormData ì ë£ì¼ë©´ "[object Object]" 144 // 문ìì´ì´ ëì´ filename ìë íí¸ë¡ ì ì¡ëê³ , ìë²ê° 422 "Expected UploadFile, 145 // received: str" 를 ë¸ë¤. 첫 ìëë ì본ì´ë¼ ì±ê³µíê³ ì¬ìëë§ ì¤í¨í´ ì¶ì ì´ 146 // ì´ë ¤ì ë¤(ì´ì ë¡ê·¸ 201 -> 409 -> 422). 147 // antd ê·ì½ëë¡ UploadFile ëí¼ì ë´ê³ ì본ì originFileObj ë¡ ì°¸ì¡°ë¥¼ ë³´ì¡´íë¤. 148 // ì¤íë ëë ëí¼ë§ ë³µì¬íê³ originFileObj ë ì°¸ì¡°ë¡ ì´ìë¨ëë¤. 149 const wrapped = { 150 uid: file.uid, 151 name: file.name, 152 size: file.size, 153 type: file.type, 154 originFileObj: file 155 }; 156 return [...prev, wrapped]; 157 }); 158 if (duplicate) { 159 messageApi.info({ 160 key: `upload-dup-${file.name}`, 161 content: `"${file.name}" ì(ë) ì´ë¯¸ ë기ì´ì ììµëë¤.` 162 }); 163 return Upload.LIST_IGNORE; 164 } 165 if (!canAdd) { 166 messageApi.error({ 167 key: "upload-max-files", 168 content: `í ë²ì ìµë ${FILE_UPLOAD.MAX_FILES}ê°ê¹ì§ ì ë¡ëí ì ììµëë¤` 169 }); 170 return Upload.LIST_IGNORE; 171 } 172 return false; 173 }, 174 onRemove: (file) => { 175 if (uploading) return false; 176 setFileList((prev) => prev.filter((f) => f.uid !== file.uid)); 177 setUploadStatuses((prev) => { 178 const next = { ...prev }; 179 delete next[file.uid]; 180 return next; 181 }); 182 } 183 }; 184 const handleCancel = useCallback(() => { 185 // Why: ì ë¡ë ì¤ X/Esc/mask í´ë¦/ì·¨ìë¡ ë«ê¸°ë¥¼ ìëíë©´, ì´ì ë ë§ë ëì ì§í ì¤ì¸ run ì 186 // abort íë¤. handleUpload ì abort ì²ë¦¬ ë¶ê¸°ê° ì´ë¯¸ ì¬ë¼ê° íì¼ì ë³´ì¡´í ì± uploading=false 187 // ë¡ ì 리íê³ ìë´ë¥¼ ëì´ë¤. ì¬ê¸°ìë abort ë§ í¸ë¦¬ê±°íê³ ì¤ì ë«ê¸°/리ì ì ì¬ì©ìê° í ë² 188 // ë ë«ì ë(ëë abort ì²ë¦¬ í) ìííë¤. abort ì§í ê³§ì¥ onClose íë©´ 루íê° ìì§ 189 // setUploading(false) ì ì´ë¼ ë«í ë¤ í ì¤í¸ê° ë¨ë ì í¼ëì´ ì¬ë°íë¯ë¡ ë«ì§ ìëë¤. 190 if (uploading) { 191 abortRef.current?.abort(); 192 return; 193 } 194 setFileList([]); 195 setSelectedCategory(undefined); 196 setUploadStatuses({}); 197 onClose(); 198 }, [onClose, uploading]); 199 const handleUpload = useCallback(async () => { 200 if (uploading) { 201 return; 202 } 203 if (fileList.length === 0) { 204 messageApi.warning("ì ë¡ëí íì¼ì 1ê° ì´ì ì íí´ì£¼ì¸ì"); 205 return; 206 } 207 // Why: í¼í© ì±ê³µ/ì¤í¨ í ì¬ì©ìê° ì¶ê° íì¼ì ëëê·¸íë©´ beforeUpload ê° 208 // uploadStatuses 를 ë¹ì effect ê° handleUpload 를 ì¬ì¤ííë¤. ì´ë ì±ê³µíë 209 // íì¼ë ë¤ì POST /documents/upload ë¡ ì¬ë¼ê° ìë²ì ì¤ë³µ ìì±. fileList ì 210 // status='done' ë ë¨ììì¼ë¯ë¡ ê·¸ê²ì¼ë¡ ì±ê³µë¶ì ìë³í´ skip & íì ì ì§. 211 const initialStatuses = fileList.reduce((acc, file) => { 212 if (file.status === "done") { 213 acc[file.uid] = { 214 status: "success", 215 progress: 100, 216 name: file.name 217 }; 218 } else { 219 acc[file.uid] = { 220 status: "queued", 221 progress: 0, 222 name: file.name 223 }; 224 } 225 return acc; 226 }, {}); 227 setUploadStatuses(initialStatuses);
228 // ì´ë² ì ë¡ë run ì AbortController. "ì ë¡ë ì¤ë¨" ë²í¼ / handleCancel ì´ ì´ signal ì 229 // abort íë¤. 모ë íì¼ì´ ê°ì signal ì ê³µì íë¯ë¡ í ë²ì abort ë¡ íì¬ íì¼ì´ ì·¨ìëë¤. 230 const controller = new AbortController(); 231 abortRef.current = controller; 232 setUploading(true); 233 // ì ë¡ë ìì ìì ì ì¹´í ê³ ë¦¬ ì íì ë¡ì»¬ ë³ìë¡ ìº¡ì²íë¤. ì¬ì©ìê° ë£¨í ì§í ì¤ì 234 // ì¹´í ê³ ë¦¬ ëë¡ë¤ì´ì ë°ê¾¸ë©´ ë¨ì íì¼ë¤ì´ ì ì¹´í ê³ ë¦¬ë¡ ì¬ë¼ê° "ì¹´í ê³ ë¦¬ A ì ííëë° 235 // B ë¡ ë¤ì´ê°" ì´ë¼ë í¼ëì´ ë°ì. 루í ì ì²´ê° í ë²ì ì íì¼ë¡ ì¼ê´ëê² ì ë¡ëëê² ê³ ì . 236 const uploadCategoryId = selectedCategory; 237 try { 238 let successful = 0; 239 let failed = 0; 240 for (const file of fileList) { 241 // ì´ë¯¸ ì±ê³µí íì¼ì ìë² ì¬ì ë¡ë ë°©ì§ë¥¼ ìí´ ê±´ëë (initialStatuses ìì 'success' ë¡ ë³´ì¡´ë¨). 242 if (file.status === "done") continue; 243 const uid = file.uid; 244 const rawFile = file.originFileObj; 245 const fileToUpload = rawFile ?? file; 246 const displayName = uploadStatuses[uid]?.name || file.name; 247 // Mark as uploading 248 setUploadStatuses((prev) => ({ 249 ...prev, 250 [uid]: { 251 ...prev[uid] || { 252 progress: 0, 253 name: displayName 254 }, 255 status: "uploading", 256 progress: prev[uid]?.progress ?? 0, 257 name: displayName 258 } 259 })); 260 setFileList((prev) => { 261 const existing = prev.find((p) => p.uid === uid); 262 return prev.map((f) => f.uid === uid ? { 263 ...f, 264 name: f.name || displayName, 265 status: "uploading", 266 percent: existing?.percent ?? 0 267 } : f); 268 }); 269 try { 270 const uploaded = await uploadDocument(fileToUpload, uploadCategoryId, { 271 timeout: FILE_UPLOAD.UPLOAD_TIMEOUT_MS, 272 signal: controller.signal, 273 onUploadProgress: (event) => { 274 // Why: HTTP/2 + gzip ëë chunked transfer íê²½ìì final progress ì´ë²¤í¸ê° 275 // event.loaded > event.total (101~105%) ëë event.total === 0 (NaN/Infinity) ë¡ 276 // ëë¬íë ì¬ë¡ê° ìë¤. ê·¸ëë¡ antd Progress ì ë기면 ë§ëê° overshoot ëê±°ë 277 // ììí "Uploading" ìíë¡ ë¨ëë¤. 0~100 í´ë¨í + total=0 ì undefined ë°í. 278 const rawPercent = event.total ? Math.round(event.loaded / event.total * 100) : undefined; 279 const percent = rawPercent === undefined || !Number.isFinite(rawPercent) ? undefined : Math.min(100, Math.max(0, rawPercent)); 280 // Why: onUploadProgress ë XHR ë°ì´í¸ë§ë¤ trigger ë ì ìì´, í° íì¼ ì ë¡ë 281 // ì ì´ë¹ ìë°±~ìì² ë² ë ê°ì setState ê° ì¤íë¼ render storm ì´ ë°ìíë¤. 282 // ë°±ë¶ì¨ì´ ë°ëì§ ììì¼ë©´ state update 를 ê±´ëë°ì´ ë ë íì를 0~100 íë¡ ì í. 283 setUploadStatuses((prev) => { 284 const prevProgress = prev[uid]?.progress; 285 const nextProgress = percent ?? prevProgress ?? 0; 286 if (prev[uid]?.status === "uploading" && prevProgress === nextProgress) { 287 return prev; 288 } 289 return { 290 ...prev, 291 [uid]: { 292 ...prev[uid] || { 293 status: "uploading", 294 progress: 0, 295 name: displayName 296 }, 297 status: "uploading", 298 progress: nextProgress, 299 name: displayName 300 } 301 }; 302 }); 303 setFileList((prev) => { 304 const existing = prev.find((p) => p.uid === uid); 305 const nextPercent = percent ?? existing?.percent; 306 if (existing && existing.status === "uploading" && existing.percent === nextPercent) { 307 return prev; 308 } 309 return prev.map((f) => f.uid === uid ? { 310 ...f, 311 name: f.name || displayName, 312 status: "uploading", 313 percent: nextPercent 314 } : f); 315 }); 316 } 317 }); 318 // 벡í°íê° ëëë©´ ì´ë íë©´ì ìë ì림(VectorizationNotifier). 319 watchVectorization([{ 320 id: uploaded.id, 321 filename: uploaded.filename 322 }]); 323 successful += 1; 324 setUploadStatuses((prev) => ({ 325 ...prev, 326 [uid]: { 327 ...prev[uid] || { 328 progress: 0, 329 name: displayName 330 }, 331 status: "success", 332 progress: 100, 333 name: displayName 334 } 335 })); 336 setFileList((prev) => prev.map((f) => f.uid === uid ? { 337 ...f, 338 name: f.name || displayName, 339 status: "done", 340 percent: 100 341 } : f)); 342 } catch (error) { 343 // ì¬ì©ìê° ì¤ë¨(abort)í ê²½ì°: ìë¬ê° ìëë¼ "ì¤ë¨ë¨" ì¼ë¡ ë¤ë£¬ë¤. ì§í ì¤ì´ë íì¼ê³¼
344 // ìì§ ë기ì´ì ë¨ì íì¼ì 'cancelled' ë¡ í기íê³ ë£¨í를 ë¹ ì ¸ëê°ë¤. ì´ë¯¸ ì±ê³µí 345 // íì¼(ì쪽 batch)ì ìë²ì ììíëì¼ë¯ë¡ 'success' ê·¸ëë¡ ëë¤. 346 if (isAbortError(error) || controller.signal.aborted) { 347 // ì§í ì¤ + ëê¸°ì´ íì¼ì 'cancelled' ë¡. ì´ë¯¸ 'success' ì¸ íì¼ì ê·¸ëë¡ ë³´ì¡´íë¤. 348 setUploadStatuses((prev) => { 349 const next = { ...prev }; 350 for (const [key, st] of Object.entries(prev)) { 351 if (st.status === "uploading" || st.status === "queued") { 352 next[key] = { 353 ...st, 354 status: "cancelled" 355 }; 356 } 357 } 358 return next; 359 }); 360 // Why: fileList ì status ë antd Dragger ë´ë¶ í기ìë§ ì°ì¸ë¤. ì¤ë¨ íì¼ì 'error' 361 // ë¡ ëë©´ ë¹¨ê° ì¤í¨ë¡ ë³´ì´ë¯ë¡, ì±ê³µë¶('done')ì ì ì§íê³ ë머ì§ë ì¤ë¦½ ìíë¡ ëë린ë¤. 362 setFileList((prev) => prev.map((f) => f.status === "done" ? f : { 363 ...f, 364 status: undefined, 365 error: undefined 366 })); 367 messageApi.info("ì ë¡ë를 ì¤ë¨íìµëë¤. ì´ë¯¸ ì¬ë¼ê° íì¼ì ì ì§ë©ëë¤."); 368 break; 369 } 370 failed += 1; 371 const errorMessage = extractErrorMessage(error, "ì ë¡ëì ì¤í¨íìµëë¤"); 372 setUploadStatuses((prev) => ({ 373 ...prev, 374 [uid]: { 375 ...prev[uid] || { 376 progress: 0, 377 name: displayName 378 }, 379 status: "error", 380 error: errorMessage, 381 progress: prev[uid]?.progress ?? 0, 382 name: displayName 383 } 384 })); 385 setFileList((prev) => prev.map((f) => f.uid === uid ? { 386 ...f, 387 name: f.name || displayName, 388 status: "error", 389 error: new Error(errorMessage) 390 } : f)); 391 } 392 } 393 // Why: ì¤ë¨ëë©´ success/warning/error ìì½ í ì¤í¸ì onSuccess()/handleCancel() ì ê±´ëë´ë¤. 394 // ì´ë¯¸ ì±ê³µí íì¼ì´ ììëë¼ë onSuccess(reload)ë ì¬ì©ìê° ëª¨ë¬ì ë«ì ë ì¼ì´ëë ë¦ì§ 395 // ìì¼ë©°, ì¤ë¨ ì§í ì¶ê° í ì¤í¸ë¡ ì¬ì©ì를 í¼ëì¤ë½ê² íì§ ì기 ìí¨. 396 if (controller.signal.aborted) { 397 // ì±ê³µë¶ì´ ììì¼ë©´ ë¶ëª¨ 목ë¡ì ê°±ì í´ ìì¸ ìí를 ë³¼ ì ìê² íë¤. 398 if (successful > 0) { 399 onSuccess(); 400 } 401 } else if (failed === 0) { 402 messageApi.success(`${successful}ê° íì¼ì´ 모ë ì ë¡ëëììµëë¤`); 403 onSuccess(); 404 handleCancel(); 405 } else if (successful > 0) { 406 messageApi.warning(`${successful}ê° ì ë¡ë ìë£, ${failed}ê° ì¤í¨`); 407 onSuccess(); 408 } else { 409 messageApi.error("모ë ì ë¡ëê° ì¤í¨íìµëë¤"); 410 } 411 } catch (error) { 412 messageApi.error(extractErrorMessage(error, "ì ë¡ëì ì¤í¨íìµëë¤")); 413 } finally { 414 setUploading(false); 415 // ì´ë² run ì 컨í¸ë¡¤ë¬ ì 리. ì´í unmount cleanup ì´ stale 컨í¸ë¡¤ë¬ë¥¼ abort íì§ ìëë¡. 416 if (abortRef.current === controller) { 417 abortRef.current = null; 418 } 419 } 420 }, [ 421 fileList, 422 messageApi, 423 onSuccess, 424 selectedCategory, 425 uploadStatuses, 426 handleCancel, 427 uploading 428 ]); 429 const uploadStatusCount = Object.keys(uploadStatuses).length; 430 useEffect(() => { 431 if (!autoUpload || uploading) return; 432 if (fileList.length === 0) return; 433 if (uploadStatusCount > 0) return; 434 // queueMicrotask: handleUpload ê° setUploading ë± synchronous setState 를 ë¶ë¥´ë¯ë¡ 435 // effect 본문 ì§ì í¸ì¶ì React 19 set-state-in-effect 룰 ìë°. microtask íí¼. 436 queueMicrotask(() => { 437 void handleUpload(); 438 }); 439 }, [ 440 autoUpload, 441 uploading, 442 fileList.length, 443 uploadStatusCount, 444 handleUpload 445 ]); 446 return /* @__PURE__ */ _jsxDEV(Modal, { 447 title: "문ì ì ë¡ë", 448 open, 449 onOk: handleUpload, 450 onCancel: handleCancel, 451 confirmLoading: uploading, 452 okText: "ì ë¡ë", 453 cancelText: "ì·¨ì", 454 width: MODAL_WIDTH.md, 455 // Why: ì´ì abort ê° ìì¼ë¯ë¡ ì§í ì¤ ë«ê¸°ë¥¼ ë§ì§ ìëë¤. X/Esc/mask/ì·¨ìë handleCancel 456 // ë¡ ëª¨ì´ë©°, uploading ì¤ì´ë©´ in-flight ìì²ì abort íë¤(루í abort ë¶ê¸°ê° ì´ë¯¸ ì¬ë¼ê°
457 // íì¼ì ë³´ì¡´íê³ uploading=false ë¡ ì 리). ë«ê¸°ë abort ì²ë¦¬ê° ëë ë¤ í ë² ë ë«ì ë 458 // ìíëë¯ë¡, í ì¤í¸ê° ì¬ë¼ì§ ëª¨ë¬ ë¤ì ë¨ë ì í¼ëë ì¬ë°íì§ ìëë¤. 459 okButtonProps: { disabled: uploading }, 460 children: /* @__PURE__ */ _jsxDEV(Space, { 461 orientation: "vertical", 462 style: { width: "100%" }, 463 size: "large", 464 children: [ 465 /* @__PURE__ */ _jsxDEV("div", { children: [ 466 /* @__PURE__ */ _jsxDEV(Text, { 467 strong: true, 468 children: "ì¹´í ê³ ë¦¬ (ì í ì¬í):" 469 }, void 0, false, { 470 fileName: _jsxFileName, 471 lineNumber: 468, 472 columnNumber: 11 473 }, this), 474 /* @__PURE__ */ _jsxDEV(Select, { 475 placeholder: "ì í ì í¨ (미ë¶ë¥)", 476 style: { 477 width: "100%", 478 marginTop: 8 479 }, 480 value: selectedCategory, 481 onChange: setSelectedCategory, 482 allowClear: true, 483 options: categoryOptions, 484 // Why: "ëëê·¸ ì ìë ì ë¡ë"ê° ì¼ì ¸ ìì¼ë©´ íì¼ì´ fileList ì ë¤ì´ì¤ë ìê° 485 // (microtask) ê·¸ ìì ì selectedCategory ë¡ ì¦ì ì ë¡ëê° ë°ì¬ëë¤. uploadStatuses 486 // ê° ì±ìì§ ë¤ìë ì´ Select 를 ê³ì íì± ìíë¡ ëë©´, ì¬ì©ìê° "ì¹´í ê³ ë¦¬ë¥¼ 487 // ì§ì íë¤"ê³ ëë¼ì§ë§ ì´ë¯¸ ë°ì¬ë ì ë¡ëìë ë°ìëì§ ìë 기ë§ì UIê° ëë¤ 488 // (ì¤ì 문ì: "ì§ì íëë° ë¯¸ë¶ë¥ë¡ ê°"). ë°ì¬ë ë¤ìë ë¹íì±íí´ ì ì§í ì í¸ë¥¼ 489 // ì¤ë¤ â ìë ì ë¡ë ì체를 ë§ì§ë ìëë¤(그건 ë³ë ì í ê²°ì ). 490 disabled: Object.keys(uploadStatuses).length > 0 491 }, void 0, false, { 492 fileName: _jsxFileName, 493 lineNumber: 469, 494 columnNumber: 11 495 }, this), 496 /* @__PURE__ */ _jsxDEV(Text, { 497 type: "secondary", 498 style: { 499 fontSize: 12, 500 display: "block", 501 marginTop: 4 502 }, 503 children: ["미ì§ì ì '미ë¶ë¥'ë¡ ì ë¡ëë©ëë¤. ê°ì íì¼ì ì¹´í ê³ ë¦¬ë§ë¤ í ë²ì©ë§ ì¬ë¦´ ì ììµëë¤.", autoUpload && /* @__PURE__ */ _jsxDEV(_Fragment, { children: [" ", /* @__PURE__ */ _jsxDEV(Text, { 504 type: "warning", 505 style: { fontSize: 12 }, 506 children: "ëëê·¸ ì ìë ì ë¡ëê° ì¼ì ¸ ìì´ íì¼ì ì¶ê°íë©´ ì¦ì ì ë¡ëë©ëë¤ â ì¹´í ê³ ë¦¬ë íì¼ì ì¶ê°í기 ì ì 먼ì ì ííì¸ì." 507 }, void 0, false, { 508 fileName: _jsxFileName, 509 lineNumber: 490, 510 columnNumber: 17 511 }, this)] }, void 0, true, { 512 fileName: _jsxFileName, 513 lineNumber: 488, 514 columnNumber: 15 515 }, this)] 516 }, void 0, true, { 517 fileName: _jsxFileName, 518 lineNumber: 485, 519 columnNumber: 11 520 }, this) 521 ] }, void 0, true, { 522 fileName: _jsxFileName, 523 lineNumber: 467, 524 columnNumber: 9 525 }, this),
526 /* @__PURE__ */ _jsxDEV(Space, { 527 align: "center", 528 children: [/* @__PURE__ */ _jsxDEV(Switch, { 529 size: "small", 530 "aria-label": "ëëê·¸ ì ìë ì ë¡ë", 531 checked: autoUpload, 532 onChange: setAutoUpload 533 }, void 0, false, { 534 fileName: _jsxFileName, 535 lineNumber: 499, 536 columnNumber: 11 537 }, this), /* @__PURE__ */ _jsxDEV(Text, { 538 type: "secondary", 539 children: "ëëê·¸ ì ìë ì ë¡ë" 540 }, void 0, false, { 541 fileName: _jsxFileName, 542 lineNumber: 500, 543 columnNumber: 11 544 }, this)] 545 }, void 0, true, { 546 fileName: _jsxFileName, 547 lineNumber: 498, 548 columnNumber: 9 549 }, this), 550 /* @__PURE__ */ _jsxDEV(Dragger, { 551 ...uploadProps, 552 children: [ 553 /* @__PURE__ */ _jsxDEV("p", { 554 className: "ant-upload-drag-icon", 555 children: /* @__PURE__ */ _jsxDEV(InboxOutlined, {}, void 0, false, { 556 fileName: _jsxFileName, 557 lineNumber: 506, 558 columnNumber: 13 559 }, this) 560 }, void 0, false, { 561 fileName: _jsxFileName, 562 lineNumber: 505, 563 columnNumber: 11 564 }, this), 565 /* @__PURE__ */ _jsxDEV("p", { 566 className: "ant-upload-text", 567 children: "íì¼ì ì´ ììì ëëê·¸íê±°ë í´ë¦íì¬ ì ë¡ëíì¸ì" 568 }, void 0, false, { 569 fileName: _jsxFileName, 570 lineNumber: 508, 571 columnNumber: 11 572 }, this), 573 /* @__PURE__ */ _jsxDEV("p", { 574 className: "ant-upload-hint", 575 children: [ 576 "ì§ì íì: ", 577 FILE_UPLOAD.SUPPORTED_TYPES.join(", "), 578 /* @__PURE__ */ _jsxDEV("br", {}, void 0, false, { 579 fileName: _jsxFileName, 580 lineNumber: 511, 581 columnNumber: 13 582 }, this), 583 "ìµë: ", 584 FILE_UPLOAD.MAX_FILES, 585 "ê° íì¼, ê° 100MB", 586 /* @__PURE__ */ _jsxDEV("br", {}, void 0, false, { 587 fileName: _jsxFileName, 588 lineNumber: 513, 589 columnNumber: 13 590 }, this), 591 /* @__PURE__ */ _jsxDEV(Text, { 592 type: "secondary", 593 style: { fontSize: 12 }, 594 children: "ì ë¡ë í ìì¸(벡í°í) ì²ë¦¬ê° ëëì¼ ê²ì·ëµë³ì ë°ìë©ëë¤ â 목ë¡ìì ìí를 íì¸íì¸ì." 595 }, void 0, false, { 596 fileName: _jsxFileName, 597 lineNumber: 514, 598 columnNumber: 13 599 }, this) 600 ] 601 }, void 0, true, { 602 fileName: _jsxFileName, 603 lineNumber: 509, 604 columnNumber: 11 605 }, this) 606 ] 607 }, void 0, true, { 608 fileName: _jsxFileName, 609 lineNumber: 504, 610 columnNumber: 9 611 }, this), 612 Object.keys(uploadStatuses).length > 0 ? /* @__PURE__ */ _jsxDEV(Space, { 613 orientation: "vertical", 614 style: { width: "100%" }, 615 children: [/* @__PURE__ */ _jsxDEV(Text, { 616 strong: true, 617 children: "ì ë¡ë ì§í ìí©" 618 }, void 0, false, { 619 fileName: _jsxFileName, 620 lineNumber: 521, 621 columnNumber: 13 622 }, this), /* @__PURE__ */ _jsxDEV("div", { 623 style: { 624 maxHeight: 240, 625 overflowY: "auto" 626 }, 627 children: fileList.map((file) => { 628 const state = uploadStatuses[file.uid]; 629 if (!state) return null; 630 const progressStatus = state.status === "error" ? "exception" : state.status === "success" ? "success" : state.status === "uploading" ? "active" : "normal"; 631 const statusLabel = state.status === "queued" ? "ë기" : state.status === "uploading" ? "ì ë¡ë ì¤" : state.status === "success" ? "ìë£" : state.status === "cancelled" ? "ì¤ë¨ë¨" : "ì¤í¨"; 632 return /* @__PURE__ */ _jsxDEV("div", { 633 style: { 634 display: "flex", 635 flexDirection: "column", 636 gap: 4, 637 marginBottom: 8 638 }, 639 children: [/* @__PURE__ */ _jsxDEV("div", { 640 style: { 641 display: "flex", 642 alignItems: "center", 643 gap: 8 644 }, 645 children: [ 646 /* @__PURE__ */ _jsxDEV(Text, { 647 ellipsis: true, 648 title: file.name, 649 style: { flex: 1 }, 650 children: uploadStatuses[file.uid]?.name || file.name 651 }, void 0, false, { 652 fileName: _jsxFileName, 653 lineNumber: 548, 654 columnNumber: 23 655 }, this),
656 /* @__PURE__ */ _jsxDEV(Progress, { 657 percent: state.progress, 658 size: "small", 659 status: progressStatus, 660 style: { 661 flexBasis: 200, 662 marginBottom: 0 663 } 664 }, void 0, false, { 665 fileName: _jsxFileName, 666 lineNumber: 551, 667 columnNumber: 23 668 }, this), 669 /* @__PURE__ */ _jsxDEV(Text, { 670 type: "secondary", 671 style: { 672 width: 80, 673 textAlign: "right" 674 }, 675 children: statusLabel 676 }, void 0, false, { 677 fileName: _jsxFileName, 678 lineNumber: 557, 679 columnNumber: 23 680 }, this) 681 ] 682 }, void 0, true, { 683 fileName: _jsxFileName, 684 lineNumber: 547, 685 columnNumber: 21 686 }, this), state.error && /* @__PURE__ */ _jsxDEV(Text, { 687 type: "danger", 688 style: { marginLeft: 2 }, 689 children: state.error 690 }, void 0, false, { 691 fileName: _jsxFileName, 692 lineNumber: 562, 693 columnNumber: 23 694 }, this)] 695 }, file.uid, true, { 696 fileName: _jsxFileName, 697 lineNumber: 546, 698 columnNumber: 19 699 }, this); 700 }) 701 }, void 0, false, { 702 fileName: _jsxFileName, 703 lineNumber: 522, 704 columnNumber: 13 705 }, this)] 706 }, void 0, true, { 707 fileName: _jsxFileName, 708 lineNumber: 520, 709 columnNumber: 11 710 }, this) : fileList.length > 1 && /* @__PURE__ */ _jsxDEV(Text, { 711 type: "secondary", 712 children: [ 713 "ì¼ê´ ì ë¡ë: ", 714 fileList.length, 715 "ê° íì¼ ì íë¨" 716 ] 717 }, void 0, true, { 718 fileName: _jsxFileName, 719 lineNumber: 573, 720 columnNumber: 13 721 }, this), 722 uploading && /* @__PURE__ */ _jsxDEV(Space, { 723 orientation: "vertical", 724 style: { width: "100%" }, 725 size: 4, 726 children: [/* @__PURE__ */ _jsxDEV(Button, { 727 danger: true, 728 onClick: () => abortRef.current?.abort(), 729 block: true, 730 children: "ì ë¡ë ì¤ë¨" 731 }, void 0, false, { 732 fileName: _jsxFileName, 733 lineNumber: 583, 734 columnNumber: 13 735 }, this), /* @__PURE__ */ _jsxDEV(Text, { 736 type: "secondary", 737 style: { fontSize: 12 }, 738 children: "ì ë¡ëê° ì§í ì¤ì ëë¤. ì¤ë¨í´ë ì´ë¯¸ ì¬ë¼ê° íì¼ì ì ì§ë©ëë¤." 739 }, void 0, false, { 740 fileName: _jsxFileName, 741 lineNumber: 586, 742 columnNumber: 13 743 }, this)] 744 }, void 0, true, { 745 fileName: _jsxFileName, 746 lineNumber: 582, 747 columnNumber: 11 748 }, this) 749 ] 750 }, void 0, true, { 751 fileName: _jsxFileName, 752 lineNumber: 465, 753 columnNumber: 7 754 }, this) 755 }, void 0, false, { 756 fileName: _jsxFileName, 757 lineNumber: 450, 758 columnNumber: 5 759 }, this); 760} 761_s(DocumentUpload, "YrnrbmUq/VyQBQqsOg99ImZycho=", false, function() { 762 return [AntdApp.useApp, useDocumentStore]; 763}); 764_c = DocumentUpload; 765var _c; 766$RefreshReg$(_c, "DocumentUpload"); 767import * as RefreshRuntime from "/@react-refresh"; 768const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; 769import * as __vite_react_currentExports from "/src/components/Documents/DocumentUpload.tsx"; 770if (import.meta.hot && !inWebWorker) { 771 if (!window.$RefreshReg$) { 772 throw new Error( 773 "@vitejs/plugin-react can't detect preamble. Something is wrong." 774 ); 775 } 776 777 const currentExports = __vite_react_currentExports; 778 queueMicrotask(() => { 779 RefreshRuntime.registerExportsForReactRefresh("/home/bang/datatek_rag/frontend/src/components/Documents/DocumentUpload.tsx", currentExports); 780 import.meta.hot.accept((nextExports) => { 781 if (!nextExports) return; 782 const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate("/home/bang/datatek_rag/frontend/src/components/Documents/DocumentUpload.tsx", currentExports, nextExports); 783 if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage); 784 }); 785 }); 786} 787function $RefreshReg$(type, id) { return RefreshRuntime.register(type, "/home/bang/datatek_rag/frontend/src/components/Documents/DocumentUpload.tsx" + ' ' + id); } 788function $RefreshSig$() { return RefreshRuntime.createSignatureFunctionForTransform(); } 789 790//# sourceMappingURL=data:application/json;base64,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QyxNQUFEO1NBQU0sTUFBSztTQUFTLE9BQU8sRUFBRSxZQUFZLEVBQUU7bUJBQ3hDLE1BQU07UUFDSDs7OztnQkFFTDtVQXBCSyxLQUFLOzs7O2NBb0JWO01BRVQsQ0FBQztLQUNFOzs7O2FBQ0E7Ozs7O2VBRVAsU0FBUyxTQUFTLEtBQ2hCLHdCQUFDLE1BQUQ7S0FBTSxNQUFLO2VBQVg7TUFBdUI7TUFDWixTQUFTO01BQU87S0FDckI7Ozs7OztJQU1ULGFBQ0Msd0JBQUMsT0FBRDtLQUFPLGFBQVk7S0FBVyxPQUFPLEVBQUUsT0FBTyxPQUFPO0tBQUcsTUFBTTtlQUE5RCxDQUNFLHdCQUFDLFFBQUQ7TUFBUTtNQUFPLGVBQWUsU0FBUyxTQUFTLE1BQU07TUFBRztnQkFBTTtLQUV2RDs7OztlQUNSLHdCQUFDLE1BQUQ7TUFBTSxNQUFLO01BQVksT0FBTyxFQUFFLFVBQVUsR0FBRztnQkFBRztLQUUxQzs7OzthQUNEOzs7Ozs7R0FFSjs7Ozs7O0NBQ0Y7Ozs7O0FBRVgiLCJuYW1lcyI6W10sInNvdXJjZXMiOlsiRG9jdW1lbnRVcGxvYWQudHN4Il0sInZlcnNpb24iOjMsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHVzZVN0YXRlLCB1c2VFZmZlY3QsIHVzZUNhbGxiYWNrLCB1c2VSZWYgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgYXhpb3MgZnJvbSAnYXhpb3MnO1xuaW1wb3J0IHsgQXBwIGFzIEFudGRBcHAsIE1vZGFsLCBVcGxvYWQsIFNlbGVjdCwgU3BhY2UsIFR5cG9ncmFwaHksIFByb2dyZXNzLCBTd2l0Y2gsIEJ1dHRvbiB9IGZyb20gJ2FudGQnO1xuaW1wb3J0IHsgSW5ib3hPdXRsaW5lZCB9IGZyb20gJ0BhbnQtZGVzaWduL2ljb25zJztcbmltcG9ydCB0eXBlIHsgVXBsb2FkRmlsZSwgVXBsb2FkUHJvcHMgfSBmcm9tICdhbnRkJztcbmltcG9ydCB7IHVwbG9hZERvY3VtZW50IH0gZnJvbSAnLi4vLi4vYXBpL2RvY3VtZW50cyc7XG5pbXBvcnQgeyB3YXRjaFZlY3Rvcml6YXRpb24gfSBmcm9tICcuLi8uLi9zdG9yZS92ZWN0b3JpemF0aW9uV2F0Y2hTdG9yZSc7XG5pbXBvcnQgeyB1c2VEb2N1bWVudFN0b3JlIH0gZnJvbSAnLi4vLi4vc3RvcmUvZG9jdW1lbnRTdG9yZSc7XG5pbXBvcnQgeyBmbGF0dGVuQ2F0ZWdvcmllcyB9IGZyb20gJy4uLy4uL3V0aWxzL2NhdGVnb3J5VXRpbHMnO1xuaW1wb3J0IHsgZXh0cmFjdEVycm9yTWVzc2FnZSB9IGZyb20gJy4uLy4uL3V0aWxzL2Vycm9yVXRpbHMnO1xuaW1wb3J0IHsgRklMRV9VUExPQUQsIE1PREFMX1dJRFRILCBTVE9SQUdFX0tFWVMgfSBmcm9tICcuLi8uLi9jb25zdGFudHMnO1xuaW1wb3J0IHsgZ2V0RmlsZUV4dGVuc2lvbiB9IGZyb20gJy4uLy4uL3V0aWxzL2ZpbGVVdGlscyc7XG5pbXBvcnQgeyBmb3JtYXRGaWxlU2l6ZSB9IGZyb20gJy4uLy4uL3V0aWxzL2Zvcm1hdHRlcnMnO1xuaW1wb3J0IHsgc2FmZUdldEl0ZW0sIHNhZmVTZXRJdGVtIH0gZnJvbSAnLi4vLi4vdXRpbHMvc3RvcmFnZVV0aWxzJztcblxuY29uc3QgeyBEcmFnZ2VyIH0gPSBVcGxvYWQ7XG5jb25zdCB7IFRleHQgfSA9IFR5cG9ncmFwaHk7XG5cbmludGVyZmFjZSBEb2N1bWVudFVwbG9hZFByb3BzIHtcbiAgb3BlbjogYm9vbGVhbjtcbiAgb25DbG9zZTogKCkgPT4gdm9pZDtcbiAgb25TdWNjZXNzOiAoKSA9PiB2b2lkO1xuICAvKiog7Y6Y7J207KeAKOusuOyEnCDrqqnroZ0p7J2YIO2YhOyerCDsubTthYzqs6Drpqwg7ZWE7YSwLiDrqqjri6zsnbQg7Je066a0IOuVjCDquLDrs7gg7ISg7YOd7Jy866GcIOyDgeyGje2VnOuLpC5cbiAgICogV2h5OiDsubTthYzqs6Drpqwg65Sl66eB7YGs66GcIO2VhO2EsOqwgCDqsbjrprAg66qp66Gd7JeQ7IScIOuqqOuLrOydtCDrr7jshKDtg53snLzroZwg65yo66m0LCDsgqzsmqnsnpDripRcbiAgICogXCLsnbQg7Lm07YWM6rOg66asIOyViOyXkOyEnCDsmKzrprDri6RcIuqzoCDsnbjsi53tlZjripTrjbAg7Iuk7KCc66Gc64qUIOuvuOu2hOulmOuhnCDqsIDqs6Ag7ZWE7YSwIOuVjOusuOyXkFxuICAgKiDrs7TsnbTsp4Drj4Qg7JWK64qU64ukLiDrrLjrp6Ug7IOB7IaN7Jy866GcIOyduOyLneqzvCDrj5nsnpHsnYQg7J287LmY7Iuc7YKo64ukLiDsgqzsmqnsnpDripQg7Jes7KCE7Z6IXG4gICAqIOuqqOuLrOyXkOyEnCDsnpDsnKDroa3qsowg67OA6rK97ZWgIOyImCDsnojri6QuICovXG4gIGRlZmF1bHRDYXRlZ29yeUlkPzogc3RyaW5nO1xufVxuXG50eXBlIFVwbG9hZFN0YXRlID0ge1xuICAvLyBXaHk6ICdjYW5jZWxsZWQnIOuKlCDsgqzsmqnsnpDqsIAg66qF7Iuc7KCB7Jy866GcIOykkeuLqO2VnCDtjIzsnbwo7KeE7ZaJIOykkSArIOuMgOq4sOyXtCnsnYQgJ2Vycm9yJyDsmYAg6rWs67aE7ZW0XG4gIC8vIOykkeumveyggeycvOuhnChcIuykkeuLqOuQqFwiKSDrs7Tsl6zso7zquLAg7JyE7ZWcIOyDge2DnC4gJ2Vycm9yJyDroZwg7ZGc6riw7ZWY66m0IOyEnOuyhC/rhKTtirjsm4ztgawg7Iuk7Yyo7LKY65+8IOuztOyXrFxuICAvLyDsmKTtlbTrpbwg7KSA64ukLlxuICBzdGF0dXM6ICdxdWV1ZWQnIHwgJ3VwbG9hZGluZycgfCAnc3VjY2VzcycgfCAnZXJyb3InIHwgJ2NhbmNlbGxlZCc7XG4gIHByb2dyZXNzOiBudW1iZXI7XG4gIGVycm9yPzogc3RyaW5nO1xuICBuYW1lPzogc3RyaW5nO1xufTtcblxuLy8gYXhpb3Mg7Leo7IaMIOyXkOufrOyduOyngCDqsqzqs6DtlZjqsowg7YyQ67OE7ZWc64ukLiBheGlvcy5pc0NhbmNlbCDsmbjsl5Ag7ZmY6rK97JeQIOuUsOudvCBuYW1lIOunjCDri6Trpbhcbi8vIENhbmNlbGVkRXJyb3IgLyBBYm9ydEVycm9yIOuPhCDtlajqu5gg7J247KCV7ZWc64ukLlxuZnVuY3Rpb24gaXNBYm9ydEVycm9yKGVycjogdW5rbm93bik6IGJvb2xlYW4ge1xuICBpZiAoYXhpb3MuaXNDYW5jZWwoZXJyKSkgcmV0dXJuIHRydWU7XG4gIGNvbnN0IG5hbW
790UgPSAoZXJyIGFzIHsgbmFtZT86IHN0cmluZyB9IHwgbnVsbCB8IHVuZGVmaW5lZCk/Lm5hbWU7XG4gIHJldHVybiBuYW1lID09PSAnQ2FuY2VsZWRFcnJvcicgfHwgbmFtZSA9PT0gJ0Fib3J0RXJyb3InO1xufVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBEb2N1bWVudFVwbG9hZCh7IG9wZW4sIG9uQ2xvc2UsIG9uU3VjY2VzcywgZGVmYXVsdENhdGVnb3J5SWQgfTogRG9jdW1lbnRVcGxvYWRQcm9wcykge1xuICBjb25zdCB7IG1lc3NhZ2U6IG1lc3NhZ2VBcGkgfSA9IEFudGRBcHAudXNlQXBwKCk7XG4gIC8vIFdoeTogdXNlRG9jdW1lbnRTdG9yZSgpIOyghOyytCDqtazrj4Ug4oaSIDEwME1CIOyXheuhnOuTnCBwcm9ncmVzcyDsnbTrsqTtirgg64+E7KSRIHN0b3JlIOydmCDrqqjrk6BcbiAgLy8gbXV0YXRpb24g7J20IGRyYWdnZXIgKyBwZXItZmlsZSBQcm9ncmVzcyDsnqzroIzrjZQgc3Rvcm0uIFIxNjcvUjE2OC9SMTc1IO2MqO2EtOycvOuhnCBjYXRlZ29yaWVzXG4gIC8vIHNsaWNlIOunjCDqtazrj4UuXG4gIGNvbnN0IGNhdGVnb3JpZXMgPSB1c2VEb2N1bWVudFN0b3JlKChzKSA9PiBzLmNhdGVnb3JpZXMpO1xuICBjb25zdCBbdXBsb2FkaW5nLCBzZXRVcGxvYWRpbmddID0gdXNlU3RhdGUoZmFsc2UpO1xuICBjb25zdCBbZmlsZUxpc3QsIHNldEZpbGVMaXN0XSA9IHVzZVN0YXRlPFVwbG9hZEZpbGVbXT4oW10pO1xuICBjb25zdCBbc2VsZWN0ZWRDYXRlZ29yeSwgc2V0U2VsZWN0ZWRDYXRlZ29yeV0gPSB1c2VTdGF0ZTxzdHJpbmcgfCB1bmRlZmluZWQ+KHVuZGVmaW5lZCk7XG4gIGNvbnN0IFt1cGxvYWRTdGF0dXNlcywgc2V0VXBsb2FkU3RhdHVzZXNdID0gdXNlU3RhdGU8UmVjb3JkPHN0cmluZywgVXBsb2FkU3RhdGU+Pih7fSk7XG4gIC8vIFdoeTogUjE4MCDsnZggXCJwcmVzZXJ2ZSBhdXRvVXBsb2FkIGFjcm9zcyByZW9wZW5cIiDsnZjrj4TqsIAgdXNlU3RhdGUgbGF6eSBpbml0IOydtOudvFxuICAvLyBEb2N1bWVudFVwbG9hZCBjb21wb25lbnQg6rCAIHVubW91bnQg65CY66m0IChwYXJlbnQg7J2YIG9wZW49ZmFsc2Ug6rCAIG1vZGFsIOuLq+qzoCBjb21wb25lbnQg64+EXG4gIC8vIHVubW91bnQpIOuLpOydjCBtb3VudCDsi5wgZGVmYXVsdCB0cnVlIOuhnCByZXNldCDrkJjslrQg7IKs7Jqp7J6QIHByZWZlcmVuY2Ugc2lsZW50IOyGkOyLpC4gbG9jYWxTdG9yYWdlXG4gIC8vIOuhnCDsmIHqtawg67O07KG0LiAndHJ1ZScgLyAnZmFsc2UnIOuqheyLnCDrrLjsnpDsl7Qg7IKs7JqpLlxuICBjb25zdCBbYXV0b1VwbG9hZCwgc2V0QXV0b1VwbG9hZF0gPSB1c2VTdGF0ZSgoKSA9PiB7XG4gICAgY29uc3Qgc3RvcmVkID0gc2FmZUdldEl0ZW0oU1RPUkFHRV9LRVlTLkRPQ1VNRU5UX1VQTE9BRF9BVVRPKTtcbiAgICBpZiAoc3RvcmVkID09PSAnZmFsc2UnKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xuICAvLyBXaHk6IOy0iOq4sCBtb3VudCDsi5wgdXNlU3RhdGUgaW5pdCDsnLzroZwg7J297J2AIOqwkuydhCDsponsi5wg64uk7IucIHNldEl0ZW0g7ZWY66m0IGNyb3NzLXRhYiDsi5zrgpjrpqzsmKRcbiAgLy8g7JeQ7IScIOuLpOuluCDtg63snbQg642UIOy1nOyLoOqwkuycvOuhnCDrsJTqvrwg7KeB7ZuEIOuzuCDtg63snbQgbW91bnQg7ZWY66m0IHN0YWxlIOqwkuycvOuhnCDrja7slrTsk7DquLAg6rCA64qlLlxuICAvLyAoc3RvcmFnZSBldmVudCBsaXN0ZW5lciDqsIAg7JeG7Ja0IOuLpOuluCDtg63snZgg67OA6rK97J2EIOyViCDrs7TripQg7IOB7ZmpICsg67O4IO2DreydmCBtb3VudCDqsIAg6re4IOydtO2bhOudvOuPhFxuICAvLyB1c2VTdGF0ZSBpbml0IOydtCBjYWNoZSBoaXQg7Jy866GcIOyYmyDqsJIg7J297J2MLikg7LKrIG1vdW50IOydmCByZWR1bmRhbnQgd3JpdGUg66W8IHNraXAuXG4gIGNvbnN0IGF1dG9VcGxvYWREaWRNb3VudFJlZiA9IHVzZVJlZihmYWxzZSk7XG4gIC8vIFdoeTog7KeE7ZaJIOykkeyduCDsl4XroZzrk5wgcnVuIOydhCDspJHri6jtlZjquLAg7JyE7ZWcIEFib3J0Q29udHJvbGxlci4g66qo65OgIGluLWZsaWdodCBheGlvcyDsmpTssq3sl5BcbiAgLy8g6rCZ7J2AIHNpZ25hbCDsnYQg64SY6rKoIO2VnCDrsojsnZggYWJvcnQoKSDroZwg7ZiE7J6sIO2MjOydvOydhCDst6jshoztlZjqs6Ag66Oo7ZSE66W8IOu5oOyguOuCmOqwhOuLpC5cbiAgY29uc3QgYWJvcnRSZWYgPSB1c2VSZWY8QWJvcnRDb250cm9sbGVyIHwgbnVsbD4obnVsbCk7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFhdXRvVXBsb2FkRGlkTW91bnRSZWYuY3VycmVudCkge1xuICAgICAgYXV0b1VwbG9hZERpZE1vdW50UmVmLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzYWZlU2V0SXRlbShTVE9SQUdFX0tFWVMuRE9DVU1FTlRfVVBMT0FEX0FVVE8sIGF1dG9VcGxvYWQgPyAndHJ1ZScgOiAnZmFsc2UnKTtcbiAgfSwgW2F1dG9VcGxvYWRdKTtcblxuICAvLyBXaHk6IOydtOyghOyXlCBsYXp5LVxuICAvLyBpbml0IOycvOuhnOunjCDsnb3slrQgVGFiIEEg6rCAIGF1dG8tdXBsb2FkIE9GRiDroZwg67CU6r+U64+EIOydtOuvuCBtb3VudCDrkJwgVGFiIEIg65iQ64qUXG4gIC8vIOymieyLnCByZW9wZW4g7IucIHN0YWxlIHRydWUg7Jyg7KeAIOKGkiDsgqzsmqnsnpDqsIAgVGFiIEIg7JeQ7IScIO2MjOydvCDrk5zrnpjqt7gg7IucIOydmOuPhOy5mFxuICAvLyDslYrsnYAg7J6Q64+ZIOyXheuhnOuTnCDrsJzsgqwgKFRhYiBBIOydmCBwcmVmZXJlbmNlIOustOyLnCkuIHN0b3JhZ2UgZXZlbnQg66GcIGNyb3NzLXRhYlxuICAvLyBzeW5jIOKAlCDri6Trpbgg7YOt7J2YIOuzgOqyvSDsponsi5wg67CY7JiBLlxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGNvbnN0IG9uU3RvcmFnZSA9IChlOiBTdG9yYWdlRXZlbnQpID0+IHtcbiAgICAgIGlmIChlLmtleSA9PT0gU1RPUkFHRV9LRVlTLkRPQ1VNRU5UX1VQTE9BRF9BVVRPICYmIGUubmV3VmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgY29uc3QgbmV4dCA9IGUubmV3VmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgc2V0QXV0b1VwbG9hZChuZXh0KTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHdpbmRvdy5hZGR
790FdmVudExpc3RlbmVyKCdzdG9yYWdlJywgb25TdG9yYWdlKTtcbiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3N0b3JhZ2UnLCBvblN0b3JhZ2UpO1xuICB9LCBbXSk7XG5cbiAgLy8gV2h5OiDsl4XroZzrk5wg7KeE7ZaJIOykkeyXkCDsu7Ttj6zrhIztirjqsIAgdW5tb3VudCDrkJjrqbQo67aA66qo6rCAIOuqqOuLrOydhCDsoJzqsbApIGluLWZsaWdodCDsmpTssq3snbQg64Ko7JWEXG4gIC8vIOyZhOujjCDsi5wgc2V0VXBsb2FkU3RhdHVzZXMg6rCAIOyCrOudvOynhCDsu7Ttj6zrhIztirjsl5Agc2V0U3RhdGUg66W8IOyLnOuPhO2VnOuLpC4gdW5tb3VudCDsi5wg64Ko7J2AXG4gIC8vIOy7qO2KuOuhpOufrOulvCBhYm9ydCDtlbQg7JqU7LKt7J2EIOuBiuqzoCBzZXRTdGF0ZS1hZnRlci11bm1vdW50IOulvCDrsKnsp4DtlZzri6QuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGFib3J0UmVmLmN1cnJlbnQ/LmFib3J0KCk7XG4gICAgfTtcbiAgfSwgW10pO1xuXG4gIC8vIOuqqOuLrOydtCDri6vtmJTri6Qg64uk7IucIOyXtOumrOuptCDsnbTsoIQg7IS47IWY7J2YIGZpbGVMaXN0IC8gdXBsb2FkU3RhdHVzZXMgLyBzZWxlY3RlZENhdGVnb3J5IOqwgFxuICAvLyDqt7jrjIDroZwg64Ko7JWEIOyeiOyWtCDsgqzsmqnsnpAg7Zi864+ZIOycoOuwnC4gb3BlbiA9PT0gdHJ1ZSDroZwg67CU64CUIOuVjCDstIjquLDtmZQuXG4gIC8vIFdoeTogYXV0b1VwbG9hZCDripQg7IKs7Jqp7J6Q6rCAIOuqheyLnOyggeycvOuhnCDrgYgg7ZmY6rK9ICjrjIDrn4kg6rKA7YagIO2bhCDrqoXsi5zsoIEgVXBsb2FkIO2BtOumrSkg7JeQ7IScXG4gIC8vIOuqqOuLrCDri6vqs6Ag64uk7IucIOyXtOuptCBzaWxlbnQg66GcIOuLpOyLnCDsvJzsoLgsIOuLpOydjCDrk5zrnpjqt7gg7IucIOydmOuPhOy5mCDslYrsnYAg7J6Q64+ZIOyXheuhnOuTnCDrsJzsg50uIOuLpOuluFxuICAvLyBzZXNzaW9uLXN0YXRlIChmaWxlTGlzdCDrk7EpIOyZgCDri6zrpqwg7IKs7Jqp7J6QIHByZWZlcmVuY2Ug6528IHJlc2V0IOuMgOyDgeyXkOyEnCDsoJzsmbjtlbQg67O07KG0LlxuICAvLyBxdWV1ZU1pY3JvdGFzazogc2V0U3RhdGUg6rCAIGVmZmVjdCBib2R5IOyXkCDsp4HsoJEg7J6I7Jy866m0IFJlYWN0IDE5IHNldC1zdGF0ZS1pbi1lZmZlY3Qg6rCAXG4gIC8vIOyeoeuKlOuLpC4gbWljcm90YXNrIOuhnCDsmK7quLDrqbQgY29tbWl0IOynge2bhCDqsJnsnYAgdGljayDsl5Ag7Iuk7ZaJ65CY7Ja0IOyCrOyaqeyekCDssrTqsJAg64+Z7J28LlxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghb3BlbikgcmV0dXJuO1xuICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IHtcbiAgICAgIHNldEZpbGVMaXN0KFtdKTtcbiAgICAgIC8vIFdoeTogdW5kZWZpbmVkIOuhnCDrpqzshYvtlZjrqbQg7Lm07YWM6rOg66asIO2VhO2EsOqwgCDqsbjrprAg66qp66Gd7JeQ7IScIOyXsCDrqqjri6zsnbQg66y466el7J2EIOyeg+uKlOuLpFxuICAgICAgLy8gKOuUpeunge2BrCDsnKDsnoUgKyDshLHqs7Ug7ZuEIOyekOuPmSDri6vtnpgg4oaSIOyerOyYpO2UiCDrqqjrkZApLiDtjpjsnbTsp4DqsIAg64SY6rKo7KSAIOq4sOuzuOqwkuycvOuhnCDrs7Xsm5AuXG4gICAgICBzZXRTZWxlY3RlZENhdGVnb3J5KGRlZmF1bHRDYXRlZ29yeUlkKTtcbiAgICAgIHNldFVwbG9hZFN0YXR1c2VzKHt9KTtcbiAgICB9KTtcbiAgfSwgW29wZW4sIGRlZmF1bHRDYXRlZ29yeUlkXSk7XG5cbiAgY29uc3QgY2F0ZWdvcnlPcHRpb25zID0gZmxhdHRlbkNhdGVnb3JpZXMoY2F0ZWdvcmllcyk7XG5cbiAgY29uc3QgdXBsb2FkUHJvcHM6IFVwbG9hZFByb3BzID0ge1xuICAgIG5hbWU6ICdmaWxlJyxcbiAgICBtdWx0aXBsZTogdHJ1ZSxcbiAgICBmaWxlTGlzdCxcbiAgICBkaXNhYmxlZDogdXBsb2FkaW5nLFxuICAgIGJlZm9yZVVwbG9hZDogKGZpbGUpID0+IHtcbiAgICAgIC8vIENsZWFyIG9sZCBzdGF0dXMgdHJhY2VzIHdoZW4gdXNlciBzZWxlY3RzIG5ldyBmaWxlcyBhZnRlciBhIHByZXZpb3VzIHVwbG9hZCBydW5cbiAgICAgIGlmICghdXBsb2FkaW5nICYmIE9iamVjdC5rZXlzKHVwbG9hZFN0YXR1c2VzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgIHNldFVwbG9hZFN0YXR1c2VzKHt9KTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2hlY2sgZmlsZSB0eXBlXG4gICAgICBjb25zdCBmaWxlRXh0ID0gZ2V0RmlsZUV4dGVuc2lvbihmaWxlLm5hbWUpO1xuICAgICAgaWYgKCFmaWxlRXh0IHx8ICFGSUxFX1VQTE9BRC5TVVBQT1JURURfVFlQRVMuaW5jbHVkZXMoZmlsZUV4dCkpIHtcbiAgICAgICAgbWVzc2FnZUFwaS5lcnJvcihcbiAgICAgICAgICBg7KeA7JuQ7ZWY7KeAIOyViuuKlCDtjIzsnbwg7ZiV7IudOiAke2ZpbGVFeHQgfHwgJ+yVjCDsiJgg7JeG7J2MJ30uIOyngOybkCDtmJXsi506ICR7RklMRV9VUExPQUQuU1VQUE9SVEVEX1RZUEVTLmpvaW4oJywgJyl9YFxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gVXBsb2FkLkxJU1RfSUdOT1JFO1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBmaWxlIHNpemVcbiAgICAgIGlmIChmaWxlLnNpemUgPiBGSUxFX1VQTE9BRC5NQVhfU0laRSkge1xuICAgICAgICBtZXNzYWdlQXBpLmVycm9yKGBcIiR7ZmlsZS5uYW1lfVwiIO2MjOydvOydtCDrhIjrrLQg7YG964uI64ukLiDstZzrjIAg7YGs6riwOiAke2Zvcm1hdEZpbGVTaXplKEZJTEVfVVBMT0FELk1BWF9TSVpFKX1gKTtcbiAgICAgICAgcmV0dXJuIFVwbG9hZC5MSVNUX0lHTk9SRTtcbiAgICAgIH1cblxuICAgICAgbGV0IGNhbkFkZCA9IHRydWU7XG4gICAgICBsZXQgZHVwbGljYXRlID0gZmFsc2U7XG5cbiAgICAgIC8vIENoZWNrIGZpbGUgY291bnQgKHVzZSBsYXRlc3Qgc3RhdGUgaW5zaWRlIHVwZGF0ZXIgdG8gYXZvaWQgc3RhbGUgbGVuZ3RoIHdpdGggbXVsdGktc2VsZWN0KVxuICAgICAgc2V0RmlsZUxpc3QoKHByZXYpID0+IHtcbiAgICAgICAgLy8g6rCZ7J2AIG5hbWUrc2l6ZStsYXN0TW9kaWZpZWQg7KGw7ZWp7J20IOydtOuvuCDrpqzsiqTtirjsl5Ag7J6I7Jy866m0IOykkeuztSDstpTqsIAg66eJ6riwLlxuICAgICAgICAvLyBBbnRkIOydmCB1aWQg64qUIOunpOuyiCDsg4jroZwg7IOd6rKoIGRlZHVwIOyXre2VoOydhCDrqrvtlZjrr4DroZwg67OE64+EIO2CpOuhnCDruYTqtZAuXG4gICAgICAgIGNvbnN0IGZpbGVLZXkgPSBgJHtmaWxlLm5hbWV9OiR7ZmlsZS5zaXplfTokeyhmaWxlIGFzIEZpbGUpLmxhc3RNb2RpZmllZCA/PyAnJ31gO1
790xuICAgICAgICBjb25zdCBhbHJlYWR5UHJlc2VudCA9IHByZXYuc29tZShcbiAgICAgICAgICAoZikgPT4gYCR7Zi5uYW1lfToke2Yuc2l6ZSA/PyAnJ306JHsoZiBhcyBVcGxvYWRGaWxlICYgeyBsYXN0TW9kaWZpZWQ/OiBudW1iZXIgfSkubGFzdE1vZGlmaWVkID8/ICcnfWAgPT09IGZpbGVLZXksXG4gICAgICAgICk7XG4gICAgICAgIGlmIChhbHJlYWR5UHJlc2VudCkge1xuICAgICAgICAgIGR1cGxpY2F0ZSA9IHRydWU7XG4gICAgICAgICAgcmV0dXJuIHByZXY7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYWN0aXZlQ291bnQgPSBwcmV2LmZpbHRlcigoZikgPT4gdXBsb2FkU3RhdHVzZXNbZi51aWRdPy5zdGF0dXMgIT09ICdzdWNjZXNzJykubGVuZ3RoO1xuICAgICAgICBpZiAoYWN0aXZlQ291bnQgPj0gRklMRV9VUExPQUQuTUFYX0ZJTEVTKSB7XG4gICAgICAgICAgY2FuQWRkID0gZmFsc2U7XG4gICAgICAgICAgcmV0dXJuIHByZXY7XG4gICAgICAgIH1cbiAgICAgICAgLy8gV2h5OiBSY0ZpbGUo7KeE7KecIEZpbGUp7J2EIGZpbGVMaXN0IOyXkCDqt7jrjIDroZwg64u07Jy866m0LCDsnbTtm4Qg7KeE7ZaJ66WgL+yDge2DnCDqsLHsi6DsnbRcbiAgICAgICAgLy8gYHsgLi4uZiwgc3RhdHVzOiAndXBsb2FkaW5nJyB9YCDroZwg7Iqk7ZSE66CI65Oc7ZWY64qUIOyInOqwhCBGaWxlIOydtCDslYTri4wg7Y+J67KU7ZWcIOqwneyytOqwgFxuICAgICAgICAvLyDrkJzri6QuIEZpbGUg7J2YIG5hbWUvc2l6ZS/rjbDsnbTthLDripQg7ZSE66Gc7Yag7YOA7J6FIGdldHRlciDrnbwg7Iqk7ZSE66CI65Oc6rCAIOuzteyCrO2VmOyngCDrqrvtlZzri6RcbiAgICAgICAgLy8gKG93biBlbnVtZXJhYmxlIOydtCDruYTslrQg7J6I64ukKS4g6re4IOqwneyytOulvCBGb3JtRGF0YSDsl5Ag64Sj7Jy866m0IFwiW29iamVjdCBPYmplY3RdXCJcbiAgICAgICAgLy8g66y47J6Q7Je07J20IOuQmOyWtCBmaWxlbmFtZSDsl4bripQg7YyM7Yq466GcIOyghOyGoeuQmOqzoCwg7ISc67KE6rCAIDQyMiBcIkV4cGVjdGVkIFVwbG9hZEZpbGUsXG4gICAgICAgIC8vIHJlY2VpdmVkOiBzdHJcIiDrpbwg64K464ukLiDssqsg7Iuc64+E64qUIOybkOuzuOydtOudvCDshLHqs7XtlZjqs6Ag7J6s7Iuc64+E66eMIOyLpO2MqO2VtCDstpTsoIHsnbRcbiAgICAgICAgLy8g7Ja066Ck7Jug64ukKOyatOyYgSDroZzqt7ggMjAxIC0+IDQwOSAtPiA0MjIpLlxuICAgICAgICAvLyBhbnRkIOq3nOyVveuMgOuhnCBVcGxvYWRGaWxlIOuemO2NvOyXkCDri7Tqs6Ag7JuQ67O47J2AIG9yaWdpbkZpbGVPYmog66GcIOywuOyhsOulvCDrs7TsobTtlZzri6QuXG4gICAgICAgIC8vIOyKpO2UhOugiOuTnOuKlCDrnpjtjbzrp4wg67O17IKs7ZWY6rOgIG9yaWdpbkZpbGVPYmog64qUIOywuOyhsOuhnCDsgrTslYTrgqjripTri6QuXG4gICAgICAgIGNvbnN0IHdyYXBwZWQ6IFVwbG9hZEZpbGUgPSB7XG4gICAgICAgICAgdWlkOiBmaWxlLnVpZCxcbiAgICAgICAgICBuYW1lOiBmaWxlLm5hbWUsXG4gICAgICAgICAgc2l6ZTogZmlsZS5zaXplLFxuICAgICAgICAgIHR5cGU6IGZpbGUudHlwZSxcbiAgICAgICAgICBvcmlnaW5GaWxlT2JqOiBmaWxlLFxuICAgICAgICB9O1xuICAgICAgICByZXR1cm4gWy4uLnByZXYsIHdyYXBwZWRdO1xuICAgICAgfSk7XG5cbiAgICAgIGlmIChkdXBsaWNhdGUpIHtcbiAgICAgICAgbWVzc2FnZUFwaS5pbmZvKHtcbiAgICAgICAgICBrZXk6IGB1cGxvYWQtZHVwLSR7ZmlsZS5uYW1lfWAsXG4gICAgICAgICAgY29udGVudDogYFwiJHtmaWxlLm5hbWV9XCIg7J2AKOuKlCkg7J2066+4IOuMgOq4sOyXtOyXkCDsnojsirXri4jri6QuYCxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBVcGxvYWQuTElTVF9JR05PUkU7XG4gICAgICB9XG5cbiAgICAgIGlmICghY2FuQWRkKSB7XG4gICAgICAgIG1lc3NhZ2VBcGkuZXJyb3Ioe1xuICAgICAgICAgIGtleTogJ3VwbG9hZC1tYXgtZmlsZXMnLFxuICAgICAgICAgIGNvbnRlbnQ6IGDtlZwg67KI7JeQIOy1nOuMgCAke0ZJTEVfVVBMT0FELk1BWF9GSUxFU33qsJzquYzsp4Ag7JeF66Gc65Oc7ZWgIOyImCDsnojsirXri4jri6RgLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFVwbG9hZC5MSVNUX0lHTk9SRTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZhbHNlOyAvLyBQcmV2ZW50IGF1dG8gdXBsb2FkXG4gICAgfSxcbiAgICBvblJlbW92ZTogKGZpbGUpID0+IHtcbiAgICAgIGlmICh1cGxvYWRpbmcpIHJldHVybiBmYWxzZTtcbiAgICAgIHNldEZpbGVMaXN0KChwcmV2KSA9PiBwcmV2LmZpbHRlcigoZikgPT4gZi51aWQgIT09IGZpbGUudWlkKSk7XG4gICAgICBzZXRVcGxvYWRTdGF0dXNlcygocHJldikgPT4ge1xuICAgICAgICBjb25zdCBuZXh0ID0geyAuLi5wcmV2IH07XG4gICAgICAgIGRlbGV0ZSBuZXh0W2ZpbGUudWlkXTtcbiAgICAgICAgcmV0dXJuIG5leHQ7XG4gICAgICB9KTtcbiAgICB9LFxuICB9O1xuXG4gIGNvbnN0IGhhbmRsZUNhbmNlbCA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICAvLyBXaHk6IOyXheuhnOuTnCDspJEgWC9Fc2MvbWFzayDtgbTrpq0v7Leo7IaM66GcIOuLq+q4sOulvCDsi5zrj4TtlZjrqbQsIOydtOygnOuKlCDrp4nripQg64yA7IugIOynhO2WiSDspJHsnbggcnVuIOydhFxuICAgIC8vIGFib3J0IO2VnOuLpC4gaGFuZGxlVXBsb2FkIOydmCBhYm9ydCDsspjrpqwg67aE6riw6rCAIOydtOuvuCDsmKzrnbzqsIQg7YyM7J287J2EIOuztOyhtO2VnCDssYQgdXBsb2FkaW5nPWZhbHNlXG4gICAgLy8g66GcIOygleumrO2VmOqzoCDslYjrgrTrpbwg652E7Jq064ukLiDsl6zquLDshJzripQgYWJvcnQg66eMIO2KuOumrOqxsO2VmOqzoCDsi6TsoJwg64ur6riwL+umrOyFi+ydgCDsgqzsmqnsnpDqsIAg7ZWcIOuyiFxuICAgIC8vIOuNlCDri6vsnYQg65WMKOuYkOuKlCBhYm9ydCDsspjrpqwg7ZuEKSDsiJjtlontlZzri6QuIGFib3J0IOynge2bhCDqs6fsnqUgb25DbG9zZSDtlZjrqbQg66Oo7ZSE6rCAIOyVhOyngVxuICAgIC8vIHNldFVwbG9hZGluZyhmYWxzZSkg7KCE7J206528IOuLq+2ejCDrkqQg7Yag7Iqk7Yq46rCAIOucqOuKlCDsmJsg7Zi8656A7J20IOyerOuwnO2VmOuvgOuhnCDri6vsp4Ag7JWK64qU64ukLlxuICAgIGlmICh1cGxvYWRpbmcpIHtcbiAgICAgIGFib3J0UmVmLmN1cnJlbnQ/LmFib3J0KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHNldEZpbGVMaXN0KFtdKTtcbiAgICBzZXRTZWxlY3RlZENhdGVnb3J5KHVuZGVmaW5lZCk7XG4gICAgc2V0VXBsb2FkU3RhdHVzZXMoe30pO1xuICAgIG9uQ2xvc2UoKTtcbiAgfSwgW29uQ2xvc2UsIHVwbG9hZGluZ10pO1xuXG4gIGNvbnN0IGhhbmRsZVVwbG9h
790ZCA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBpZiAodXBsb2FkaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChmaWxlTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgIG1lc3NhZ2VBcGkud2FybmluZygn7JeF66Gc65Oc7ZWgIO2MjOydvOydhCAx6rCcIOydtOyDgSDshKDtg53tlbTso7zshLjsmpQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBXaHk6IO2YvO2VqSDshLHqs7Uv7Iuk7YyoIO2bhCDsgqzsmqnsnpDqsIAg7LaU6rCAIO2MjOydvOydhCDrk5zrnpjqt7jtlZjrqbQgYmVmb3JlVXBsb2FkIOqwgFxuICAgIC8vIHVwbG9hZFN0YXR1c2VzIOulvCDruYTsm4wgZWZmZWN0IOqwgCBoYW5kbGVVcGxvYWQg66W8IOyerOyLpO2Wie2VnOuLpC4g7J2065WMIOyEseqzte2WiOuNmFxuICAgIC8vIO2MjOydvOuPhCDri6Tsi5wgUE9TVCAvZG9jdW1lbnRzL3VwbG9hZCDroZwg7Jis65286rCAIOyEnOuyhOyXkCDspJHrs7Ug7IOd7ISxLiBmaWxlTGlzdCDsnZhcbiAgICAvLyBzdGF0dXM9J2RvbmUnIOuKlCDrgqjslYTsnojsnLzrr4DroZwg6re46rKD7Jy866GcIOyEseqzteu2hOydhCDsi53rs4TtlbQgc2tpcCAmIO2RnOyLnCDsnKDsp4AuXG4gICAgY29uc3QgaW5pdGlhbFN0YXR1c2VzID0gZmlsZUxpc3QucmVkdWNlPFJlY29yZDxzdHJpbmcsIFVwbG9hZFN0YXRlPj4oKGFjYywgZmlsZSkgPT4ge1xuICAgICAgaWYgKGZpbGUuc3RhdHVzID09PSAnZG9uZScpIHtcbiAgICAgICAgYWNjW2ZpbGUudWlkXSA9IHsgc3RhdHVzOiAnc3VjY2VzcycsIHByb2dyZXNzOiAxMDAsIG5hbWU6IGZpbGUubmFtZSB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWNjW2ZpbGUudWlkXSA9IHsgc3RhdHVzOiAncXVldWVkJywgcHJvZ3Jlc3M6IDAsIG5hbWU6IGZpbGUubmFtZSB9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIGFjYztcbiAgICB9LCB7fSk7XG4gICAgc2V0VXBsb2FkU3RhdHVzZXMoaW5pdGlhbFN0YXR1c2VzKTtcblxuICAgIC8vIOydtOuyiCDsl4XroZzrk5wgcnVuIOydmCBBYm9ydENvbnRyb2xsZXIuIFwi7JeF66Gc65OcIOykkeuLqFwiIOuyhO2KvCAvIGhhbmRsZUNhbmNlbCDsnbQg7J20IHNpZ25hbCDsnYRcbiAgICAvLyBhYm9ydCDtlZzri6QuIOuqqOuToCDtjIzsnbzsnbQg6rCZ7J2AIHNpZ25hbCDsnYQg6rO17Jyg7ZWY66+A66GcIO2VnCDrsojsnZggYWJvcnQg66GcIO2YhOyerCDtjIzsnbzsnbQg7Leo7IaM65Cc64ukLlxuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAgYWJvcnRSZWYuY3VycmVudCA9IGNvbnRyb2xsZXI7XG5cbiAgICBzZXRVcGxvYWRpbmcodHJ1ZSk7XG4gICAgLy8g7JeF66Gc65OcIOyLnOyekSDsi5zsoJDsnZgg7Lm07YWM6rOg66asIOyEoO2DneydhCDroZzsu6wg67OA7IiY66GcIOy6oeyymO2VnOuLpC4g7IKs7Jqp7J6Q6rCAIOujqO2UhCDsp4Ttlokg7KSR7JeQXG4gICAgLy8g7Lm07YWM6rOg66asIOuTnOuhreuLpOyatOydhCDrsJTqvrjrqbQg64Ko7J2AIO2MjOydvOuTpOydtCDsg4gg7Lm07YWM6rOg66as66GcIOyYrOudvOqwgCBcIuy5tO2FjOqzoOumrCBBIOyEoO2Dne2WiOuKlOuNsFxuICAgIC8vIEIg66GcIOuTpOyWtOqwkFwiIOydtOudvOuKlCDtmLzrnoDsnbQg67Cc7IOdLiDro6jtlIQg7KCE7LK06rCAIO2VnCDrsojsnZgg7ISg7YOd7Jy866GcIOydvOq0gOuQmOqyjCDsl4XroZzrk5zrkJjqsowg6rOg7KCVLlxuICAgIGNvbnN0IHVwbG9hZENhdGVnb3J5SWQgPSBzZWxlY3RlZENhdGVnb3J5O1xuICAgIHRyeSB7XG4gICAgICBsZXQgc3VjY2Vzc2Z1bCA9IDA7XG4gICAgICBsZXQgZmFpbGVkID0gMDtcblxuICAgICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVMaXN0KSB7XG4gICAgICAgIC8vIOydtOuvuCDshLHqs7XtlZwg7YyM7J287J2AIOyEnOuyhCDsnqzsl4XroZzrk5wg67Cp7KeA66W8IOychO2VtCDqsbTrhIjrnIAgKGluaXRpYWxTdGF0dXNlcyDsl5DshJwgJ3N1Y2Nlc3MnIOuhnCDrs7TsobTrkKgpLlxuICAgICAgICBpZiAoZmlsZS5zdGF0dXMgPT09ICdkb25lJykgY29udGludWU7XG4gICAgICAgIGNvbnN0IHVpZCA9IGZpbGUudWlkO1xuICAgICAgICBjb25zdCByYXdGaWxlID0gKGZpbGUgYXMgVXBsb2FkRmlsZSkub3JpZ2luRmlsZU9iaiBhcyBGaWxlIHwgdW5kZWZpbmVkO1xuICAgICAgICBjb25zdCBmaWxlVG9VcGxvYWQgPSByYXdGaWxlID8/IChmaWxlIGFzIHVua25vd24gYXMgRmlsZSk7XG4gICAgICAgIGNvbnN0IGRpc3BsYXlOYW1lID0gdXBsb2FkU3RhdHVzZXNbdWlkXT8ubmFtZSB8fCBmaWxlLm5hbWU7XG5cbiAgICAgICAgLy8gTWFyayBhcyB1cGxvYWRpbmdcbiAgICAgICAgc2V0VXBsb2FkU3RhdHVzZXMoKHByZXYpID0+ICh7XG4gICAgICAgICAgLi4ucHJldixcbiAgICAgICAgICBbdWlkXTogeyAuLi4ocHJldlt1aWRdIHx8IHsgcHJvZ3Jlc3M6IDAsIG5hbWU6IGRpc3BsYXlOYW1lIH0pLCBzdGF0dXM6ICd1cGxvYWRpbmcnLCBwcm9ncmVzczogcHJldlt1aWRdPy5wcm9ncmVzcyA/PyAwLCBuYW1lOiBkaXNwbGF5TmFtZSB9LFxuICAgICAgICB9KSk7XG4gICAgICAgIHNldEZpbGVMaXN0KChwcmV2KSA9PiB7XG4gICAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBwcmV2LmZpbmQoKHApID0+IHAudWlkID09PSB1aWQpO1xuICAgICAgICAgIHJldHVybiBwcmV2Lm1hcCgoZikgPT5cbiAgICAgICAgICAgIGYudWlkID09PSB1aWRcbiAgICAgICAgICAgICAgPyB7IC4uLmYsIG5hbWU6IGYubmFtZSB8fCBkaXNwbGF5TmFtZSwgc3RhdHVzOiAndXBsb2FkaW5nJywgcGVyY2VudDogZXhpc3Rpbmc/LnBlcmNlbnQgPz8gMCB9XG4gICAgICAgICAgICAgIDogZlxuICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgdXBsb2FkZWQgPSBhd2FpdCB1cGxvYWREb2N1bWVudChmaWxlVG9VcGxvYWQsIHVwbG9hZENhdGVnb3J5SWQsIHtcbiAgICAgICAgICAgIHRpbWVvdXQ6IEZJTEVfVVBMT0FELlVQTE9BRF9USU1FT1VUX01TLFxuICAgICAgICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICAgICAgICAgIG9uVXBsb2FkUHJvZ3Jlc3M6IChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAvLyBXaHk6IEhUVFAvMiArIGd6aXAg65iQ64qUIGNodW5rZWQgdHJhbnNmZXIg7ZmY6rK97JeQ7IScIGZpbmFsIHByb2dyZXNzIOydtOuypO2KuOqwgFxuICAgICAgICAgICAgICAvLyBldmVudC5sb2FkZWQgPiBldmVudC50b3RhbCAoMTAxfjEwNSUpIOuYkOuKlCBldmVudC50b3RhbCA9PT0gMCAoTmFOL0luZmluaXR5KSDroZxcbiAgICAgICAgICAgICAgLy8g64+E64us7ZWY64qUIOyCrOuhgOqwgCDsnojri6QuIOq3uOuMgOuhnCBhbnRkIFByb2dyZXNzIOyXkCDrhJjquLDrqbQg66eJ64yA6rCAIG92ZXJzaG9vdCDrkJjqsbDrgphcbiAgICAgICAgICAgICAgLy8g7JiB7JuQ7Z6IIFwiVXBsb2FkaW5nXCIg7IOB7YOc66GcIOu
790CqOuKlOuLpC4gMH4xMDAg7YG0656o7ZSEICsgdG90YWw9MCDsi5wgdW5kZWZpbmVkIOuwmO2ZmC5cbiAgICAgICAgICAgICAgY29uc3QgcmF3UGVyY2VudCA9IGV2ZW50LnRvdGFsXG4gICAgICAgICAgICAgICAgPyBNYXRoLnJvdW5kKChldmVudC5sb2FkZWQgLyBldmVudC50b3RhbCkgKiAxMDApXG4gICAgICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgIGNvbnN0IHBlcmNlbnQgPVxuICAgICAgICAgICAgICAgIHJhd1BlcmNlbnQgPT09IHVuZGVmaW5lZCB8fCAhTnVtYmVyLmlzRmluaXRlKHJhd1BlcmNlbnQpXG4gICAgICAgICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgICAgOiBNYXRoLm1pbigxMDAsIE1hdGgubWF4KDAsIHJhd1BlcmNlbnQpKTtcbiAgICAgICAgICAgICAgLy8gV2h5OiBvblVwbG9hZFByb2dyZXNzIOuKlCBYSFIg67CU7J207Yq466eI64ukIHRyaWdnZXIg65CgIOyImCDsnojslrQsIO2BsCDtjIzsnbwg7JeF66Gc65OcXG4gICAgICAgICAgICAgIC8vIOyLnCDstIjri7kg7IiY67CxfuyImOyynCDrsogg65GQIOqwnOydmCBzZXRTdGF0ZSDqsIAg7Iuk7ZaJ64+8IHJlbmRlciBzdG9ybSDsnbQg67Cc7IOd7ZaI64ukLlxuICAgICAgICAgICAgICAvLyDrsLHrtoTsnKjsnbQg67CU64CM7KeAIOyViuyVmOycvOuptCBzdGF0ZSB1cGRhdGUg66W8IOqxtOuEiOubsOyWtCDroIzrjZQg7Zqf7IiY66W8IDB+MTAwIO2ajOuhnCDsoJztlZwuXG4gICAgICAgICAgICAgIHNldFVwbG9hZFN0YXR1c2VzKChwcmV2KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcHJldlByb2dyZXNzID0gcHJldlt1aWRdPy5wcm9ncmVzcztcbiAgICAgICAgICAgICAgICBjb25zdCBuZXh0UHJvZ3Jlc3MgPSBwZXJjZW50ID8/IHByZXZQcm9ncmVzcyA/PyAwO1xuICAgICAgICAgICAgICAgIGlmIChwcmV2W3VpZF0/LnN0YXR1cyA9PT0gJ3VwbG9hZGluZycgJiYgcHJldlByb2dyZXNzID09PSBuZXh0UHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBwcmV2O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgLi4ucHJldixcbiAgICAgICAgICAgICAgICAgIFt1aWRdOiB7XG4gICAgICAgICAgICAgICAgICAgIC4uLihwcmV2W3VpZF0gfHwgeyBzdGF0dXM6ICd1cGxvYWRpbmcnLCBwcm9ncmVzczogMCwgbmFtZTogZGlzcGxheU5hbWUgfSksXG4gICAgICAgICAgICAgICAgICAgIHN0YXR1czogJ3VwbG9hZGluZycsXG4gICAgICAgICAgICAgICAgICAgIHByb2dyZXNzOiBuZXh0UHJvZ3Jlc3MsXG4gICAgICAgICAgICAgICAgICAgIG5hbWU6IGRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgc2V0RmlsZUxpc3QoKHByZXYpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZyA9IHByZXYuZmluZCgocCkgPT4gcC51aWQgPT09IHVpZCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dFBlcmNlbnQgPSBwZXJjZW50ID8/IGV4aXN0aW5nPy5wZXJjZW50O1xuICAgICAgICAgICAgICAgIGlmIChleGlzdGluZyAmJiBleGlzdGluZy5zdGF0dXMgPT09ICd1cGxvYWRpbmcnICYmIGV4aXN0aW5nLnBlcmNlbnQgPT09IG5leHRQZXJjZW50KSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gcHJldjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXYubWFwKChmKSA9PlxuICAgICAgICAgICAgICAgICAgZi51aWQgPT09IHVpZFxuICAgICAgICAgICAgICAgICAgICA/IHsgLi4uZiwgbmFtZTogZi5uYW1lIHx8IGRpc3BsYXlOYW1lLCBzdGF0dXM6ICd1cGxvYWRpbmcnLCBwZXJjZW50OiBuZXh0UGVyY2VudCB9XG4gICAgICAgICAgICAgICAgICAgIDogZlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvLyDrsqHthLDtmZTqsIAg64Gd64KY66m0IOyWtOuKkCDtmZTrqbTsl5Ag7J6I65OgIOyVjOumvChWZWN0b3JpemF0aW9uTm90aWZpZXIpLlxuICAgICAgICAgIHdhdGNoVmVjdG9yaXphdGlvbihbeyBpZDogdXBsb2FkZWQuaWQsIGZpbGVuYW1lOiB1cGxvYWRlZC5maWxlbmFtZSB9XSk7XG5cbiAgICAgICAgICBzdWNjZXNzZnVsICs9IDE7XG4gICAgICAgICAgc2V0VXBsb2FkU3RhdHVzZXMoKHByZXYpID0+ICh7XG4gICAgICAgICAgICAuLi5wcmV2LFxuICAgICAgICAgICAgW3VpZF06IHsgLi4uKHByZXZbdWlkXSB8fCB7IHByb2dyZXNzOiAwLCBuYW1lOiBkaXNwbGF5TmFtZSB9KSwgc3RhdHVzOiAnc3VjY2VzcycsIHByb2dyZXNzOiAxMDAsIG5hbWU6IGRpc3BsYXlOYW1lIH0sXG4gICAgICAgICAgfSkpO1xuICAgICAgICAgIHNldEZpbGVMaXN0KChwcmV2KSA9PlxuICAgICAgICAgICAgcHJldi5tYXAoKGYpID0+XG4gICAgICAgICAgICAgIGYudWlkID09PSB1aWQgPyB7IC4uLmYsIG5hbWU6IGYubmFtZSB8fCBkaXNwbGF5TmFtZSwgc3RhdHVzOiAnZG9uZScsIHBlcmNlbnQ6IDEwMCB9IDogZlxuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgLy8g7IKs7Jqp7J6Q6rCAIOykkeuLqChhYm9ydCntlZwg6rK97JqwOiDsl5Drn6zqsIAg7JWE64uI6528IFwi7KSR64uo65CoXCIg7Jy866GcIOuLpOujrOuLpC4g7KeE7ZaJIOykkeydtOuNmCDtjIzsnbzqs7xcbiAgICAgICAgICAvLyDslYTsp4Eg64yA6riw7Je07JeQIOuCqOydgCDtjIzsnbzsnYQgJ2NhbmNlbGxlZCcg66GcIO2RnOq4sO2VmOqzoCDro6jtlITrpbwg67mg7KC464KY6rCE64ukLiDsnbTrr7gg7ISx6rO17ZWcXG4gICAgICAgICAgLy8g7YyM7J28KOyVnuyqvSBiYXRjaCnsnYAg7ISc67KE7JeQIOyYgeyGje2ZlOuQkOycvOuvgOuhnCAnc3VjY2Vzcycg6re464yA66GcIOuRlOuLpC5cbiAgICAgICAgICBpZiAoaXNBYm9ydEVycm9yKGVycm9yKSB8fCBjb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgICAgICAvLyDsp4Ttlokg7KSRICsg64yA6riw7Je0IO2MjOydvOydhCAnY2FuY2VsbGVkJyDroZwuIOydtOuvuCAnc3VjY2Vzcycg7J24IO2MjOydvOydgCDqt7jrjIDroZwg67O07KG07ZWc64ukLlxuICAgICAgICAgICAgc2V0VXBsb2FkU3RhdHVzZXMoKHByZXYpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgbmV4dCA9IHsgLi4ucHJldiB9O1xuICAgICAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHN0XSBvZiBPYmplY3QuZW50cmllcyhwcmV2KSkge1xuICAgICAgICAgICAgICAgIGlmIChzdC5zdGF0dXMgPT09ICd1cGxvYWRpbmcnIHx8IHN0LnN0YXR1cyA9PT0gJ3F1ZXVlZCcpIHtcbiAgICAgICAgICAgICAgICAgIG5leHRba2V5XSA9IHsgLi4uc3QsIHN0YXR1czogJ2NhbmNlbGxlZCcgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgI
790H1cbiAgICAgICAgICAgICAgcmV0dXJuIG5leHQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIFdoeTogZmlsZUxpc3Qg7J2YIHN0YXR1cyDripQgYW50ZCBEcmFnZ2VyIOuCtOu2gCDtkZzquLDsl5Drp4wg7JOw7J2464ukLiDspJHri6gg7YyM7J287J2EICdlcnJvcidcbiAgICAgICAgICAgIC8vIOuhnCDrkZDrqbQg67mo6rCEIOyLpO2MqOuhnCDrs7TsnbTrr4DroZwsIOyEseqzteu2hCgnZG9uZScp7J2AIOycoOyngO2VmOqzoCDrgpjrqLjsp4DripQg7KSR66a9IOyDge2DnOuhnCDrkJjrj4zrprDri6QuXG4gICAgICAgICAgICBzZXRGaWxlTGlzdCgocHJldikgPT5cbiAgICAgICAgICAgICAgcHJldi5tYXAoKGYpID0+XG4gICAgICAgICAgICAgICAgZi5zdGF0dXMgPT09ICdkb25lJyA/IGYgOiB7IC4uLmYsIHN0YXR1czogdW5kZWZpbmVkLCBlcnJvcjogdW5kZWZpbmVkIH1cbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIG1lc3NhZ2VBcGkuaW5mbygn7JeF66Gc65Oc66W8IOykkeuLqO2WiOyKteuLiOuLpC4g7J2066+4IOyYrOudvOqwhCDtjIzsnbzsnYAg7Jyg7KeA65Cp64uI64ukLicpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZmFpbGVkICs9IDE7XG4gICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gZXh0cmFjdEVycm9yTWVzc2FnZShlcnJvciwgJ+yXheuhnOuTnOyXkCDsi6TtjKjtlojsirXri4jri6QnKTtcbiAgICAgICAgICBzZXRVcGxvYWRTdGF0dXNlcygocHJldikgPT4gKHtcbiAgICAgICAgICAgIC4uLnByZXYsXG4gICAgICAgICAgICBbdWlkXToge1xuICAgICAgICAgICAgICAuLi4ocHJldlt1aWRdIHx8IHsgcHJvZ3Jlc3M6IDAsIG5hbWU6IGRpc3BsYXlOYW1lIH0pLFxuICAgICAgICAgICAgICBzdGF0dXM6ICdlcnJvcicsXG4gICAgICAgICAgICAgIGVycm9yOiBlcnJvck1lc3NhZ2UsXG4gICAgICAgICAgICAgIHByb2dyZXNzOiBwcmV2W3VpZF0/LnByb2dyZXNzID8/IDAsXG4gICAgICAgICAgICAgIG5hbWU6IGRpc3BsYXlOYW1lLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KSk7XG4gICAgICAgICAgc2V0RmlsZUxpc3QoKHByZXYpID0+XG4gICAgICAgICAgICBwcmV2Lm1hcCgoZikgPT5cbiAgICAgICAgICAgICAgZi51aWQgPT09IHVpZFxuICAgICAgICAgICAgICAgID8geyAuLi5mLCBuYW1lOiBmLm5hbWUgfHwgZGlzcGxheU5hbWUsIHN0YXR1czogJ2Vycm9yJywgZXJyb3I6IG5ldyBFcnJvcihlcnJvck1lc3NhZ2UpIH1cbiAgICAgICAgICAgICAgICA6IGZcbiAgICAgICAgICAgIClcbiAgICAgICAgICApO1xuICAgICAgICAgIC8vIENvbnRpbnVlIHdpdGggcmVtYWluaW5nIGZpbGVzXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gV2h5OiDspJHri6jrkJjrqbQgc3VjY2Vzcy93YXJuaW5nL2Vycm9yIOyalOyVvSDthqDsiqTtirjsmYAgb25TdWNjZXNzKCkvaGFuZGxlQ2FuY2VsKCkg7J2EIOqxtOuEiOubtOuLpC5cbiAgICAgIC8vIOydtOuvuCDshLHqs7XtlZwg7YyM7J287J20IOyeiOyXiOuNlOudvOuPhCBvblN1Y2Nlc3MocmVsb2FkKeuKlCDsgqzsmqnsnpDqsIAg66qo64us7J2EIOuLq+ydhCDrlYwg7J287Ja064KY64+EIOuKpuyngFxuICAgICAgLy8g7JWK7Jy866mwLCDspJHri6gg7KeB7ZuEIOy2lOqwgCDthqDsiqTtirjroZwg7IKs7Jqp7J6Q66W8IO2YvOuegOyKpOufveqyjCDtlZjsp4Ag7JWK6riwIOychO2VqC5cbiAgICAgIGlmIChjb250cm9sbGVyLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgIC8vIOyEseqzteu2hOydtCDsnojsl4jsnLzrqbQg67aA66qoIOuqqeuhneydhCDqsLHsi6DtlbQg7IOJ7J24IOyDge2DnOulvCDrs7wg7IiYIOyeiOqyjCDtlZzri6QuXG4gICAgICAgIGlmIChzdWNjZXNzZnVsID4gMCkge1xuICAgICAgICAgIG9uU3VjY2VzcygpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGZhaWxlZCA9PT0gMCkge1xuICAgICAgICBtZXNzYWdlQXBpLnN1Y2Nlc3MoYCR7c3VjY2Vzc2Z1bH3qsJwg7YyM7J287J20IOuqqOuRkCDsl4XroZzrk5zrkJjsl4jsirXri4jri6RgKTtcbiAgICAgICAgb25TdWNjZXNzKCk7XG4gICAgICAgIGhhbmRsZUNhbmNlbCgpOyAvLyBjbG9zZSBhbmQgcmVzZXQgd2hlbiBldmVyeXRoaW5nIHN1Y2NlZWRlZFxuICAgICAgfSBlbHNlIGlmIChzdWNjZXNzZnVsID4gMCkge1xuICAgICAgICBtZXNzYWdlQXBpLndhcm5pbmcoYCR7c3VjY2Vzc2Z1bH3qsJwg7JeF66Gc65OcIOyZhOujjCwgJHtmYWlsZWR96rCcIOyLpO2MqGApO1xuICAgICAgICBvblN1Y2Nlc3MoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1lc3NhZ2VBcGkuZXJyb3IoJ+uqqOuToCDsl4XroZzrk5zqsIAg7Iuk7Yyo7ZaI7Iq164uI64ukJyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIG1lc3NhZ2VBcGkuZXJyb3IoZXh0cmFjdEVycm9yTWVzc2FnZShlcnJvciwgJ+yXheuhnOuTnOyXkCDsi6TtjKjtlojsirXri4jri6QnKSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHNldFVwbG9hZGluZyhmYWxzZSk7XG4gICAgICAvLyDsnbTrsoggcnVuIOydmCDsu6jtirjroaTrn6wg7KCV66asLiDsnbTtm4QgdW5tb3VudCBjbGVhbnVwIOydtCBzdGFsZSDsu6jtirjroaTrn6zrpbwgYWJvcnQg7ZWY7KeAIOyViuuPhOuhnS5cbiAgICAgIGlmIChhYm9ydFJlZi5jdXJyZW50ID09PSBjb250cm9sbGVyKSB7XG4gICAgICAgIGFib3J0UmVmLmN1cnJlbnQgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgfSwgW2ZpbGVMaXN0LCBtZXNzYWdlQXBpLCBvblN1Y2Nlc3MsIHNlbGVjdGVkQ2F0ZWdvcnksIHVwbG9hZFN0YXR1c2VzLCBoYW5kbGVDYW5jZWwsIHVwbG9hZGluZ10pO1xuXG4gIGNvbnN0IHVwbG9hZFN0YXR1c0NvdW50ID0gT2JqZWN0LmtleXModXBsb2FkU3RhdHVzZXMpLmxlbmd0aDtcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghYXV0b1VwbG9hZCB8fCB1cGxvYWRpbmcpIHJldHVybjtcbiAgICBpZiAoZmlsZUxpc3QubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgaWYgKHVwbG9hZFN0YXR1c0NvdW50ID4gMCkgcmV0dXJuO1xuICAgIC8vIHF1ZXVlTWljcm90YXNrOiBoYW5kbGVVcGxvYWQg6rCAIHNldFVwbG9hZGluZyDrk7Egc3luY2hyb25vdXMgc2V0U3RhdGUg66W8IOu2gOultOuvgOuhnFxuICAgIC8vIGVmZmVjdCDrs7jrrLgg7KeB7KCRIO2YuOy2nOydgCBSZWFjdCAxOSBzZXQtc3RhdGUtaW4tZWZmZWN0IOujsCDsnITrsJguIG1pY3JvdGFzayDtmoztlLwuXG4gICAgcXVldWVNaWNyb3Rhc2soKCkgPT4geyB2b2lkIGhhbmRsZVVwbG9h
790ZCgpOyB9KTtcbiAgfSwgW2F1dG9VcGxvYWQsIHVwbG9hZGluZywgZmlsZUxpc3QubGVuZ3RoLCB1cGxvYWRTdGF0dXNDb3VudCwgaGFuZGxlVXBsb2FkXSk7XG5cbiAgcmV0dXJuIChcbiAgICA8TW9kYWxcbiAgICAgIHRpdGxlPVwi66y47IScIOyXheuhnOuTnFwiXG4gICAgICBvcGVuPXtvcGVufVxuICAgICAgb25Paz17aGFuZGxlVXBsb2FkfVxuICAgICAgb25DYW5jZWw9e2hhbmRsZUNhbmNlbH1cbiAgICAgIGNvbmZpcm1Mb2FkaW5nPXt1cGxvYWRpbmd9XG4gICAgICBva1RleHQ9XCLsl4XroZzrk5xcIlxuICAgICAgY2FuY2VsVGV4dD1cIuy3qOyGjFwiXG4gICAgICB3aWR0aD17TU9EQUxfV0lEVEgubWR9XG4gICAgICAvLyBXaHk6IOydtOygnCBhYm9ydCDqsIAg7J6I7Jy866+A66GcIOynhO2WiSDspJEg64ur6riw66W8IOunieyngCDslYrripTri6QuIFgvRXNjL21hc2sv7Leo7IaM64qUIGhhbmRsZUNhbmNlbFxuICAgICAgLy8g66GcIOuqqOydtOupsCwgdXBsb2FkaW5nIOykkeydtOuptCBpbi1mbGlnaHQg7JqU7LKt7J2EIGFib3J0IO2VnOuLpCjro6jtlIQgYWJvcnQg67aE6riw6rCAIOydtOuvuCDsmKzrnbzqsIRcbiAgICAgIC8vIO2MjOydvOydhCDrs7TsobTtlZjqs6AgdXBsb2FkaW5nPWZhbHNlIOuhnCDsoJXrpqwpLiDri6vquLDripQgYWJvcnQg7LKY66as6rCAIOuBneuCnCDrkqQg7ZWcIOuyiCDrjZQg64ur7J2EIOuVjFxuICAgICAgLy8g7IiY7ZaJ65CY66+A66GcLCDthqDsiqTtirjqsIAg7IKs65287KeEIOuqqOuLrCDrkqTsl5Ag65yo642YIOyYmyDtmLzrnoDrj4Qg7J6s67Cc7ZWY7KeAIOyViuuKlOuLpC5cbiAgICAgIG9rQnV0dG9uUHJvcHM9e3sgZGlzYWJsZWQ6IHVwbG9hZGluZyB9fVxuICAgID5cbiAgICAgIDxTcGFjZSBvcmllbnRhdGlvbj1cInZlcnRpY2FsXCIgc3R5bGU9e3sgd2lkdGg6ICcxMDAlJyB9fSBzaXplPVwibGFyZ2VcIj5cbiAgICAgICAgey8qIENhdGVnb3J5IFNlbGVjdG9yICovfVxuICAgICAgICA8ZGl2PlxuICAgICAgICAgIDxUZXh0IHN0cm9uZz7subTthYzqs6DrpqwgKOyEoO2DnSDsgqztla0pOjwvVGV4dD5cbiAgICAgICAgICA8U2VsZWN0XG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIuyEoO2DnSDslYgg7ZWoICjrr7jrtoTrpZgpXCJcbiAgICAgICAgICAgIHN0eWxlPXt7IHdpZHRoOiAnMTAwJScsIG1hcmdpblRvcDogOCB9fVxuICAgICAgICAgICAgdmFsdWU9e3NlbGVjdGVkQ2F0ZWdvcnl9XG4gICAgICAgICAgICBvbkNoYW5nZT17c2V0U2VsZWN0ZWRDYXRlZ29yeX1cbiAgICAgICAgICAgIGFsbG93Q2xlYXJcbiAgICAgICAgICAgIG9wdGlvbnM9e2NhdGVnb3J5T3B0aW9uc31cbiAgICAgICAgICAgIC8vIFdoeTogXCLrk5zrnpjqt7gg7IucIOyekOuPmSDsl4XroZzrk5xcIuqwgCDsvJzsoLgg7J6I7Jy866m0IO2MjOydvOydtCBmaWxlTGlzdCDsl5Ag65Ok7Ja07Jik64qUIOyInOqwhFxuICAgICAgICAgICAgLy8gKG1pY3JvdGFzaykg6re4IOyLnOygkOydmCBzZWxlY3RlZENhdGVnb3J5IOuhnCDsponsi5wg7JeF66Gc65Oc6rCAIOuwnOyCrOuQnOuLpC4gdXBsb2FkU3RhdHVzZXNcbiAgICAgICAgICAgIC8vIOqwgCDssYTsm4zsp4Qg65Kk7JeQ64+EIOydtCBTZWxlY3Qg66W8IOqzhOyGjSDtmZzshLEg7IOB7YOc66GcIOuRkOuptCwg7IKs7Jqp7J6Q6rCAIFwi7Lm07YWM6rOg66as66W8XG4gICAgICAgICAgICAvLyDsp4DsoJXtlojri6RcIuqzoCDripDrgbzsp4Drp4wg7J2066+4IOuwnOyCrOuQnCDsl4XroZzrk5zsl5DripQg67CY7JiB65CY7KeAIOyViuuKlCDquLDrp4zsoIEgVUnqsIAg65Cc64ukXG4gICAgICAgICAgICAvLyAo7Iuk7KCcIOusuOydmDogXCLsp4DsoJXtlojripTrjbAg66+467aE66WY66GcIOqwkFwiKS4g67Cc7IKs65CcIOuSpOyXkOuKlCDruYTtmZzshLHtmZTtlbQg7KCV7KeB7ZWcIOyLoO2YuOulvFxuICAgICAgICAgICAgLy8g7KSA64ukIOKAlCDsnpDrj5kg7JeF66Gc65OcIOyekOyytOulvCDrp4nsp4DripQg7JWK64qU64ukKOq3uOqxtCDrs4Trj4Qg7KCc7ZKIIOqysOyglSkuXG4gICAgICAgICAgICBkaXNhYmxlZD17T2JqZWN0LmtleXModXBsb2FkU3RhdHVzZXMpLmxlbmd0aCA+IDB9XG4gICAgICAgICAgLz5cbiAgICAgICAgICB7Lyog7LKY7J2MIOyTsOuKlCDsgqzsmqnsnpDqsIAgXCLsi5zrj4TtlbTrtJDslbwg7JWE64qUXCIg7KCV7LGF7J2EIOuvuOumrCDslYjrgrQoVVgg6rCQ7IKsKS4gKi99XG4gICAgICAgICAgPFRleHQgdHlwZT1cInNlY29uZGFyeVwiIHN0eWxlPXt7IGZvbnRTaXplOiAxMiwgZGlzcGxheTogJ2Jsb2NrJywgbWFyZ2luVG9wOiA0IH19PlxuICAgICAgICAgICAg66+47KeA7KCVIOyLnCAn66+467aE66WYJ+uhnCDsl4XroZzrk5zrkKnri4jri6QuIOqwmeydgCDtjIzsnbzsnYAg7Lm07YWM6rOg66as66eI64ukIO2VnCDrsojslKnrp4wg7Jis66a0IOyImCDsnojsirXri4jri6QuXG4gICAgICAgICAgICB7YXV0b1VwbG9hZCAmJiAoXG4gICAgICAgICAgICAgIDw+XG4gICAgICAgICAgICAgICAgeycgJ31cbiAgICAgICAgICAgICAgICA8VGV4dCB0eXBlPVwid2FybmluZ1wiIHN0eWxlPXt7IGZvbnRTaXplOiAxMiB9fT5cbiAgICAgICAgICAgICAgICAgIOuTnOuemOq3uCDsi5wg7J6Q64+ZIOyXheuhnOuTnOqwgCDsvJzsoLgg7J6I7Ja0IO2MjOydvOydhCDstpTqsIDtlZjrqbQg7KaJ7IucIOyXheuhnOuTnOuQqeuLiOuLpCDigJQg7Lm07YWM6rOg66as64qUXG4gICAgICAgICAgICAgICAgICDtjIzsnbzsnYQg7LaU6rCA7ZWY6riwIOyghOyXkCDrqLzsoIAg7ISg7YOd7ZWY7IS47JqULlxuICAgICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgPC8+XG4gICAgICAgICAgICApfVxuICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxTcGFjZSBhbGlnbj1cImNlbnRlclwiPlxuICAgICAgICAgIDxTd2l0Y2ggc2l6ZT1cInNtYWxsXCIgYXJpYS1sYWJlbD1cIuuTnOuemOq3uCDsi5wg7J6Q64+ZIOyXheuhnOuTnFwiIGNoZWNrZWQ9e2F1dG9VcGxvYWR9IG9uQ2hhbmdlPXtzZXRBdXRvVXBsb2FkfSAvPlxuICAgICAgICAgIDxUZXh0IHR5cGU9XCJzZWNvbmRhcnlcIj7rk5zrnpjqt7gg7IucIOyekOuPmSDsl4XroZzrk5w8L1RleHQ+XG4gICAgICAgIDwvU3BhY2U+XG5cbiAgICAgICAgey8qIEZpbGUg
790VXBsb2FkIERyYWdnZXIgKi99XG4gICAgICAgIDxEcmFnZ2VyIHsuLi51cGxvYWRQcm9wc30+XG4gICAgICAgICAgPHAgY2xhc3NOYW1lPVwiYW50LXVwbG9hZC1kcmFnLWljb25cIj5cbiAgICAgICAgICAgIDxJbmJveE91dGxpbmVkIC8+XG4gICAgICAgICAgPC9wPlxuICAgICAgICAgIDxwIGNsYXNzTmFtZT1cImFudC11cGxvYWQtdGV4dFwiPu2MjOydvOydhCDsnbQg7JiB7Jet7JeQIOuTnOuemOq3uO2VmOqxsOuCmCDtgbTrpq3tlZjsl6wg7JeF66Gc65Oc7ZWY7IS47JqUPC9wPlxuICAgICAgICAgIDxwIGNsYXNzTmFtZT1cImFudC11cGxvYWQtaGludFwiPlxuICAgICAgICAgICAg7KeA7JuQIO2YleyLnToge0ZJTEVfVVBMT0FELlNVUFBPUlRFRF9UWVBFUy5qb2luKCcsICcpfVxuICAgICAgICAgICAgPGJyIC8+XG4gICAgICAgICAgICDstZzrjIA6IHtGSUxFX1VQTE9BRC5NQVhfRklMRVN96rCcIO2MjOydvCwg6rCBIDEwME1CXG4gICAgICAgICAgICA8YnIgLz5cbiAgICAgICAgICAgIDxUZXh0IHR5cGU9XCJzZWNvbmRhcnlcIiBzdHlsZT17eyBmb250U2l6ZTogMTIgfX0+XG4gICAgICAgICAgICAgIOyXheuhnOuTnCDtm4Qg7IOJ7J24KOuyoe2EsO2ZlCkg7LKY66as6rCAIOuBneuCmOyVvCDqsoDsg4nCt+uLteuzgOyXkCDrsJjsmIHrkKnri4jri6Qg4oCUIOuqqeuhneyXkOyEnCDsg4Htg5zrpbwg7ZmV7J247ZWY7IS47JqULlxuICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgIDwvcD5cbiAgICAgICAgPC9EcmFnZ2VyPlxuICAgICAgICB7T2JqZWN0LmtleXModXBsb2FkU3RhdHVzZXMpLmxlbmd0aCA+IDAgPyAoXG4gICAgICAgICAgPFNwYWNlIG9yaWVudGF0aW9uPVwidmVydGljYWxcIiBzdHlsZT17eyB3aWR0aDogJzEwMCUnIH19PlxuICAgICAgICAgICAgPFRleHQgc3Ryb25nPuyXheuhnOuTnCDsp4Ttlokg7IOB7ZmpPC9UZXh0PlxuICAgICAgICAgICAgPGRpdiBzdHlsZT17eyBtYXhIZWlnaHQ6IDI0MCwgb3ZlcmZsb3dZOiAnYXV0bycgfX0+XG4gICAgICAgICAgICAgIHtmaWxlTGlzdC5tYXAoKGZpbGUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdGF0ZSA9IHVwbG9hZFN0YXR1c2VzW2ZpbGUudWlkXTtcbiAgICAgICAgICAgICAgICBpZiAoIXN0YXRlKSByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICBjb25zdCBwcm9ncmVzc1N0YXR1cyA9XG4gICAgICAgICAgICAgICAgICBzdGF0ZS5zdGF0dXMgPT09ICdlcnJvcidcbiAgICAgICAgICAgICAgICAgICAgPyAnZXhjZXB0aW9uJ1xuICAgICAgICAgICAgICAgICAgICA6IHN0YXRlLnN0YXR1cyA9PT0gJ3N1Y2Nlc3MnXG4gICAgICAgICAgICAgICAgICAgICAgPyAnc3VjY2VzcydcbiAgICAgICAgICAgICAgICAgICAgICA6IHN0YXRlLnN0YXR1cyA9PT0gJ3VwbG9hZGluZydcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ2FjdGl2ZSdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogJ25vcm1hbCc7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RhdHVzTGFiZWwgPVxuICAgICAgICAgICAgICAgICAgc3RhdGUuc3RhdHVzID09PSAncXVldWVkJ1xuICAgICAgICAgICAgICAgICAgICA/ICfrjIDquLAnXG4gICAgICAgICAgICAgICAgICAgIDogc3RhdGUuc3RhdHVzID09PSAndXBsb2FkaW5nJ1xuICAgICAgICAgICAgICAgICAgICAgID8gJ+yXheuhnOuTnCDspJEnXG4gICAgICAgICAgICAgICAgICAgICAgOiBzdGF0ZS5zdGF0dXMgPT09ICdzdWNjZXNzJ1xuICAgICAgICAgICAgICAgICAgICAgICAgPyAn7JmE66OMJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBzdGF0ZS5zdGF0dXMgPT09ICdjYW5jZWxsZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgID8gJ+ykkeuLqOuQqCdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgOiAn7Iuk7YyoJztcblxuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICA8ZGl2IGtleT17ZmlsZS51aWR9IHN0eWxlPXt7IGRpc3BsYXk6ICdmbGV4JywgZmxleERpcmVjdGlvbjogJ2NvbHVtbicsIGdhcDogNCwgbWFyZ2luQm90dG9tOiA4IH19PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPXt7IGRpc3BsYXk6ICdmbGV4JywgYWxpZ25JdGVtczogJ2NlbnRlcicsIGdhcDogOCB9fT5cbiAgICAgICAgICAgICAgICAgICAgICA8VGV4dCBlbGxpcHNpcyB0aXRsZT17ZmlsZS5uYW1lfSBzdHlsZT17eyBmbGV4OiAxIH19PlxuICAgICAgICAgICAgICAgICAgICAgICAge3VwbG9hZFN0YXR1c2VzW2ZpbGUudWlkXT8ubmFtZSB8fCBmaWxlLm5hbWV9XG4gICAgICAgICAgICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgICAgICAgICAgICAgIDxQcm9ncmVzc1xuICAgICAgICAgICAgICAgICAgICAgICAgcGVyY2VudD17c3RhdGUucHJvZ3Jlc3N9XG4gICAgICAgICAgICAgICAgICAgICAgICBzaXplPVwic21hbGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHVzPXtwcm9ncmVzc1N0YXR1c31cbiAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlPXt7IGZsZXhCYXNpczogMjAwLCBtYXJnaW5Cb3R0b206IDAgfX1cbiAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgIDxUZXh0IHR5cGU9XCJzZWNvbmRhcnlcIiBzdHlsZT17eyB3aWR0aDogODAsIHRleHRBbGlnbjogJ3JpZ2h0JyB9fT5cbiAgICAgICAgICAgICAgICAgICAgICAgIHtzdGF0dXNMYWJlbH1cbiAgICAgICAgICAgICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICB7c3RhdGUuZXJyb3IgJiYgKFxuICAgICAgICAgICAgICAgICAgICAgIDxUZXh0IHR5cGU9XCJkYW5nZXJcIiBzdHlsZT17eyBtYXJnaW5MZWZ0OiAyIH19PlxuICAgICAgICAgICAgICAgICAgICAgICAge3N0YXRlLmVycm9yfVxuICAgICAgICAgICAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICAgICAgICAgICAgKX1cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIH0pfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9TcGFjZT5cbiAgICAgICAgKSA6IChcbiAgICAgICAgICBmaWxlTGlzdC5sZW5ndGggPiAxICYmIChcbiAgICAgICAgICAgIDxUZXh0IHR5cGU9XCJzZWNvbmRhcnlcIj5cbiAgICAgICAgICAgICAg7J286rSEIOyXheuhnOuTnDoge2ZpbGVMaXN0Lmxlbmd0aH3qsJwg7YyM7J28IOyEoO2DneuQqFxuICAgICAgICAgICAgPC9UZXh0PlxuICAgICAgICAgIClcbiAgICAgICAgKX1cbiAgICAgICAgey8qIFdoeTog64yA65+JKOy1nOuMgCA1MOqwnC/qsIEgMTAwTUIpIOyXheuhnOuTnCDspJEg7IKs7Jqp7J6Q6rCAIOqwh+2eiOyngCDslYrrj4TroZ0g66qF7Iuc7KCBIOykkeuLqCDrsoTtirzsnYRcbiAgICAgICAgICAgIOygnOqzte2VnOuLpC4g7YG066atIOyLnCDtmITsnqwgaW4tZmxpZ2h0IOyalOyyreydhCBhYm9ydCDtlZjqs6Ag64Ko7J2AIOuMgOq4sOyXtOydhCDrqYjstpjri6QuIOydtOuvuCDsmKzrnbzqsIRcbiAgICAgICAgICAgIO2MjOydvOydgCDshJzrsoTsl5Ag7JiB7IaN7ZmU64+8IOq3uOuMgOuhnCDsnKDsp4DrkJzri6QuICovfVxuICAgICAgICB7dXBsb2FkaW5nICYmIChcbiAgICAgICAgICA8U3B
790hY2Ugb3JpZW50YXRpb249XCJ2ZXJ0aWNhbFwiIHN0eWxlPXt7IHdpZHRoOiAnMTAwJScgfX0gc2l6ZT17NH0+XG4gICAgICAgICAgICA8QnV0dG9uIGRhbmdlciBvbkNsaWNrPXsoKSA9PiBhYm9ydFJlZi5jdXJyZW50Py5hYm9ydCgpfSBibG9jaz5cbiAgICAgICAgICAgICAg7JeF66Gc65OcIOykkeuLqFxuICAgICAgICAgICAgPC9CdXR0b24+XG4gICAgICAgICAgICA8VGV4dCB0eXBlPVwic2Vjb25kYXJ5XCIgc3R5bGU9e3sgZm9udFNpemU6IDEyIH19PlxuICAgICAgICAgICAgICDsl4XroZzrk5zqsIAg7KeE7ZaJIOykkeyeheuLiOuLpC4g7KSR64uo7ZW064+EIOydtOuvuCDsmKzrnbzqsIQg7YyM7J287J2AIOycoOyngOuQqeuLiOuLpC5cbiAgICAgICAgICAgIDwvVGV4dD5cbiAgICAgICAgICA8L1NwYWNlPlxuICAgICAgICApfVxuICAgICAgPC9TcGFjZT5cbiAgICA8L01vZGFsPlxuICApO1xufVxuIl19
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.