__vite_ssr_exportName__("RELAY_ROUTE_ID", () => { try { return RELAY_ROUTE_ID } catch {} });
__vite_ssr_exportName__("connectionRouteId", () => { try { return connectionRouteId } catch {} });
__vite_ssr_exportName__("connectionRoutes", () => { try { return connectionRoutes } catch {} });
__vite_ssr_exportName__("entryWithRoutes", () => { try { return entryWithRoutes } catch {} });
__vite_ssr_exportName__("routeEntry", () => { try { return routeEntry } catch {} });
__vite_ssr_exportName__("routeHttpBaseUrl", () => { try { return routeHttpBaseUrl } catch {} });
__vite_ssr_exportName__("connectionRouteKind", () => { try { return connectionRouteKind } catch {} });
__vite_ssr_exportName__("insertRoute", () => { try { return insertRoute } catch {} });
__vite_ssr_exportName__("upsertRoute", () => { try { return upsertRoute } catch {} });
__vite_ssr_exportName__("findRouteToSameAddress", () => { try { return findRouteToSameAddress } catch {} });
__vite_ssr_exportName__("connectionRouteLabel", () => { try { return connectionRouteLabel } catch {} });
__vite_ssr_exportName__("connectionRouteAddress", () => { try { return connectionRouteAddress } catch {} });
__vite_ssr_exportName__("hasSavedBearerRoute", () => { try { return hasSavedBearerRoute } catch {} });
__vite_ssr_exportName__("hasRelayRoute", () => { try { return hasRelayRoute } catch {} });
__vite_ssr_exportName__("mergeLearnedRoutes", () => { try { return mergeLearnedRoutes } catch {} });
__vite_ssr_exportName__("sendsTokenInClear", () => { try { return sendsTokenInClear } catch {} });
__vite_ssr_exportName__("usableRoutes", () => { try { return usableRoutes } catch {} });
__vite_ssr_exportName__("credentialConnectionId", () => { try { return credentialConnectionId } catch {} });
__vite_ssr_exportName__("isLearned", () => { try { return isLearned } catch {} });
__vite_ssr_exportName__("routesAfterRemoving", () => { try { return routesAfterRemoving } catch {} });
__vite_ssr_exportName__("removedWithRelay", () => { try { return removedWithRelay } catch {} });
__vite_ssr_exportName__("sshTargetKey", () => { try { return sshTargetKey } catch {} });
const __vite_ssr_import_0__ = await __vite_ssr_import__("/@fs/home/ubuntu/wt/pr-24263/packages/shared/src/hostClassification.ts", {"importedNames":["isLocalLoopbackHost","isPrivateNetworkHost","isSharedAddressSpaceHost","isTailnetHost"]});
const __vite_ssr_import_1__ = await __vite_ssr_import__("/@fs/home/ubuntu/wt/pr-24263/node_modules/.pnpm/effect@4.0.5/node_modules/effect/dist/Option.js");
const __vite_ssr_import_2__ = await __vite_ssr_import__("/@fs/home/ubuntu/wt/pr-24263/packages/client-runtime/src/connection/catalog.ts", {"importedNames":["BearerConnectionProfile"]});
const __vite_ssr_import_3__ = await __vite_ssr_import__("/@fs/home/ubuntu/wt/pr-24263/packages/client-runtime/src/connection/model.ts", {"importedNames":["BearerConnectionTarget"]});




