@jmnuf/ao
Version:
A simple typescript based full-stack api endpoint creator that is meant to somewhat follow web standards in its implementation.
117 lines (114 loc) • 29.4 kB
JavaScript
//#region src/utils.ts
const HttpMethods = [
"GET",
"POST",
"PUT",
"DELETE"
];
const GeneratorHTTPHeaderName = "X-AncientOnes-Streaming";
//#endregion
//#region src/apostles.ts
const DEBUG_PATHING_PROPERTY = "__DEBUG_PATHING__";
async function* streamToGenerator(reader) {
const decode = (data) => new TextDecoder().decode(data);
do {
const step = await reader.read();
if (step.done) return;
const json = decode(step.value);
const data = JSON.parse(json);
yield data.data;
} while (true);
}
const PROTOCOL_CHECK_REGEX = /^https?:\/\//;
function createApostle(origin) {
origin = origin.trim();
if (!origin.match(PROTOCOL_CHECK_REGEX)) throw new Error("Origin must start with the protocol (http:// or https://)");
while (origin.endsWith("/")) origin = origin.substring(0, origin.length - 1);
const pushParams = (path, params = {}) => {
for (const param of Object.keys(params)) path += "/" + params[param];
return path;
};
const doFetch = async (method, path, config = {}) => {
try {
if (config.params) for (const key of Object.keys(config.params ?? {})) path += "/" + config.params[key];
const url = new URL(path);
if (config.query) for (const key of Object.keys(config.query ?? {})) {
const val = config.query[key];
if (!Array.isArray(val)) {
url.searchParams.append(key, val);
continue;
}
for (const v of val) url.searchParams.append(key, v);
}
const response = await fetch(url, {
method,
body: config.body
});
if (!response.ok) {
const message = await response.text();
return {
ok: false,
status: response.status,
response,
error: new Error(message)
};
}
const status = response.status;
const generatorHeader = response.headers.get(GeneratorHTTPHeaderName);
if (generatorHeader === "Generator" || generatorHeader === "AsyncGenerator") {
if (!response.body) return {
ok: false,
status,
response,
error: new Error("Received generator header but there's no body to read stream from")
};
const reader = response.body.getReader();
const generator = streamToGenerator(reader);
return {
ok: true,
status,
response,
data: generator
};
}
const res = await response.json();
return {
ok: true,
status,
response,
data: res.data
};
} catch (err) {
const error = new Error("Fetch request failed", { cause: err });
return {
ok: false,
error
};
}
};
const methods = HttpMethods.map((x) => x.toLowerCase());
const p = new Proxy({ pathing: origin }, { get(target, property) {
if (typeof property === "symbol") return target[property];
if (property === DEBUG_PATHING_PROPERTY) return target.pathing;
if (methods.includes(property)) return doFetch.bind(null, property.toUpperCase(), target.pathing);
return pathing(origin + "/" + property);
} });
const pathing = (path) => {
const data = { pathing: path };
const fn = (params) => {
data.pathing = pushParams(data.pathing, params);
return proxy;
};
const proxy = new Proxy(fn, { get(target, property) {
if (typeof property === "symbol") return target[property];
if (property === DEBUG_PATHING_PROPERTY) return data.pathing;
if (methods.includes(property)) return doFetch.bind(null, property.toUpperCase(), data.pathing);
return pathing(`${data.pathing}/${property}`);
} });
return proxy;
};
return p;
}
//#endregion
export { DEBUG_PATHING_PROPERTY, createApostle };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBvc3RsZXMuanMiLCJuYW1lcyI6WyJyZWFkZXI6IFJlYWRhYmxlU3RyZWFtRGVmYXVsdFJlYWRlcjxVaW50OEFycmF5PEFycmF5QnVmZmVyTGlrZT4+IiwiZGF0YTogYW55Iiwib3JpZ2luOiBzdHJpbmciLCJwYXRoOiBzdHJpbmciLCJwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4iLCJtZXRob2Q6IEhUVFBNZXRob2QiLCJjb25maWc6IEZldGNoQ29uZmlnIiwicHJvcGVydHk6IHN5bWJvbCB8ICh0eXBlb2YgbWV0aG9kcylbbnVtYmVyXSB8IChzdHJpbmcgJiB7fSkiXSwic291cmNlcyI6WyJzcmMvdXRpbHMudHMiLCJzcmMvYXBvc3RsZXMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNvbnN0IFN0YXR1c01hcCA9IHtcclxuICAxMDA6IFwiQ29udGludWVcIixcclxuICAxMDE6IFwiU3dpdGNoaW5nIFByb3RvY29sc1wiLFxyXG4gIDEwMjogXCJQcm9jZXNzaW5nXCIsXHJcbiAgMTAzOiBcIkVhcmx5IEhpbnRzXCIsXHJcbiAgMjAwOiBcIk9LXCIsXHJcbiAgMjAxOiBcIkNyZWF0ZWRcIixcclxuICAyMDI6IFwiQWNjZXB0ZWRcIixcclxuICAyMDM6IFwiTm9uLUF1dGhvcml0YXRpdmUgSW5mb3JtYXRpb25cIixcclxuICAyMDQ6IFwiTm8gQ29udGVudFwiLFxyXG4gIDIwNTogXCJSZXNldCBDb250ZW50XCIsXHJcbiAgMjA2OiBcIlBhcnRpYWwgQ29udGVudFwiLFxyXG4gIDIwNzogXCJNdWx0aS1TdGF0dXNcIixcclxuICAyMDg6IFwiQWxyZWFkeSBSZXBvcnRlZFwiLFxyXG4gIDMwMDogXCJNdWx0aXBsZSBDaG9pY2VzXCIsXHJcbiAgMzAxOiBcIk1vdmVkIFBlcm1hbmVudGx5XCIsXHJcbiAgMzAyOiBcIkZvdW5kXCIsXHJcbiAgMzAzOiBcIlNlZSBPdGhlclwiLFxyXG4gIDMwNDogXCJOb3QgTW9kaWZpZWRcIixcclxuICAzMDc6IFwiVGVtcG9yYXJ5IFJlZGlyZWN0XCIsXHJcbiAgMzA4OiBcIlBlcm1hbmVudCBSZWRpcmVjdFwiLFxyXG4gIDQwMDogXCJCYWQgUmVxdWVzdFwiLFxyXG4gIDQwMTogXCJVbmF1dGhvcml6ZWRcIixcclxuICA0MDI6IFwiUGF5bWVudCBSZXF1aXJlZFwiLFxyXG4gIDQwMzogXCJGb3JiaWRkZW5cIixcclxuICA0MDQ6IFwiTm90IEZvdW5kXCIsXHJcbiAgNDA1OiBcIk1ldGhvZCBOb3QgQWxsb3dlZFwiLFxyXG4gIDQwNjogXCJOb3QgQWNjZXB0YWJsZVwiLFxyXG4gIDQwNzogXCJQcm94eSBBdXRoZW50aWNhdGlvbiBSZXF1aXJlZFwiLFxyXG4gIDQwODogXCJSZXF1ZXN0IFRpbWVvdXRcIixcclxuICA0MDk6IFwiQ29uZmxpY3RcIixcclxuICA0MTA6IFwiR29uZVwiLFxyXG4gIDQxMTogXCJMZW5ndGggUmVxdWlyZWRcIixcclxuICA0MTI6IFwiUHJlY29uZGl0aW9uIEZhaWxlZFwiLFxyXG4gIDQxMzogXCJQYXlsb2FkIFRvbyBMYXJnZVwiLFxyXG4gIDQxNDogXCJVUkkgVG9vIExvbmdcIixcclxuICA0MTU6IFwiVW5zdXBwb3J0ZWQgTWVkaWEgVHlwZVwiLFxyXG4gIDQxNjogXCJSYW5nZSBOb3QgU2F0aXNmaWFibGVcIixcclxuICA0MTc6IFwiRXhwZWN0YXRpb24gRmFpbGVkXCIsXHJcbiAgNDE4OiBcIkknbSBhIHRlYXBvdFwiLFxyXG4gIDQyMTogXCJNaXNkaXJlY3RlZCBSZXF1ZXN0XCIsXHJcbiAgNDIyOiBcIlVucHJvY2Vzc2FibGUgQ29udGVudFwiLFxyXG4gIDQyMzogXCJMb2NrZWRcIixcclxuICA0MjQ6IFwiRmFpbGVkIERlcGVuZGVuY3lcIixcclxuICA0MjU6IFwiVG9vIEVhcmx5XCIsXHJcbiAgNDI2OiBcIlVwZ3JhZGUgUmVxdWlyZWRcIixcclxuICA0Mjg6IFwiUHJlY29uZGl0aW9uIFJlcXVpcmVkXCIsXHJcbiAgNDI5OiBcIlRvbyBNYW55IFJlcXVlc3RzXCIsXHJcbiAgNDMxOiBcIlJlcXVlc3QgSGVhZGVyIEZpZWxkcyBUb28gTGFyZ2VcIixcclxuICA0NTE6IFwiVW5hdmFpbGFibGUgRm9yIExlZ2FsIFJlYXNvbnNcIixcclxuICA1MDA6IFwiSW50ZXJuYWwgU2VydmVyIEVycm9yXCIsXHJcbiAgNTAxOiBcIk5vdCBJbXBsZW1lbnRlZFwiLFxyXG4gIDUwMjogXCJCYWQgR2F0ZXdheVwiLFxyXG4gIDUwMzogXCJTZXJ2aWNlIFVuYXZhaWxhYmxlXCIsXHJcbiAgNTA0OiBcIkdhdGV3YXkgVGltZW91dFwiLFxyXG4gIDUwNTogXCJIVFRQIFZlcnNpb24gTm90IFN1cHBvcnRlZFwiLFxyXG4gIDUwNjogXCJWYXJpYW50IEFsc28gTmVnb3RpYXRlc1wiLFxyXG4gIDUwNzogXCJJbnN1ZmZpY2llbnQgU3RvcmFnZVwiLFxyXG4gIDUwODogXCJMb29wIERldGVjdGVkXCIsXHJcbiAgNTEwOiBcIk5vdCBFeHRlbmRlZFwiLFxyXG4gIDUxMTogXCJOZXR3b3JrIEF1dGhlbnRpY2F0aW9uIFJlcXVpcmVkXCIsXHJcbn0gYXMgY29uc3Q7XHJcblxyXG5leHBvcnQgdHlwZSBQcmV0dGlmeTxUPiA9IHtcclxuICBbSyBpbiBrZXlvZiBUXTogVFtLXTtcclxufSAmIHVua25vd247XHJcbi8vIHR5cGUgSXNUeXBlPFZhbHVlLCBUeXBlPiA9IFZhbHVlIGV4dGVuZHMgVHlwZSA/IHRydWUgOiBmYWxzZTtcclxuLy8gdHlwZSBJc1N0cjxWYWx1ZT4gPSBJc1R5cGU8VmFsdWUsIHN0cmluZz47XHJcbmV4cG9ydCB0eXBlIEFuZDxBIGV4dGVuZHMgYm9vbGVhbiwgQiBleHRlbmRzIGJvb2xlYW4+ID0gQSBleHRlbmRzIHRydWUgPyBCIGV4dGVuZHMgdHJ1ZSA/IHRydWUgOiBmYWxzZSA6IGZhbHNlO1xyXG4vLyB0eXBlIFdoZW48Q29uZCBleHRlbmRzIGJvb2xlYW4sIE9uVHJ1ZT4gPSBDb25kIGV4dGVuZHMgdHJ1ZSA/IE9uVHJ1ZSA6IG5ldmVyO1xyXG5leHBvcnQgdHlwZSBJZjxDb25kIGV4dGVuZHMgYm9vbGVhbiwgT25UcnVlLCBPbkZhbHNlPiA9IENvbmQgZXh0ZW5kcyB0cnVlID8gT25UcnVlIDogT25GYWxzZTtcclxuXHJcbmV4cG9ydCB0eXBlIFNwbGl0U3RyaW5nPFN0ciBleHRlbmRzIHN0cmluZywgRGVsaW1pdGVyIGV4dGVuZHMgc3RyaW5nLCBJZ25vcmVFbXB0eSBleHRlbmRzIGJvb2xlYW4gPSBmYWxzZT4gPVxyXG4gIHN0cmluZyBleHRlbmRzIFN0clxyXG4gID8gc3RyaW5nW11cclxuICA6IFN0ciBleHRlbmRzIFwiXCJcclxuICA/IFtdXHJcbiAgOiBTdHIgZXh0ZW5kcyBgJHtpbmZlciBUfSR7RGVsaW1pdGVyfSR7aW5mZXIgVX1gXHJcbiAgPyBJZjxJZ25vcmVFbXB0eSwgSWY8QW5kPElnbm9yZUVtcHR5LCBUIGV4dGVuZHMgXCJcIiA/IHRydWUgOiBmYWxzZT4sIFsuLi5TcGxpdFN0cmluZzxVLCBEZWxpbWl0ZXIsIElnbm9yZUVtcHR5Pl0sIFtULCAuLi5TcGxpdFN0cmluZzxVLCBEZWxpbWl0ZXIsIElnbm9yZUVtcHR5Pl0+LCBbVCwgLi4uU3BsaXRTdHJpbmc8VSwgRGVsaW1pdGVyLCBJZ25vcmVFbXB0eT5dPlxyXG4gIDogW1N0cl07XHJcblxyXG5leHBvcnQgdHlwZSBKb2luU3RyaW5nPFBpZWNlcyBleHRlbmRzIGFueVtdLCBKb2luZXIgZXh0ZW5kcyBzdHJpbmcgPSBcIlwiLCBKb2luZWQgZXh0ZW5kcyBzdHJpbmcgPSBcIlwiPiA9XHJcbiAgUGllY2VzIGV4dGVuZHMgW11cclxuICA/IEpvaW5lZFxyXG4gIDogUGllY2VzIGV4dGVuZHMgW2luZmVyIEhlYWQsIC4uLmluZmVyIFRhaWxdXHJcbiAgPyBIZWFkIGV4dGVuZHMgc3RyaW5nXHJcbiAgPyBKb2luU3RyaW5nPFRhaWwsIEpvaW5lciwgSm9pbmVkIGV4dGVuZHMgXCJcIiA/IGAke0hlYWR9YCA6IGAke0pvaW5lZH0ke0pvaW5lcn0ke0hlYWR9YD5cclxuICA6IEpvaW5TdHJpbmc8VGFpbCwgSm9pbmVyLCBKb2luZWQ+XHJcbiAgOiBuZXZlcjtcclxuXHJcbmV4cG9ydCB0eXBlIFVuaW9uVG9JbnRlcnNlY3Rpb248VT4gPVxyXG4gIChVIGV4dGVuZHMgYW55ID8gKHg6IFUpID0+IHZvaWQgOiBuZXZlcikgZXh0ZW5kcyAoKHg6IGluZmVyIEkpID0+IHZvaWQpID8gSSA6IG5ldmVyO1xyXG5cclxuZXhwb3J0IHR5cGUgVW5pb25Ub1Bhcm08VT4gPSBVIGV4dGVuZHMgYW55ID8gKGs6IFUpID0+IHZvaWQgOiBuZXZlcjtcclxuZXhwb3J0IHR5cGUgVW5pb25Ub1NlY3Q8VT4gPSBVbmlvblRvUGFybTxVPiBleHRlbmRzICgoazogaW5mZXIgSSkgPT4gdm9pZCkgPyBJIDogbmV2ZXI7XHJcbmV4cG9ydCB0eXBlIEV4dHJhY3RQYXJtPEY+ID0gRiBleHRlbmRzIHsgKGE6IGluZmVyIEEpOiB2b2lkIH0gPyBBIDogbmV2ZXI7XHJcblxyXG5leHBvcnQgdHlwZSBVbmlvblNwbGljZU9uZTxVbmlvbj4gPSBFeGNsdWRlPFVuaW9uLCBVbmlvbkV4dHJhY3RPbmU8VW5pb24+PjtcclxuZXhwb3J0IHR5cGUgVW5pb25FeHRyYWN0T25lPFVuaW9uPiA9IEV4dHJhY3RQYXJtPFVuaW9uVG9TZWN0PFVuaW9uVG9QYXJtPFVuaW9uPj4+O1xyXG5cclxuZXhwb3J0IHR5cGUgVW5pb25Ub1R1cGxlPFVuaW9uPiA9IFVuaW9uVG9UdXBsZVJlYzxVbmlvbiwgW10+O1xyXG5leHBvcnQgdHlwZSBVbmlvblRvVHVwbGVSZWM8VW5pb24sIFJzbHQgZXh0ZW5kcyBhbnlbXT4gPVxyXG4gIFVuaW9uU3BsaWNlT25lPFVuaW9uPiBleHRlbmRzIG5ldmVyID8gW1VuaW9uRXh0cmFjdE9uZTxVbmlvbj4sIC4uLlJzbHRdXHJcbiAgOiBVbmlvblRvVHVwbGVSZWM8VW5pb25TcGxpY2VPbmU8VW5pb24+LCBbVW5pb25FeHRyYWN0T25lPFVuaW9uPiwgLi4uUnNsdF0+O1xyXG5cclxuZXhwb3J0IHR5cGUgSm9pblR1cGxlPFR1cGxlIGV4dGVuZHMgc3RyaW5nW10sIERlbGltIGV4dGVuZHMgc3RyaW5nPiA9IFR1cGxlIGV4dGVuZHMgW11cclxuICA/IFwiXCJcclxuICA6IFR1cGxlIGV4dGVuZHMgW2luZmVyIEhlYWQgZXh0ZW5kcyBzdHJpbmcsIC4uLmluZmVyIFRhaWwgZXh0ZW5kcyBzdHJpbmdbXV1cclxuICA/IEpvaW5UdXBsZVJlYzxIZWFkLCBEZWxpbSwgVGFpbD5cclxuICA6IG5ldmVyO1xyXG5leHBvcnQgdHlwZSBKb2luVHVwbGVSZWM8QWNjIGV4dGVuZHMgc3RyaW5nLCBEZWxpbSBleHRlbmRzIHN0cmluZywgVHVwbGUgZXh0ZW5kcyBzdHJpbmdbXT4gPVxyXG4gIFR1cGxlIGV4dGVuZHMgW11cclxuICA/IEFjY1xyXG4gIDogVHVwbGUgZXh0ZW5kcyBbaW5mZXIgSGVhZCBleHRlbmRzIHN0cmluZywgLi4uaW5mZXIgVGFpbCBleHRlbmRzIHN0cmluZ1tdXVxyXG4gID8gSm9pblR1cGxlUmVjPGAke0FjY30ke0RlbGltfSR7SGVhZH1gLCBEZWxpbSwgVGFpbD5cclxuICA6IEFjYztcclxuXHJcbmV4cG9ydCB0eXBlIFR1cGxlUHVzaDxUdXBsZSBleHRlbmRzIGFueVtdLCBWYWx1ZT4gPSBbLi4uVHVwbGUsIFZhbHVlXTtcclxuZXhwb3J0IHR5cGUgVHVwbGVSZW1vdmU8VHVwbGUgZXh0ZW5kcyBhbnlbXSwgVmFsdWU+ID0gVW5pb25Ub1R1cGxlPEV4Y2x1ZGU8VHVwbGVbbnVtYmVyXSwgVmFsdWU+PjtcclxuXHJcbmV4cG9ydCB0eXBlIFNpbXBsaWZ5Qm9vbGVhbkxpdGVyYWw8Qm9vbCBleHRlbmRzIGJvb2xlYW4+ID0gQm9vbCBleHRlbmRzIHRydWUgPyBib29sZWFuIDogQm9vbCBleHRlbmRzIGZhbHNlID8gYm9vbGVhbiA6IGJvb2xlYW47XHJcblxyXG5leHBvcnQgdHlwZSBUdXBsZVRvQXJyYXlzVW5pb248VHVwbGUgZXh0ZW5kcyBhbnlbXSwgU2ltcGxpZnlCb29sZWFuIGV4dGVuZHMgYm9vbGVhbiA9IGZhbHNlPiA9IFR1cGxlIGV4dGVuZHMgW11cclxuICA/IG5ldmVyXHJcbiAgOiBUdXBsZSBleHRlbmRzIFtpbmZlciBIZWFkLCAuLi5pbmZlciBUYWlsIGV4dGVuZHMgYW55W11dXHJcbiAgPyBUdXBsZVRvQXJyYXlzVW5pb25SZWM8QXJyYXk8U2ltcGxpZnlCb29sZWFuIGV4dGVuZHMgdHJ1ZSA/IEhlYWQgZXh0ZW5kcyBib29sZWFuID8gU2ltcGxpZnlCb29sZWFuTGl0ZXJhbDxIZWFkPiA6IEhlYWQgOiBIZWFkPiwgVGFpbCwgU2ltcGxpZnlCb29sZWFuPlxyXG4gIDogbmV2ZXI7XHJcbmV4cG9ydCB0eXBlIFR1cGxlVG9BcnJheXNVbmlvblJlYzxBY2MsIFR1cGxlIGV4dGVuZHMgYW55W10sIFNpbXBsaWZ5Qm9vbGVhbiBleHRlbmRzIGJvb2xlYW4+ID0gVHVwbGUgZXh0ZW5kcyBbXVxyXG4gID8gQWNjXHJcbiAgOiBUdXBsZSBleHRlbmRzIFtpbmZlciBIZWFkLCAuLi5pbmZlciBUYWlsXVxyXG4gID8gVHVwbGVUb0FycmF5c1VuaW9uUmVjPEFjYyB8IEFycmF5PFNpbXBsaWZ5Qm9vbGVhbiBleHRlbmRzIHRydWUgPyBIZWFkIGV4dGVuZHMgYm9vbGVhbiA/IFNpbXBsaWZ5Qm9vbGVhbkxpdGVyYWw8SGVhZD4gOiBIZWFkIDogSGVhZD4sIFRhaWwsIFNpbXBsaWZ5Qm9vbGVhbj5cclxuICA6IEFjYztcclxuXHJcbmV4cG9ydCB0eXBlIE9iamVjdFZhbHVlczxUIGV4dGVuZHMgUmVjb3JkPGFueSwgYW55Pj4gPSBVbmlvblRvSW50ZXJzZWN0aW9uPFRba2V5b2YgVF0+O1xyXG5cclxuZXhwb3J0IHR5cGUgRmluZFBhdGhQYXJhbXM8UGF0aCBleHRlbmRzIHN0cmluZz4gPSBGaW5kUGF0aFBhcmFtc1JlYzxTcGxpdFN0cmluZzxQYXRoLCBcIi9cIiwgdHJ1ZT4sIHt9PjtcclxudHlwZSBGaW5kUGF0aFBhcmFtc1JlYzxQYXJ0cyBleHRlbmRzIHN0cmluZ1tdLCBGb3VuZFBhcmFtcyBleHRlbmRzIHsgW3BhcmFtOiBzdHJpbmcgfCBuZXZlcl06IHN0cmluZyB8IHN0cmluZ1tdIH0+ID1cclxuICBQYXJ0cyBleHRlbmRzIFtdXHJcbiAgPyBGb3VuZFBhcmFtc1xyXG4gIDogUGFydHMgZXh0ZW5kcyBbaW5mZXIgSGVhZCBleHRlbmRzIHN0cmluZywgLi4uaW5mZXIgVGFpbCBleHRlbmRzIHN0cmluZ1tdXVxyXG4gID8gSGVhZCBleHRlbmRzIGA6JHtpbmZlciBQYXJhbSBleHRlbmRzIHN0cmluZ31gXHJcbiAgPyBQYXJhbSBleHRlbmRzIGtleW9mIEZvdW5kUGFyYW1zXHJcbiAgPyAoRm91bmRQYXJhbXNbUGFyYW1dIGV4dGVuZHMgc3RyaW5nXHJcbiAgICA/IE9taXQ8Rm91bmRQYXJhbXMsIFBhcmFtPiAmIHsgW1AgaW4gUGFyYW1dOiBbc3RyaW5nLCBzdHJpbmddIH1cclxuICAgIDogRm91bmRQYXJhbXNbUGFyYW1dIGV4dGVuZHMgc3RyaW5nW11cclxuICAgID8gT21pdDxGb3VuZFBhcmFtcywgUGFyYW0+ICYgeyBbUCBpbiBQYXJhbV06IFR1cGxlUHVzaDxGb3VuZFBhcmFtc1tQYXJhbV0sIHN0cmluZz47IH1cclxuICAgIDogRm91bmRQYXJhbXMgJiB7IFtQIGluIFBhcmFtXTogc3RyaW5nOyB9XHJcbiAgKVxyXG4gIDogRm91bmRQYXJhbXMgJiB7IFtQIGluIFBhcmFtXTogc3RyaW5nOyB9XHJcbiAgOiBGaW5kUGF0aFBhcmFtc1JlYzxUYWlsLCBGb3VuZFBhcmFtcz5cclxuICA6IG5ldmVyO1xyXG5cclxuZXhwb3J0IHR5cGUgUHJpbWl0aXZlUmVzcG9uc2UgPSBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuO1xyXG5leHBvcnQgdHlwZSBBcnJheVJlc3BvbnNlID0gUHJldHRpZnk8QXJyYXk8UHJpbWl0aXZlUmVzcG9uc2U+IHwgVHVwbGVUb0FycmF5c1VuaW9uPFVuaW9uVG9UdXBsZTxQcmltaXRpdmVSZXNwb25zZT4sIHRydWU+PjtcclxuZXhwb3J0IHR5cGUgT2JqZWN0UmVzcG9uc2UgPSB7IFtLIGluIHN0cmluZyB8IG51bWJlcl06IFByaW1pdGl2ZVJlc3BvbnNlIHwgQXJyYXlSZXNwb25zZSB8IE9iamVjdFJlc3BvbnNlOyB9O1xyXG5leHBvcnQgdHlwZSBTaW1wbGVSZXNwb25zZSA9IFByaW1pdGl2ZVJlc3BvbnNlIHwgQXJyYXlSZXNwb25zZSB8IE9iamVjdFJlc3BvbnNlO1xyXG5leHBvcnQgdHlwZSBHZW5lcmF0b3JSZXNwb25zZSA9IEdlbmVyYXRvcjxTaW1wbGVSZXNwb25zZT4gfCBBc3luY0dlbmVyYXRvcjxTaW1wbGVSZXNwb25zZT47XHJcbmV4cG9ydCB0eXBlIFJlc3BvbnNlVmFsdWVUeXBlID0gUHJpbWl0aXZlUmVzcG9uc2UgfCBBcnJheVJlc3BvbnNlIHwgT2JqZWN0UmVzcG9uc2UgfCBHZW5lcmF0b3JSZXNwb25zZTtcclxuZXhwb3J0IHR5cGUgUmVzcG9uc2VEYXRhPFQgZXh0ZW5kcyBSZXNwb25zZVZhbHVlVHlwZT4gPSB7XHJcbiAgb2s6IHRydWU7XHJcbiAgc3RhdHVzOiBudW1iZXI7XHJcbiAgZGF0YTogVCBleHRlbmRzIEdlbmVyYXRvcjxpbmZlciBVPiA/IEFzeW5jR2VuZXJhdG9yPFU+IDogVDtcclxuICByZXNwb25zZTogUmVzcG9uc2U7XHJcbn0gfCB7XHJcbiAgb2s6IGZhbHNlO1xyXG4gIHN0YXR1cz86IG51bWJlcjtcclxuICByZXNwb25zZT86IFJlc3BvbnNlO1xyXG4gIGVycm9yOiBFcnJvcjtcclxufTtcclxuXHJcblxyXG5leHBvcnQgY29uc3QgSHR0cE1ldGhvZHMgPSBbXCJHRVRcIiwgXCJQT1NUXCIsIFwiUFVUXCIsIFwiREVMRVRFXCJdIGFzIGNvbnN0O1xyXG5leHBvcnQgdHlwZSBIVFRQTWV0aG9kID0gKHR5cGVvZiBIdHRwTWV0aG9kcylbbnVtYmVyXTtcclxuZXhwb3J0IHR5cGUgQ29va2llID0ge1xyXG4gIHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQ7XHJcbiAgc2VjdXJlOiBib29sZWFuO1xyXG4gIGV4cGlyZURhdGU6IERhdGUgfCB1bmRlZmluZWQ7XHJcbiAgbWF4QWdlOiBudW1iZXIgfCB1bmRlZmluZWQ7XHJcbiAgc2FtZVNpdGU6IFwiU3RyaWN0XCIgfCBcIkxheFwiIHwgXCJOb25lXCIgfCB1bmRlZmluZWQ7XHJcbiAgcmVtb3ZlKCk6IHZvaWQ7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBpc0dlbmVyYXRvck9iamVjdChvYmo6IGFueSk6IG9iaiBpcyBHZW5lcmF0b3I8YW55PiB7XHJcbiAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gZmFsc2U7XHJcbiAgaWYgKHR5cGVvZiBvYmogIT09IFwib2JqZWN0XCIpIHJldHVybiBmYWxzZTtcclxuICAvLyBJZiBzb21lb25lIGNoYW5nZXMgdGhpcyB2YWx1ZSwgdGhleSBzaG91bGQgYmUgc3RyaWtlbiBkb3duIGJ5IHRoZSBlbnRpcmUgcGFudGhlb24gb2YgZWxkcml0Y2ggaG9ycm9ycyBhbmQgR29kcyBvZiBhbGwgcmVsaWdpb25zL215dGhvbG9naWVzXHJcbiAgaWYgKG9ialtTeW1ib2wudG9TdHJpbmdUYWddICE9PSBcIkdlbmVyYXRvclwiKSByZXR1cm4gZmFsc2U7XHJcbiAgcmV0dXJuIHRydWU7XHJcbn1cclxuZXhwb3J0IGZ1bmN0aW9uIGlzQXN5bmNHZW5lcmF0b3JPYmplY3Qob2JqOiBhbnkpOiBvYmogaXMgQXN5bmNHZW5lcmF0b3I8YW55PiB7XHJcbiAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gZmFsc2U7XHJcbiAgaWYgKHR5cGVvZiBvYmogIT09IFwib2JqZWN0XCIpIHJldHVybiBmYWxzZTtcclxuICAvLyBJZiBzb21lb25lIGNoYW5nZXMgdGhpcyB2YWx1ZSwgdGhleSBzaG91bGQgYmUgc3RyaWtlbiBkb3duIGJ5IHRoZSBlbnRpcmUgcGFudGhlb24gb2YgZWxkcml0Y2ggaG9ycm9ycyBhbmQgR29kcyBvZiBhbGwgcmVsaWdpb25zL215dGhvbG9naWVzXHJcbiAgaWYgKG9ialtTeW1ib2wudG9TdHJpbmdUYWddICE9PSBcIkFzeW5jR2VuZXJhdG9yXCIpIHJldHVybiBmYWxzZTtcclxuICByZXR1cm4gdHJ1ZTtcclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IEdlbmVyYXRvckhUVFBIZWFkZXJOYW1lID0gXCJYLUFuY2llbnRPbmVzLVN0cmVhbWluZ1wiO1xyXG5cclxuIiwiaW1wb3J0IHR5cGUge1xyXG4gIEFuY2llbnRPbmUsXHJcbiAgUm91dGVIYW5kbGVyLFxyXG59IGZyb20gXCIuL2FuY2llbnRzXCI7XHJcbmltcG9ydCB0eXBlIHtcclxuICBIVFRQTWV0aG9kLFxyXG4gIE9iamVjdFZhbHVlcyxcclxuICBQcmV0dGlmeSxcclxuICBSZXNwb25zZURhdGEsXHJcbiAgUmVzcG9uc2VWYWx1ZVR5cGUsXHJcbiAgU3BsaXRTdHJpbmcsXHJcbiAgVHVwbGVQdXNoLFxyXG4gIFR1cGxlUmVtb3ZlLFxyXG4gIFVuaW9uVG9UdXBsZVxyXG59IGZyb20gXCIuL3V0aWxzXCI7XHJcbmltcG9ydCB7XHJcbiAgSHR0cE1ldGhvZHMsXHJcbiAgR2VuZXJhdG9ySFRUUEhlYWRlck5hbWUsXHJcbn0gZnJvbSBcIi4vdXRpbHNcIjtcclxuXHJcbnR5cGUgRmluZFBhdGhQYXJhbU5hbWVzPFBhdGggZXh0ZW5kcyBzdHJpbmc+ID0gRmluZFBhdGhQYXJhbU5hbWVzUmVjPFNwbGl0U3RyaW5nPFBhdGgsIFwiL1wiLCB0cnVlPiwgW10+O1xyXG50eXBlIEZpbmRQYXRoUGFyYW1OYW1lc1JlYzxQYXRoUGFydHMgZXh0ZW5kcyBzdHJpbmdbXSwgTmFtZXMgZXh0ZW5kcyBzdHJpbmdbXT4gPVxyXG4gIFBhdGhQYXJ0cyBleHRlbmRzIFtdXHJcbiAgPyBOYW1lc1xyXG4gIDogUGF0aFBhcnRzIGV4dGVuZHMgW2luZmVyIEhlYWQgZXh0ZW5kcyBzdHJpbmcsIC4uLmluZmVyIFRhaWwgZXh0ZW5kcyBzdHJpbmdbXV1cclxuICA/IEhlYWQgZXh0ZW5kcyBgOiR7aW5mZXIgUGF0aFBhcmFtIGV4dGVuZHMgc3RyaW5nfWBcclxuICA/IEZpbmRQYXRoUGFyYW1OYW1lc1JlYzxUYWlsLCBUdXBsZVB1c2g8TmFtZXMsIFBhdGhQYXJhbT4+XHJcbiAgOiBGaW5kUGF0aFBhcmFtTmFtZXNSZWM8VGFpbCwgTmFtZXM+XHJcbiAgOiBuZXZlclxyXG4gIDtcclxuXHJcblxyXG5leHBvcnQgdHlwZSBBcG9zdGxlPEFuY2llbnQgZXh0ZW5kcyBBbmNpZW50T25lPGFueSwgUmVjb3JkPHN0cmluZywgeyBbTSBpbiBMb3dlcmNhc2U8SFRUUE1ldGhvZD5dOiBSb3V0ZUhhbmRsZXI8YW55LCBhbnk+IH0+Pj4gPVxyXG4gIEFuY2llbnQgZXh0ZW5kcyBBbmNpZW50T25lPGluZmVyIFByZWZpeCBleHRlbmRzIHN0cmluZywgYW55PlxyXG4gID8gT2JqZWN0VmFsdWVzPHsgW1BhdGggaW4ga2V5b2YgQW5jaWVudFtcIl9fVFlQRV9MRVZFTF9UXCJdYXMgUGF0aCBleHRlbmRzIHN0cmluZyA/IFBhdGggOiBuZXZlcl06IFBhdGggZXh0ZW5kcyBzdHJpbmcgPyBDcmVhdGVSb3V0aW5lPFNwbGl0U3RyaW5nPGAke1ByZWZpeH0ke1BhdGh9YCwgXCIvXCIsIHRydWU+LCBQYXRoLCBBbmNpZW50W1wiX19UWVBFX0xFVkVMX1RcIl0sIEZpbmRQYXRoUGFyYW1OYW1lczxQYXRoPj4gOiBuZXZlcjsgfT5cclxuICA6IG5ldmVyO1xyXG5cclxudHlwZSBDcmVhdGVSb3V0aW5lPFBhdGhQYXJ0cyBleHRlbmRzIHN0cmluZ1tdLCBGdWxsUGF0aCBleHRlbmRzIHN0cmluZywgSGFuZGxlcnMgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB7IFtNIGluIExvd2VyY2FzZTxIVFRQTWV0aG9kPl06IFJvdXRlSGFuZGxlcjxhbnksIGFueT4gfT4sIFBhdGhQYXJhbU5hbWVzIGV4dGVuZHMgc3RyaW5nW10+ID1cclxuICBQYXRoUGFydHMgZXh0ZW5kcyBbXVxyXG4gID8ge1xyXG4gICAgW00gaW4ga2V5b2YgSGFuZGxlcnNbRnVsbFBhdGhdYXMgTSBleHRlbmRzIFwiXCIgPyBuZXZlciA6IEhhbmRsZXJzW0Z1bGxQYXRoXVtNXSBleHRlbmRzIG5ldmVyID8gbmV2ZXIgOiBIYW5kbGVyc1tGdWxsUGF0aF1bTV0gZXh0ZW5kcyBSb3V0ZUhhbmRsZXI8YW55LCBhbnk+ID8gTSA6IG5ldmVyXTogSGFuZGxlcnNbRnVsbFBhdGhdW01dIGV4dGVuZHMgUm91dGVIYW5kbGVyPGluZmVyIFJldHVybiwgaW5mZXIgUGF0aFBhcmFtcz5cclxuICAgID8gUGF0aFBhcmFtTmFtZXMgZXh0ZW5kcyBbXVxyXG4gICAgPyAoY2ZnPzogeyBxdWVyeT86IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHN0cmluZ1tdPjsgfSkgPT4gUHJvbWlzZTxSZXNwb25zZURhdGE8UmV0dXJuPj5cclxuICAgIDogUHJldHRpZnk8T21pdDxQYXRoUGFyYW1zLCBQYXRoUGFyYW1OYW1lc1tudW1iZXJdPj4gZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBuZXZlcj5cclxuICAgID8gKGNmZz86IHsgcXVlcnk/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBzdHJpbmdbXT47IH0pID0+IFByb21pc2U8UmVzcG9uc2VEYXRhPFJldHVybj4+XHJcbiAgICA6IChjZmc6IHsgcGFyYW1zOiBQcmV0dGlmeTxPbWl0PFBhdGhQYXJhbXMsIFBhdGhQYXJhbU5hbWVzW251bWJlcl0+PiwgcXVlcnk/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmcgfCBzdHJpbmdbXT47IH0pID0+IFByb21pc2U8UmVzcG9uc2VEYXRhPFJldHVybj4+XHJcbiAgICA6IG5ldmVyO1xyXG4gIH1cclxuICA6IFBhdGhQYXJ0cyBleHRlbmRzIFtpbmZlciBIZWFkIGV4dGVuZHMgc3RyaW5nLCAuLi5pbmZlciBUYWlsIGV4dGVuZHMgc3RyaW5nW11dXHJcbiAgPyBIZWFkIGV4dGVuZHMgYDoke2luZmVyIFBhdGhQYXJhbX1gXHJcbiAgPyBUYWlsIGV4dGVuZHMgW11cclxuICAvLyBAdHMtZXhwZWN0LWVycm9yIFR1cGxlUmVtb3ZlIGRvZXNuJ3QgZXhwbGljaXRseSByZXR1cm4gc3RyaW5nW10gYnV0IGl0IGlzIGEgc3RyaW5nW10gYmVjYXVzZSB0aGUgcGFzc2VkIHR1cGxlIGlzIGEgc3RyaW5nW11cclxuICA/IHsgKHBhcmFtczogeyBbcGFyYW0gaW4gUGF0aFBhcmFtXTogc3RyaW5nIH0pOiBDcmVhdGVSb3V0aW5lPFtdLCBGdWxsUGF0aCwgSGFuZGxlcnMsIFBhdGhQYXJhbU5hbWVzPjsgfSAmIENyZWF0ZVJvdXRpbmU8W10sIEZ1bGxQYXRoLCBIYW5kbGVycywgVHVwbGVSZW1vdmU8UGF0aFBhcmFtTmFtZXMsIFBhdGhQYXJhbT4+XHJcbiAgOiAocGFyYW1zOiB7IFtwYXJhbSBpbiBQYXRoUGFyYW1dOiBzdHJpbmcgfSkgPT4gQ3JlYXRlUm91dGluZTxUYWlsLCBGdWxsUGF0aCwgSGFuZGxlcnMsIEV4Y2x1ZGU8UGF0aFBhcmFtTmFtZXMsIFBhdGhQYXJhbT4+XHJcbiAgOiB7IFtwYXRoIGluIEhlYWRdOiBDcmVhdGVSb3V0aW5lPFRhaWwsIEZ1bGxQYXRoLCBIYW5kbGVycywgUGF0aFBhcmFtTmFtZXM+OyB9XHJcbiAgOiBDcmVhdGVSb3V0aW5lPFtdLCBGdWxsUGF0aCwgSGFuZGxlcnMsIFBhdGhQYXJhbU5hbWVzPjtcclxuXHJcbmV4cG9ydCBjb25zdCBERUJVR19QQVRISU5HX1BST1BFUlRZID0gXCJfX0RFQlVHX1BBVEhJTkdfX1wiO1xyXG5cclxuYXN5bmMgZnVuY3Rpb24qIHN0cmVhbVRvR2VuZXJhdG9yKHJlYWRlcjogUmVhZGFibGVTdHJlYW1EZWZhdWx0UmVhZGVyPFVpbnQ4QXJyYXk8QXJyYXlCdWZmZXJMaWtlPj4pIHtcclxuICBjb25zdCBkZWNvZGUgPSAoZGF0YTogYW55KSA9PiBuZXcgVGV4dERlY29kZXIoKS5kZWNvZGUoZGF0YSk7XHJcbiAgZG8ge1xyXG4gICAgY29uc3Qgc3RlcCA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XHJcbiAgICBpZiAoc3RlcC5kb25lKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGNvbnN0IGpzb24gPSBkZWNvZGUoc3RlcC52YWx1ZSk7XHJcbiAgICBjb25zdCBkYXRhID0gSlNPTi5wYXJzZShqc29uKTtcclxuICAgIHlpZWxkIGRhdGEuZGF0YTtcclxuICB9IHdoaWxlICh0cnVlKTtcclxufVxyXG5jb25zdCBQUk9UT0NPTF9DSEVDS19SRUdFWCA9IC9eaHR0cHM/OlxcL1xcLy87XHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVBcG9zdGxlPFxyXG4gIEFuY2llbnQgZXh0ZW5kcyBBbmNpZW50T25lPGFueSwgUmVjb3JkPHN0cmluZywgeyBbTSBpbiBMb3dlcmNhc2U8SFRUUE1ldGhvZD5dOiBSb3V0ZUhhbmRsZXI8YW55LCBhbnk+IH0+PlxyXG4+KG9yaWdpbjogc3RyaW5nKTogQXBvc3RsZTxBbmNpZW50PiB7XHJcbiAgb3JpZ2luID0gb3JpZ2luLnRyaW0oKTtcclxuICBpZiAoIW9yaWdpbi5tYXRjaChQUk9UT0NPTF9DSEVDS19SRUdFWCkpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihcIk9yaWdpbiBtdXN0IHN0YXJ0IHdpdGggdGhlIHByb3RvY29sIChodHRwOi8vIG9yIGh0dHBzOi8vKVwiKTtcclxuICB9XHJcbiAgd2hpbGUgKG9yaWdpbi5lbmRzV2l0aChcIi9cIikpIHtcclxuICAgIG9yaWdpbiA9IG9yaWdpbi5zdWJzdHJpbmcoMCwgb3JpZ2luLmxlbmd0aCAtIDEpO1xyXG4gIH1cclxuICBjb25zdCBwdXNoUGFyYW1zID0gKHBhdGg6IHN0cmluZywgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge30pID0+IHtcclxuICAgIGZvciAoY29uc3QgcGFyYW0gb2YgT2JqZWN0LmtleXMocGFyYW1zKSkge1xyXG4gICAgICBwYXRoICs9IFwiL1wiICsgcGFyYW1zW3BhcmFtXTtcclxuICAgIH1cclxuICAgIHJldHVybiBwYXRoO1xyXG4gIH07XHJcbiAgdHlwZSBGZXRjaENvbmZpZyA9IHtcclxuICAgIHBhcmFtcz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XHJcbiAgICBxdWVyeT86IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHN0cmluZ1tdPjtcclxuICAgIGJvZHk/OiBCb2R5SW5pdDtcclxuICB9O1xyXG4gIGNvbnN0IGRvRmV0Y2ggPSBhc3luYyAobWV0aG9kOiBIVFRQTWV0aG9kLCBwYXRoOiBzdHJpbmcsIGNvbmZpZzogRmV0Y2hDb25maWcgPSB7fSk6IFByb21pc2U8UmVzcG9uc2VEYXRhPFJlc3BvbnNlVmFsdWVUeXBlPj4gPT4ge1xyXG4gICAgdHJ5IHtcclxuICAgICAgaWYgKGNvbmZpZy5wYXJhbXMpIHtcclxuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhjb25maWcucGFyYW1zID8/IHt9KSkge1xyXG4gICAgICAgICAgcGF0aCArPSBcIi9cIiArIGNvbmZpZy5wYXJhbXNba2V5XTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgdXJsID0gbmV3IFVSTChwYXRoKTtcclxuICAgICAgaWYgKGNvbmZpZy5xdWVyeSkge1xyXG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGNvbmZpZy5xdWVyeSA/PyB7fSkpIHtcclxuICAgICAgICAgIGNvbnN0IHZhbCA9IGNvbmZpZy5xdWVyeVtrZXldITtcclxuICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWwpKSB7XHJcbiAgICAgICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgdmFsKTtcclxuICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IHYgb2YgdmFsKSB7XHJcbiAgICAgICAgICAgIHVybC5zZWFyY2hQYXJhbXMuYXBwZW5kKGtleSwgdik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7XHJcbiAgICAgICAgbWV0aG9kLFxyXG4gICAgICAgIGJvZHk6IGNvbmZpZy5ib2R5LFxyXG4gICAgICB9KTtcclxuICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xyXG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XHJcbiAgICAgICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cywgcmVzcG9uc2UsIGVycm9yOiBuZXcgRXJyb3IobWVzc2FnZSkgfTtcclxuICAgICAgfVxyXG4gICAgICBjb25zdCBzdGF0dXMgPSByZXNwb25zZS5zdGF0dXM7XHJcbiAgICAgIGNvbnN0IGdlbmVyYXRvckhlYWRlciA9IHJlc3BvbnNlLmhlYWRlcnMuZ2V0KEdlbmVyYXRvckhUVFBIZWFkZXJOYW1lKTtcclxuICAgICAgaWYgKGdlbmVyYXRvckhlYWRlciA9PT0gXCJHZW5lcmF0b3JcIiB8fCBnZW5lcmF0b3JIZWFkZXIgPT09IFwiQXN5bmNHZW5lcmF0b3JcIikge1xyXG4gICAgICAgIGlmICghcmVzcG9uc2UuYm9keSkge1xyXG4gICAgICAgICAgcmV0dXJuIHsgb2s6IGZhbHNlLCBzdGF0dXMsIHJlc3BvbnNlLCBlcnJvcjogbmV3IEVycm9yKFwiUmVjZWl2ZWQgZ2VuZXJhdG9yIGhlYWRlciBidXQgdGhlcmUncyBubyBib2R5IHRvIHJlYWQgc3RyZWFtIGZyb21cIikgfTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgcmVhZGVyID0gcmVzcG9uc2UuYm9keS5nZXRSZWFkZXIoKTtcclxuICAgICAgICBjb25zdCBnZW5lcmF0b3IgPSBzdHJlYW1Ub0dlbmVyYXRvcihyZWFkZXIpO1xyXG4gICAgICAgIHJldHVybiB7IG9rOiB0cnVlLCBzdGF0dXMsIHJlc3BvbnNlLCBkYXRhOiBnZW5lcmF0b3IgfTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgcmVzID0gYXdhaXQgcmVzcG9uc2UuanNvbigpIGFzIHsgZGF0YTogYW55IH07XHJcbiAgICAgIC8vIE1heWJlIGhhbmRsZSBvdGhlciBzdHVmZiBoZXJlXHJcbiAgICAgIHJldHVybiB7IG9rOiB0cnVlLCBzdGF0dXMsIHJlc3BvbnNlLCBkYXRhOiByZXMuZGF0YSB9O1xyXG4gICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgIC8vIEB0cy1pZ25vcmUgQ2F1c2UgaXMgbm90IHN1cHBvcnRlZCBpbiBteSB2ZXJzaW9uIG9mIHRzYywgVE9ETzogZml4IGl0XHJcbiAgICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKFwiRmV0Y2ggcmVxdWVzdCBmYWlsZWRcIiwgeyBjYXVzZTogZXJyIH0pO1xyXG4gICAgICByZXR1cm4geyBvazogZmFsc2UsIGVycm9yIH07XHJcbiAgICB9XHJcbiAgfTtcclxuICBjb25zdCBtZXRob2RzID0gSHR0cE1ldGhvZHMubWFwKCh4KSA9PiB4LnRvTG93ZXJDYXNlKCkpIGFzIFVuaW9uVG9UdXBsZTxMb3dlcmNhc2U8SFRUUE1ldGhvZD4+O1xyXG5cclxuICBjb25zdCBwID0gbmV3IFByb3h5KHsgcGF0aGluZzogb3JpZ2luIH0sIHtcclxuICAgIGdldCh0YXJnZXQsIHByb3BlcnR5OiBzeW1ib2wgfCAodHlwZW9mIG1ldGhvZHMpW251bWJlcl0gfCAoc3RyaW5nICYge30pKSB7XHJcbiAgICAgIGlmICh0eXBlb2YgcHJvcGVydHkgPT09IFwic3ltYm9sXCIpIHtcclxuICAgICAgICByZXR1cm4gKHRhcmdldCBhcyBhbnkpW3Byb3BlcnR5XTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHByb3BlcnR5ID09PSBERUJVR19QQVRISU5HX1BST1BFUlRZKSByZXR1cm4gdGFyZ2V0LnBhdGhpbmc7XHJcblxyXG4gICAgICBpZiAobWV0aG9kcy5pbmNsdWRlcyhwcm9wZXJ0eSBhcyBhbnkpKSB7XHJcbiAgICAgICAgcmV0dXJuIGRvRmV0Y2guYmluZChudWxsLCBwcm9wZXJ0eS50b1VwcGVyQ2FzZSgpIGFzIGFueSwgdGFyZ2V0LnBhdGhpbmcpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gcGF0aGluZyhvcmlnaW4gKyBcIi9cIiArIHByb3BlcnR5KTtcclxuICAgIH1cclxuICB9KTtcclxuICBjb25zdCBwYXRoaW5nID0gKHBhdGg6IHN0cmluZykgPT4ge1xyXG4gICAgY29uc3QgZGF0YSA9IHsgcGF0aGluZzogcGF0aCB9O1xyXG4gICAgY29uc3QgZm4gPSAocGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KSA9PiB7XHJcbiAgICAgIGRhdGEucGF0aGluZyA9IHB1c2hQYXJhbXMoZGF0YS5wYXRoaW5nLCBwYXJhbXMpO1xyXG4gICAgICByZXR1cm4gcHJveHk7XHJcbiAgICB9O1xyXG4gICAgY29uc3QgcHJveHkgPSBuZXcgUHJveHkoZm4sIHtcclxuICAgICAgZ2V0KHRhcmdldCwgcHJvcGVydHkpIHtcclxuICAgICAgICBpZiAodHlwZW9mIHByb3BlcnR5ID09PSBcInN5bWJvbFwiKSB7XHJcbiAgICAgICAgICAvLyBAdHMtaWdub3JlXHJcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0W3Byb3BlcnR5XTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0eSA9PT0gREVCVUdfUEFUSElOR19QUk9QRVJUWSkgcmV0dXJuIGRhdGEucGF0aGluZztcclxuICAgICAgICBpZiAobWV0aG9kcy5pbmNsdWRlcyhwcm9wZXJ0eSBhcyBhbnkpKSB7XHJcbiAgICAgICAgICByZXR1cm4gZG9GZXRjaC5iaW5kKG51bGwsIHByb3BlcnR5LnRvVXBwZXJDYXNlKCkgYXMgYW55LCBkYXRhLnBhdGhpbmcpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHBhdGhpbmcoYCR7ZGF0YS5wYXRoaW5nfS8ke3Byb3BlcnR5fWApO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBwcm94eTtcclxuICB9O1xyXG4gIHJldHVybiBwIGFzIGFueTtcclxufVxyXG4iXSwibWFwcGluZ3MiOiI7O01BMkthLGNBQWM7Q0FBQztDQUFPO0NBQVE7Q0FBTztBQUFTO01BMEI5QywwQkFBMEI7Ozs7TUM1STFCLHlCQUF5QjtBQUV0QyxnQkFB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