const RELAY_ROUTE_ID = "relay";
function connectionRouteId(target) {
	switch (target._tag) {
		case "PrimaryConnectionTarget": return "primary";
		case "RelayConnectionTarget": return RELAY_ROUTE_ID;
		case "BearerConnectionTarget":
		case "SshConnectionTarget": return target.connectionId;
	}
};
function connectionRoutes(entry) {
	return [{
		target: entry.target,
		profile: entry.profile
	}, ...entry.alternateRoutes ?? []];
};
function entryWithRoutes(entry, routes) {
	const [first, ...rest] = routes;
	if (first === undefined) {
		throw new Error("A saved environment needs at least one route.");
	};
	const { alternateRoutes: _previous, ...base } = entry;
	return {
		...base,
		target: first.target,
		profile: first.profile,
		...rest.length === 0 ? {} : { alternateRoutes: rest }
	};
};
function routeEntry(entry, route) {
	return entryWithRoutes(entry, [route]);
};
function routeHttpBaseUrl(route) {
	if (route.target._tag === "PrimaryConnectionTarget") return route.target.httpBaseUrl;
	const profile = __vite_ssr_import_1__.getOrNull(route.profile);
	return profile?._tag === "BearerConnectionProfile" ? profile.httpBaseUrl : null;
};
function routeHostname(route) {
	const httpBaseUrl = routeHttpBaseUrl(route);
	if (httpBaseUrl === null) return null;
	try {
		return new URL(httpBaseUrl).hostname;
	} catch {
		return null;
	}
}
function connectionRouteKind(route) {
	switch (route.target._tag) {
		case "RelayConnectionTarget": return "relay";
		case "SshConnectionTarget": return "ssh";
		case "PrimaryConnectionTarget":
		case "BearerConnectionTarget": {
			const hostname = routeHostname(route);
			if (hostname === null) return "public";
			if ((0,__vite_ssr_import_0__.isLocalLoopbackHost)(hostname)) return "loopback";
			const profile = __vite_ssr_import_1__.getOrNull(route.profile);
			const tailscale = profile?._tag === "BearerConnectionProfile" && profile.network === "tailscale";
			if (tailscale || (0,__vite_ssr_import_0__.isTailnetHost)(hostname)) return "tailnet";
			if ((0,__vite_ssr_import_0__.isSharedAddressSpaceHost)(hostname)) return "vpn";
			return (0,__vite_ssr_import_0__.isPrivateNetworkHost)(hostname) ? "lan" : "public";
		}
	}
};
const ROUTE_KIND_RANK = {
	loopback: 0,
	lan: 1,
	tailnet: 2,
	vpn: 2,
	public: 3,
	ssh: 4,
	relay: 5
};
function insertRoute(routes, route) {
	const rank = ROUTE_KIND_RANK[connectionRouteKind(route)];
	const index = routes.findIndex((existing) => ROUTE_KIND_RANK[connectionRouteKind(existing)] > rank);
	return index === -1 ? [...routes, route] : [
		...routes.slice(0, index),
		route,
		...routes.slice(index)
	];
};
function upsertRoute(routes, route) {
	const id = connectionRouteId(route.target);
	return routes.some((existing) => connectionRouteId(existing.target) === id) ? routes.map((existing) => connectionRouteId(existing.target) === id ? route : existing) : insertRoute(routes, route);
};
function findRouteToSameAddress(routes, route) {
	const key = routeAddressKey(route);
	return key === null ? undefined : routes.find((existing) => routeAddressKey(existing) === key);
};
function routeAddressKey(route) {
	const profile = __vite_ssr_import_1__.getOrNull(route.profile);
	switch (profile?._tag) {
		case "BearerConnectionProfile": return `bearer:${profile.httpBaseUrl.replace(/\/+$/, "")}`;
		case "SshConnectionProfile": return `ssh:${sshTargetKey(profile.target)}`;
		default: return null;
	}
}
function connectionRouteLabel(route) {
	switch (connectionRouteKind(route)) {
		case "relay": return "T3 Connect";
		case "loopback": return "This device";
		case "lan": return "LAN";
		case "tailnet": return "Tailscale";
		case "vpn": return "VPN";
		case "ssh": {
			const profile = __vite_ssr_import_1__.getOrNull(route.profile);
			return profile?._tag === "SshConnectionProfile" ? `SSH ${profile.target.username ? `${profile.target.username}@` : ""}${profile.target.hostname}` : "SSH";
		}
		case "public": return routeHostname(route) ?? "Remote link";
	}
};
function connectionRouteAddress(route) {
	if (route.target._tag === "SshConnectionTarget") {
		const profile = __vite_ssr_import_1__.getOrNull(route.profile);
		return profile?._tag === "SshConnectionProfile" ? profile.target.alias : null;
	};
	return routeHttpBaseUrl(route);
};
/** Learned routes alone must not make relay environments manually retryable. */
const hasSavedBearerRoute = (entry) => connectionRoutes(entry).some((r) => !isLearned(r) && r.target._tag === "BearerConnectionTarget");
function hasRelayRoute(entry) {
	return [entry.target, ...(entry.alternateRoutes ?? []).map((route) => route.target)].some((target) => target._tag === "RelayConnectionTarget");
};
function mergeLearnedRoutes(input) {
	const { entry } = input;
	const active = input.activeRoute.target;
	const saved = connectionRoutes(entry);
	if (active._tag !== "RelayConnectionTarget" && active._tag !== "BearerConnectionTarget") {
		return null;
	};
	const activeProfile = __vite_ssr_import_1__.getOrNull(input.activeRoute.profile);
	const authorization = active._tag === "RelayConnectionTarget" || activeProfile?._tag === "BearerConnectionProfile" && activeProfile.authorization === "t3-connect" ? "t3-connect" : undefined;
	const sharedCredential = authorization === undefined && active._tag === "BearerConnectionTarget" ? credentialConnectionId(active.connectionId) : undefined;
	const reported = new Map();
	const tailscaleOrigins = new Set();
	for (const endpoint of input.reported) {
		let url;
		try {
			url = new URL(endpoint.httpBaseUrl);
		} catch {
			continue;
		};
		if (url.protocol !== "http:" && url.protocol !== "https:") continue;
		if (url.protocol === "http:" && !input.allowInsecure) continue;
		// A loopback address names whichever device opens it, never the server.
		if ((0,__vite_ssr_import_0__.isLocalLoopbackHost)(url.hostname)) continue;
		reported.set(url.origin, url);
		if (endpoint.kind === "tailnet") tailscaleOrigins.add(url.origin);
	};
	const normalized = (url) => url.replace(/\/+$/, "");
	const known = new Set(saved.flatMap((route) => {
		const url = routeHttpBaseUrl(route);
		return url === null || isLearned(route) ? [] : [normalized(url)];
	}));
	const kept = saved.flatMap((route) => {
		const url = routeHttpBaseUrl(route);
		if (!isLearned(route)) {
			return [url === null || !reported.has(normalized(url)) ? route : withNetwork(route, tailscaleOrigins.has(normalized(url)))];
		};
		if (url === null || !reported.has(normalized(url)) || known.has(normalized(url))) return [];
		if (sendsTokenInClear(saved, route, tailscaleOrigins.has(normalized(url)))) return [];
		known.add(normalized(url));
		return [withNetwork(route, tailscaleOrigins.has(normalized(url)))];
	});
	let next = kept;
	for (const url of reported.values()) {
		if (known.has(url.origin)) continue;
		if (url.protocol === "http:" && sharedCredential !== undefined && !tailscaleOrigins.has(url.origin) && !tokenAllowsPlainHttp(saved, sharedCredential)) {
			continue;
		};
		const httpBaseUrl = `${url.origin}/`;
		const connectionId = learnedConnectionId(entry.target.environmentId, url.origin, sharedCredential);
		next = insertRoute(next, {
			target: new __vite_ssr_import_3__.BearerConnectionTarget({
				environmentId: entry.target.environmentId,
				label: entry.target.label,
				connectionId
			}),
			profile: __vite_ssr_import_1__.some(new __vite_ssr_import_2__.BearerConnectionProfile({
				connectionId,
				environmentId: entry.target.environmentId,
				label: entry.target.label,
				httpBaseUrl,
				wsBaseUrl: `${url.protocol === "https:" ? "wss:" : "ws:"}//${url.host}/`,
				learned: true,
				...authorization === undefined ? {} : { authorization },
				...tailscaleOrigins.has(url.origin) ? { network: "tailscale" } : {}
			}))
		});
	};
	const signature = (routes) => routes.map((route) => `${connectionRouteId(route.target)} ${routeHttpBaseUrl(route) ?? ""} ${connectionRouteKind(route)}`).join("\n");
	return signature(saved) === signature(next) ? null : next;
};
// A paired token goes to a plain HTTP address outside the tailnet only when
// it was paired that way, so a token paired over HTTPS, loopback, or the
// tailnet keeps to the transports it was issued for.
function tokenAllowsPlainHttp(routes, credentialId) {
	const credentialRoute = routes.find((route) => connectionRouteId(route.target) === credentialId);
	return credentialRoute !== undefined && routeHttpBaseUrl(credentialRoute)?.startsWith("http:") === true && (connectionRouteKind(credentialRoute) === "lan" || connectionRouteKind(credentialRoute) === "public");
}
/**
* Whether connecting over `route` would send a paired token over plain HTTP
* that it wasn't paired over. Checked against the token the route borrows,
* so a route learned before this rule existed is refused too.
*/
function sendsTokenInClear(routes, route, tailscale) {
	const profile = __vite_ssr_import_1__.getOrNull(route.profile);
	if (profile?._tag !== "BearerConnectionProfile" || profile.authorization === "t3-connect") {
		return false;
	};
	if ((tailscale ?? profile.network === "tailscale") || !profile.httpBaseUrl.startsWith("http:")) {
		return false;
	};
	const credentialId = credentialConnectionId(connectionRouteId(route.target));
	return credentialId !== connectionRouteId(route.target) && !tokenAllowsPlainHttp(routes, credentialId);
};
/** Routes a connect may use: none sends a paired token over plain HTTP it wasn't paired over. */
function usableRoutes(entry) {
	const routes = connectionRoutes(entry);
	return routes.filter((route) => !sendsTokenInClear(routes, route));
};
function withNetwork(route, tailscale) {
	const profile = __vite_ssr_import_1__.getOrNull(route.profile);
	if (profile?._tag !== "BearerConnectionProfile") return route;
	if (profile.network === "tailscale" === tailscale) return route;
	return {
		target: route.target,
		profile: __vite_ssr_import_1__.some(new __vite_ssr_import_2__.BearerConnectionProfile({
			connectionId: profile.connectionId,
			environmentId: profile.environmentId,
			label: profile.label,
			httpBaseUrl: profile.httpBaseUrl,
			wsBaseUrl: profile.wsBaseUrl,
			...profile.learned === undefined ? {} : { learned: profile.learned },
			...profile.authorization === undefined ? {} : { authorization: profile.authorization },
			...tailscale ? { network: "tailscale" } : {}
		}))
	};
}
function learnedConnectionId(environmentId, origin, sharedCredential) {
	return sharedCredential === undefined ? `learned:${environmentId}:${origin}` : `learned:${environmentId}:${origin}@${sharedCredential}`;
}
function credentialConnectionId(connectionId) {
	const at = connectionId.indexOf("@");
	return connectionId.startsWith("learned:") && at !== -1 ? connectionId.slice(at + 1) : connectionId;
};
function isLearned(route) {
	const profile = __vite_ssr_import_1__.getOrNull(route.profile);
	return profile?._tag === "BearerConnectionProfile" && profile.learned === true;
};
/**
* A learned route borrows the credential of the route it was learned over, so
* it cannot outlive that route: removing T3 Connect also removes routes learned
* through it, and removing a paired address removes routes that borrow its
* token.
*/
function routesAfterRemoving(routes, removedId) {
	const removed = routes.find((route) => connectionRouteId(route.target) === removedId);
	if (removed === undefined) return routes;
	return routes.filter((route) => {
		if (route === removed) return false;
		if (!isLearned(route)) return true;
		const profile = __vite_ssr_import_1__.getOrNull(route.profile);
		if (profile?._tag === "BearerConnectionProfile" && profile.authorization === "t3-connect") {
			return removed.target._tag !== "RelayConnectionTarget";
		};
		return credentialConnectionId(connectionRouteId(route.target)) !== removedId;
	});
};
function removedWithRelay(entry) {
	return routesAfterRemoving(connectionRoutes(entry), RELAY_ROUTE_ID).length === 0;
};
function sshTargetKey(target) {
	return JSON.stringify([
		target.alias,
		target.hostname,
		target.username,
		target.port
	]);
}
//# sourceMappingSource=vite-generated
//# sourceMappingURL=data:application/json;base64,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QVUsT0FBTztFQUFVLE9BQU87Q0FBSSxDQUFDO0FBQ3JGIiwibmFtZXMiOltdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlcyI6WyJyb3V0ZXMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgaXNMb2NhbExvb3BiYWNrSG9zdCxcbiAgaXNQcml2YXRlTmV0d29ya0hvc3QsXG4gIGlzU2hhcmVkQWRkcmVzc1NwYWNlSG9zdCxcbiAgaXNUYWlsbmV0SG9zdCxcbn0gZnJvbSBcIkB0M3Rvb2xzL3NoYXJlZC9ob3N0Q2xhc3NpZmljYXRpb25cIjtcbmltcG9ydCB0eXBlIHsgRGVza3RvcFNzaEVudmlyb25tZW50VGFyZ2V0IH0gZnJvbSBcIkB0M3Rvb2xzL2NvbnRyYWN0c1wiO1xuaW1wb3J0ICogYXMgT3B0aW9uIGZyb20gXCJlZmZlY3QvT3B0aW9uXCI7XG5cbmltcG9ydCB7XG4gIEJlYXJlckNvbm5lY3Rpb25Qcm9maWxlLFxuICB0eXBlIENvbm5lY3Rpb25DYXRhbG9nRW50cnksXG4gIHR5cGUgQ29ubmVjdGlvblJvdXRlLFxufSBmcm9tIFwiLi9jYXRhbG9nLnRzXCI7XG5pbXBvcnQgeyBCZWFyZXJDb25uZWN0aW9uVGFyZ2V0LCB0eXBlIENvbm5lY3Rpb25UYXJnZXQgfSBmcm9tIFwiLi9tb2RlbC50c1wiO1xuXG5leHBvcnQgdHlwZSBDb25uZWN0aW9uUm91dGVLaW5kID1cbiAgfCBcInJlbGF5XCJcbiAgfCBcImxvb3BiYWNrXCJcbiAgfCBcImxhblwiXG4gIHwgXCJ0YWlsbmV0XCJcbiAgfCBcInZwblwiXG4gIHwgXCJwdWJsaWNcIlxuICB8IFwic3NoXCI7XG5cbmV4cG9ydCBjb25zdCBSRUxBWV9ST1VURV9JRCA9IFwicmVsYXlcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbm5lY3Rpb25Sb3V0ZUlkKHRhcmdldDogQ29ubmVjdGlvblRhcmdldCk6IHN0cmluZyB7XG4gIHN3aXRjaCAodGFyZ2V0Ll90YWcpIHtcbiAgICBjYXNlIFwiUHJpbWFyeUNvbm5lY3Rpb25UYXJnZXRcIjpcbiAgICAgIHJldHVybiBcInByaW1hcnlcIjtcbiAgICBjYXNlIFwiUmVsYXlDb25uZWN0aW9uVGFyZ2V0XCI6XG4gICAgICByZXR1cm4gUkVMQVlfUk9VVEVfSUQ7XG4gICAgY2FzZSBcIkJlYXJlckNvbm5lY3Rpb25UYXJnZXRcIjpcbiAgICBjYXNlIFwiU3NoQ29ubmVjdGlvblRhcmdldFwiOlxuICAgICAgcmV0dXJuIHRhcmdldC5jb25uZWN0aW9uSWQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbm5lY3Rpb25Sb3V0ZXMoZW50cnk6IENvbm5lY3Rpb25DYXRhbG9nRW50cnkpOiBSZWFkb25seUFycmF5PENvbm5lY3Rpb25Sb3V0ZT4ge1xuICByZXR1cm4gW3sgdGFyZ2V0OiBlbnRyeS50YXJnZXQsIHByb2ZpbGU6IGVudHJ5LnByb2ZpbGUgfSwgLi4uKGVudHJ5LmFsdGVybmF0ZVJvdXRlcyA/PyBbXSldO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZW50cnlXaXRoUm91dGVzKFxuICBlbnRyeTogQ29ubmVjdGlvbkNhdGFsb2dFbnRyeSxcbiAgcm91dGVzOiBSZWFkb25seUFycmF5PENvbm5lY3Rpb25Sb3V0ZT4sXG4pOiBDb25uZWN0aW9uQ2F0YWxvZ0VudHJ5IHtcbiAgY29uc3QgW2ZpcnN0LCAuLi5yZXN0XSA9IHJvdXRlcztcbiAgaWYgKGZpcnN0ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJBIHNhdmVkIGVudmlyb25tZW50IG5lZWRzIGF0IGxlYXN0IG9uZSByb3V0ZS5cIik7XG4gIH1cbiAgY29uc3QgeyBhbHRlcm5hdGVSb3V0ZXM6IF9wcmV2aW91cywgLi4uYmFzZSB9ID0gZW50cnk7XG4gIHJldHVybiB7XG4gICAgLi4uYmFzZSxcbiAgICB0YXJnZXQ6IGZpcnN0LnRhcmdldCxcbiAgICBwcm9maWxlOiBmaXJzdC5wcm9maWxlLFxuICAgIC4uLihyZXN0Lmxlbmd0aCA9PT0gMCA/IHt9IDogeyBhbHRlcm5hdGVSb3V0ZXM6IHJlc3QgfSksXG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByb3V0ZUVudHJ5KFxuICBlbnRyeTogQ29ubmVjdGlvbkNhdGFsb2dFbnRyeSxcbiAgcm91dGU6IENvbm5lY3Rpb25Sb3V0ZSxcbik6IENvbm5lY3Rpb25DYXRhbG9nRW50cnkge1xuICByZXR1cm4gZW50cnlXaXRoUm91dGVzKGVudHJ5LCBbcm91dGVdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdXRlSHR0cEJhc2VVcmwocm91dGU6IENvbm5lY3Rpb25Sb3V0ZSk6IHN0cmluZyB8IG51bGwge1xuICBpZiAocm91dGUudGFyZ2V0Ll90YWcgPT09IFwiUHJpbWFyeUNvbm5lY3Rpb25UYXJnZXRcIikgcmV0dXJuIHJvdXRlLnRhcmdldC5odHRwQmFzZVVybDtcbiAgY29uc3QgcHJvZmlsZSA9IE9wdGlvbi5nZXRPck51bGwocm91dGUucHJvZmlsZSk7XG4gIHJldHVybiBwcm9maWxlPy5fdGFnID09PSBcIkJlYXJlckNvbm5lY3Rpb25Qcm9maWxlXCIgPyBwcm9maWxlLmh0dHBCYXNlVXJsIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gcm91dGVIb3N0bmFtZShyb3V0ZTogQ29ubmVjdGlvblJvdXRlKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IGh0dHBCYXNlVXJsID0gcm91dGVIdHRwQmFzZVVybChyb3V0ZSk7XG4gIGlmIChodHRwQmFzZVVybCA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG5ldyBVUkwoaHR0cEJhc2VVcmwpLmhvc3RuYW1lO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY29ubmVjdGlvblJvdXRlS2luZChyb3V0ZTogQ29ubmVjdGlvblJvdXRlKTogQ29ubmVjdGlvblJvdXRlS2luZCB7XG4gIHN3aXRjaCAocm91dGUudGFyZ2V0Ll90YWcpIHtcbiAgICBjYXNlIFwiUmVsYXlDb25uZWN0aW9uVGFyZ2V0XCI6XG4gICAgICByZXR1cm4gXCJyZWxheVwiO1xuICAgIGNhc2UgXCJTc2hDb25uZWN0aW9uVGFyZ2V0XCI6XG4gICAgICByZXR1cm4gXCJzc2hcIjtcbiAgICBjYXNlIFwiUHJpbWFyeUNvbm5lY3Rpb25UYXJnZXRcIjpcbiAgICBjYXNlIFwiQmVhcmVyQ29ubmVjdGlvblRhcmdldFwiOiB7XG4gICAgICBjb25zdCBob3N0bmFtZSA9IHJvdXRlSG9zdG5hbWUocm91dGUpO1xuICAgICAgaWYgKGhvc3RuYW1lID09PSBudWxsKSByZXR1cm4gXCJwdWJsaWNcIjtcbiAgICAgIGlmIChpc0xvY2FsTG9vcGJhY2tIb3N0KGhvc3RuYW1lKSkgcmV0dXJuIFwibG9vcGJhY2tcIjtcbiAgICAgIGNvbnN0IHByb2ZpbGUgPSBPcHRpb24uZ2V0T3JOdWxsKHJvdXRlLnByb2ZpbGUpO1xuICAgICAgY29uc3QgdGFpbHNjYWxlID1cbiAgICAgICAgcHJvZmlsZT8uX3RhZyA9PT0gXCJCZWFyZXJDb25uZWN0aW9uUHJvZmlsZVwiICYmIHByb2ZpbGUubmV0d29yayA9PT0gXCJ0YWlsc2NhbGVcIjtcbiAgICAgIGlmICh0YWlsc2NhbGUgfHwgaXNUYWlsbmV0SG9zdChob3N0bmFtZSkpIHJldHVybiBcInRhaWxuZXRcIjtcbiAgICAgIGlmIChpc1NoYXJlZEFkZHJlc3NTcGFjZUhvc3QoaG9zdG5hbWUpKSByZXR1cm4gXCJ2cG5cIjtcbiAgICAgIHJldHVybiBpc1ByaXZhdGVOZXR3b3JrSG9zdChob3N0bmFtZSkgPyBcImxhblwiIDogXCJwdWJsaWNcIjtcbiAgICB9XG4gIH1cbn1cblxuY29uc3QgUk9VVEVfS0lORF9SQU5LOiBSZWNvcmQ8Q29ubmVjdGlvblJvdXRlS2luZCwgbnVtYmVyPiA9IHtcbiAgbG9vcGJhY2s6IDAsXG4gIGxhbjogMSxcbiAgdGFpbG5ldDogMixcbiAgdnBuOiAyLFxuICBwdWJsaWM6IDMsXG4gIHNzaDogNCxcbiAgcmVsYXk6IDUsXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gaW5zZXJ0Um91dGUoXG4gIHJvdXRlczogUmVhZG9ubHlBcnJheTxDb25uZWN0aW9uUm91dGU+LFxuICByb3V0ZTogQ29ubmVjdGlvblJvdXRlLFxuKTogUmVhZG9ubHlBcnJheTxDb25uZWN0aW9uUm91dGU+IHtcbiAgY29uc3QgcmFuayA9IFJPVVRFX0tJTkRfUkFOS1tjb25uZWN0aW9uUm91dGVLaW5kKHJvdXRlKV07XG4gIGNvbnN0IGluZGV4ID0gcm91dGVzLmZpbmRJbmRleChcbiAgICAoZXhpc3RpbmcpID0+IFJPVVRFX0tJTkRfUkFOS1tjb25uZWN0aW9uUm91dGVLaW5kKGV4aXN0aW5nKV0gPiByYW5rLFxuICApO1xuICByZXR1cm4gaW5kZXggPT09IC0xXG4gICAgPyBbLi4ucm91dGVzLCByb3V0ZV1cbiAgICA6IFsuLi5yb3V0ZXMuc2xpY2UoMCwgaW5kZXgpLCByb3V0ZSwgLi4ucm91dGVzLnNsaWNlKGluZGV4KV07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1cHNlcnRSb3V0ZShcbiAgcm91dGVzOiBSZWFkb25seUFycmF5PENvbm5lY3Rpb25Sb3V0ZT4sXG4gIHJvdXRlOiBDb25uZWN0aW9uUm91dGUsXG4pOiBSZWFkb25seUFycmF5PENvbm5lY3Rpb25Sb3V0ZT4ge1xuICBjb25zdCBpZCA9IGNvbm5lY3Rpb25Sb3V0ZUlkKHJvdXRlLnRhcmdldCk7XG4gIHJldHVybiByb3V0ZXMuc29tZSgoZXhpc3RpbmcpID0+IGNvbm5lY3Rpb25Sb3V0ZUlkKGV4aXN0aW5nLnRhcmdldCkgPT09IGlkKVxuICAgID8gcm91dGVzLm1hcCgoZXhpc3RpbmcpID0+IChjb25uZWN0aW9uUm91dGVJZChleGlzdGluZy50YXJnZXQpID09PSBpZCA/IHJvdXRlIDogZXhpc3RpbmcpKVxuICAgIDogaW5zZXJ0Um91dGUocm91dGVzLCByb3V0ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmaW5kUm91dGVUb1NhbWVBZGRyZXNzKFxuICByb3V0ZXM6IFJlYWRvbmx5QXJyYXk8Q29ubmVjdGlvblJvdXRlPixcbiAgcm91dGU6IENvbm5lY3Rpb25Sb3V0ZSxcbik6IENvbm5lY3Rpb25Sb3V0ZSB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGtleSA9IHJvdXRlQWRkcmVzc0tleShyb3V0ZSk7XG4gIHJldHVybiBrZXkgPT09IG51bGwgPyB1bmRlZmluZWQgOiByb3V0ZXMuZmluZCgoZXhpc3RpbmcpID0+IHJvdXRlQWRkcmVzc0tleShleGlzdGluZykgPT09IGtleSk7XG59XG5cbmZ1bmN0aW9uIHJvdXRlQWRkcmVzc0tleShyb3V0ZTogQ29ubmVjdGlvblJvdXRlKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IHByb2ZpbGUgPSBPcHRpb24uZ2V0T3JOdWxsKHJvdXRlLnByb2ZpbGUpO1xuICBzd2l0Y2ggKHByb2ZpbGU/Ll90YWcpIHtcbiAgICBjYXNlIFwiQmVhcmVyQ29ubmVjdGlvblByb2ZpbGVcIjpcbiAgICAgIHJldHVybiBgYmVhcmVyOiR7cHJvZmlsZS5odHRwQmFzZVVybC5yZXBsYWNlKC9cXC8rJC8sIFwiXCIpfWA7XG4gICAgY2FzZSBcIlNzaENvbm5lY3Rpb25Qcm9maWxlXCI6XG4gICAgICByZXR1cm4gYHNzaDoke3NzaFRhcmdldEtleShwcm9maWxlLnRhcmdldCl9YDtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbm5lY3Rpb25Sb3V0ZUxhYmVsKHJvdXRlOiBDb25uZWN0aW9uUm91dGUpOiBzdHJpbmcge1xuICBzd2l0Y2ggKGNvbm5lY3Rpb25Sb3V0ZUtpbmQocm91dGUpKSB7XG4gICAgY2FzZSBcInJlbGF5XCI6XG4gICAgICByZXR1cm4gXCJUMyBDb25uZWN0XCI7XG4gICAgY2FzZSBcImxvb3BiYWNrXCI6XG4gICAgICByZXR1cm4gXCJUaGlzIGRldmljZVwiO1xuICAgIGNhc2UgXCJsYW5cIjpcbiAgICAgIHJldHVybiBcIkxBTlwiO1xuICAgIGNhc2UgXCJ0YWlsbmV0XCI6XG4gICAgICByZXR1cm4gXCJUYWlsc2NhbGVcIjtcbiAgICBjYXNlIFwidnBuXCI6XG4gICAgICByZXR1cm4gXCJWUE5cIjtcbiAgICBjYXNlIFwic3NoXCI6IHtcbiAgICAgIGNvbnN0IHByb2ZpbGUgPSBPcHRpb24uZ2V0T3JOdWxsKHJvdXRlLnByb2ZpbGUpO1xuICAgICAgcmV0dXJuIHByb2ZpbGU/Ll90YWcgPT09IFwiU3NoQ29ubmVjdGlvblByb2ZpbGVcIlxuICAgICAgICA/IGBTU0ggJHtwcm9maWxlLnRhcmdldC51c2VybmFtZSA/IGAke3Byb2ZpbGUudGFyZ2V0LnVzZXJuYW1lfUBgIDogXCJcIn0ke3Byb2ZpbGUudGFyZ2V0Lmhvc3RuYW1lfWBcbiAgICAgICAgOiBcIlNTSFwiO1xuICAgIH1cbiAgICBjYXNlIFwicHVibGljXCI6XG4gICAgICByZXR1cm4gcm91dGVIb3N0bmFtZShyb3V0ZSkgPz8gXCJSZW1vdGUgbGlua1wiO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb25uZWN0aW9uUm91dGVBZGRyZXNzKHJvdXRlOiBDb25uZWN0aW9uUm91dGUpOiBzdHJpbmcgfCBudWxsIHtcbiAgaWYgKHJvdXRlLnRhcmdldC5fdGFnID09PSBcIlNzaENvbm5lY3Rpb25UYXJnZXRcIikge1xuICAgIGNvbnN0IHByb2ZpbGUgPSBPcHRpb24uZ2V0T3JOdWxsKHJvdXRlLnByb2ZpbGUpO1xuICAgIHJldHVybiBwcm9maWxlPy5fdGFnID09PSBcIlNzaENvbm5lY3Rpb25Qcm9maWxlXCIgPyBwcm9maWxlLnRhcmdldC5hbGlhcyA6IG51bGw7XG4gIH1cbiAgcmV0dXJuIHJvdXRlSHR0cEJhc2VVcmwocm91dGUpO1xufVxuXG4vKiogTGVhcm5lZCByb3V0ZXMgYWxvbmUgbXVzdCBub3QgbWFrZSByZWxheSBlbnZpcm9ubWVudHMgbWFudWFsbHkgcmV0cnlhYmxlLiAqL1xuZXhwb3J0IGNvbnN0IGhhc1NhdmVkQmVhcmVyUm91dGUgPSAoZW50cnk6IENvbm5lY3Rpb25DYXRhbG9nRW50cnkpID0+XG4gIGNvbm5lY3Rpb25Sb3V0ZXMoZW50cnkpLnNvbWUoKHIpID0+ICFpc0xlYXJuZWQocikgJiYgci50YXJnZXQuX3RhZyA9PT0gXCJCZWFyZXJDb25uZWN0aW9uVGFyZ2V0XCIpO1xuXG5leHBvcnQgZnVuY3Rpb24gaGFzUmVsYXlSb3V0ZShcbiAgZW50cnk6IFBpY2s8Q29ubmVjdGlvbkNhdGFsb2dFbnRyeSwgXCJ0YXJnZXRcIiB8IFwiYWx0ZXJuYXRlUm91dGVzXCI+LFxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBbZW50cnkudGFyZ2V0LCAuLi4oZW50cnkuYWx0ZXJuYXRlUm91dGVzID8/IFtdKS5tYXAoKHJvdXRlKSA9PiByb3V0ZS50YXJnZXQpXS5zb21lKFxuICAgICh0YXJnZXQpID0+IHRhcmdldC5fdGFnID09PSBcIlJlbGF5Q29ubmVjdGlvblRhcmdldFwiLFxuICApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VMZWFybmVkUm91dGVzKGlucHV0OiB7XG4gIHJlYWRvbmx5IGVudHJ5OiBDb25uZWN0aW9uQ2F0YWxvZ0VudHJ5O1xuICByZWFkb25seSBhY3RpdmVSb3V0ZTogQ29ubmVjdGlvblJvdXRlO1xuICByZWFkb25seSByZXBvcnRlZDogUmVhZG9ubHlBcnJheTxSZXBvcnRlZEVuZHBvaW50PjtcbiAgLyoqIFBsYWluIEhUVFAgcm91dGVzIGFyZSB1bnVzYWJsZSBmcm9tIGFuIEhUVFBTIHBhZ2UgKG1peGVkIGNvbnRlbnQpLiAqL1xuICByZWFkb25seSBhbGxvd0luc2VjdXJlOiBib29sZWFuO1xufSk6IFJlYWRvbmx5QXJyYXk8Q29ubmVjdGlvblJvdXRlPiB8IG51bGwge1xuICBjb25zdCB7IGVudHJ5IH0gPSBpbnB1dDtcbiAgY29uc3QgYWN0aXZlID0gaW5wdXQuYWN0aXZlUm91dGUudGFyZ2V0O1xuICBjb25zdCBzYXZlZCA9IGNvbm5lY3Rpb25Sb3V0ZXMoZW50cnkpO1xuICBpZiAoYWN0aXZlLl90YWcgIT09IFwiUmVsYXlDb25uZWN0aW9uVGFyZ2V0XCIgJiYgYWN0aXZlLl90YWcgIT09IFwiQmVhcmVyQ29ubmVjdGlvblRhcmdldFwiKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgY29uc3QgYWN0aXZlUHJvZmlsZSA9IE9wdGlvbi5nZXRPck51bGwoaW5wdXQuYWN0aXZlUm91dGUucHJvZmlsZSk7XG4gIGNvbnN0IGF1dGhvcml6YXRpb24gPVxuICAgIGFjdGl2ZS5fdGFnID09PSBcIlJlbGF5Q29ubmVjdGlvblRhcmdldFwiIHx8XG4gICAgKGFjdGl2ZVByb2ZpbGU/Ll90YWcgPT09IFwiQmVhcmVyQ29ubmVjdGlvblByb2ZpbGVcIiAmJlxuICAgICAgYWN0aXZlUHJvZmlsZS5hdXRob3JpemF0aW9uID09PSBcInQzLWNvbm5lY3RcIilcbiAgICAgID8gKFwidDMtY29ubmVjdFwiIGFzIGNvbnN0KVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHNoYXJlZENyZWRlbnRpYWwgPVxuICAgIGF1dGhvcml6YXRpb24gPT09IHVuZGVmaW5lZCAmJiBhY3RpdmUuX3RhZyA9PT0gXCJCZWFyZXJDb25uZWN0aW9uVGFyZ2V0XCJcbiAgICAgID8gY3JlZGVudGlhbENvbm5lY3Rpb25JZChhY3RpdmUuY29ubmVjdGlvbklkKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHJlcG9ydGVkID0gbmV3IE1hcDxzdHJpbmcsIFVSTD4oKTtcbiAgY29uc3QgdGFpbHNjYWxlT3JpZ2lucyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBmb3IgKGNvbnN0IGVuZHBvaW50IG9mIGlucHV0LnJlcG9ydGVkKSB7XG4gICAgbGV0IHVybDogVVJMO1xuICAgIHRyeSB7XG4gICAgICB1cmwgPSBuZXcgVVJMKGVuZHBvaW50Lmh0dHBCYXNlVXJsKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAodXJsLnByb3RvY29sICE9PSBcImh0dHA6XCIgJiYgdXJsLnByb3RvY29sICE9PSBcImh0dHBzOlwiKSBjb250aW51ZTtcbiAgICBpZiAodXJsLnByb3RvY29sID09PSBcImh0dHA6XCIgJiYgIWlucHV0LmFsbG93SW5zZWN1cmUpIGNvbnRpbnVlO1xuICAgIC8vIEEgbG9vcGJhY2sgYWRkcmVzcyBuYW1lcyB3aGljaGV2ZXIgZGV2aWNlIG9wZW5zIGl0LCBuZXZlciB0aGUgc2VydmVyLlxuICAgIGlmIChpc0xvY2FsTG9vcGJhY2tIb3N0KHVybC5ob3N0bmFtZSkpIGNvbnRpbnVlO1xuICAgIHJlcG9ydGVkLnNldCh1cmwub3JpZ2luLCB1cmwpO1xuICAgIGlmIChlbmRwb2ludC5raW5kID09PSBcInRhaWxuZXRcIikgdGFpbHNjYWxlT3JpZ2lucy5hZGQodXJsLm9yaWdpbik7XG4gIH1cbiAgY29uc3Qgbm9ybWFsaXplZCA9ICh1cmw6IHN0cmluZykgPT4gdXJsLnJlcGxhY2UoL1xcLyskLywgXCJcIik7XG4gIGNvbnN0IGtub3duID0gbmV3IFNldChcbiAgICBzYXZlZC5mbGF0TWFwKChyb3V0ZSkgPT4ge1xuICAgICAgY29uc3QgdXJsID0gcm91dGVIdHRwQmFzZVVybChyb3V0ZSk7XG4gICAgICByZXR1cm4gdXJsID09PSBudWxsIHx8IGlzTGVhcm5lZChyb3V0ZSkgPyBbXSA6IFtub3JtYWxpemVkKHVybCldO1xuICAgIH0pLFxuICApO1xuICBjb25zdCBrZXB0ID0gc2F2ZWQuZmxhdE1hcCgocm91dGUpOiBSZWFkb25seUFycmF5PENvbm5lY3Rpb25Sb3V0ZT4gPT4ge1xuICAgIGNvbnN0IHVybCA9IHJvdXRlSHR0cEJhc2VVcmwocm91dGUpO1xuICAgIGlmICghaXNMZWFybmVkKHJvdXRlKSkge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgdXJsID09PSBudWxsIHx8ICFyZXBvcnRlZC5oYXMobm9ybWFsaXplZCh1cmwpKVxuICAgICAgICAgID8gcm91dGVcbiAgICAgICAgICA6IHdpdGhOZXR3b3JrKHJvdXRlLCB0YWlsc2NhbGVPcmlnaW5zLmhhcyhub3JtYWxpemVkKHVybCkpKSxcbiAgICAgIF07XG4gICAgfVxuICAgIGlmICh1cmwgPT09IG51bGwgfHwgIXJlcG9ydGVkLmhhcyhub3JtYWxpemVkKHVybCkpIHx8IGtub3duLmhhcyhub3JtYWxpemVkKHVybCkpKSByZXR1cm4gW107XG4gICAgaWYgKHNlbmRzVG9rZW5JbkNsZWFyKHNhdmVkLCByb3V0ZSwgdGFpbHNjYWxlT3JpZ2lucy5oYXMobm9ybWFsaXplZCh1cmwpKSkpIHJldHVybiBbXTtcbiAgICBrbm93bi5hZGQobm9ybWFsaXplZCh1cmwpKTtcbiAgICByZXR1cm4gW3dpdGhOZXR3b3JrKHJvdXRlLCB0YWlsc2NhbGVPcmlnaW5zLmhhcyhub3JtYWxpemVkKHVybCkpKV07XG4gIH0pO1xuICBsZXQgbmV4dDogUmVhZG9ubHlBcnJheTxDb25uZWN0aW9uUm91dGU+ID0ga2VwdDtcbiAgZm9yIChjb25zdCB1cmwgb2YgcmVwb3J0ZWQudmFsdWVzKCkpIHtcbiAgICBpZiAoa25vd24uaGFzKHVybC5vcmlnaW4pKSBjb250aW51ZTtcbiAgICBpZiAoXG4gICAgICB1cmwucHJvdG9jb2wgPT09IFwiaHR0cDpcIiAmJlxuICAgICAgc2hhcmVkQ3JlZGVudGlhbCAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAhdGFpbHNjYWxlT3JpZ2lucy5oYXModXJsLm9yaWdpbikgJiZcbiAgICAgICF0b2tlbkFsbG93c1BsYWluSHR0cChzYXZlZCwgc2hhcmVkQ3JlZGVudGlhbClcbiAgICApIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjb25zdCBodHRwQmFzZVVybCA9IGAke3VybC5vcmlnaW59L2A7XG4gICAgY29uc3QgY29ubmVjdGlvbklkID0gbGVhcm5lZENvbm5lY3Rpb25JZChcbiAgICAgIGVudHJ5LnRhcmdldC5lbnZpcm9ubWVudElkLFxuICAgICAgdXJsLm9yaWdpbixcbiAgICAgIHNoYXJlZENyZWRlbnRpYWwsXG4gICAgKTtcbiAgICBuZXh0ID0gaW5zZXJ0Um91dGUobmV4dCwge1xuICAgICAgdGFyZ2V0OiBuZXcgQmVhcmVyQ29ubmVjdGlvblRhcmdldCh7XG4gICAgICAgIGVudmlyb25tZW50SWQ6IGVudHJ5LnRhcmdldC5lbnZpcm9ubWVudElkLFxuICAgICAgICBsYWJlbDogZW50cnkudGFyZ2V0LmxhYmVsLFxuICAgICAgICBjb25uZWN0aW9uSWQsXG4gICAgICB9KSxcbiAgICAgIHByb2ZpbGU6IE9wdGlvbi5zb21lKFxuICAgICAgICBuZXcgQmVhcmVyQ29ubmVjdGlvblByb2ZpbGUoe1xuICAgICAgICAgIGNvbm5lY3Rpb25JZCxcbiAgICAgICAgICBlbnZpcm9ubWVudElkOiBlbnRyeS50YXJnZXQuZW52aXJvbm1lbnRJZCxcbiAgICAgICAgICBsYWJlbDogZW50cnkudGFyZ2V0LmxhYmVsLFxuICAgICAgICAgIGh0dHBCYXNlVXJsLFxuICAgICAgICAgIHdzQmFzZVVybDogYCR7dXJsLnByb3RvY29sID09PSBcImh0dHBzOlwiID8gXCJ3c3M6XCIgOiBcIndzOlwifS8vJHt1cmwuaG9zdH0vYCxcbiAgICAgICAgICBsZWFybmVkOiB0cnVlLFxuICAgICAgICAgIC4uLihhdXRob3JpemF0aW9uID09PSB1bmRlZmluZWQgPyB7fSA6IHsgYXV0aG9yaXphdGlvbiB9KSxcbiAgICAgICAgICAuLi4odGFpbHNjYWxlT3JpZ2lucy5oYXModXJsLm9yaWdpbikgPyB7IG5ldHdvcms6IFwidGFpbHNjYWxlXCIgYXMgY29uc3QgfSA6IHt9KSxcbiAgICAgICAgfSksXG4gICAgICApLFxuICAgIH0pO1xuICB9XG4gIGNvbnN0IHNpZ25hdHVyZSA9IChyb3V0ZXM6IFJlYWRvbmx5QXJyYXk8Q29ubmVjdGlvblJvdXRlPikgPT5cbiAgICByb3V0ZXNcbiAgICAgIC5tYXAoXG4gICAgICAgIChyb3V0ZSkgPT5cbiAgICAgICAgICBgJHtjb25uZWN0aW9uUm91dGVJZChyb3V0ZS50YXJnZXQpfSAke3JvdXRlSHR0cEJhc2VVcmwocm91dGUpID8/IFwiXCJ9ICR7Y29ubmVjdGlvblJvdXRlS2luZChyb3V0ZSl9YCxcbiAgICAgIClcbiAgICAgIC5qb2luKFwiXFxuXCIpO1xuICByZXR1cm4gc2lnbmF0dXJlKHNhdmVkKSA9PT0gc2lnbmF0dXJlKG5leHQpID8gbnVsbCA6IG5leHQ7XG59XG5cbi8vIEEgcGFpcmVkIHRva2VuIGdvZXMgdG8gYSBwbGFpbiBIVFRQIGFkZHJlc3Mgb3V0c2lkZSB0aGUgdGFpbG5ldCBvbmx5IHdoZW5cbi8vIGl0IHdhcyBwYWlyZWQgdGhhdCB3YXksIHNvIGEgdG9rZW4gcGFpcmVkIG92ZXIgSFRUUFMsIGxvb3BiYWNrLCBvciB0aGVcbi8vIHRhaWxuZXQga2VlcHMgdG8gdGhlIHRyYW5zcG9ydHMgaXQgd2FzIGlzc3VlZCBmb3IuXG5mdW5jdGlvbiB0b2tlbkFsbG93c1BsYWluSHR0cChcbiAgcm91dGVzOiBSZWFkb25seUFycmF5PENvbm5lY3Rpb25Sb3V0ZT4sXG4gIGNyZWRlbnRpYWxJZDogc3RyaW5nLFxuKTogYm9vbGVhbiB7XG4gIGNvbnN0IGNyZWRlbnRpYWxSb3V0ZSA9IHJvdXRlcy5maW5kKChyb3V0ZSkgPT4gY29ubmVjdGlvblJvdXRlSWQocm91dGUudGFyZ2V0KSA9PT0gY3JlZGVudGlhbElkKTtcbiAgcmV0dXJuIChcbiAgICBjcmVkZW50aWFsUm91dGUgIT09IHVuZGVmaW5lZCAmJlxuICAgIHJvdXRlSHR0cEJhc2VVcmwoY3JlZGVudGlhbFJvdXRlKT8uc3RhcnRzV2l0aChcImh0dHA6XCIpID09PSB0cnVlICYmXG4gICAgKGNvbm5lY3Rpb25Sb3V0ZUtpbmQoY3JlZGVudGlhbFJvdXRlKSA9PT0gXCJsYW5cIiB8fFxuICAgICAgY29ubmVjdGlvblJvdXRlS2luZChjcmVkZW50aWFsUm91dGUpID09PSBcInB1YmxpY1wiKVxuICApO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgY29ubmVjdGluZyBvdmVyIGByb3V0ZWAgd291bGQgc2VuZCBhIHBhaXJlZCB0b2tlbiBvdmVyIHBsYWluIEhUVFBcbiAqIHRoYXQgaXQgd2Fzbid0IHBhaXJlZCBvdmVyLiBDaGVja2VkIGFnYWluc3QgdGhlIHRva2VuIHRoZSByb3V0ZSBib3Jyb3dzLFxuICogc28gYSByb3V0ZSBsZWFybmVkIGJlZm9yZSB0aGlzIHJ1bGUgZXhpc3RlZCBpcyByZWZ1c2VkIHRvby5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbmRzVG9rZW5JbkNsZWFyKFxuICByb3V0ZXM6IFJlYWRvbmx5QXJyYXk8Q29ubmVjdGlvblJvdXRlPixcbiAgcm91dGU6IENvbm5lY3Rpb25Sb3V0ZSxcbiAgdGFpbHNjYWxlPzogYm9vbGVhbixcbik6IGJvb2xlYW4ge1xuICBjb25zdCBwcm9maWxlID0gT3B0aW9uLmdldE9yTnVsbChyb3V0ZS5wcm9maWxlKTtcbiAgaWYgKHByb2ZpbGU/Ll90YWcgIT09IFwiQmVhcmVyQ29ubmVjdGlvblByb2ZpbGVcIiB8fCBwcm9maWxlLmF1dGhvcml6YXRpb24gPT09IFwidDMtY29ubmVjdFwiKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICgodGFpbHNjYWxlID8/IHByb2ZpbGUubmV0d29yayA9PT0gXCJ0YWlsc2NhbGVcIikgfHwgIXByb2ZpbGUuaHR0cEJhc2VVcmwuc3RhcnRzV2l0aChcImh0dHA6XCIpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGNyZWRlbnRpYWxJZCA9IGNyZWRlbnRpYWxDb25uZWN0aW9uSWQoY29ubmVjdGlvblJvdXRlSWQocm91dGUudGFyZ2V0KSk7XG4gIHJldHVybiAoXG4gICAgY3JlZGVudGlhbElkICE9PSBjb25uZWN0aW9uUm91dGVJZChyb3V0ZS50YXJnZXQpICYmICF0b2tlbkFsbG93c1BsYWluSHR0cChyb3V0ZXMsIGNyZWRlbnRpYWxJZClcbiAgKTtcbn1cblxuLyoqIFJvdXRlcyBhIGNvbm5lY3QgbWF5IHVzZTogbm9uZSBzZW5kcyBhIHBhaXJlZCB0b2tlbiBvdmVyIHBsYWluIEhUVFAgaXQgd2Fzbid0IHBhaXJlZCBvdmVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzYWJsZVJvdXRlcyhlbnRyeTogQ29ubmVjdGlvbkNhdGFsb2dFbnRyeSk6IFJlYWRvbmx5QXJyYXk8Q29ubmVjdGlvblJvdXRlPiB7XG4gIGNvbnN0IHJvdXRlcyA9IGNvbm5lY3Rpb25Sb3V0ZXMoZW50cnkpO1xuICByZXR1cm4gcm91dGVzLmZpbHRlcigocm91dGUpID0+ICFzZW5kc1Rva2VuSW5DbGVhcihyb3V0ZXMsIHJvdXRlKSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVwb3J0ZWRFbmRwb2ludCB7XG4gIHJlYWRvbmx5IGh0dHBCYXNlVXJsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGtpbmQ/OiBzdHJpbmc7XG59XG5cbmZ1bmN0aW9uIHdpdGhOZXR3b3JrKHJvdXRlOiBDb25uZWN0aW9uUm91dGUsIHRhaWxzY2FsZTogYm9vbGVhbik6IENvbm5lY3Rpb25Sb3V0ZSB7XG4gIGNvbnN0IHByb2ZpbGUgPSBPcHRpb24uZ2V0T3JOdWxsKHJvdXRlLnByb2ZpbGUpO1xuICBpZiAocHJvZmlsZT8uX3RhZyAhPT0gXCJCZWFyZXJDb25uZWN0aW9uUHJvZmlsZVwiKSByZXR1cm4gcm91dGU7XG4gIGlmICgocHJvZmlsZS5uZXR3b3JrID09PSBcInRhaWxzY2FsZVwiKSA9PT0gdGFpbHNjYWxlKSByZXR1cm4gcm91dGU7XG4gIHJldHVybiB7XG4gICAgdGFyZ2V0OiByb3V0ZS50YXJnZXQsXG4gICAgcHJvZmlsZTogT3B0aW9uLnNvbWUoXG4gICAgICBuZXcgQmVhcmVyQ29ubmVjdGlvblByb2ZpbGUoe1xuICAgICAgICBjb25uZWN0aW9uSWQ6IHByb2ZpbGUuY29ubmVjdGlvbklkLFxuICAgICAgICBlbnZpcm9ubWVudElkOiBwcm9maWxlLmVudmlyb25tZW50SWQsXG4gICAgICAgIGxhYmVsOiBwcm9maWxlLmxhYmVsLFxuICAgICAgICBodHRwQmFzZVVybDogcHJvZmlsZS5odHRwQmFzZVVybCxcbiAgICAgICAgd3NCYXNlVXJsOiBwcm9maWxlLndzQmFzZVVybCxcbiAgICAgICAgLi4uKHByb2ZpbGUubGVhcm5lZCA9PT0gdW5kZWZpbmVkID8ge30gOiB7IGxlYXJuZWQ6IHByb2ZpbGUubGVhcm5lZCB9KSxcbiAgICAgICAgLi4uKHByb2ZpbGUuYXV0aG9yaXphdGlvbiA9PT0gdW5kZWZpbmVkID8ge30gOiB7IGF1dGhvcml6YXRpb246IHByb2ZpbGUuYXV0aG9yaXphdGlvbiB9KSxcbiAgICAgICAgLi4uKHRhaWxzY2FsZSA/IHsgbmV0d29yazogXCJ0YWlsc2NhbGVcIiBhcyBjb25zdCB9IDoge30pLFxuICAgICAgfSksXG4gICAgKSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gbGVhcm5lZENvbm5lY3Rpb25JZChcbiAgZW52aXJvbm1lbnRJZDogc3RyaW5nLFxuICBvcmlnaW46IHN0cmluZyxcbiAgc2hhcmVkQ3JlZGVudGlhbDogc3RyaW5nIHwgdW5kZWZpbmVkLFxuKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNoYXJlZENyZWRlbnRpYWwgPT09IHVuZGVmaW5lZFxuICAgID8gYGxlYXJuZWQ6JHtlbnZpcm9ubWVudElkfToke29yaWdpbn1gXG4gICAgOiBgbGVhcm5lZDoke2Vudmlyb25tZW50SWR9OiR7b3JpZ2lufUAke3NoYXJlZENyZWRlbnRpYWx9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWRlbnRpYWxDb25uZWN0aW9uSWQoY29ubmVjdGlvbklkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBhdCA9IGNvbm5lY3Rpb25JZC5pbmRleE9mKFwiQFwiKTtcbiAgcmV0dXJuIGNvbm5lY3Rpb25JZC5zdGFydHNXaXRoKFwibGVhcm5lZDpcIikgJiYgYXQgIT09IC0xXG4gICAgPyBjb25uZWN0aW9uSWQuc2xpY2UoYXQgKyAxKVxuICAgIDogY29ubmVjdGlvbklkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNMZWFybmVkKHJvdXRlOiBDb25uZWN0aW9uUm91dGUpOiBib29sZWFuIHtcbiAgY29uc3QgcHJvZmlsZSA9IE9wdGlvbi5nZXRPck51bGwocm91dGUucHJvZmlsZSk7XG4gIHJldHVybiBwcm9maWxlPy5fdGFnID09PSBcIkJlYXJlckNvbm5lY3Rpb25Qcm9maWxlXCIgJiYgcHJvZmlsZS5sZWFybmVkID09PSB0cnVlO1xufVxuXG4vKipcbiAqIEEgbGVhcm5lZCByb3V0ZSBib3Jyb3dzIHRoZSBjcmVkZW50aWFsIG9mIHRoZSByb3V0ZSBpdCB3YXMgbGVhcm5lZCBvdmVyLCBzb1xuICogaXQgY2Fubm90IG91dGxpdmUgdGhhdCByb3V0ZTogcmVtb3ZpbmcgVDMgQ29ubmVjdCBhbHNvIHJlbW92ZXMgcm91dGVzIGxlYXJuZWRcbiAqIHRocm91Z2ggaXQsIGFuZCByZW1vdmluZyBhIHBhaXJlZCBhZGRyZXNzIHJlbW92ZXMgcm91dGVzIHRoYXQgYm9ycm93IGl0c1xuICogdG9rZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb3V0ZXNBZnRlclJlbW92aW5nKFxuICByb3V0ZXM6IFJlYWRvbmx5QXJyYXk8Q29ubmVjdGlvblJvdXRlPixcbiAgcmVtb3ZlZElkOiBzdHJpbmcsXG4pOiBSZWFkb25seUFycmF5PENvbm5lY3Rpb25Sb3V0ZT4ge1xuICBjb25zdCByZW1vdmVkID0gcm91dGVzLmZpbmQoKHJvdXRlKSA9PiBjb25uZWN0aW9uUm91dGVJZChyb3V0ZS50YXJnZXQpID09PSByZW1vdmVkSWQpO1xuICBpZiAocmVtb3ZlZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gcm91dGVzO1xuICByZXR1cm4gcm91dGVzLmZpbHRlcigocm91dGUpID0+IHtcbiAgICBpZiAocm91dGUgPT09IHJlbW92ZWQpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoIWlzTGVhcm5lZChyb3V0ZSkpIHJldHVybiB0cnVlO1xuICAgIGNvbnN0IHByb2ZpbGUgPSBPcHRpb24uZ2V0T3JOdWxsKHJvdXRlLnByb2ZpbGUpO1xuICAgIGlmIChwcm9maWxlPy5fdGFnID09PSBcIkJlYXJlckNvbm5lY3Rpb25Qcm9maWxlXCIgJiYgcHJvZmlsZS5hdXRob3JpemF0aW9uID09PSBcInQzLWNvbm5lY3RcIikge1xuICAgICAgcmV0dXJuIHJlbW92ZWQudGFyZ2V0Ll90YWcgIT09IFwiUmVsYXlDb25uZWN0aW9uVGFyZ2V0XCI7XG4gICAgfVxuICAgIHJldHVybiBjcmVkZW50aWFsQ29ubmVjdGlvbklkKGNvbm5lY3Rpb25Sb3V0ZUlkKHJvdXRlLnRhcmdldCkpICE9PSByZW1vdmVkSWQ7XG4gIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlZFdpdGhSZWxheShlbnRyeTogQ29ubmVjdGlvbkNhdGFsb2dFbnRyeSk6IGJvb2xlYW4ge1xuICByZXR1cm4gcm91dGVzQWZ0ZXJSZW1vdmluZyhjb25uZWN0aW9uUm91dGVzKGVudHJ5KSwgUkVMQVlfUk9VVEVfSUQpLmxlbmd0aCA9PT0gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNzaFRhcmdldEtleSh0YXJnZXQ6IERlc2t0b3BTc2hFbnZpcm9ubWVudFRhcmdldCk6IHN0cmluZyB7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShbdGFyZ2V0LmFsaWFzLCB0YXJnZXQuaG9zdG5hbWUsIHRhcmdldC51c2VybmFtZSwgdGFyZ2V0LnBvcnRdKTtcbn1cbiJdLCJmaWxlIjoiL0Bmcy9ob21lL3VidW50dS93dC9wci0yNDI2My9wYWNrYWdlcy9jbGllbnQtcnVudGltZS9zcmMvY29ubmVjdGlvbi9yb3V0ZXMudHMifQ==

//# vitestCache=W3siZmlsZSI6IjEiLCJpZCI6IjEiLCJ1cmwiOiIyIiwiaW1wb3J0cyI6IjMiLCJtYXBwaW5ncyI6ZmFsc2UsImRlcHMiOiI0IiwiZHluYW1pY0RlcHMiOiI1Iiwic3RhdGljTW9ja3MiOm51bGx9LCIvaG9tZS91YnVudHUvd3QvcHItMjQyNjMvcGFja2FnZXMvY2xpZW50LXJ1bnRpbWUvc3JjL2Nvbm5lY3Rpb24vcm91dGVzLnRzIiwiL0Bmcy9ob21lL3VidW50dS93dC9wci0yNDI2My9wYWNrYWdlcy9jbGllbnQtcnVudGltZS9zcmMvY29ubmVjdGlvbi9yb3V0ZXMudHMiLHsidXJscyI6IjYiLCJpZHMiOiI3In0sWyI4IiwiOSIsIjEwIiwiMTEiXSxbXSxbIjgiLCI5IiwiMTAiLCIxMSJdLHt9LCIvQGZzL2hvbWUvdWJ1bnR1L3d0L3ByLTI0MjYzL3BhY2thZ2VzL3NoYXJlZC9zcmMvaG9zdENsYXNzaWZpY2F0aW9uLnRzIiwiL0Bmcy9ob21lL3VidW50dS93dC9wci0yNDI2My9ub2RlX21vZHVsZXMvLnBucG0vZWZmZWN0QDQuMC41L25vZGVfbW9kdWxlcy9lZmZlY3QvZGlzdC9PcHRpb24uanMiLCIvQGZzL2hvbWUvdWJ1bnR1L3d0L3ByLTI0MjYzL3BhY2thZ2VzL2NsaWVudC1ydW50aW1lL3NyYy9jb25uZWN0aW9uL2NhdGFsb2cudHMiLCIvQGZzL2hvbWUvdWJ1bnR1L3d0L3ByLTI0MjYzL3BhY2thZ2VzL2NsaWVudC1ydW50aW1lL3NyYy9jb25uZWN0aW9uL21vZGVsLnRzIl0=