sdc_client 0.159.0 → 0.160.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ### Added
6
+ - `SdcQuerySet.load(modelQuery, { limit })` loads at most `limit` instances; the server slices the query (needs SimpleDomControl with `limit` support, the same release).
7
+
3
8
  ## 0.159.0
4
9
 
5
10
  ### Added
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
24
24
  \**********************/
25
25
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
26
26
 
27
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AbstractSDC: () => (/* reexport safe */ _simpleDomControl_AbstractSDC_js__WEBPACK_IMPORTED_MODULE_1__.AbstractSDC),\n/* harmony export */ SdcModel: () => (/* reexport safe */ _simpleDomControl_sdc_model_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]),\n/* harmony export */ SdcQuerySet: () => (/* reexport safe */ _simpleDomControl_sdc_model_js__WEBPACK_IMPORTED_MODULE_2__.SdcQuerySet),\n/* harmony export */ allOff: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.allOff),\n/* harmony export */ app: () => (/* reexport safe */ _simpleDomControl_sdc_main_js__WEBPACK_IMPORTED_MODULE_0__.app),\n/* harmony export */ checkIfParamNumberBoolOrString: () => (/* reexport safe */ _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__.checkIfParamNumberBoolOrString),\n/* harmony export */ clearErrorsInForm: () => (/* reexport safe */ _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__.clearErrorsInForm),\n/* harmony export */ controllerFactory: () => (/* reexport safe */ _simpleDomControl_sdc_controller_js__WEBPACK_IMPORTED_MODULE_7__.controllerFactory),\n/* harmony export */ on: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.on),\n/* harmony export */ registerModel: () => (/* reexport safe */ _simpleDomControl_sdc_socket_js__WEBPACK_IMPORTED_MODULE_3__.registerModel),\n/* harmony export */ runControlFlowFunctions: () => (/* reexport safe */ _simpleDomControl_sdc_controller_js__WEBPACK_IMPORTED_MODULE_7__.runControlFlowFunctions),\n/* harmony export */ setErrorsInForm: () => (/* reexport safe */ _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__.setErrorsInForm),\n/* harmony export */ setEvent: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.setEvent),\n/* harmony export */ socketReconnect: () => (/* binding */ socketReconnect),\n/* harmony export */ test_utils: () => (/* binding */ test_utils),\n/* harmony export */ trigger: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.trigger)\n/* harmony export */ });\n/* harmony import */ var _simpleDomControl_sdc_main_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./simpleDomControl/sdc_main.js */ \"./src/simpleDomControl/sdc_main.js\");\n/* harmony import */ var _simpleDomControl_AbstractSDC_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./simpleDomControl/AbstractSDC.js */ \"./src/simpleDomControl/AbstractSDC.js\");\n/* harmony import */ var _simpleDomControl_sdc_model_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./simpleDomControl/sdc_model.js */ \"./src/simpleDomControl/sdc_model.js\");\n/* harmony import */ var _simpleDomControl_sdc_socket_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./simpleDomControl/sdc_socket.js */ \"./src/simpleDomControl/sdc_socket.js\");\n/* harmony import */ var js_cookie__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! js-cookie */ \"./node_modules/js-cookie/dist/js.cookie.mjs\");\n/* harmony import */ var _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./simpleDomControl/sdc_events.js */ \"./src/simpleDomControl/sdc_events.js\");\n/* harmony import */ var _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./simpleDomControl/sdc_utils.js */ \"./src/simpleDomControl/sdc_utils.js\");\n/* harmony import */ var _simpleDomControl_sdc_controller_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./simpleDomControl/sdc_controller.js */ \"./src/simpleDomControl/sdc_controller.js\");\n/* harmony import */ var _simpleDomControl_sdc_server_call_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./simpleDomControl/sdc_server_call.js */ \"./src/simpleDomControl/sdc_server_call.js\");\n/* harmony import */ var _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./simpleDomControl/sdc_test_utils.js */ \"./src/simpleDomControl/sdc_test_utils.js\");\n\n\n\n\n\n\n\n\n\n\n\n\nconst socketReconnect = _simpleDomControl_sdc_server_call_js__WEBPACK_IMPORTED_MODULE_8__.close;\nconst test_utils = {\n get_controller: _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__.get_controller,\n getCsrfToken: _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__.getCsrfToken,\n controllerFromTestHtml: _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__.controllerFromTestHtml,\n logout: () => {\n js_cookie__WEBPACK_IMPORTED_MODULE_4__[\"default\"].remove(\"sessionid\");\n console.log(\"Logged out\");\n },\n login: (user) => {\n const sessionId = globalThis.SDC_TEST_USER?.[user];\n if (!sessionId) {\n js_cookie__WEBPACK_IMPORTED_MODULE_4__[\"default\"].remove(\"sessionid\");\n console.warn(`Unknown test user: ${user}`);\n return false;\n }\n js_cookie__WEBPACK_IMPORTED_MODULE_4__[\"default\"].set(\"sessionid\", sessionId);\n console.log(`Logged in as ${user}`);\n return true;\n },\n};\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvaW5kZXguanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBcUQ7QUFDVztBQUNRO0FBQ1A7QUFDakM7QUFNVTs7QUFNRDtBQUlLO0FBQ2dCO0FBS2hCOztBQUU5Qyx3QkFBd0IsdUVBQUs7QUFDN0I7QUFDQSxnQkFBZ0I7QUFDaEIsY0FBYztBQUNkLHdCQUF3QjtBQUN4QjtBQUNBLElBQUksaURBQU87QUFDWDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxNQUFNLGlEQUFPO0FBQ2IseUNBQXlDLEtBQUs7QUFDOUM7QUFDQTtBQUNBLElBQUksaURBQU87QUFDWCxnQ0FBZ0MsS0FBSztBQUNyQztBQUNBLEdBQUc7QUFDSDs7QUFtQkUiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9zZGNfY2xpZW50Ly4vc3JjL2luZGV4LmpzP2U1ZjciXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgYXBwIH0gZnJvbSBcIi4vc2ltcGxlRG9tQ29udHJvbC9zZGNfbWFpbi5qc1wiO1xuaW1wb3J0IHsgQWJzdHJhY3RTREMgfSBmcm9tIFwiLi9zaW1wbGVEb21Db250cm9sL0Fic3RyYWN0U0RDLmpzXCI7XG5pbXBvcnQgU2RjTW9kZWwsIHsgU2RjUXVlcnlTZXQgfSBmcm9tIFwiLi9zaW1wbGVEb21Db250cm9sL3NkY19tb2RlbC5qc1wiO1xuaW1wb3J0IHsgcmVnaXN0ZXJNb2RlbCB9IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX3NvY2tldC5qc1wiO1xuaW1wb3J0IENvb2tpZXMgZnJvbSBcImpzLWNvb2tpZVwiO1xuaW1wb3J0IHtcbiAgb24sXG4gIHRyaWdnZXIsXG4gIGFsbE9mZixcbiAgc2V0RXZlbnQsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX2V2ZW50cy5qc1wiO1xuXG5pbXBvcnQge1xuICBjbGVhckVycm9yc0luRm9ybSxcbiAgc2V0RXJyb3JzSW5Gb3JtLFxuICBjaGVja0lmUGFyYW1OdW1iZXJCb29sT3JTdHJpbmcsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX3V0aWxzLmpzXCI7XG5pbXBvcnQge1xuICBjb250cm9sbGVyRmFjdG9yeSxcbiAgcnVuQ29udHJvbEZsb3dGdW5jdGlvbnMsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX2NvbnRyb2xsZXIuanNcIjtcbmltcG9ydCB7IGNsb3NlIH0gZnJvbSBcIi4vc2ltcGxlRG9tQ29udHJvbC9zZGNfc2VydmVyX2NhbGwuanNcIjtcbmltcG9ydCB7XG4gIGdldF9jb250cm9sbGVyLFxuICBnZXRDc3JmVG9rZW4sXG4gIGNvbnRyb2xsZXJGcm9tVGVzdEh0bWwsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX3Rlc3RfdXRpbHMuanNcIjtcblxuY29uc3Qgc29ja2V0UmVjb25uZWN0ID0gY2xvc2U7XG5jb25zdCB0ZXN0X3V0aWxzID0ge1xuICBnZXRfY29udHJvbGxlcixcbiAgZ2V0Q3NyZlRva2VuLFxuICBjb250cm9sbGVyRnJvbVRlc3RIdG1sLFxuICBsb2dvdXQ6ICgpID0+IHtcbiAgICBDb29raWVzLnJlbW92ZShcInNlc3Npb25pZFwiKTtcbiAgICBjb25zb2xlLmxvZyhcIkxvZ2dlZCBvdXRcIik7XG4gIH0sXG4gIGxvZ2luOiAodXNlcikgPT4ge1xuICAgIGNvbnN0IHNlc3Npb25JZCA9IGdsb2JhbFRoaXMuU0RDX1RFU1RfVVNFUj8uW3VzZXJdO1xuICAgIGlmICghc2Vzc2lvbklkKSB7XG4gICAgICBDb29raWVzLnJlbW92ZShcInNlc3Npb25pZFwiKTtcbiAgICAgIGNvbnNvbGUud2FybihgVW5rbm93biB0ZXN0IHVzZXI6ICR7dXNlcn1gKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgQ29va2llcy5zZXQoXCJzZXNzaW9uaWRcIiwgc2Vzc2lvbklkKTtcbiAgICBjb25zb2xlLmxvZyhgTG9nZ2VkIGluIGFzICR7dXNlcn1gKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbn07XG5cbmV4cG9ydCB7XG4gIGFwcCxcbiAgQWJzdHJhY3RTREMsXG4gIG9uLFxuICB0cmlnZ2VyLFxuICBhbGxPZmYsXG4gIHNldEV2ZW50LFxuICBjbGVhckVycm9yc0luRm9ybSxcbiAgc2V0RXJyb3JzSW5Gb3JtLFxuICBjaGVja0lmUGFyYW1OdW1iZXJCb29sT3JTdHJpbmcsXG4gIGNvbnRyb2xsZXJGYWN0b3J5LFxuICBydW5Db250cm9sRmxvd0Z1bmN0aW9ucyxcbiAgc29ja2V0UmVjb25uZWN0LFxuICB0ZXN0X3V0aWxzLFxuICBTZGNNb2RlbCxcbiAgU2RjUXVlcnlTZXQsXG4gIHJlZ2lzdGVyTW9kZWwsXG59O1xuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/index.js\n\n}");
27
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ AbstractSDC: () => (/* reexport safe */ _simpleDomControl_AbstractSDC_js__WEBPACK_IMPORTED_MODULE_1__.AbstractSDC),\n/* harmony export */ SdcModel: () => (/* reexport safe */ _simpleDomControl_sdc_model_js__WEBPACK_IMPORTED_MODULE_2__[\"default\"]),\n/* harmony export */ SdcQuerySet: () => (/* reexport safe */ _simpleDomControl_sdc_model_js__WEBPACK_IMPORTED_MODULE_2__.SdcQuerySet),\n/* harmony export */ allOff: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.allOff),\n/* harmony export */ app: () => (/* reexport safe */ _simpleDomControl_sdc_main_js__WEBPACK_IMPORTED_MODULE_0__.app),\n/* harmony export */ checkIfParamNumberBoolOrString: () => (/* reexport safe */ _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__.checkIfParamNumberBoolOrString),\n/* harmony export */ clearErrorsInForm: () => (/* reexport safe */ _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__.clearErrorsInForm),\n/* harmony export */ controllerFactory: () => (/* reexport safe */ _simpleDomControl_sdc_controller_js__WEBPACK_IMPORTED_MODULE_7__.controllerFactory),\n/* harmony export */ on: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.on),\n/* harmony export */ registerModel: () => (/* reexport safe */ _simpleDomControl_sdc_socket_js__WEBPACK_IMPORTED_MODULE_3__.registerModel),\n/* harmony export */ runControlFlowFunctions: () => (/* reexport safe */ _simpleDomControl_sdc_controller_js__WEBPACK_IMPORTED_MODULE_7__.runControlFlowFunctions),\n/* harmony export */ setErrorsInForm: () => (/* reexport safe */ _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__.setErrorsInForm),\n/* harmony export */ setEvent: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.setEvent),\n/* harmony export */ socketReconnect: () => (/* binding */ socketReconnect),\n/* harmony export */ test_utils: () => (/* binding */ test_utils),\n/* harmony export */ trigger: () => (/* reexport safe */ _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__.trigger)\n/* harmony export */ });\n/* harmony import */ var _simpleDomControl_sdc_main_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./simpleDomControl/sdc_main.js */ \"./src/simpleDomControl/sdc_main.js\");\n/* harmony import */ var _simpleDomControl_AbstractSDC_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./simpleDomControl/AbstractSDC.js */ \"./src/simpleDomControl/AbstractSDC.js\");\n/* harmony import */ var _simpleDomControl_sdc_model_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./simpleDomControl/sdc_model.js */ \"./src/simpleDomControl/sdc_model.js\");\n/* harmony import */ var _simpleDomControl_sdc_socket_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./simpleDomControl/sdc_socket.js */ \"./src/simpleDomControl/sdc_socket.js\");\n/* harmony import */ var js_cookie__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! js-cookie */ \"./node_modules/js-cookie/dist/js.cookie.mjs\");\n/* harmony import */ var _simpleDomControl_sdc_events_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./simpleDomControl/sdc_events.js */ \"./src/simpleDomControl/sdc_events.js\");\n/* harmony import */ var _simpleDomControl_sdc_utils_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./simpleDomControl/sdc_utils.js */ \"./src/simpleDomControl/sdc_utils.js\");\n/* harmony import */ var _simpleDomControl_sdc_controller_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./simpleDomControl/sdc_controller.js */ \"./src/simpleDomControl/sdc_controller.js\");\n/* harmony import */ var _simpleDomControl_sdc_server_call_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./simpleDomControl/sdc_server_call.js */ \"./src/simpleDomControl/sdc_server_call.js\");\n/* harmony import */ var _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./simpleDomControl/sdc_test_utils.js */ \"./src/simpleDomControl/sdc_test_utils.js\");\n\n\n\n\n\n\n\n\n\n\n\n\nconst socketReconnect = _simpleDomControl_sdc_server_call_js__WEBPACK_IMPORTED_MODULE_8__.close;\nconst test_utils = {\n get_controller: _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__.get_controller,\n getCsrfToken: _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__.getCsrfToken,\n controllerFromTestHtml: _simpleDomControl_sdc_test_utils_js__WEBPACK_IMPORTED_MODULE_9__.controllerFromTestHtml,\n logout: () => {\n js_cookie__WEBPACK_IMPORTED_MODULE_4__[\"default\"].remove(\"sessionid\");\n console.log(\"Logged out\");\n },\n login: (user) => {\n const sessionId = globalThis.SDC_TEST_USER?.[user];\n if (!sessionId) {\n js_cookie__WEBPACK_IMPORTED_MODULE_4__[\"default\"].remove(\"sessionid\");\n console.warn(`Unknown test user: ${user}`);\n return false;\n }\n js_cookie__WEBPACK_IMPORTED_MODULE_4__[\"default\"].set(\"sessionid\", sessionId);\n console.log(`Logged in as ${user}`);\n return true;\n },\n};\n\nif(window) {\n window.sdcApp = _simpleDomControl_sdc_main_js__WEBPACK_IMPORTED_MODULE_0__.app;\n}\n\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvaW5kZXguanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBcUQ7QUFDVztBQUNRO0FBQ1A7QUFDakM7QUFNVTs7QUFNRDtBQUlLO0FBQ2dCO0FBS2hCOztBQUU5Qyx3QkFBd0IsdUVBQUs7QUFDN0I7QUFDQSxnQkFBZ0I7QUFDaEIsY0FBYztBQUNkLHdCQUF3QjtBQUN4QjtBQUNBLElBQUksaURBQU87QUFDWDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxNQUFNLGlEQUFPO0FBQ2IseUNBQXlDLEtBQUs7QUFDOUM7QUFDQTtBQUNBLElBQUksaURBQU87QUFDWCxnQ0FBZ0MsS0FBSztBQUNyQztBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBLGtCQUFrQiw4REFBRztBQUNyQjs7QUFtQkUiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9zZGNfY2xpZW50Ly4vc3JjL2luZGV4LmpzP2U1ZjciXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgYXBwIH0gZnJvbSBcIi4vc2ltcGxlRG9tQ29udHJvbC9zZGNfbWFpbi5qc1wiO1xuaW1wb3J0IHsgQWJzdHJhY3RTREMgfSBmcm9tIFwiLi9zaW1wbGVEb21Db250cm9sL0Fic3RyYWN0U0RDLmpzXCI7XG5pbXBvcnQgU2RjTW9kZWwsIHsgU2RjUXVlcnlTZXQgfSBmcm9tIFwiLi9zaW1wbGVEb21Db250cm9sL3NkY19tb2RlbC5qc1wiO1xuaW1wb3J0IHsgcmVnaXN0ZXJNb2RlbCB9IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX3NvY2tldC5qc1wiO1xuaW1wb3J0IENvb2tpZXMgZnJvbSBcImpzLWNvb2tpZVwiO1xuaW1wb3J0IHtcbiAgb24sXG4gIHRyaWdnZXIsXG4gIGFsbE9mZixcbiAgc2V0RXZlbnQsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX2V2ZW50cy5qc1wiO1xuXG5pbXBvcnQge1xuICBjbGVhckVycm9yc0luRm9ybSxcbiAgc2V0RXJyb3JzSW5Gb3JtLFxuICBjaGVja0lmUGFyYW1OdW1iZXJCb29sT3JTdHJpbmcsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX3V0aWxzLmpzXCI7XG5pbXBvcnQge1xuICBjb250cm9sbGVyRmFjdG9yeSxcbiAgcnVuQ29udHJvbEZsb3dGdW5jdGlvbnMsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX2NvbnRyb2xsZXIuanNcIjtcbmltcG9ydCB7IGNsb3NlIH0gZnJvbSBcIi4vc2ltcGxlRG9tQ29udHJvbC9zZGNfc2VydmVyX2NhbGwuanNcIjtcbmltcG9ydCB7XG4gIGdldF9jb250cm9sbGVyLFxuICBnZXRDc3JmVG9rZW4sXG4gIGNvbnRyb2xsZXJGcm9tVGVzdEh0bWwsXG59IGZyb20gXCIuL3NpbXBsZURvbUNvbnRyb2wvc2RjX3Rlc3RfdXRpbHMuanNcIjtcblxuY29uc3Qgc29ja2V0UmVjb25uZWN0ID0gY2xvc2U7XG5jb25zdCB0ZXN0X3V0aWxzID0ge1xuICBnZXRfY29udHJvbGxlcixcbiAgZ2V0Q3NyZlRva2VuLFxuICBjb250cm9sbGVyRnJvbVRlc3RIdG1sLFxuICBsb2dvdXQ6ICgpID0+IHtcbiAgICBDb29raWVzLnJlbW92ZShcInNlc3Npb25pZFwiKTtcbiAgICBjb25zb2xlLmxvZyhcIkxvZ2dlZCBvdXRcIik7XG4gIH0sXG4gIGxvZ2luOiAodXNlcikgPT4ge1xuICAgIGNvbnN0IHNlc3Npb25JZCA9IGdsb2JhbFRoaXMuU0RDX1RFU1RfVVNFUj8uW3VzZXJdO1xuICAgIGlmICghc2Vzc2lvbklkKSB7XG4gICAgICBDb29raWVzLnJlbW92ZShcInNlc3Npb25pZFwiKTtcbiAgICAgIGNvbnNvbGUud2FybihgVW5rbm93biB0ZXN0IHVzZXI6ICR7dXNlcn1gKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgQ29va2llcy5zZXQoXCJzZXNzaW9uaWRcIiwgc2Vzc2lvbklkKTtcbiAgICBjb25zb2xlLmxvZyhgTG9nZ2VkIGluIGFzICR7dXNlcn1gKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbn07XG5cbmlmKHdpbmRvdykge1xuICB3aW5kb3cuc2RjQXBwID0gYXBwO1xufVxuXG5leHBvcnQge1xuICBhcHAsXG4gIEFic3RyYWN0U0RDLFxuICBvbixcbiAgdHJpZ2dlcixcbiAgYWxsT2ZmLFxuICBzZXRFdmVudCxcbiAgY2xlYXJFcnJvcnNJbkZvcm0sXG4gIHNldEVycm9yc0luRm9ybSxcbiAgY2hlY2tJZlBhcmFtTnVtYmVyQm9vbE9yU3RyaW5nLFxuICBjb250cm9sbGVyRmFjdG9yeSxcbiAgcnVuQ29udHJvbEZsb3dGdW5jdGlvbnMsXG4gIHNvY2tldFJlY29ubmVjdCxcbiAgdGVzdF91dGlscyxcbiAgU2RjTW9kZWwsXG4gIFNkY1F1ZXJ5U2V0LFxuICByZWdpc3Rlck1vZGVsLFxufTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/index.js\n\n}");
28
28
 
29
29
  /***/ },
30
30
 
@@ -84,7 +84,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
84
84
  \*******************************************/
85
85
  (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
86
86
 
87
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SdcQuerySet: () => (/* binding */ SdcQuerySet),\n/* harmony export */ \"default\": () => (/* binding */ SdcModel)\n/* harmony export */ });\n/* harmony import */ var _sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./sdc_utils.js */ \"./src/simpleDomControl/sdc_utils.js\");\n/* harmony import */ var _sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sdc_socket.js */ \"./src/simpleDomControl/sdc_socket.js\");\n/* harmony import */ var _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sdc_main.js */ \"./src/simpleDomControl/sdc_main.js\");\n/* harmony import */ var _sdc_events_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sdc_events.js */ \"./src/simpleDomControl/sdc_events.js\");\n\n\n\n\n\nconst MAX_FILE_UPLOAD = 25000;\nconst CONNECTING_REQUEST_ID = \"_connecting_process\";\n\n/**\n * Copy a model instance for another queryset. A new instance of the same class is\n * created from the serialized field values (structuredClone cannot copy the\n * WeakRef/Proxy members of a model).\n */\nconst cloneModel = (original) => {\n const copy = new original.constructor({});\n copy.setValues(original.serialize());\n return copy;\n}\n\nclass SdcModelError extends Error {\n constructor(props) {\n if (typeof props === 'string') {\n props = {\n msg: props,\n is_error: true,\n header: 'Error'\n }\n }\n super(props.msg)\n this.msg = props.msg;\n this.header = props.header;\n this.is_error = props.is_error;\n this.html = props.html;\n }\n}\n\nclass FileLoaded {\n constructor({ name, url }) {\n this.name = name;\n this.url = url;\n this.content = null;\n }\n\n async load(force = false) {\n if (force || !this.content) {\n this.content = await new Promise((resolve, reject) => {\n $.get(this.url).then(resolve).catch(\n () => {\n resolve('');\n }\n );\n });\n }\n\n return this.content;\n }\n\n async text() {\n return this.load();\n }\n\n static isValid(value) {\n return (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !(value instanceof File) &&\n typeof value.url === \"string\" &&\n typeof value.name === \"string\"\n );\n }\n\n\n}\n\n/**\n * Normalize an incoming primary key value.\n *\n * `-1` is used throughout this module as the sentinel for \"new object / no pk\".\n *\n * @param {*} pk\n * @returns {number}\n */\nfunction normalizePk(pk) {\n const normalizedPk = parseInt(pk ?? -1, 10);\n return Number.isNaN(normalizedPk) ? -1 : normalizedPk;\n}\n\n/**\n * Decide whether an argument of `create()` is an options object\n * (`{elem, data}`) or the data itself. It is treated as options if it is\n * a non-empty plain object whose keys are only `elem` and/or `data`, and\n * `elem` (if present) is an SdcModel.\n *\n * @param {*} arg\n * @returns {boolean}\n */\nfunction isCreateOptions(arg) {\n if (!arg || typeof arg !== \"object\" || arg instanceof SdcModel) {\n return false;\n }\n const keys = Object.keys(arg);\n if (keys.length === 0 || !keys.every((k) => k === \"elem\" || k === \"data\")) {\n return false;\n }\n if (\"elem\" in arg && arg.elem !== null && !(arg.elem instanceof SdcModel)) {\n return false;\n }\n return !(\"data\" in arg) || arg.data === null || typeof arg.data === \"object\";\n}\n\nclass SdcQuerySet {\n /**\n * Lightweight client-side collection wrapper around the SDC model websocket.\n *\n * The queryset exposes array-like access through a proxy while also keeping\n * track of socket state and outstanding requests for that model.\n *\n * @param {string} modelName\n * @param {object} modelQuery\n */\n constructor(modelName, modelQuery = {}) {\n this.valuesList = [];\n this.loaded = false;\n this.modelName = modelName;\n this.modelQuery = modelQuery ?? {};\n this._onNoOpenRequests = [];\n this._isConnected = false;\n this._isConnectingProcess = false;\n this._autoReconnect = true;\n this.socket = null;\n // Request resolvers are stored by websocket event id until the server responds.\n this.openRequest = {};\n this.modelId = 0;\n this.onUpdate = () => {\n };\n this.onCreate = () => {\n };\n // Called with the removed models when rows of this queryset are deleted on the\n // server. If not set, onUpdate is called instead.\n this.onDelete = null;\n\n return new Proxy(this, {\n get(target, prop) {\n if (typeof prop !== \"symbol\" && !isNaN(prop)) {\n return target.valuesList[prop];\n }\n return target[prop];\n },\n\n set(target, prop, value) {\n if (!isNaN(prop)) {\n target.valuesList[prop] = value;\n return true;\n }\n target[prop] = value;\n return true;\n }\n });\n }\n\n [Symbol.iterator]() {\n let idx = -1;\n return {\n next: () => {\n ++idx;\n if (idx < this.valuesList.length) {\n return { value: this.valuesList[idx], done: false };\n }\n return { value: null, done: true };\n },\n };\n }\n\n set on_create(handler) {\n this.onCreate = handler;\n }\n\n set on_update(handler) {\n this.onUpdate = handler;\n }\n\n set on_delete(handler) {\n this.onDelete = handler;\n }\n\n /**\n * Remove the models with the given ids from the local list.\n *\n * @param {Array<number>} ids\n * @returns {Array<SdcModel>} the removed models\n */\n _removeIds(ids) {\n const removed = this.valuesList.filter((item) => ids.includes(item.id));\n this.valuesList = this.valuesList.filter((item) => !ids.includes(item.id));\n return removed;\n }\n\n /**\n *\n *\n * @param {Array<integr|string>|integer|SdcModel|SdcQuerySet|string} ids\n */\n setIds(ids) {\n const vl = this._setIds(ids);\n const filter = {\n id__in: vl.map((x) => x.id)\n }\n\n this.setFilter(filter);\n return vl;\n }\n\n /**\n *\n *\n * @param {Array<integr|string>|integer|SdcModel|SdcQuerySet|string} ids\n */\n _setIds(ids) {\n\n if (ids === null || ids === \"\" || Array.isArray(ids) && ids.length === 0) {\n this.valuesList = [];\n return this.valuesList;\n } else if (ids instanceof SdcQuerySet || ids instanceof SdcModel) {\n // Models already in this queryset are kept (so references to them stay valid);\n // other models are copied into it.\n const sources = ids instanceof SdcModel ? [ids] : ids.valuesList;\n this.valuesList = sources.map((source) => {\n const existing = source.id !== null ? this.byId(source.id) : null;\n if (existing) {\n return existing;\n }\n const copy = cloneModel(source);\n copy._setQuerySet(this, true);\n return copy;\n });\n return this.valuesList;\n }\n\n let numList, numId = Number.NaN;\n if (Number.isInteger(ids)) {\n numId = ids;\n } else if (ids instanceof Array) {\n const tempNumList = ids.map((x) => parseInt(x));\n if (!tempNumList.some(Number.isNaN)) {\n numList = tempNumList;\n }\n } else if (typeof ids === \"string\") {\n const tempNumList = ids.split(',').map((x) => parseInt(x));\n if (!tempNumList.some(Number.isNaN)) {\n numList = tempNumList\n } else {\n numId = parseInt(ids);\n }\n }\n\n if (!Number.isNaN(numId)) {\n this.valuesList = this.valuesList.filter((item) => numId === item.id);\n if (this.valuesList.length === 0) {\n const newModel = this.new();\n newModel.id = numId;\n }\n } else if (numList) {\n this.valuesList = this.valuesList.filter((item) => numList.includes(item.id));\n const valueIds = this.getIds();\n numList.filter(x => !valueIds.includes(x)).forEach((id) => {\n this.valuesList.push(new ((0,_sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__.getModel)(this.modelName))({ id }));\n });\n }\n return this.valuesList;\n }\n\n getIds() {\n return this.valuesList.map(x => x.id);\n }\n\n /**\n * Number of model instances currently present in the queryset cache.\n *\n * @returns {number}\n */\n get length() {\n return this.valuesList.length;\n }\n\n /**\n * Resolve a model instance by id, loading the queryset first if needed.\n *\n * @param {*} id\n * @returns {SdcModel|null}\n */\n byId(id) {\n if (id !== null) {\n const normalizedId = normalizePk(id);\n return this.valuesList.find((elm) => elm.id === normalizedId) ?? null;\n }\n\n return null;\n }\n\n /**\n * Merge additional query constraints into the current queryset.\n *\n * @param {object} modelQuery\n * @returns {SdcQuerySet}\n */\n setFilter(modelQuery) {\n this.modelQuery = modelQuery;\n return this;\n }\n\n addFilter(modelQuery) {\n this.modelQuery = Object.assign({}, this.modelQuery, modelQuery);\n return this;\n }\n\n /**\n * @param {?object} values\n * @returns {SdcModel}\n */\n new(values = {}) {\n const newModel = new ((0,_sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__.getModel)(this.modelName))(values);\n newModel._setQuerySet(this, false);\n this.valuesList.push(newModel);\n return newModel;\n }\n\n /**\n * Load model instances matching the current query into the queryset cache.\n *\n * @param {?object} modelQuery\n * @returns {Promise<SdcQuerySet>}\n */\n load(modelQuery = null) {\n this.valuesList = [];\n this.modelQuery = modelQuery ?? this.modelQuery;\n return this._sendLoad();\n }\n\n /**\n * Load model instances matching the current query into the queryset cache.\n *\n * @param {?object} modelQuery\n * @param {?SdcModel} item\n * @returns {Promise<SdcQuerySet>}\n */\n update({ modelQuery = null, item = null }) {\n this.modelQuery = modelQuery ?? this.modelQuery;\n let loadQuery = item ? { id: item.id } : this.modelQuery;\n return this._sendLoad(loadQuery);\n }\n\n /**\n *\n * @param pk {integr}\n * @param elem {SdcModel}\n * @returns {Promise<unknown>}\n */\n delete({ pk = null, id = null, elem = null }) {\n pk ??= id;\n pk = !elem ? pk : elem.id;\n if (pk === null) {\n throw new Error(\"pk or elem must be set\");\n }\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n return this.isConnected().then(() => {\n return new Promise((resolve, reject) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"delete\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n id: pk,\n pk\n },\n }),\n );\n\n this.openRequest[event_id] = [(res) => {\n this._removeIds([normalizePk(pk)]);\n resolve(res);\n }, reject];\n });\n });\n }\n\n /**\n * Request the server-side queryset data over the model websocket.\n *\n * @returns {Promise<*>}\n */\n _sendLoad(loadQuery = null) {\n return this.isConnected().then(() => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n return new Promise((resolve, reject) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"load\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: loadQuery ?? this.modelQuery,\n },\n }),\n );\n\n this.openRequest[event_id] = [(data) => {\n this.loaded = true;\n resolve(data);\n }, reject];\n });\n });\n }\n\n /**\n * Render the list-view endpoint for the current model.\n *\n * @param {object} options\n * @returns {*}\n */\n _sendListView({\n modelQuery = {},\n cbResolve = null,\n cbReject = null,\n templateContext = {},\n }) {\n return this.view({\n modelQuery,\n cbResolve,\n cbReject,\n templateContext,\n eventType: \"list_view\",\n });\n }\n\n /**\n * Render a named model view and append its HTML to a container element.\n *\n * @param {object} options\n * @returns {*}\n */\n view({\n viewName = \"html_list_template\",\n modelQuery = {},\n cbResolve = null,\n cbReject = null,\n templateContext = {},\n eventType = \"named_view\",\n }) {\n let $divList = $('<div class=\"container-fluid\">');\n this.isConnected().then(() => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: eventType,\n event_id,\n args: {\n view_name: viewName,\n model_name: this.modelName,\n model_query: modelQuery,\n template_context: templateContext,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (data) => {\n $divList.append(data.html);\n _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__.app.refresh($divList);\n cbResolve && cbResolve(data);\n },\n (res) => {\n cbReject && cbReject(res);\n },\n ];\n });\n\n return $divList;\n }\n\n /**\n * Render the detail-view endpoint for a single model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n _sendDetailView({\n pk = null,\n id = null,\n cbResolve = null,\n cbReject = null,\n templateContext = {},\n }) {\n pk ??= id;\n pk = normalizePk(pk);\n let $divList = $('<div class=\"container-fluid\">');\n\n this.isConnected().then(() => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"detail_view\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n id: pk,\n pk,\n template_context: templateContext,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (data) => {\n $divList.append(data.html);\n _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__.app.refresh($divList);\n cbResolve && cbResolve(data);\n },\n (res) => {\n cbReject && cbReject(res);\n },\n ];\n });\n\n return $divList;\n }\n\n /**\n * Fetch a model form fragment and attach the SDC form metadata expected by\n * the rest of the client.\n *\n * @param {string} eventType\n * @param {SdcModel} modelObj\n * @param formName\n * @param $divForm\n * @param cbResolve\n * @param cbReject\n * @param formId\n */\n getForm({ modelObj, eventType, formName, $divForm, cbResolve, cbReject, formId }) {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n const pk = modelObj.id ?? -1;\n this.isConnected().then(() => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: eventType,\n event_id,\n args: {\n model_name: this.modelName,\n id: pk,\n pk,\n form_name: formName,\n },\n }),\n );\n });\n\n const className = pk === null || pk === -1 ? \"create\" : \"edit\";\n\n this.openRequest[event_id] = [\n (data) => {\n $divForm.append(data.html);\n let $form = $divForm\n .closest(\"form\")\n .addClass(\n `sdc-model-${className}-form sdc-model-form ${formId}`,\n )\n .data(\"model\", modelObj)\n .data(\"model_pk\", pk)\n .data(\"form_name\", formName);\n modelObj.addForm($form);\n if ($form.length > 0 && !$form[0].hasAttribute(\"sdc_submit\")) {\n $form.attr(\"sdc_submit\", \"submitModelFormDistributor\");\n }\n\n _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__.app.refresh($divForm).then(() => null);\n cbResolve && cbResolve(data);\n },\n (res) => {\n cbReject && cbReject(res);\n },\n ];\n }\n\n /**\n * Fetch a single model instance matching the current query.\n *\n * @param {?object} modelQuery\n * @param {?boolean} doNotLoad true if modelQuery contains id or pk and object does not need to be loaded.\n * @returns {Promise<SdcModel>}\n */\n async get(modelQuery = null, doNotLoad = false) {\n if (doNotLoad) {\n const id = modelQuery?.id ?? this.modelQuery?.id;\n if(modelQuery) {\n this.setFilter(modelQuery);\n }\n return this.byId(id) ?? this.new(modelQuery || this.modelQuery);\n }\n await this.load(modelQuery);\n if (this.length !== 1) {\n throw new Error(`model query returns ${this.length} but only 1 expected.`);\n }\n\n this.addFilter({ id: this.valuesList[0].id });\n\n return this.valuesList[0];\n }\n\n detailView({ pk, cbResolve = null, cbReject = null, templateContext = {} }) {\n return this._sendDetailView({\n id: pk,\n cbResolve,\n cbReject,\n templateContext,\n });\n }\n\n listView({ modelQuery = {}, searchValues = {}, cbResolve = null, cbReject = null, templateContext = {} }) {\n return this._sendListView({\n modelQuery: Object.assign({}, this.modelQuery, modelQuery, { '__search_values': searchValues }),\n cbResolve,\n cbReject,\n templateContext,\n });\n }\n\n save({ pk = null, id = null, formName = \"edit_form\", data = null } = {}) {\n pk ??= id;\n const normPk = normalizePk(pk);\n return this.isConnected().then(() => {\n let elemList;\n if (normPk > -1) {\n const elem = this.byId(normPk);\n if (!elem) {\n return Promise.reject(new SdcModelError(`Element not found with ID: ${normPk}`));\n }\n elemList = [elem];\n } else {\n elemList = this.valuesList;\n }\n let pList = [];\n elemList.forEach((elem) => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n pList.push(\n new Promise((resolve, reject) => {\n this._readFiles(elem).then((files) => {\n const sendData = data ? { ...data } : elem.serialize();\n sendData.id = elem.id;\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"save\",\n event_id,\n args: {\n form_name: formName,\n model_name: this.modelName,\n model_query: this.modelQuery,\n data: sendData,\n id: sendData.id,\n pk: sendData.id,\n files: files,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (res) => {\n let data =\n typeof res.data.instance === \"string\"\n ? JSON.parse(res.data.instance)\n : res.data.instance;\n res.data.instance = this._parseServerRes(data);\n resolve(res);\n },\n reject,\n ];\n });\n }),\n );\n });\n\n return Promise.all(pList);\n });\n }\n\n /**\n * Create a new instance in the DB.\n *\n * @param {{elem?: SdcModel, data?: object} | object} arg\n * Either an options object containing `elem` and/or `data`,\n * or `data` directly.\n *\n * @example\n * create({ elem, data });\n * create({ elem });\n * create(data);\n * @returns {Promise<unknown>}\n */\n create(arg = null) {\n let { elem = null, data = null } = isCreateOptions(arg) ? arg : { data: arg };\n if (data && typeof data === \"object\" && Object.keys(data).length === 0) {\n data = null;\n }\n\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n if (!elem) {\n elem = this.new(data);\n }\n return this.isConnected().then(() => {\n return new Promise((resolve, reject) => {\n this._readFiles(elem).then((files) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"create\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n data: data ?? elem?.serialize() ?? {},\n files: files,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (res) => {\n let data =\n typeof res.data.instance === \"string\"\n ? JSON.parse(res.data.instance)\n : res.data.instance;\n if (elem) {\n elem.id = data[0]?.id || data[0]?.pk;\n }\n res.data.instance = this._parseServerRes(data)[0];\n resolve(res);\n },\n reject,\n ];\n });\n });\n });\n }\n\n /**\n * Ensure the websocket is open and has completed the server-side connect\n * handshake before issuing model requests.\n *\n * Multiple callers can arrive while a connection attempt is already in\n * progress. In that case they are queued behind the same synthetic request id.\n *\n * @returns {Promise<void>}\n */\n isConnected() {\n return new Promise((resolve, reject) => {\n if (this._isConnected) {\n resolve();\n } else if (\n !this._isConnectingProcess ||\n !this.openRequest[CONNECTING_REQUEST_ID]\n ) {\n this._isConnectingProcess = true;\n this.openRequest[CONNECTING_REQUEST_ID] = [() => {\n }, () => {\n }];\n this._connectToServer().then(() => {\n resolve(this._checkConnection());\n });\n } else {\n const [resolveOrigin, rejectOrigin] =\n this.openRequest[CONNECTING_REQUEST_ID];\n this.openRequest[CONNECTING_REQUEST_ID] = [\n () => {\n resolveOrigin();\n resolve();\n },\n () => {\n rejectOrigin();\n reject();\n },\n ];\n }\n });\n }\n\n /**\n * Close the websocket and disable automatic reconnect for this queryset.\n */\n close() {\n if (this.socket) {\n this._autoReconnect = false;\n this.socket.onclose = () => {\n };\n this.socket.close();\n delete this[\"socket\"];\n }\n\n this.valuesList.forEach((elem) => {\n elem._onClose()\n });\n }\n\n /**\n * Upload attached `File` values in fixed-size chunks before save/create calls.\n *\n * @param {SdcModel} elem\n * @returns {Promise<object>}\n */\n _readFiles(elem) {\n let toSolve = [];\n let files = {};\n if (!elem) {\n return Promise.resolve(files);\n }\n Object.keys(elem.constructor.fields).forEach((key) => {\n const value = elem[key];\n if (value instanceof File) {\n toSolve.push(\n new Promise((resolve, reject) => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.openRequest[event_id] = [resolve, reject];\n\n value.arrayBuffer().then((buffer) => {\n let result = new Uint8Array(buffer);\n let numberOfChunks = Math.ceil(result.length / MAX_FILE_UPLOAD);\n files[key] = {\n id: event_id,\n file_name: value.name,\n field_name: key,\n content_length: value.size,\n };\n for (let i = 0; i < numberOfChunks; ++i) {\n const chunk = Array.from(result.slice(\n MAX_FILE_UPLOAD * i,\n MAX_FILE_UPLOAD * (i + 1),\n ));\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"upload\",\n event_id,\n args: {\n chunk,\n idx: i,\n number_of_chunks: numberOfChunks,\n file_name: value.name,\n field_name: key,\n content_length: value.size,\n content_type: value.type,\n model_name: this.modelName,\n model_query: this.modelQuery,\n },\n }),\n );\n }\n }).catch((err) => {\n this._closeOpenRequest(event_id);\n reject(err);\n });\n }),\n );\n }\n });\n\n return Promise.all(toSolve).then(() => {\n return files;\n });\n }\n\n /**\n * Route websocket responses to the matching pending request and update local\n * state when the server sends model payloads.\n *\n * @param {MessageEvent} e\n */\n async _onMessage(e) {\n let data = JSON.parse(e.data);\n if (data.is_error) {\n if (Object.hasOwn(this.openRequest, data.event_id)) {\n this.openRequest[data.event_id][1](new SdcModelError(data));\n this._closeOpenRequest(data.event_id);\n }\n if (data.msg || data.header) {\n (0,_sdc_events_js__WEBPACK_IMPORTED_MODULE_3__.trigger)(\"pushErrorMsg\", data.header || \"\", data.msg || \"\");\n }\n\n if (data.type === \"connect\") {\n this.openRequest[CONNECTING_REQUEST_ID][1](new SdcModelError(data));\n this._closeOpenRequest(CONNECTING_REQUEST_ID);\n this._autoReconnect = false;\n this.socket.close();\n }\n } else {\n if (data.msg || data.header) {\n (0,_sdc_events_js__WEBPACK_IMPORTED_MODULE_3__.trigger)(\"pushMsg\", data.header || \"\", data.msg || \"\");\n }\n\n if (data.type === \"connect\") {\n this._isConnected = true;\n this._isConnectingProcess = false;\n this.openRequest[CONNECTING_REQUEST_ID][0](data);\n this._closeOpenRequest(CONNECTING_REQUEST_ID);\n } else if ([\"load\", \"list_view\", \"named_view\", \"detail_view\"].includes(data.type)) {\n const jsonRes = JSON.parse(data.args.data);\n data.args.data = await this._parseServerRes(jsonRes);\n } else if (data.type === \"on_update\" || data.type === \"on_create\") {\n const jsonRes = JSON.parse(data.args.data);\n\n let obj = await this._parseServerRes(jsonRes);\n let cb;\n\n if (data.type === \"on_create\") {\n cb = this.onCreate;\n } else {\n cb = this.onUpdate;\n }\n\n cb(obj);\n data.args.data = obj;\n } else if (data.type === \"on_delete\") {\n const ids = JSON.parse(data.args.data).map((x) => normalizePk(x.id ?? x.pk));\n const removed = this._removeIds(ids);\n (this.onDelete ?? this.onUpdate)(removed);\n data.args.data = removed;\n }\n\n let instance = data.data?.instance;\n if (instance) {\n data.data.instance = JSON.parse(data.data.instance);\n }\n\n if (Object.hasOwn(this.openRequest, data.event_id)) {\n this.openRequest[data.event_id][0](data);\n this._closeOpenRequest(data.event_id);\n }\n }\n }\n\n /**\n * Wait until all in-flight websocket requests for this queryset are resolved.\n *\n * @returns {Promise<void>}\n */\n noOpenRequests() {\n return new Promise((resolve) => {\n if (Object.keys(this.openRequest).length === 0) {\n return resolve();\n }\n\n this._onNoOpenRequests.push(resolve);\n });\n }\n\n /**\n * Remove a completed request and wake any `noOpenRequests()` waiters when the\n * request map becomes empty.\n *\n * @param {string} eventId\n */\n _closeOpenRequest(eventId) {\n delete this.openRequest[eventId];\n if (Object.keys(this.openRequest).length === 0) {\n this._onNoOpenRequests.forEach((x) => x());\n this._onNoOpenRequests = [];\n }\n }\n\n /**\n * Establish the raw websocket connection for this queryset.\n *\n * @returns {Promise<void>}\n */\n _connectToServer() {\n return new Promise((resolve) => {\n const modelIdentifier =\n `${this.modelName}` + (this.modelId > 0 ? `/${this.modelId}` : \"\");\n if (window.location.protocol === \"https:\") {\n this.socket = new WebSocket(\n `wss://${window.location.host}/sdc_ws/model/${modelIdentifier}`,\n );\n } else {\n this.socket = new WebSocket(\n `ws://${window.location.host}/sdc_ws/model/${modelIdentifier}`,\n );\n }\n\n this.socket.onmessage = this._onMessage.bind(this);\n\n this.socket.onclose = (e) => {\n console.error(\n `SDC Model (${this.modelName}, ${this.modelId}) Socket closed unexpectedly`,\n );\n this._isConnected = false;\n for (const value of Object.values(this.openRequest)) {\n value[1](e);\n }\n this.openRequest = {};\n\n this._isConnectingProcess = false;\n setTimeout(() => {\n if (this._autoReconnect && !this._isConnected) {\n // isConnected() opens the socket and sends the connect handshake, so\n // live updates work again and later requests reuse this connection.\n this.isConnected().catch(() => {\n });\n }\n }, 1000);\n };\n\n this.socket.onerror = (err) => {\n console.error(`Model Socket encountered error: ${err} Closing socket`);\n if (this._isConnected) {\n try {\n this.socket.close();\n } catch (e) {\n }\n }\n };\n\n this.socket.onopen = () => {\n resolve();\n };\n });\n }\n\n /**\n * Perform the application-level connect handshake once the websocket opens.\n *\n * @returns {Promise<*>}\n */\n _checkConnection() {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n return new Promise((resolve, reject) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"connect\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n },\n }),\n );\n\n this.openRequest[event_id] = [resolve, reject];\n });\n }\n\n /**\n * Convert the backend model payload into locally tracked model objects.\n *\n * @param {Array<object>} results\n */\n _parseServerRes(results) {\n const newModels = []\n for (const x of results) {\n const ModelClass = (0,_sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__.getModel)(this.modelName);\n if (!ModelClass) {\n throw new Error(`${this.modelName} is no SdcModel. mybe the models ar not importad.`);\n }\n const newModel = new ModelClass({ 'id': x.id ?? x.pk, ...x.fields });\n const currentModel = this.byId(newModel.id);\n if (currentModel) {\n currentModel.setValues(newModel);\n newModels.push(currentModel);\n } else {\n this.valuesList.push(newModel);\n newModel._setQuerySet(this, true);\n newModels.push(newModel);\n }\n }\n this.valuesList.sort((a, b) => a._id - b._id);\n return newModels;\n }\n}\n\nclass SdcModel {\n static fields = {};\n\n /**\n * Base model wrapper used by SDC model registrations.\n *\n * @param {string} modelName\n */\n constructor(modelName) {\n this._id = null;\n this._forms = [];\n this.loaded = false;\n this.formId = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.modelName = modelName;\n }\n\n /**\n *\n * @param {object?} modelQuerySet\n * @param {AbstractSDC} parent\n * @returns {SdcQuerySet}\n */\n static querySet(modelQuerySet = null, parent = null) {\n const { modelName } = new this({});\n if (!parent) {\n return new SdcQuerySet(modelName, modelQuerySet);\n }\n\n return parent.querySet(modelName, modelQuerySet);\n }\n\n addForm($form) {\n // Remove old listeners if form already set\n const onChange = this._onChange.bind(this);\n\n this._forms.push($form);\n\n if ($form) {\n // Attach delegated event handler to all inputs\n $form.on(\n \"input.formWatcher change.formWatcher\",\n \"input, select, textarea\",\n onChange\n );\n }\n }\n\n _onChange(event) {\n const { name } = event.target;\n if (this.constructor.fields[name]) {\n try {\n this[`set${name}`]((0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.getValueFromField)(event.target));\n } catch {\n // Invalid input (e.g. an empty required field) is kept in the form and\n // validated by the server on submit.\n return;\n }\n // Show the new value in the other forms of this model, not in the input being edited.\n this._updateForm(name, event.target);\n }\n }\n\n _updateForm(fieldName, skipElement = null) {\n const self = this;\n this._forms.forEach(($form) => {\n $form.find(`[name=\"${fieldName}\"]`).each(function () {\n if (this !== skipElement) {\n (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.setValueInField)(this, self[fieldName]);\n }\n });\n });\n }\n\n setValues(data = {}) {\n throw new Error(\"setValues() must be implemented by subclass\");\n }\n\n /**\n * Attach the queryset that owns this model instance.\n *\n * @param {SdcQuerySet} querySet\n * @param {boolean} isLoaded\n */\n _setQuerySet(querySet, isLoaded) {\n this._querySet = new WeakRef(querySet);\n this.loaded = isLoaded;\n }\n\n get querySet() {\n return this._querySet.deref();\n }\n\n save({ formName = \"edit_form\", data = null } = {}) {\n return this._querySet.deref().save({ pk: this.id, formName, data });\n }\n\n /**\n * Create this instance in the DB.\n *\n * @param {{data?: object} | object | null} values\n * Either `{ data }` or `data` directly.\n * @returns {Promise<unknown>}\n */\n create(values = null) {\n const data = isCreateOptions(values) ? (values.data ?? null) : values;\n return this._querySet.deref().create({ elem: this, data });\n }\n\n delete() {\n return this._querySet.deref().delete({ elem: this });\n }\n\n load() {\n return this._querySet.deref().update({ item: this });\n }\n\n update() {\n return this.load();\n }\n\n get id() {\n return this._id;\n }\n\n set id(data) {\n this._id = data;\n }\n\n set pk(data) {\n this.id = data;\n }\n\n get pk() {\n return this._id;\n }\n\n close() {\n return this._querySet.deref().close();\n }\n\n _onClose() {\n Object.keys(this.constructor.fields)\n .filter((x) => this[`_${x}`] instanceof SdcQuerySet)\n .forEach((x) => this[`_${x}`].close());\n }\n\n /**\n * Request the server-rendered detail view for this model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n detailView({ cbResolve = null, cbReject = null, templateContext = {} }) {\n return this._querySet.deref().detailView({ pk: this.id, cbResolve, cbReject, templateContext });\n }\n\n serialize() {\n return Object.entries(this.constructor.fields).reduce((acc, [key, val]) => {\n const value = this[key];\n if (value instanceof SdcQuerySet) {\n if (val.many_to_many || val.one_to_many) {\n acc[key] = value.getIds();\n } else {\n const allIds = value.getIds();\n if (allIds.length > 0) {\n acc[key] = allIds[0];\n } else {\n acc[key] = null;\n }\n\n }\n } else if (val.is_relation && value instanceof SdcModel) {\n acc[key] = value.id ?? null;\n } else if (value instanceof Date) {\n // Django's DateField does not accept a full ISO datetime.\n acc[key] = val.type === \"DateField\" ? (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.formatDate)(value) : value.toISOString();\n } else {\n acc[key] = value;\n }\n\n return acc\n }, {});\n }\n\n toJson() {\n const res = {}\n for (let key in this.constructor.fields) {\n const value = this[key];\n\n if (value instanceof File) {\n res[key] = value.name;\n } else if (value instanceof SdcModel) {\n res[key] = value.id;\n } else if (value instanceof SdcQuerySet) {\n res[key] = value.getIds();\n } else {\n res[key] = value;\n }\n }\n\n return res;\n }\n\n /**\n * Backwards-compatible alias for syncing values from a form into the model.\n *\n * @param {*} $forms\n * @returns {*}\n */\n syncFormToModel($forms) {\n return this.syncForm($forms);\n }\n\n /**\n * Resolve the form collection associated with this model instance.\n *\n * @param {*} $forms\n * @returns {*}\n */\n _resolveForms($forms) {\n if (!$forms || !$forms.hasClass(this.formId)) {\n return $(`.${this.formId}`);\n }\n\n return $forms;\n }\n\n /**\n * Copy the current model state into matching form fields.\n *\n * @param {*} $forms\n */\n syncModelToForm($forms) {\n $forms = this._resolveForms($forms);\n\n const self = this;\n const { fields } = this.constructor;\n $forms.each(function () {\n const pk = normalizePk($(this).data(\"model_pk\"));\n // Create forms carry model_pk -1 while the new model's id is still null.\n if (normalizePk(self.id) !== pk) {\n return;\n }\n\n for (let formItem of this.elements) {\n let { name } = formItem;\n if (name && name !== \"\" && !!fields[name]) {\n (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.setValueInField)(formItem, self[name])\n }\n }\n });\n }\n\n /**\n * Copy matching form values back onto the current model instance.\n *\n * Hidden inputs are parsed to their original primitive type when possible.\n *\n * @param {*} $forms\n * @returns {*}\n */\n syncForm($forms) {\n $forms = this._resolveForms($forms);\n\n const self = this;\n const { fields } = this.constructor;\n const returnValue = {}\n\n function setValueInForm(name, value) {\n if (fields[name]) {\n try {\n self[name] = value;\n } catch {\n // Invalid values are still sent to the server, which returns the form\n // errors; the model keeps its last valid value.\n }\n }\n returnValue[name] = value;\n }\n\n $forms.each(function () {\n const pk = normalizePk($(this).data(\"model_pk\"));\n if (self.id !== pk && (self.id !== null || pk !== -1)) {\n return;\n }\n\n for (let formItem of this.elements) {\n setValueInForm(formItem.name, (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.getValueFromField)(formItem));\n }\n\n return self;\n });\n\n return returnValue;\n }\n\n /**\n * Render the correct server-side form for this model state.\n *\n * @param {object} options\n * @returns {*}\n */\n form({ cbResolve = null, cbReject = null } = {}) {\n if (this.id === null || this.id === -1) {\n return this._createForm({ cbReject, cbResolve });\n }\n return this._editForm({ cbReject, cbResolve });\n }\n\n /**\n * Render the create form for a new model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n _createForm({ cbResolve = null, cbReject = null }) {\n let $divForm = $(\"<div>\");\n this._querySet.deref().getForm({\n modelObj: this,\n eventType: \"create_form\",\n formName: null,\n $divForm,\n cbResolve,\n cbReject,\n formId: this.formId,\n });\n\n return $divForm;\n }\n\n /**\n * Render the edit form for an existing model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n _editForm({ cbResolve = null, cbReject = null }) {\n let $divForm = $(\"<div>\");\n\n this._querySet.deref().getForm({\n modelObj: this,\n eventType: \"edit_form\",\n formName: null,\n $divForm,\n cbResolve,\n cbReject,\n formId: this.formId,\n });\n\n return $divForm;\n }\n\n /**\n * Render a named server-side form for this model.\n *\n * @param {object} options\n * @returns {*}\n */\n namedForm({ formName, cbResolve = null, cbReject = null }) {\n let $divForm = $('<div class=\"container-fluid\">');\n\n this._querySet.deref().getForm({\n modelObj: this,\n eventType: \"named_form\",\n formName,\n $divForm,\n cbResolve,\n cbReject,\n formId: this.formId,\n });\n\n return $divForm;\n }\n\n /**\n * Validate a field value using the supplied field config.\n *\n * @param {*} value\n * @param {object} config\n */\n validate(value, config) {\n const err = validateField(value, config);\n if (err) throw new Error(err);\n }\n\n /**\n * Convert a raw input value into the shape expected by the field config.\n *\n * @param {*} value\n * @param {object} config\n * @returns {*}\n */\n parseValue(value, config) {\n const {\n type,\n many_to_many: manyToMany,\n one_to_many: oneToMany,\n many_to_one: manyToOne,\n one_to_one: oneToOne,\n } = config;\n if (value === null) {\n return null;\n }\n\n if ((manyToMany || oneToMany || manyToOne || oneToOne) && value && typeof value === 'string') {\n return JSON.parse(value);\n }\n\n switch (type) {\n case \"CharField\":\n case \"TextField\":\n case \"SlugField\":\n case \"UUIDField\":\n case \"EmailField\":\n return `${value}`;\n\n case \"IntegerField\":\n case \"SmallIntegerField\":\n case \"BigIntegerField\":\n case \"PositiveIntegerField\":\n case \"PositiveSmallIntegerField\":\n case \"PositiveBigIntegerField\":\n case \"AutoField\":\n case \"SmallAutoField\":\n case \"BigAutoField\":\n return parseInt(value, 10);\n\n case \"FloatField\":\n case \"DecimalField\":\n return parseFloat(value);\n\n case \"BooleanField\":\n return !!value;\n\n case \"DateField\":\n case \"DateTimeField\":\n return (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.toDate)(value);\n\n case \"URLField\":\n return new URL(value);\n\n case \"FileField\":\n if (value == null) {\n return null;\n }\n\n if (typeof value === \"string\") {\n return null;\n }\n\n if (FileLoaded.isValid(value)) {\n return new FileLoaded(value);\n }\n\n if (value instanceof FileLoaded) {\n return new FileLoaded(value);\n }\n\n if (typeof File !== \"undefined\" && value instanceof File) {\n // Size and type are checked in validate().\n return value;\n }\n break;\n\n case \"JSONField\":\n if (typeof value === \"object\") {\n return value;\n }\n if (typeof value === \"string\") {\n return JSON.parse(value);\n }\n break;\n\n default:\n break;\n }\n\n return value;\n }\n}\n\n/**\n * Validate a field value against the field metadata received from the backend.\n *\n * @param {*} value\n * @param {object} config\n * @returns {?string}\n */\nfunction validateField(value, config) {\n const {\n type,\n required,\n max_length: maxLength,\n is_relation: isRelation,\n many_to_many: manyToMany,\n one_to_many: oneToMany,\n many_to_one: manyToOne,\n one_to_one: oneToOne,\n related_model: relatedModel,\n } = config;\n\n void isRelation;\n\n if (required) {\n if (value === null || value === undefined || value === \"\") {\n return \"This field is required\";\n }\n }\n\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n\n if (manyToMany || oneToMany || manyToOne || oneToOne) {\n if (!(value instanceof SdcQuerySet) || value.modelName !== relatedModel) {\n if(typeof value === 'string') {\n value = JSON.parse(value);\n }\n\n if ((manyToMany || manyToOne) && Array.isArray(value) && value.some((x) => !Number.isNaN(parseInt(x)))) {\n return null;\n }\n if (typeof value !== \"object\" && Number.isNaN(parseInt(value))) {\n return \"Must be object or ID\";\n }\n return null;\n }\n }\n\n switch (type) {\n case \"CharField\":\n case \"TextField\":\n if (typeof value !== \"string\") {\n return \"Must be a string\";\n }\n if (maxLength && value.length > maxLength) {\n return `Max length is ${maxLength}`;\n }\n break;\n\n case \"IntegerField\":\n case \"SmallIntegerField\":\n case \"BigIntegerField\":\n case \"PositiveIntegerField\":\n case \"PositiveSmallIntegerField\":\n case \"PositiveBigIntegerField\":\n case \"AutoField\":\n case \"SmallAutoField\":\n case \"BigAutoField\":\n if (!isFinite(parseInt(value))) {\n return \"Must be an integer\";\n }\n break;\n\n case \"FloatField\":\n case \"DecimalField\":\n if (!isFinite(parseFloat(value))) {\n return \"Must be a number\";\n }\n break;\n\n case \"BooleanField\":\n if (typeof value !== \"boolean\") {\n return \"Must be a boolean\";\n }\n break;\n\n case \"DateField\":\n case \"DateTimeField\":\n if (isNaN(Date.parse(value))) {\n return \"Must be a valid date\";\n }\n break;\n\n case \"EmailField\":\n if (typeof value !== \"string\" || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {\n return \"Invalid email\";\n }\n break;\n\n case \"URLField\":\n try {\n new URL(value);\n } catch {\n return \"Invalid URL\";\n }\n break;\n\n case \"UUIDField\":\n if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value)) {\n return \"Invalid UUID\";\n }\n break;\n\n case \"JSONField\":\n if (typeof value === \"string\") {\n try {\n JSON.parse(value);\n } catch {\n return \"Must be valid JSON\";\n }\n }\n break;\n case \"FileField\":\n if (!FileLoaded.isValid(value) && !(value instanceof File) && !(value instanceof FileLoaded)) {\n return \"Must be a valid file\";\n }\n if (typeof File !== \"undefined\" && value instanceof File) {\n if (config.max_size && value.size > config.max_size) {\n return `File too large (max ${config.max_size} bytes)`;\n }\n if (config.allowed_types && !config.allowed_types.includes(value.type)) {\n return `Invalid file type (${value.type})`;\n }\n }\n break;\n default:\n break;\n }\n\n return null;\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvc2ltcGxlRG9tQ29udHJvbC9zZGNfbW9kZWwuanMiLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBQWdHO0FBQ3REO0FBQ047QUFDTTs7QUFFMUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7QUFDMUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLFdBQVc7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNLFdBQVc7QUFDakI7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0Esd0NBQXdDO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkI7QUFDQSxpQkFBaUI7QUFDakIsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxlQUFlO0FBQzVCLGVBQWUsaUJBQWlCO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLDBEQUEwRDtBQUN2RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsMERBQTBEO0FBQ3ZFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLHdEQUFRLG9CQUFvQixJQUFJO0FBQ2xFLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLEdBQUc7QUFDaEIsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQixlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNDQUFzQztBQUN0QztBQUNBOztBQUVBO0FBQ0EsYUFBYSxTQUFTO0FBQ3RCLGVBQWU7QUFDZjtBQUNBLGlCQUFpQjtBQUNqQiwwQkFBMEIsd0RBQVE7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxTQUFTO0FBQ3RCLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxTQUFTO0FBQ3RCLGFBQWEsV0FBVztBQUN4QixlQUFlO0FBQ2Y7QUFDQSxXQUFXLGdDQUFnQztBQUMzQztBQUNBLDZCQUE2QixjQUFjO0FBQzNDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQixrQkFBa0I7QUFDbEIsZUFBZTtBQUNmO0FBQ0EsV0FBVyxtQ0FBbUM7QUFDOUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQixxREFBTTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1AsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIscURBQU07QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckIsZUFBZTtBQUNmO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBLHNDQUFzQztBQUN0QyxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQixlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBLHVCQUF1QixxREFBTTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSw2Q0FBRztBQUNiO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEMsbUJBQW1CO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHVCQUF1QixxREFBTTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLDZDQUFHO0FBQ2I7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQixhQUFhLFVBQVU7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxzRUFBc0U7QUFDbEYscUJBQXFCLHFEQUFNO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QixVQUFVLHVCQUF1QixPQUFPO0FBQ2pFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSw2Q0FBRztBQUNYO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFNBQVM7QUFDdEIsYUFBYSxVQUFVO0FBQ3ZCLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDLGFBQWE7QUFDMUQ7O0FBRUEscUJBQXFCLDJCQUEyQjs7QUFFaEQ7QUFDQTs7QUFFQSxlQUFlLDZEQUE2RDtBQUM1RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBLGFBQWEsZUFBZSxtQkFBbUIsMkRBQTJEO0FBQzFHO0FBQ0Esa0NBQWtDLGlDQUFpQyxpQ0FBaUM7QUFDcEc7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBLFNBQVMsNERBQTRELElBQUk7QUFDekU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnRkFBZ0YsT0FBTztBQUN2RjtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHFEQUFNO0FBQy9CO0FBQ0E7QUFDQTtBQUNBLHdDQUF3QyxVQUFVO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUI7QUFDbkIsaUJBQWlCO0FBQ2pCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1g7QUFDQSxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsZ0NBQWdDLFVBQVU7QUFDeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFlBQVk7QUFDMUIsY0FBYyxNQUFNO0FBQ3BCO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQSxVQUFVLDJCQUEyQixpQ0FBaUM7QUFDdEU7QUFDQTtBQUNBOztBQUVBLHFCQUFxQixxREFBTTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscURBQXFEO0FBQ3JEO0FBQ0EsZUFBZTtBQUNmLGFBQWE7QUFDYjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxVQUFVO0FBQ3ZCLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkIscURBQU07QUFDbkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCLG9CQUFvQjtBQUNsRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixtQkFBbUI7QUFDbkI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxjQUFjO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsdURBQU87QUFDZjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxRQUFRLHVEQUFPO0FBQ2Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0EsUUFBUTtBQUNSOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZUFBZSw0QkFBNEIsYUFBYTtBQUNuRTtBQUNBO0FBQ0EsbUJBQW1CLHFCQUFxQixnQkFBZ0IsZ0JBQWdCO0FBQ3hFO0FBQ0EsUUFBUTtBQUNSO0FBQ0Esa0JBQWtCLHFCQUFxQixnQkFBZ0IsZ0JBQWdCO0FBQ3ZFO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLHdCQUF3QixlQUFlLElBQUksYUFBYTtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0EseURBQXlELEtBQUs7QUFDOUQ7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0E7QUFDQSxxQkFBcUIscURBQU07QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLGVBQWU7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsd0RBQVE7QUFDakM7QUFDQSwyQkFBMkIsZ0JBQWdCO0FBQzNDO0FBQ0Esd0NBQXdDLGlDQUFpQztBQUN6RTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRWU7QUFDZjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQixxREFBTTtBQUN4QjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhLFNBQVM7QUFDdEIsYUFBYSxhQUFhO0FBQzFCLGVBQWU7QUFDZjtBQUNBO0FBQ0EsWUFBWSxZQUFZLGFBQWE7QUFDckM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0EsbUJBQW1CLEtBQUssR0FBRyxnRUFBaUI7QUFDNUMsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLFVBQVU7QUFDckM7QUFDQSxVQUFVLDhEQUFlO0FBQ3pCO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDs7QUFFQSxxQkFBcUI7QUFDckI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLGFBQWE7QUFDMUIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVMsc0NBQXNDLElBQUk7QUFDbkQseUNBQXlDLDZCQUE2QjtBQUN0RTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGVBQWUsaUJBQWlCO0FBQzlDLGlCQUFpQixNQUFNO0FBQ3ZCLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsa0JBQWtCO0FBQzdEOztBQUVBO0FBQ0EsMkNBQTJDLFlBQVk7QUFDdkQ7O0FBRUE7QUFDQSwyQ0FBMkMsWUFBWTtBQUN2RDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsOEJBQThCLEVBQUU7QUFDaEMsK0JBQStCLEVBQUU7QUFDakM7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCLGVBQWU7QUFDZjtBQUNBLGVBQWUseURBQXlEO0FBQ3hFLCtDQUErQyxtREFBbUQ7QUFDbEc7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBOztBQUVBO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsUUFBUTtBQUNSO0FBQ0EsOENBQThDLHlEQUFVO0FBQ3hELFFBQVE7QUFDUjtBQUNBOztBQUVBO0FBQ0EsS0FBSyxJQUFJO0FBQ1Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLEdBQUc7QUFDaEIsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsR0FBRztBQUNoQixlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsbUJBQW1CLFlBQVk7QUFDL0I7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLEdBQUc7QUFDaEI7QUFDQTtBQUNBOztBQUVBO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBLFVBQVUsOERBQWU7QUFDekI7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxHQUFHO0FBQ2hCLGVBQWU7QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxZQUFZLFNBQVM7QUFDckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNDQUFzQyxnRUFBaUI7QUFDdkQ7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCLGVBQWU7QUFDZjtBQUNBLFNBQVMsb0NBQW9DLElBQUk7QUFDakQ7QUFDQSxnQ0FBZ0MscUJBQXFCO0FBQ3JEO0FBQ0EsNEJBQTRCLHFCQUFxQjtBQUNqRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckIsZUFBZTtBQUNmO0FBQ0EsZ0JBQWdCLG1DQUFtQztBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCLGVBQWU7QUFDZjtBQUNBLGNBQWMsbUNBQW1DO0FBQ2pEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCLGVBQWU7QUFDZjtBQUNBLGNBQWMsNkNBQTZDO0FBQzNEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxHQUFHO0FBQ2hCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsR0FBRztBQUNoQixhQUFhLFFBQVE7QUFDckIsZUFBZTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrQkFBa0IsTUFBTTs7QUFFeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGVBQWUscURBQU07O0FBRXJCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsV0FBVyxRQUFRO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLFVBQVU7QUFDMUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0Esc0JBQXNCLEVBQUUsVUFBVSxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEdBQUc7QUFDcEY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLGlCQUFpQjtBQUN6RDtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9zZGNfY2xpZW50Ly4vc3JjL3NpbXBsZURvbUNvbnRyb2wvc2RjX21vZGVsLmpzPzk5MWIiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZm9ybWF0RGF0ZSwgZ2V0VmFsdWVGcm9tRmllbGQsIHNldFZhbHVlSW5GaWVsZCwgdG9EYXRlLCB1dWlkdjQgfSBmcm9tIFwiLi9zZGNfdXRpbHMuanNcIjtcbmltcG9ydCB7IGdldE1vZGVsIH0gZnJvbSBcIi4vc2RjX3NvY2tldC5qc1wiXG5pbXBvcnQgeyBhcHAgfSBmcm9tIFwiLi9zZGNfbWFpbi5qc1wiO1xuaW1wb3J0IHsgdHJpZ2dlciB9IGZyb20gXCIuL3NkY19ldmVudHMuanNcIjtcblxuY29uc3QgTUFYX0ZJTEVfVVBMT0FEID0gMjUwMDA7XG5jb25zdCBDT05ORUNUSU5HX1JFUVVFU1RfSUQgPSBcIl9jb25uZWN0aW5nX3Byb2Nlc3NcIjtcblxuLyoqXG4gKiBDb3B5IGEgbW9kZWwgaW5zdGFuY2UgZm9yIGFub3RoZXIgcXVlcnlzZXQuIEEgbmV3IGluc3RhbmNlIG9mIHRoZSBzYW1lIGNsYXNzIGlzXG4gKiBjcmVhdGVkIGZyb20gdGhlIHNlcmlhbGl6ZWQgZmllbGQgdmFsdWVzIChzdHJ1Y3R1cmVkQ2xvbmUgY2Fubm90IGNvcHkgdGhlXG4gKiBXZWFrUmVmL1Byb3h5IG1lbWJlcnMgb2YgYSBtb2RlbCkuXG4gKi9cbmNvbnN0IGNsb25lTW9kZWwgPSAob3JpZ2luYWwpID0+IHtcbiAgY29uc3QgY29weSA9IG5ldyBvcmlnaW5hbC5jb25zdHJ1Y3Rvcih7fSk7XG4gIGNvcHkuc2V0VmFsdWVzKG9yaWdpbmFsLnNlcmlhbGl6ZSgpKTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbmNsYXNzIFNkY01vZGVsRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgaWYgKHR5cGVvZiBwcm9wcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHByb3BzID0ge1xuICAgICAgICBtc2c6IHByb3BzLFxuICAgICAgICBpc19lcnJvcjogdHJ1ZSxcbiAgICAgICAgaGVhZGVyOiAnRXJyb3InXG4gICAgICB9XG4gICAgfVxuICAgIHN1cGVyKHByb3BzLm1zZylcbiAgICB0aGlzLm1zZyA9IHByb3BzLm1zZztcbiAgICB0aGlzLmhlYWRlciA9IHByb3BzLmhlYWRlcjtcbiAgICB0aGlzLmlzX2Vycm9yID0gcHJvcHMuaXNfZXJyb3I7XG4gICAgdGhpcy5odG1sID0gcHJvcHMuaHRtbDtcbiAgfVxufVxuXG5jbGFzcyBGaWxlTG9hZGVkIHtcbiAgY29uc3RydWN0b3IoeyBuYW1lLCB1cmwgfSkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgdGhpcy51cmwgPSB1cmw7XG4gICAgdGhpcy5jb250ZW50ID0gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGxvYWQoZm9yY2UgPSBmYWxzZSkge1xuICAgIGlmIChmb3JjZSB8fCAhdGhpcy5jb250ZW50KSB7XG4gICAgICB0aGlzLmNvbnRlbnQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICQuZ2V0KHRoaXMudXJsKS50aGVuKHJlc29sdmUpLmNhdGNoKFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoJycpO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNvbnRlbnQ7XG4gIH1cblxuICBhc3luYyB0ZXh0KCkge1xuICAgIHJldHVybiB0aGlzLmxvYWQoKTtcbiAgfVxuXG4gIHN0YXRpYyBpc1ZhbGlkKHZhbHVlKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgICB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiZcbiAgICAgICFBcnJheS5pc0FycmF5KHZhbHVlKSAmJlxuICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIEZpbGUpICYmXG4gICAgICB0eXBlb2YgdmFsdWUudXJsID09PSBcInN0cmluZ1wiICYmXG4gICAgICB0eXBlb2YgdmFsdWUubmFtZSA9PT0gXCJzdHJpbmdcIlxuICAgICk7XG4gIH1cblxuXG59XG5cbi8qKlxuICogTm9ybWFsaXplIGFuIGluY29taW5nIHByaW1hcnkga2V5IHZhbHVlLlxuICpcbiAqIGAtMWAgaXMgdXNlZCB0aHJvdWdob3V0IHRoaXMgbW9kdWxlIGFzIHRoZSBzZW50aW5lbCBmb3IgXCJuZXcgb2JqZWN0IC8gbm8gcGtcIi5cbiAqXG4gKiBAcGFyYW0geyp9IHBrXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mdW5jdGlvbiBub3JtYWxpemVQayhwaykge1xuICBjb25zdCBub3JtYWxpemVkUGsgPSBwYXJzZUludChwayA/PyAtMSwgMTApO1xuICByZXR1cm4gTnVtYmVyLmlzTmFOKG5vcm1hbGl6ZWRQaykgPyAtMSA6IG5vcm1hbGl6ZWRQaztcbn1cblxuLyoqXG4gKiBEZWNpZGUgd2hldGhlciBhbiBhcmd1bWVudCBvZiBgY3JlYXRlKClgIGlzIGFuIG9wdGlvbnMgb2JqZWN0XG4gKiAoYHtlbGVtLCBkYXRhfWApIG9yIHRoZSBkYXRhIGl0c2VsZi4gSXQgaXMgdHJlYXRlZCBhcyBvcHRpb25zIGlmIGl0IGlzXG4gKiBhIG5vbi1lbXB0eSBwbGFpbiBvYmplY3Qgd2hvc2Uga2V5cyBhcmUgb25seSBgZWxlbWAgYW5kL29yIGBkYXRhYCwgYW5kXG4gKiBgZWxlbWAgKGlmIHByZXNlbnQpIGlzIGFuIFNkY01vZGVsLlxuICpcbiAqIEBwYXJhbSB7Kn0gYXJnXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNDcmVhdGVPcHRpb25zKGFyZykge1xuICBpZiAoIWFyZyB8fCB0eXBlb2YgYXJnICE9PSBcIm9iamVjdFwiIHx8IGFyZyBpbnN0YW5jZW9mIFNkY01vZGVsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhcmcpO1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDAgfHwgIWtleXMuZXZlcnkoKGspID0+IGsgPT09IFwiZWxlbVwiIHx8IGsgPT09IFwiZGF0YVwiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoXCJlbGVtXCIgaW4gYXJnICYmIGFyZy5lbGVtICE9PSBudWxsICYmICEoYXJnLmVsZW0gaW5zdGFuY2VvZiBTZGNNb2RlbCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuICEoXCJkYXRhXCIgaW4gYXJnKSB8fCBhcmcuZGF0YSA9PT0gbnVsbCB8fCB0eXBlb2YgYXJnLmRhdGEgPT09IFwib2JqZWN0XCI7XG59XG5cbmV4cG9ydCBjbGFzcyBTZGNRdWVyeVNldCB7XG4gIC8qKlxuICAgKiBMaWdodHdlaWdodCBjbGllbnQtc2lkZSBjb2xsZWN0aW9uIHdyYXBwZXIgYXJvdW5kIHRoZSBTREMgbW9kZWwgd2Vic29ja2V0LlxuICAgKlxuICAgKiBUaGUgcXVlcnlzZXQgZXhwb3NlcyBhcnJheS1saWtlIGFjY2VzcyB0aHJvdWdoIGEgcHJveHkgd2hpbGUgYWxzbyBrZWVwaW5nXG4gICAqIHRyYWNrIG9mIHNvY2tldCBzdGF0ZSBhbmQgb3V0c3RhbmRpbmcgcmVxdWVzdHMgZm9yIHRoYXQgbW9kZWwuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlbE5hbWVcbiAgICogQHBhcmFtIHtvYmplY3R9IG1vZGVsUXVlcnlcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1vZGVsTmFtZSwgbW9kZWxRdWVyeSA9IHt9KSB7XG4gICAgdGhpcy52YWx1ZXNMaXN0ID0gW107XG4gICAgdGhpcy5sb2FkZWQgPSBmYWxzZTtcbiAgICB0aGlzLm1vZGVsTmFtZSA9IG1vZGVsTmFtZTtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBtb2RlbFF1ZXJ5ID8/IHt9O1xuICAgIHRoaXMuX29uTm9PcGVuUmVxdWVzdHMgPSBbXTtcbiAgICB0aGlzLl9pc0Nvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuX2lzQ29ubmVjdGluZ1Byb2Nlc3MgPSBmYWxzZTtcbiAgICB0aGlzLl9hdXRvUmVjb25uZWN0ID0gdHJ1ZTtcbiAgICB0aGlzLnNvY2tldCA9IG51bGw7XG4gICAgLy8gUmVxdWVzdCByZXNvbHZlcnMgYXJlIHN0b3JlZCBieSB3ZWJzb2NrZXQgZXZlbnQgaWQgdW50aWwgdGhlIHNlcnZlciByZXNwb25kcy5cbiAgICB0aGlzLm9wZW5SZXF1ZXN0ID0ge307XG4gICAgdGhpcy5tb2RlbElkID0gMDtcbiAgICB0aGlzLm9uVXBkYXRlID0gKCkgPT4ge1xuICAgIH07XG4gICAgdGhpcy5vbkNyZWF0ZSA9ICgpID0+IHtcbiAgICB9O1xuICAgIC8vIENhbGxlZCB3aXRoIHRoZSByZW1vdmVkIG1vZGVscyB3aGVuIHJvd3Mgb2YgdGhpcyBxdWVyeXNldCBhcmUgZGVsZXRlZCBvbiB0aGVcbiAgICAvLyBzZXJ2ZXIuIElmIG5vdCBzZXQsIG9uVXBkYXRlIGlzIGNhbGxlZCBpbnN0ZWFkLlxuICAgIHRoaXMub25EZWxldGUgPSBudWxsO1xuXG4gICAgcmV0dXJuIG5ldyBQcm94eSh0aGlzLCB7XG4gICAgICBnZXQodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJvcCAhPT0gXCJzeW1ib2xcIiAmJiAhaXNOYU4ocHJvcCkpIHtcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0LnZhbHVlc0xpc3RbcHJvcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRhcmdldFtwcm9wXTtcbiAgICAgIH0sXG5cbiAgICAgIHNldCh0YXJnZXQsIHByb3AsIHZhbHVlKSB7XG4gICAgICAgIGlmICghaXNOYU4ocHJvcCkpIHtcbiAgICAgICAgICB0YXJnZXQudmFsdWVzTGlzdFtwcm9wXSA9IHZhbHVlO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHRhcmdldFtwcm9wXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIGxldCBpZHggPSAtMTtcbiAgICByZXR1cm4ge1xuICAgICAgbmV4dDogKCkgPT4ge1xuICAgICAgICArK2lkeDtcbiAgICAgICAgaWYgKGlkeCA8IHRoaXMudmFsdWVzTGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm4geyB2YWx1ZTogdGhpcy52YWx1ZXNMaXN0W2lkeF0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG51bGwsIGRvbmU6IHRydWUgfTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHNldCBvbl9jcmVhdGUoaGFuZGxlcikge1xuICAgIHRoaXMub25DcmVhdGUgPSBoYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uX3VwZGF0ZShoYW5kbGVyKSB7XG4gICAgdGhpcy5vblVwZGF0ZSA9IGhhbmRsZXI7XG4gIH1cblxuICBzZXQgb25fZGVsZXRlKGhhbmRsZXIpIHtcbiAgICB0aGlzLm9uRGVsZXRlID0gaGFuZGxlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIG1vZGVscyB3aXRoIHRoZSBnaXZlbiBpZHMgZnJvbSB0aGUgbG9jYWwgbGlzdC5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBpZHNcbiAgICogQHJldHVybnMge0FycmF5PFNkY01vZGVsPn0gdGhlIHJlbW92ZWQgbW9kZWxzXG4gICAqL1xuICBfcmVtb3ZlSWRzKGlkcykge1xuICAgIGNvbnN0IHJlbW92ZWQgPSB0aGlzLnZhbHVlc0xpc3QuZmlsdGVyKChpdGVtKSA9PiBpZHMuaW5jbHVkZXMoaXRlbS5pZCkpO1xuICAgIHRoaXMudmFsdWVzTGlzdCA9IHRoaXMudmFsdWVzTGlzdC5maWx0ZXIoKGl0ZW0pID0+ICFpZHMuaW5jbHVkZXMoaXRlbS5pZCkpO1xuICAgIHJldHVybiByZW1vdmVkO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXk8aW50ZWdyfHN0cmluZz58aW50ZWdlcnxTZGNNb2RlbHxTZGNRdWVyeVNldHxzdHJpbmd9IGlkc1xuICAgKi9cbiAgc2V0SWRzKGlkcykge1xuICAgIGNvbnN0IHZsID0gdGhpcy5fc2V0SWRzKGlkcyk7XG4gICAgY29uc3QgZmlsdGVyID0ge1xuICAgICAgaWRfX2luOiB2bC5tYXAoKHgpID0+IHguaWQpXG4gICAgfVxuXG4gICAgdGhpcy5zZXRGaWx0ZXIoZmlsdGVyKTtcbiAgICByZXR1cm4gdmw7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICpcbiAgICogQHBhcmFtIHtBcnJheTxpbnRlZ3J8c3RyaW5nPnxpbnRlZ2VyfFNkY01vZGVsfFNkY1F1ZXJ5U2V0fHN0cmluZ30gaWRzXG4gICAqL1xuICBfc2V0SWRzKGlkcykge1xuXG4gICAgaWYgKGlkcyA9PT0gbnVsbCB8fCBpZHMgPT09IFwiXCIgfHwgQXJyYXkuaXNBcnJheShpZHMpICYmIGlkcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IFtdO1xuICAgICAgcmV0dXJuIHRoaXMudmFsdWVzTGlzdDtcbiAgICB9IGVsc2UgaWYgKGlkcyBpbnN0YW5jZW9mIFNkY1F1ZXJ5U2V0IHx8IGlkcyBpbnN0YW5jZW9mIFNkY01vZGVsKSB7XG4gICAgICAvLyBNb2RlbHMgYWxyZWFkeSBpbiB0aGlzIHF1ZXJ5c2V0IGFyZSBrZXB0IChzbyByZWZlcmVuY2VzIHRvIHRoZW0gc3RheSB2YWxpZCk7XG4gICAgICAvLyBvdGhlciBtb2RlbHMgYXJlIGNvcGllZCBpbnRvIGl0LlxuICAgICAgY29uc3Qgc291cmNlcyA9IGlkcyBpbnN0YW5jZW9mIFNkY01vZGVsID8gW2lkc10gOiBpZHMudmFsdWVzTGlzdDtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IHNvdXJjZXMubWFwKChzb3VyY2UpID0+IHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBzb3VyY2UuaWQgIT09IG51bGwgPyB0aGlzLmJ5SWQoc291cmNlLmlkKSA6IG51bGw7XG4gICAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICAgIHJldHVybiBleGlzdGluZztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb3B5ID0gY2xvbmVNb2RlbChzb3VyY2UpO1xuICAgICAgICBjb3B5Ll9zZXRRdWVyeVNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIGNvcHk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0aGlzLnZhbHVlc0xpc3Q7XG4gICAgfVxuXG4gICAgbGV0IG51bUxpc3QsIG51bUlkID0gTnVtYmVyLk5hTjtcbiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihpZHMpKSB7XG4gICAgICBudW1JZCA9IGlkcztcbiAgICB9IGVsc2UgaWYgKGlkcyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBjb25zdCB0ZW1wTnVtTGlzdCA9IGlkcy5tYXAoKHgpID0+IHBhcnNlSW50KHgpKTtcbiAgICAgIGlmICghdGVtcE51bUxpc3Quc29tZShOdW1iZXIuaXNOYU4pKSB7XG4gICAgICAgIG51bUxpc3QgPSB0ZW1wTnVtTGlzdDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBpZHMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIGNvbnN0IHRlbXBOdW1MaXN0ID0gaWRzLnNwbGl0KCcsJykubWFwKCh4KSA9PiBwYXJzZUludCh4KSk7XG4gICAgICBpZiAoIXRlbXBOdW1MaXN0LnNvbWUoTnVtYmVyLmlzTmFOKSkge1xuICAgICAgICBudW1MaXN0ID0gdGVtcE51bUxpc3RcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG51bUlkID0gcGFyc2VJbnQoaWRzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIU51bWJlci5pc05hTihudW1JZCkpIHtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IHRoaXMudmFsdWVzTGlzdC5maWx0ZXIoKGl0ZW0pID0+IG51bUlkID09PSBpdGVtLmlkKTtcbiAgICAgIGlmICh0aGlzLnZhbHVlc0xpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnN0IG5ld01vZGVsID0gdGhpcy5uZXcoKTtcbiAgICAgICAgbmV3TW9kZWwuaWQgPSBudW1JZDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG51bUxpc3QpIHtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IHRoaXMudmFsdWVzTGlzdC5maWx0ZXIoKGl0ZW0pID0+IG51bUxpc3QuaW5jbHVkZXMoaXRlbS5pZCkpO1xuICAgICAgY29uc3QgdmFsdWVJZHMgPSB0aGlzLmdldElkcygpO1xuICAgICAgbnVtTGlzdC5maWx0ZXIoeCA9PiAhdmFsdWVJZHMuaW5jbHVkZXMoeCkpLmZvckVhY2goKGlkKSA9PiB7XG4gICAgICAgIHRoaXMudmFsdWVzTGlzdC5wdXNoKG5ldyAoZ2V0TW9kZWwodGhpcy5tb2RlbE5hbWUpKSh7IGlkIH0pKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWx1ZXNMaXN0O1xuICB9XG5cbiAgZ2V0SWRzKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc0xpc3QubWFwKHggPT4geC5pZCk7XG4gIH1cblxuICAvKipcbiAgICogTnVtYmVyIG9mIG1vZGVsIGluc3RhbmNlcyBjdXJyZW50bHkgcHJlc2VudCBpbiB0aGUgcXVlcnlzZXQgY2FjaGUuXG4gICAqXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgbGVuZ3RoKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc0xpc3QubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgYSBtb2RlbCBpbnN0YW5jZSBieSBpZCwgbG9hZGluZyB0aGUgcXVlcnlzZXQgZmlyc3QgaWYgbmVlZGVkLlxuICAgKlxuICAgKiBAcGFyYW0geyp9IGlkXG4gICAqIEByZXR1cm5zIHtTZGNNb2RlbHxudWxsfVxuICAgKi9cbiAgYnlJZChpZCkge1xuICAgIGlmIChpZCAhPT0gbnVsbCkge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZElkID0gbm9ybWFsaXplUGsoaWQpO1xuICAgICAgcmV0dXJuIHRoaXMudmFsdWVzTGlzdC5maW5kKChlbG0pID0+IGVsbS5pZCA9PT0gbm9ybWFsaXplZElkKSA/PyBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIE1lcmdlIGFkZGl0aW9uYWwgcXVlcnkgY29uc3RyYWludHMgaW50byB0aGUgY3VycmVudCBxdWVyeXNldC5cbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IG1vZGVsUXVlcnlcbiAgICogQHJldHVybnMge1NkY1F1ZXJ5U2V0fVxuICAgKi9cbiAgc2V0RmlsdGVyKG1vZGVsUXVlcnkpIHtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBtb2RlbFF1ZXJ5O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgYWRkRmlsdGVyKG1vZGVsUXVlcnkpIHtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLm1vZGVsUXVlcnksIG1vZGVsUXVlcnkpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7P29iamVjdH0gdmFsdWVzXG4gICAqIEByZXR1cm5zIHtTZGNNb2RlbH1cbiAgICovXG4gIG5ldyh2YWx1ZXMgPSB7fSkge1xuICAgIGNvbnN0IG5ld01vZGVsID0gbmV3IChnZXRNb2RlbCh0aGlzLm1vZGVsTmFtZSkpKHZhbHVlcyk7XG4gICAgbmV3TW9kZWwuX3NldFF1ZXJ5U2V0KHRoaXMsIGZhbHNlKTtcbiAgICB0aGlzLnZhbHVlc0xpc3QucHVzaChuZXdNb2RlbCk7XG4gICAgcmV0dXJuIG5ld01vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWQgbW9kZWwgaW5zdGFuY2VzIG1hdGNoaW5nIHRoZSBjdXJyZW50IHF1ZXJ5IGludG8gdGhlIHF1ZXJ5c2V0IGNhY2hlLlxuICAgKlxuICAgKiBAcGFyYW0gez9vYmplY3R9IG1vZGVsUXVlcnlcbiAgICogQHJldHVybnMge1Byb21pc2U8U2RjUXVlcnlTZXQ+fVxuICAgKi9cbiAgbG9hZChtb2RlbFF1ZXJ5ID0gbnVsbCkge1xuICAgIHRoaXMudmFsdWVzTGlzdCA9IFtdO1xuICAgIHRoaXMubW9kZWxRdWVyeSA9IG1vZGVsUXVlcnkgPz8gdGhpcy5tb2RlbFF1ZXJ5O1xuICAgIHJldHVybiB0aGlzLl9zZW5kTG9hZCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWQgbW9kZWwgaW5zdGFuY2VzIG1hdGNoaW5nIHRoZSBjdXJyZW50IHF1ZXJ5IGludG8gdGhlIHF1ZXJ5c2V0IGNhY2hlLlxuICAgKlxuICAgKiBAcGFyYW0gez9vYmplY3R9IG1vZGVsUXVlcnlcbiAgICogQHBhcmFtIHs/U2RjTW9kZWx9IGl0ZW1cbiAgICogQHJldHVybnMge1Byb21pc2U8U2RjUXVlcnlTZXQ+fVxuICAgKi9cbiAgdXBkYXRlKHsgbW9kZWxRdWVyeSA9IG51bGwsIGl0ZW0gPSBudWxsIH0pIHtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBtb2RlbFF1ZXJ5ID8/IHRoaXMubW9kZWxRdWVyeTtcbiAgICBsZXQgbG9hZFF1ZXJ5ID0gaXRlbSA/IHsgaWQ6IGl0ZW0uaWQgfSA6IHRoaXMubW9kZWxRdWVyeTtcbiAgICByZXR1cm4gdGhpcy5fc2VuZExvYWQobG9hZFF1ZXJ5KTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gcGsge2ludGVncn1cbiAgICogQHBhcmFtIGVsZW0ge1NkY01vZGVsfVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx1bmtub3duPn1cbiAgICovXG4gIGRlbGV0ZSh7IHBrID0gbnVsbCwgaWQgPSBudWxsLCBlbGVtID0gbnVsbCB9KSB7XG4gICAgcGsgPz89IGlkO1xuICAgIHBrID0gIWVsZW0gPyBwayA6IGVsZW0uaWQ7XG4gICAgaWYgKHBrID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJwayBvciBlbGVtIG11c3QgYmUgc2V0XCIpO1xuICAgIH1cbiAgICBjb25zdCBldmVudF9pZCA9IHV1aWR2NCgpO1xuICAgIHJldHVybiB0aGlzLmlzQ29ubmVjdGVkKCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgICBldmVudF90eXBlOiBcImRlbGV0ZVwiLFxuICAgICAgICAgICAgZXZlbnRfaWQsXG4gICAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICAgICAgICBtb2RlbF9xdWVyeTogdGhpcy5tb2RlbFF1ZXJ5LFxuICAgICAgICAgICAgICBpZDogcGssXG4gICAgICAgICAgICAgIHBrXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gWyhyZXMpID0+IHtcbiAgICAgICAgICB0aGlzLl9yZW1vdmVJZHMoW25vcm1hbGl6ZVBrKHBrKV0pO1xuICAgICAgICAgIHJlc29sdmUocmVzKTtcbiAgICAgICAgfSwgcmVqZWN0XTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlci1zaWRlIHF1ZXJ5c2V0IGRhdGEgb3ZlciB0aGUgbW9kZWwgd2Vic29ja2V0LlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTwqPn1cbiAgICovXG4gIF9zZW5kTG9hZChsb2FkUXVlcnkgPSBudWxsKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNDb25uZWN0ZWQoKS50aGVuKCgpID0+IHtcbiAgICAgIGNvbnN0IGV2ZW50X2lkID0gdXVpZHY0KCk7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgICBldmVudF90eXBlOiBcImxvYWRcIixcbiAgICAgICAgICAgIGV2ZW50X2lkLFxuICAgICAgICAgICAgYXJnczoge1xuICAgICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgICAgbW9kZWxfcXVlcnk6IGxvYWRRdWVyeSA/PyB0aGlzLm1vZGVsUXVlcnksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gWyhkYXRhKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb2FkZWQgPSB0cnVlO1xuICAgICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICAgIH0sIHJlamVjdF07XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgdGhlIGxpc3QtdmlldyBlbmRwb2ludCBmb3IgdGhlIGN1cnJlbnQgbW9kZWwuXG4gICAqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgX3NlbmRMaXN0Vmlldyh7XG4gICAgICAgICAgICAgICAgICBtb2RlbFF1ZXJ5ID0ge30sXG4gICAgICAgICAgICAgICAgICBjYlJlc29sdmUgPSBudWxsLFxuICAgICAgICAgICAgICAgICAgY2JSZWplY3QgPSBudWxsLFxuICAgICAgICAgICAgICAgICAgdGVtcGxhdGVDb250ZXh0ID0ge30sXG4gICAgICAgICAgICAgICAgfSkge1xuICAgIHJldHVybiB0aGlzLnZpZXcoe1xuICAgICAgbW9kZWxRdWVyeSxcbiAgICAgIGNiUmVzb2x2ZSxcbiAgICAgIGNiUmVqZWN0LFxuICAgICAgdGVtcGxhdGVDb250ZXh0LFxuICAgICAgZXZlbnRUeXBlOiBcImxpc3Rfdmlld1wiLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciBhIG5hbWVkIG1vZGVsIHZpZXcgYW5kIGFwcGVuZCBpdHMgSFRNTCB0byBhIGNvbnRhaW5lciBlbGVtZW50LlxuICAgKlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHZpZXcoe1xuICAgICAgICAgdmlld05hbWUgPSBcImh0bWxfbGlzdF90ZW1wbGF0ZVwiLFxuICAgICAgICAgbW9kZWxRdWVyeSA9IHt9LFxuICAgICAgICAgY2JSZXNvbHZlID0gbnVsbCxcbiAgICAgICAgIGNiUmVqZWN0ID0gbnVsbCxcbiAgICAgICAgIHRlbXBsYXRlQ29udGV4dCA9IHt9LFxuICAgICAgICAgZXZlbnRUeXBlID0gXCJuYW1lZF92aWV3XCIsXG4gICAgICAgfSkge1xuICAgIGxldCAkZGl2TGlzdCA9ICQoJzxkaXYgY2xhc3M9XCJjb250YWluZXItZmx1aWRcIj4nKTtcbiAgICB0aGlzLmlzQ29ubmVjdGVkKCkudGhlbigoKSA9PiB7XG4gICAgICBjb25zdCBldmVudF9pZCA9IHV1aWR2NCgpO1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgZXZlbnRfdHlwZTogZXZlbnRUeXBlLFxuICAgICAgICAgIGV2ZW50X2lkLFxuICAgICAgICAgIGFyZ3M6IHtcbiAgICAgICAgICAgIHZpZXdfbmFtZTogdmlld05hbWUsXG4gICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgIG1vZGVsX3F1ZXJ5OiBtb2RlbFF1ZXJ5LFxuICAgICAgICAgICAgdGVtcGxhdGVfY29udGV4dDogdGVtcGxhdGVDb250ZXh0LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgdGhpcy5vcGVuUmVxdWVzdFtldmVudF9pZF0gPSBbXG4gICAgICAgIChkYXRhKSA9PiB7XG4gICAgICAgICAgJGRpdkxpc3QuYXBwZW5kKGRhdGEuaHRtbCk7XG4gICAgICAgICAgYXBwLnJlZnJlc2goJGRpdkxpc3QpO1xuICAgICAgICAgIGNiUmVzb2x2ZSAmJiBjYlJlc29sdmUoZGF0YSk7XG4gICAgICAgIH0sXG4gICAgICAgIChyZXMpID0+IHtcbiAgICAgICAgICBjYlJlamVjdCAmJiBjYlJlamVjdChyZXMpO1xuICAgICAgICB9LFxuICAgICAgXTtcbiAgICB9KTtcblxuICAgIHJldHVybiAkZGl2TGlzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgdGhlIGRldGFpbC12aWV3IGVuZHBvaW50IGZvciBhIHNpbmdsZSBtb2RlbCBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICBfc2VuZERldGFpbFZpZXcoe1xuICAgICAgICAgICAgICAgICAgICBwayA9IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIGlkID0gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgY2JSZXNvbHZlID0gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgY2JSZWplY3QgPSBudWxsLFxuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZUNvbnRleHQgPSB7fSxcbiAgICAgICAgICAgICAgICAgIH0pIHtcbiAgICBwayA/Pz0gaWQ7XG4gICAgcGsgPSBub3JtYWxpemVQayhwayk7XG4gICAgbGV0ICRkaXZMaXN0ID0gJCgnPGRpdiBjbGFzcz1cImNvbnRhaW5lci1mbHVpZFwiPicpO1xuXG4gICAgdGhpcy5pc0Nvbm5lY3RlZCgpLnRoZW4oKCkgPT4ge1xuICAgICAgY29uc3QgZXZlbnRfaWQgPSB1dWlkdjQoKTtcbiAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBldmVudDogXCJtb2RlbFwiLFxuICAgICAgICAgIGV2ZW50X3R5cGU6IFwiZGV0YWlsX3ZpZXdcIixcbiAgICAgICAgICBldmVudF9pZCxcbiAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgIG1vZGVsX3F1ZXJ5OiB0aGlzLm1vZGVsUXVlcnksXG4gICAgICAgICAgICBpZDogcGssXG4gICAgICAgICAgICBwayxcbiAgICAgICAgICAgIHRlbXBsYXRlX2NvbnRleHQ6IHRlbXBsYXRlQ29udGV4dCxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gW1xuICAgICAgICAoZGF0YSkgPT4ge1xuICAgICAgICAgICRkaXZMaXN0LmFwcGVuZChkYXRhLmh0bWwpO1xuICAgICAgICAgIGFwcC5yZWZyZXNoKCRkaXZMaXN0KTtcbiAgICAgICAgICBjYlJlc29sdmUgJiYgY2JSZXNvbHZlKGRhdGEpO1xuICAgICAgICB9LFxuICAgICAgICAocmVzKSA9PiB7XG4gICAgICAgICAgY2JSZWplY3QgJiYgY2JSZWplY3QocmVzKTtcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgfSk7XG5cbiAgICByZXR1cm4gJGRpdkxpc3Q7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2ggYSBtb2RlbCBmb3JtIGZyYWdtZW50IGFuZCBhdHRhY2ggdGhlIFNEQyBmb3JtIG1ldGFkYXRhIGV4cGVjdGVkIGJ5XG4gICAqIHRoZSByZXN0IG9mIHRoZSBjbGllbnQuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudFR5cGVcbiAgICogQHBhcmFtIHtTZGNNb2RlbH0gbW9kZWxPYmpcbiAgICogQHBhcmFtIGZvcm1OYW1lXG4gICAqIEBwYXJhbSAkZGl2Rm9ybVxuICAgKiBAcGFyYW0gY2JSZXNvbHZlXG4gICAqIEBwYXJhbSBjYlJlamVjdFxuICAgKiBAcGFyYW0gZm9ybUlkXG4gICAqL1xuICBnZXRGb3JtKHsgbW9kZWxPYmosIGV2ZW50VHlwZSwgZm9ybU5hbWUsICRkaXZGb3JtLCBjYlJlc29sdmUsIGNiUmVqZWN0LCBmb3JtSWQgfSkge1xuICAgIGNvbnN0IGV2ZW50X2lkID0gdXVpZHY0KCk7XG4gICAgY29uc3QgcGsgPSBtb2RlbE9iai5pZCA/PyAtMTtcbiAgICB0aGlzLmlzQ29ubmVjdGVkKCkudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgZXZlbnQ6IFwibW9kZWxcIixcbiAgICAgICAgICBldmVudF90eXBlOiBldmVudFR5cGUsXG4gICAgICAgICAgZXZlbnRfaWQsXG4gICAgICAgICAgYXJnczoge1xuICAgICAgICAgICAgbW9kZWxfbmFtZTogdGhpcy5tb2RlbE5hbWUsXG4gICAgICAgICAgICBpZDogcGssXG4gICAgICAgICAgICBwayxcbiAgICAgICAgICAgIGZvcm1fbmFtZTogZm9ybU5hbWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICApO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY2xhc3NOYW1lID0gcGsgPT09IG51bGwgfHwgcGsgPT09IC0xID8gXCJjcmVhdGVcIiA6IFwiZWRpdFwiO1xuXG4gICAgdGhpcy5vcGVuUmVxdWVzdFtldmVudF9pZF0gPSBbXG4gICAgICAoZGF0YSkgPT4ge1xuICAgICAgICAkZGl2Rm9ybS5hcHBlbmQoZGF0YS5odG1sKTtcbiAgICAgICAgbGV0ICRmb3JtID0gJGRpdkZvcm1cbiAgICAgICAgICAuY2xvc2VzdChcImZvcm1cIilcbiAgICAgICAgICAuYWRkQ2xhc3MoXG4gICAgICAgICAgICBgc2RjLW1vZGVsLSR7Y2xhc3NOYW1lfS1mb3JtIHNkYy1tb2RlbC1mb3JtICR7Zm9ybUlkfWAsXG4gICAgICAgICAgKVxuICAgICAgICAgIC5kYXRhKFwibW9kZWxcIiwgbW9kZWxPYmopXG4gICAgICAgICAgLmRhdGEoXCJtb2RlbF9wa1wiLCBwaylcbiAgICAgICAgICAuZGF0YShcImZvcm1fbmFtZVwiLCBmb3JtTmFtZSk7XG4gICAgICAgIG1vZGVsT2JqLmFkZEZvcm0oJGZvcm0pO1xuICAgICAgICBpZiAoJGZvcm0ubGVuZ3RoID4gMCAmJiAhJGZvcm1bMF0uaGFzQXR0cmlidXRlKFwic2RjX3N1Ym1pdFwiKSkge1xuICAgICAgICAgICRmb3JtLmF0dHIoXCJzZGNfc3VibWl0XCIsIFwic3VibWl0TW9kZWxGb3JtRGlzdHJpYnV0b3JcIik7XG4gICAgICAgIH1cblxuICAgICAgICBhcHAucmVmcmVzaCgkZGl2Rm9ybSkudGhlbigoKSA9PiBudWxsKTtcbiAgICAgICAgY2JSZXNvbHZlICYmIGNiUmVzb2x2ZShkYXRhKTtcbiAgICAgIH0sXG4gICAgICAocmVzKSA9PiB7XG4gICAgICAgIGNiUmVqZWN0ICYmIGNiUmVqZWN0KHJlcyk7XG4gICAgICB9LFxuICAgIF07XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2ggYSBzaW5nbGUgbW9kZWwgaW5zdGFuY2UgbWF0Y2hpbmcgdGhlIGN1cnJlbnQgcXVlcnkuXG4gICAqXG4gICAqIEBwYXJhbSB7P29iamVjdH0gbW9kZWxRdWVyeVxuICAgKiBAcGFyYW0gez9ib29sZWFufSBkb05vdExvYWQgdHJ1ZSBpZiBtb2RlbFF1ZXJ5IGNvbnRhaW5zIGlkIG9yIHBrIGFuZCBvYmplY3QgZG9lcyBub3QgbmVlZCB0byBiZSBsb2FkZWQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFNkY01vZGVsPn1cbiAgICovXG4gIGFzeW5jIGdldChtb2RlbFF1ZXJ5ID0gbnVsbCwgZG9Ob3RMb2FkID0gZmFsc2UpIHtcbiAgICBpZiAoZG9Ob3RMb2FkKSB7XG4gICAgICBjb25zdCBpZCA9IG1vZGVsUXVlcnk/LmlkID8/IHRoaXMubW9kZWxRdWVyeT8uaWQ7XG4gICAgICBpZihtb2RlbFF1ZXJ5KSB7XG4gICAgICAgIHRoaXMuc2V0RmlsdGVyKG1vZGVsUXVlcnkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuYnlJZChpZCkgPz8gdGhpcy5uZXcobW9kZWxRdWVyeSB8fCB0aGlzLm1vZGVsUXVlcnkpO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLmxvYWQobW9kZWxRdWVyeSk7XG4gICAgaWYgKHRoaXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYG1vZGVsIHF1ZXJ5IHJldHVybnMgJHt0aGlzLmxlbmd0aH0gYnV0IG9ubHkgMSBleHBlY3RlZC5gKTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZEZpbHRlcih7IGlkOiB0aGlzLnZhbHVlc0xpc3RbMF0uaWQgfSk7XG5cbiAgICByZXR1cm4gdGhpcy52YWx1ZXNMaXN0WzBdO1xuICB9XG5cbiAgZGV0YWlsVmlldyh7IHBrLCBjYlJlc29sdmUgPSBudWxsLCBjYlJlamVjdCA9IG51bGwsIHRlbXBsYXRlQ29udGV4dCA9IHt9IH0pIHtcbiAgICByZXR1cm4gdGhpcy5fc2VuZERldGFpbFZpZXcoe1xuICAgICAgaWQ6IHBrLFxuICAgICAgY2JSZXNvbHZlLFxuICAgICAgY2JSZWplY3QsXG4gICAgICB0ZW1wbGF0ZUNvbnRleHQsXG4gICAgfSk7XG4gIH1cblxuICBsaXN0Vmlldyh7IG1vZGVsUXVlcnkgPSB7fSwgc2VhcmNoVmFsdWVzID0ge30sIGNiUmVzb2x2ZSA9IG51bGwsIGNiUmVqZWN0ID0gbnVsbCwgdGVtcGxhdGVDb250ZXh0ID0ge30gfSkge1xuICAgIHJldHVybiB0aGlzLl9zZW5kTGlzdFZpZXcoe1xuICAgICAgbW9kZWxRdWVyeTogT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5tb2RlbFF1ZXJ5LCBtb2RlbFF1ZXJ5LCB7ICdfX3NlYXJjaF92YWx1ZXMnOiBzZWFyY2hWYWx1ZXMgfSksXG4gICAgICBjYlJlc29sdmUsXG4gICAgICBjYlJlamVjdCxcbiAgICAgIHRlbXBsYXRlQ29udGV4dCxcbiAgICB9KTtcbiAgfVxuXG4gIHNhdmUoeyBwayA9IG51bGwsIGlkID0gbnVsbCwgZm9ybU5hbWUgPSBcImVkaXRfZm9ybVwiLCBkYXRhID0gbnVsbCB9ID0ge30pIHtcbiAgICBwayA/Pz0gaWQ7XG4gICAgY29uc3Qgbm9ybVBrID0gbm9ybWFsaXplUGsocGspO1xuICAgIHJldHVybiB0aGlzLmlzQ29ubmVjdGVkKCkudGhlbigoKSA9PiB7XG4gICAgICBsZXQgZWxlbUxpc3Q7XG4gICAgICBpZiAobm9ybVBrID4gLTEpIHtcbiAgICAgICAgY29uc3QgZWxlbSA9IHRoaXMuYnlJZChub3JtUGspO1xuICAgICAgICBpZiAoIWVsZW0pIHtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QobmV3IFNkY01vZGVsRXJyb3IoYEVsZW1lbnQgbm90IGZvdW5kIHdpdGggSUQ6ICR7bm9ybVBrfWApKTtcbiAgICAgICAgfVxuICAgICAgICBlbGVtTGlzdCA9IFtlbGVtXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVsZW1MaXN0ID0gdGhpcy52YWx1ZXNMaXN0O1xuICAgICAgfVxuICAgICAgbGV0IHBMaXN0ID0gW107XG4gICAgICBlbGVtTGlzdC5mb3JFYWNoKChlbGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IGV2ZW50X2lkID0gdXVpZHY0KCk7XG4gICAgICAgIHBMaXN0LnB1c2goXG4gICAgICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fcmVhZEZpbGVzKGVsZW0pLnRoZW4oKGZpbGVzKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IHNlbmREYXRhID0gZGF0YSA/IHsgLi4uZGF0YSB9IDogZWxlbS5zZXJpYWxpemUoKTtcbiAgICAgICAgICAgICAgc2VuZERhdGEuaWQgPSBlbGVtLmlkO1xuICAgICAgICAgICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgICAgICAgICBldmVudF90eXBlOiBcInNhdmVcIixcbiAgICAgICAgICAgICAgICAgIGV2ZW50X2lkLFxuICAgICAgICAgICAgICAgICAgYXJnczoge1xuICAgICAgICAgICAgICAgICAgICBmb3JtX25hbWU6IGZvcm1OYW1lLFxuICAgICAgICAgICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgbW9kZWxfcXVlcnk6IHRoaXMubW9kZWxRdWVyeSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YTogc2VuZERhdGEsXG4gICAgICAgICAgICAgICAgICAgIGlkOiBzZW5kRGF0YS5pZCxcbiAgICAgICAgICAgICAgICAgICAgcGs6IHNlbmREYXRhLmlkLFxuICAgICAgICAgICAgICAgICAgICBmaWxlczogZmlsZXMsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gW1xuICAgICAgICAgICAgICAgIChyZXMpID0+IHtcbiAgICAgICAgICAgICAgICAgIGxldCBkYXRhID1cbiAgICAgICAgICAgICAgICAgICAgdHlwZW9mIHJlcy5kYXRhLmluc3RhbmNlID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgICAgICAgPyBKU09OLnBhcnNlKHJlcy5kYXRhLmluc3RhbmNlKVxuICAgICAgICAgICAgICAgICAgICAgIDogcmVzLmRhdGEuaW5zdGFuY2U7XG4gICAgICAgICAgICAgICAgICByZXMuZGF0YS5pbnN0YW5jZSA9IHRoaXMuX3BhcnNlU2VydmVyUmVzKGRhdGEpO1xuICAgICAgICAgICAgICAgICAgcmVzb2x2ZShyZXMpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVqZWN0LFxuICAgICAgICAgICAgICBdO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHBMaXN0KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgaW5zdGFuY2UgaW4gdGhlIERCLlxuICAgKlxuICAgKiBAcGFyYW0ge3tlbGVtPzogU2RjTW9kZWwsIGRhdGE/OiBvYmplY3R9IHwgb2JqZWN0fSBhcmdcbiAgICogICBFaXRoZXIgYW4gb3B0aW9ucyBvYmplY3QgY29udGFpbmluZyBgZWxlbWAgYW5kL29yIGBkYXRhYCxcbiAgICogICBvciBgZGF0YWAgZGlyZWN0bHkuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGNyZWF0ZSh7IGVsZW0sIGRhdGEgfSk7XG4gICAqIGNyZWF0ZSh7IGVsZW0gfSk7XG4gICAqIGNyZWF0ZShkYXRhKTtcbiAgICogQHJldHVybnMge1Byb21pc2U8dW5rbm93bj59XG4gICAqL1xuICBjcmVhdGUoYXJnID0gbnVsbCkge1xuICAgIGxldCB7IGVsZW0gPSBudWxsLCBkYXRhID0gbnVsbCB9ID0gaXNDcmVhdGVPcHRpb25zKGFyZykgPyBhcmcgOiB7IGRhdGE6IGFyZyB9O1xuICAgIGlmIChkYXRhICYmIHR5cGVvZiBkYXRhID09PSBcIm9iamVjdFwiICYmIE9iamVjdC5rZXlzKGRhdGEpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZGF0YSA9IG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgZXZlbnRfaWQgPSB1dWlkdjQoKTtcbiAgICBpZiAoIWVsZW0pIHtcbiAgICAgIGVsZW0gPSB0aGlzLm5ldyhkYXRhKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaXNDb25uZWN0ZWQoKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHRoaXMuX3JlYWRGaWxlcyhlbGVtKS50aGVuKChmaWxlcykgPT4ge1xuICAgICAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgICAgIGV2ZW50X3R5cGU6IFwiY3JlYXRlXCIsXG4gICAgICAgICAgICAgIGV2ZW50X2lkLFxuICAgICAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICAgICAgbW9kZWxfbmFtZTogdGhpcy5tb2RlbE5hbWUsXG4gICAgICAgICAgICAgICAgbW9kZWxfcXVlcnk6IHRoaXMubW9kZWxRdWVyeSxcbiAgICAgICAgICAgICAgICBkYXRhOiBkYXRhID8/IGVsZW0/LnNlcmlhbGl6ZSgpID8/IHt9LFxuICAgICAgICAgICAgICAgIGZpbGVzOiBmaWxlcyxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICB0aGlzLm9wZW5SZXF1ZXN0W2V2ZW50X2lkXSA9IFtcbiAgICAgICAgICAgIChyZXMpID0+IHtcbiAgICAgICAgICAgICAgbGV0IGRhdGEgPVxuICAgICAgICAgICAgICAgIHR5cGVvZiByZXMuZGF0YS5pbnN0YW5jZSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICAgICAgICAgICAgPyBKU09OLnBhcnNlKHJlcy5kYXRhLmluc3RhbmNlKVxuICAgICAgICAgICAgICAgICAgOiByZXMuZGF0YS5pbnN0YW5jZTtcbiAgICAgICAgICAgICAgaWYgKGVsZW0pIHtcbiAgICAgICAgICAgICAgICBlbGVtLmlkID0gZGF0YVswXT8uaWQgfHwgZGF0YVswXT8ucGs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgcmVzLmRhdGEuaW5zdGFuY2UgPSB0aGlzLl9wYXJzZVNlcnZlclJlcyhkYXRhKVswXTtcbiAgICAgICAgICAgICAgcmVzb2x2ZShyZXMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlamVjdCxcbiAgICAgICAgICBdO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZSB0aGUgd2Vic29ja2V0IGlzIG9wZW4gYW5kIGhhcyBjb21wbGV0ZWQgdGhlIHNlcnZlci1zaWRlIGNvbm5lY3RcbiAgICogaGFuZHNoYWtlIGJlZm9yZSBpc3N1aW5nIG1vZGVsIHJlcXVlc3RzLlxuICAgKlxuICAgKiBNdWx0aXBsZSBjYWxsZXJzIGNhbiBhcnJpdmUgd2hpbGUgYSBjb25uZWN0aW9uIGF0dGVtcHQgaXMgYWxyZWFkeSBpblxuICAgKiBwcm9ncmVzcy4gSW4gdGhhdCBjYXNlIHRoZXkgYXJlIHF1ZXVlZCBiZWhpbmQgdGhlIHNhbWUgc3ludGhldGljIHJlcXVlc3QgaWQuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgaXNDb25uZWN0ZWQoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGlmICh0aGlzLl9pc0Nvbm5lY3RlZCkge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAhdGhpcy5faXNDb25uZWN0aW5nUHJvY2VzcyB8fFxuICAgICAgICAhdGhpcy5vcGVuUmVxdWVzdFtDT05ORUNUSU5HX1JFUVVFU1RfSURdXG4gICAgICApIHtcbiAgICAgICAgdGhpcy5faXNDb25uZWN0aW5nUHJvY2VzcyA9IHRydWU7XG4gICAgICAgIHRoaXMub3BlblJlcXVlc3RbQ09OTkVDVElOR19SRVFVRVNUX0lEXSA9IFsoKSA9PiB7XG4gICAgICAgIH0sICgpID0+IHtcbiAgICAgICAgfV07XG4gICAgICAgIHRoaXMuX2Nvbm5lY3RUb1NlcnZlcigpLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJlc29sdmUodGhpcy5fY2hlY2tDb25uZWN0aW9uKCkpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IFtyZXNvbHZlT3JpZ2luLCByZWplY3RPcmlnaW5dID1cbiAgICAgICAgICB0aGlzLm9wZW5SZXF1ZXN0W0NPTk5FQ1RJTkdfUkVRVUVTVF9JRF07XG4gICAgICAgIHRoaXMub3BlblJlcXVlc3RbQ09OTkVDVElOR19SRVFVRVNUX0lEXSA9IFtcbiAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICByZXNvbHZlT3JpZ2luKCk7XG4gICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICByZWplY3RPcmlnaW4oKTtcbiAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF07XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2UgdGhlIHdlYnNvY2tldCBhbmQgZGlzYWJsZSBhdXRvbWF0aWMgcmVjb25uZWN0IGZvciB0aGlzIHF1ZXJ5c2V0LlxuICAgKi9cbiAgY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMuc29ja2V0KSB7XG4gICAgICB0aGlzLl9hdXRvUmVjb25uZWN0ID0gZmFsc2U7XG4gICAgICB0aGlzLnNvY2tldC5vbmNsb3NlID0gKCkgPT4ge1xuICAgICAgfTtcbiAgICAgIHRoaXMuc29ja2V0LmNsb3NlKCk7XG4gICAgICBkZWxldGUgdGhpc1tcInNvY2tldFwiXTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbHVlc0xpc3QuZm9yRWFjaCgoZWxlbSkgPT4ge1xuICAgICAgZWxlbS5fb25DbG9zZSgpXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVXBsb2FkIGF0dGFjaGVkIGBGaWxlYCB2YWx1ZXMgaW4gZml4ZWQtc2l6ZSBjaHVua3MgYmVmb3JlIHNhdmUvY3JlYXRlIGNhbGxzLlxuICAgKlxuICAgKiBAcGFyYW0ge1NkY01vZGVsfSBlbGVtXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPG9iamVjdD59XG4gICAqL1xuICBfcmVhZEZpbGVzKGVsZW0pIHtcbiAgICBsZXQgdG9Tb2x2ZSA9IFtdO1xuICAgIGxldCBmaWxlcyA9IHt9O1xuICAgIGlmICghZWxlbSkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmaWxlcyk7XG4gICAgfVxuICAgIE9iamVjdC5rZXlzKGVsZW0uY29uc3RydWN0b3IuZmllbGRzKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gZWxlbVtrZXldO1xuICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRmlsZSkge1xuICAgICAgICB0b1NvbHZlLnB1c2goXG4gICAgICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZXZlbnRfaWQgPSB1dWlkdjQoKTtcbiAgICAgICAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gW3Jlc29sdmUsIHJlamVjdF07XG5cbiAgICAgICAgICAgIHZhbHVlLmFycmF5QnVmZmVyKCkudGhlbigoYnVmZmVyKSA9PiB7XG4gICAgICAgICAgICAgIGxldCByZXN1bHQgPSBuZXcgVWludDhBcnJheShidWZmZXIpO1xuICAgICAgICAgICAgICBsZXQgbnVtYmVyT2ZDaHVua3MgPSBNYXRoLmNlaWwocmVzdWx0Lmxlbmd0aCAvIE1BWF9GSUxFX1VQTE9BRCk7XG4gICAgICAgICAgICAgIGZpbGVzW2tleV0gPSB7XG4gICAgICAgICAgICAgICAgaWQ6IGV2ZW50X2lkLFxuICAgICAgICAgICAgICAgIGZpbGVfbmFtZTogdmFsdWUubmFtZSxcbiAgICAgICAgICAgICAgICBmaWVsZF9uYW1lOiBrZXksXG4gICAgICAgICAgICAgICAgY29udGVudF9sZW5ndGg6IHZhbHVlLnNpemUsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZDaHVua3M7ICsraSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rID0gQXJyYXkuZnJvbShyZXN1bHQuc2xpY2UoXG4gICAgICAgICAgICAgICAgICBNQVhfRklMRV9VUExPQUQgKiBpLFxuICAgICAgICAgICAgICAgICAgTUFYX0ZJTEVfVVBMT0FEICogKGkgKyAxKSxcbiAgICAgICAgICAgICAgICApKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgICBldmVudDogXCJtb2RlbFwiLFxuICAgICAgICAgICAgICAgICAgICBldmVudF90eXBlOiBcInVwbG9hZFwiLFxuICAgICAgICAgICAgICAgICAgICBldmVudF9pZCxcbiAgICAgICAgICAgICAgICAgICAgYXJnczoge1xuICAgICAgICAgICAgICAgICAgICAgIGNodW5rLFxuICAgICAgICAgICAgICAgICAgICAgIGlkeDogaSxcbiAgICAgICAgICAgICAgICAgICAgICBudW1iZXJfb2ZfY2h1bmtzOiBudW1iZXJPZkNodW5rcyxcbiAgICAgICAgICAgICAgICAgICAgICBmaWxlX25hbWU6IHZhbHVlLm5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgZmllbGRfbmFtZToga2V5LFxuICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRfbGVuZ3RoOiB2YWx1ZS5zaXplLFxuICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRfdHlwZTogdmFsdWUudHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBtb2RlbF9xdWVyeTogdGhpcy5tb2RlbFF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgICAgICB0aGlzLl9jbG9zZU9wZW5SZXF1ZXN0KGV2ZW50X2lkKTtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBQcm9taXNlLmFsbCh0b1NvbHZlKS50aGVuKCgpID0+IHtcbiAgICAgIHJldHVybiBmaWxlcztcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSb3V0ZSB3ZWJzb2NrZXQgcmVzcG9uc2VzIHRvIHRoZSBtYXRjaGluZyBwZW5kaW5nIHJlcXVlc3QgYW5kIHVwZGF0ZSBsb2NhbFxuICAgKiBzdGF0ZSB3aGVuIHRoZSBzZXJ2ZXIgc2VuZHMgbW9kZWwgcGF5bG9hZHMuXG4gICAqXG4gICAqIEBwYXJhbSB7TWVzc2FnZUV2ZW50fSBlXG4gICAqL1xuICBhc3luYyBfb25NZXNzYWdlKGUpIHtcbiAgICBsZXQgZGF0YSA9IEpTT04ucGFyc2UoZS5kYXRhKTtcbiAgICBpZiAoZGF0YS5pc19lcnJvcikge1xuICAgICAgaWYgKE9iamVjdC5oYXNPd24odGhpcy5vcGVuUmVxdWVzdCwgZGF0YS5ldmVudF9pZCkpIHtcbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtkYXRhLmV2ZW50X2lkXVsxXShuZXcgU2RjTW9kZWxFcnJvcihkYXRhKSk7XG4gICAgICAgIHRoaXMuX2Nsb3NlT3BlblJlcXVlc3QoZGF0YS5ldmVudF9pZCk7XG4gICAgICB9XG4gICAgICBpZiAoZGF0YS5tc2cgfHwgZGF0YS5oZWFkZXIpIHtcbiAgICAgICAgdHJpZ2dlcihcInB1c2hFcnJvck1zZ1wiLCBkYXRhLmhlYWRlciB8fCBcIlwiLCBkYXRhLm1zZyB8fCBcIlwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGRhdGEudHlwZSA9PT0gXCJjb25uZWN0XCIpIHtcbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtDT05ORUNUSU5HX1JFUVVFU1RfSURdWzFdKG5ldyBTZGNNb2RlbEVycm9yKGRhdGEpKTtcbiAgICAgICAgdGhpcy5fY2xvc2VPcGVuUmVxdWVzdChDT05ORUNUSU5HX1JFUVVFU1RfSUQpO1xuICAgICAgICB0aGlzLl9hdXRvUmVjb25uZWN0ID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc29ja2V0LmNsb3NlKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChkYXRhLm1zZyB8fCBkYXRhLmhlYWRlcikge1xuICAgICAgICB0cmlnZ2VyKFwicHVzaE1zZ1wiLCBkYXRhLmhlYWRlciB8fCBcIlwiLCBkYXRhLm1zZyB8fCBcIlwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGRhdGEudHlwZSA9PT0gXCJjb25uZWN0XCIpIHtcbiAgICAgICAgdGhpcy5faXNDb25uZWN0ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLl9pc0Nvbm5lY3RpbmdQcm9jZXNzID0gZmFsc2U7XG4gICAgICAgIHRoaXMub3BlblJlcXVlc3RbQ09OTkVDVElOR19SRVFVRVNUX0lEXVswXShkYXRhKTtcbiAgICAgICAgdGhpcy5fY2xvc2VPcGVuUmVxdWVzdChDT05ORUNUSU5HX1JFUVVFU1RfSUQpO1xuICAgICAgfSBlbHNlIGlmIChbXCJsb2FkXCIsIFwibGlzdF92aWV3XCIsIFwibmFtZWRfdmlld1wiLCBcImRldGFpbF92aWV3XCJdLmluY2x1ZGVzKGRhdGEudHlwZSkpIHtcbiAgICAgICAgY29uc3QganNvblJlcyA9IEpTT04ucGFyc2UoZGF0YS5hcmdzLmRhdGEpO1xuICAgICAgICBkYXRhLmFyZ3MuZGF0YSA9IGF3YWl0IHRoaXMuX3BhcnNlU2VydmVyUmVzKGpzb25SZXMpO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09IFwib25fdXBkYXRlXCIgfHwgZGF0YS50eXBlID09PSBcIm9uX2NyZWF0ZVwiKSB7XG4gICAgICAgIGNvbnN0IGpzb25SZXMgPSBKU09OLnBhcnNlKGRhdGEuYXJncy5kYXRhKTtcblxuICAgICAgICBsZXQgb2JqID0gYXdhaXQgdGhpcy5fcGFyc2VTZXJ2ZXJSZXMoanNvblJlcyk7XG4gICAgICAgIGxldCBjYjtcblxuICAgICAgICBpZiAoZGF0YS50eXBlID09PSBcIm9uX2NyZWF0ZVwiKSB7XG4gICAgICAgICAgY2IgPSB0aGlzLm9uQ3JlYXRlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNiID0gdGhpcy5vblVwZGF0ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNiKG9iaik7XG4gICAgICAgIGRhdGEuYXJncy5kYXRhID0gb2JqO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLnR5cGUgPT09IFwib25fZGVsZXRlXCIpIHtcbiAgICAgICAgY29uc3QgaWRzID0gSlNPTi5wYXJzZShkYXRhLmFyZ3MuZGF0YSkubWFwKCh4KSA9PiBub3JtYWxpemVQayh4LmlkID8/IHgucGspKTtcbiAgICAgICAgY29uc3QgcmVtb3ZlZCA9IHRoaXMuX3JlbW92ZUlkcyhpZHMpO1xuICAgICAgICAodGhpcy5vbkRlbGV0ZSA/PyB0aGlzLm9uVXBkYXRlKShyZW1vdmVkKTtcbiAgICAgICAgZGF0YS5hcmdzLmRhdGEgPSByZW1vdmVkO1xuICAgICAgfVxuXG4gICAgICBsZXQgaW5zdGFuY2UgPSBkYXRhLmRhdGE/Lmluc3RhbmNlO1xuICAgICAgaWYgKGluc3RhbmNlKSB7XG4gICAgICAgIGRhdGEuZGF0YS5pbnN0YW5jZSA9IEpTT04ucGFyc2UoZGF0YS5kYXRhLmluc3RhbmNlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKE9iamVjdC5oYXNPd24odGhpcy5vcGVuUmVxdWVzdCwgZGF0YS5ldmVudF9pZCkpIHtcbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtkYXRhLmV2ZW50X2lkXVswXShkYXRhKTtcbiAgICAgICAgdGhpcy5fY2xvc2VPcGVuUmVxdWVzdChkYXRhLmV2ZW50X2lkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogV2FpdCB1bnRpbCBhbGwgaW4tZmxpZ2h0IHdlYnNvY2tldCByZXF1ZXN0cyBmb3IgdGhpcyBxdWVyeXNldCBhcmUgcmVzb2x2ZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgbm9PcGVuUmVxdWVzdHMoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICBpZiAoT2JqZWN0LmtleXModGhpcy5vcGVuUmVxdWVzdCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiByZXNvbHZlKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX29uTm9PcGVuUmVxdWVzdHMucHVzaChyZXNvbHZlKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgYSBjb21wbGV0ZWQgcmVxdWVzdCBhbmQgd2FrZSBhbnkgYG5vT3BlblJlcXVlc3RzKClgIHdhaXRlcnMgd2hlbiB0aGVcbiAgICogcmVxdWVzdCBtYXAgYmVjb21lcyBlbXB0eS5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50SWRcbiAgICovXG4gIF9jbG9zZU9wZW5SZXF1ZXN0KGV2ZW50SWQpIHtcbiAgICBkZWxldGUgdGhpcy5vcGVuUmVxdWVzdFtldmVudElkXTtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5vcGVuUmVxdWVzdCkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLl9vbk5vT3BlblJlcXVlc3RzLmZvckVhY2goKHgpID0+IHgoKSk7XG4gICAgICB0aGlzLl9vbk5vT3BlblJlcXVlc3RzID0gW107XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVzdGFibGlzaCB0aGUgcmF3IHdlYnNvY2tldCBjb25uZWN0aW9uIGZvciB0aGlzIHF1ZXJ5c2V0LlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAgICovXG4gIF9jb25uZWN0VG9TZXJ2ZXIoKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICBjb25zdCBtb2RlbElkZW50aWZpZXIgPVxuICAgICAgICBgJHt0aGlzLm1vZGVsTmFtZX1gICsgKHRoaXMubW9kZWxJZCA+IDAgPyBgLyR7dGhpcy5tb2RlbElkfWAgOiBcIlwiKTtcbiAgICAgIGlmICh3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgPT09IFwiaHR0cHM6XCIpIHtcbiAgICAgICAgdGhpcy5zb2NrZXQgPSBuZXcgV2ViU29ja2V0KFxuICAgICAgICAgIGB3c3M6Ly8ke3dpbmRvdy5sb2NhdGlvbi5ob3N0fS9zZGNfd3MvbW9kZWwvJHttb2RlbElkZW50aWZpZXJ9YCxcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc29ja2V0ID0gbmV3IFdlYlNvY2tldChcbiAgICAgICAgICBgd3M6Ly8ke3dpbmRvdy5sb2NhdGlvbi5ob3N0fS9zZGNfd3MvbW9kZWwvJHttb2RlbElkZW50aWZpZXJ9YCxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zb2NrZXQub25tZXNzYWdlID0gdGhpcy5fb25NZXNzYWdlLmJpbmQodGhpcyk7XG5cbiAgICAgIHRoaXMuc29ja2V0Lm9uY2xvc2UgPSAoZSkgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgIGBTREMgTW9kZWwgKCR7dGhpcy5tb2RlbE5hbWV9LCAke3RoaXMubW9kZWxJZH0pIFNvY2tldCBjbG9zZWQgdW5leHBlY3RlZGx5YCxcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5faXNDb25uZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiBPYmplY3QudmFsdWVzKHRoaXMub3BlblJlcXVlc3QpKSB7XG4gICAgICAgICAgdmFsdWVbMV0oZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdCA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2lzQ29ubmVjdGluZ1Byb2Nlc3MgPSBmYWxzZTtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuX2F1dG9SZWNvbm5lY3QgJiYgIXRoaXMuX2lzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgICAvLyBpc0Nvbm5lY3RlZCgpIG9wZW5zIHRoZSBzb2NrZXQgYW5kIHNlbmRzIHRoZSBjb25uZWN0IGhhbmRzaGFrZSwgc29cbiAgICAgICAgICAgIC8vIGxpdmUgdXBkYXRlcyB3b3JrIGFnYWluIGFuZCBsYXRlciByZXF1ZXN0cyByZXVzZSB0aGlzIGNvbm5lY3Rpb24uXG4gICAgICAgICAgICB0aGlzLmlzQ29ubmVjdGVkKCkuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LCAxMDAwKTtcbiAgICAgIH07XG5cbiAgICAgIHRoaXMuc29ja2V0Lm9uZXJyb3IgPSAoZXJyKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoYE1vZGVsIFNvY2tldCBlbmNvdW50ZXJlZCBlcnJvcjogJHtlcnJ9IENsb3Npbmcgc29ja2V0YCk7XG4gICAgICAgIGlmICh0aGlzLl9pc0Nvbm5lY3RlZCkge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnNvY2tldC5jbG9zZSgpO1xuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICAgIHRoaXMuc29ja2V0Lm9ub3BlbiA9ICgpID0+IHtcbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIHRoZSBhcHBsaWNhdGlvbi1sZXZlbCBjb25uZWN0IGhhbmRzaGFrZSBvbmNlIHRoZSB3ZWJzb2NrZXQgb3BlbnMuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPCo+fVxuICAgKi9cbiAgX2NoZWNrQ29ubmVjdGlvbigpIHtcbiAgICBjb25zdCBldmVudF9pZCA9IHV1aWR2NCgpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgZXZlbnQ6IFwibW9kZWxcIixcbiAgICAgICAgICBldmVudF90eXBlOiBcImNvbm5lY3RcIixcbiAgICAgICAgICBldmVudF9pZCxcbiAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgIG1vZGVsX3F1ZXJ5OiB0aGlzLm1vZGVsUXVlcnksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICApO1xuXG4gICAgICB0aGlzLm9wZW5SZXF1ZXN0W2V2ZW50X2lkXSA9IFtyZXNvbHZlLCByZWplY3RdO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgdGhlIGJhY2tlbmQgbW9kZWwgcGF5bG9hZCBpbnRvIGxvY2FsbHkgdHJhY2tlZCBtb2RlbCBvYmplY3RzLlxuICAgKlxuICAgKiBAcGFyYW0ge0FycmF5PG9iamVjdD59IHJlc3VsdHNcbiAgICovXG4gIF9wYXJzZVNlcnZlclJlcyhyZXN1bHRzKSB7XG4gICAgY29uc3QgbmV3TW9kZWxzID0gW11cbiAgICBmb3IgKGNvbnN0IHggb2YgcmVzdWx0cykge1xuICAgICAgY29uc3QgTW9kZWxDbGFzcyA9IGdldE1vZGVsKHRoaXMubW9kZWxOYW1lKTtcbiAgICAgIGlmICghTW9kZWxDbGFzcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5tb2RlbE5hbWV9IGlzIG5vIFNkY01vZGVsLiBteWJlIHRoZSBtb2RlbHMgYXIgbm90IGltcG9ydGFkLmApO1xuICAgICAgfVxuICAgICAgY29uc3QgbmV3TW9kZWwgPSBuZXcgTW9kZWxDbGFzcyh7ICdpZCc6IHguaWQgPz8geC5waywgLi4ueC5maWVsZHMgfSk7XG4gICAgICBjb25zdCBjdXJyZW50TW9kZWwgPSB0aGlzLmJ5SWQobmV3TW9kZWwuaWQpO1xuICAgICAgaWYgKGN1cnJlbnRNb2RlbCkge1xuICAgICAgICBjdXJyZW50TW9kZWwuc2V0VmFsdWVzKG5ld01vZGVsKTtcbiAgICAgICAgbmV3TW9kZWxzLnB1c2goY3VycmVudE1vZGVsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMudmFsdWVzTGlzdC5wdXNoKG5ld01vZGVsKTtcbiAgICAgICAgbmV3TW9kZWwuX3NldFF1ZXJ5U2V0KHRoaXMsIHRydWUpO1xuICAgICAgICBuZXdNb2RlbHMucHVzaChuZXdNb2RlbCk7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMudmFsdWVzTGlzdC5zb3J0KChhLCBiKSA9PiBhLl9pZCAtIGIuX2lkKTtcbiAgICByZXR1cm4gbmV3TW9kZWxzO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNkY01vZGVsIHtcbiAgc3RhdGljIGZpZWxkcyA9IHt9O1xuXG4gIC8qKlxuICAgKiBCYXNlIG1vZGVsIHdyYXBwZXIgdXNlZCBieSBTREMgbW9kZWwgcmVnaXN0cmF0aW9ucy5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IG1vZGVsTmFtZVxuICAgKi9cbiAgY29uc3RydWN0b3IobW9kZWxOYW1lKSB7XG4gICAgdGhpcy5faWQgPSBudWxsO1xuICAgIHRoaXMuX2Zvcm1zID0gW107XG4gICAgdGhpcy5sb2FkZWQgPSBmYWxzZTtcbiAgICB0aGlzLmZvcm1JZCA9IHV1aWR2NCgpO1xuICAgIHRoaXMubW9kZWxOYW1lID0gbW9kZWxOYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqIEBwYXJhbSB7b2JqZWN0P30gbW9kZWxRdWVyeVNldFxuICAgKiBAcGFyYW0ge0Fic3RyYWN0U0RDfSBwYXJlbnRcbiAgICogQHJldHVybnMge1NkY1F1ZXJ5U2V0fVxuICAgKi9cbiAgc3RhdGljIHF1ZXJ5U2V0KG1vZGVsUXVlcnlTZXQgPSBudWxsLCBwYXJlbnQgPSBudWxsKSB7XG4gICAgY29uc3QgeyBtb2RlbE5hbWUgfSA9IG5ldyB0aGlzKHt9KTtcbiAgICBpZiAoIXBhcmVudCkge1xuICAgICAgcmV0dXJuIG5ldyBTZGNRdWVyeVNldChtb2RlbE5hbWUsIG1vZGVsUXVlcnlTZXQpO1xuICAgIH1cblxuICAgIHJldHVybiBwYXJlbnQucXVlcnlTZXQobW9kZWxOYW1lLCBtb2RlbFF1ZXJ5U2V0KTtcbiAgfVxuXG4gIGFkZEZvcm0oJGZvcm0pIHtcbiAgICAvLyBSZW1vdmUgb2xkIGxpc3RlbmVycyBpZiBmb3JtIGFscmVhZHkgc2V0XG4gICAgY29uc3Qgb25DaGFuZ2UgPSB0aGlzLl9vbkNoYW5nZS5iaW5kKHRoaXMpO1xuXG4gICAgdGhpcy5fZm9ybXMucHVzaCgkZm9ybSk7XG5cbiAgICBpZiAoJGZvcm0pIHtcbiAgICAgIC8vIEF0dGFjaCBkZWxlZ2F0ZWQgZXZlbnQgaGFuZGxlciB0byBhbGwgaW5wdXRzXG4gICAgICAkZm9ybS5vbihcbiAgICAgICAgXCJpbnB1dC5mb3JtV2F0Y2hlciBjaGFuZ2UuZm9ybVdhdGNoZXJcIixcbiAgICAgICAgXCJpbnB1dCwgc2VsZWN0LCB0ZXh0YXJlYVwiLFxuICAgICAgICBvbkNoYW5nZVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBfb25DaGFuZ2UoZXZlbnQpIHtcbiAgICBjb25zdCB7IG5hbWUgfSA9IGV2ZW50LnRhcmdldDtcbiAgICBpZiAodGhpcy5jb25zdHJ1Y3Rvci5maWVsZHNbbmFtZV0pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXNbYHNldCR7bmFtZX1gXShnZXRWYWx1ZUZyb21GaWVsZChldmVudC50YXJnZXQpKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBJbnZhbGlkIGlucHV0IChlLmcuIGFuIGVtcHR5IHJlcXVpcmVkIGZpZWxkKSBpcyBrZXB0IGluIHRoZSBmb3JtIGFuZFxuICAgICAgICAvLyB2YWxpZGF0ZWQgYnkgdGhlIHNlcnZlciBvbiBzdWJtaXQuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIC8vIFNob3cgdGhlIG5ldyB2YWx1ZSBpbiB0aGUgb3RoZXIgZm9ybXMgb2YgdGhpcyBtb2RlbCwgbm90IGluIHRoZSBpbnB1dCBiZWluZyBlZGl0ZWQuXG4gICAgICB0aGlzLl91cGRhdGVGb3JtKG5hbWUsIGV2ZW50LnRhcmdldCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZUZvcm0oZmllbGROYW1lLCBza2lwRWxlbWVudCA9IG51bGwpIHtcbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICB0aGlzLl9mb3Jtcy5mb3JFYWNoKCgkZm9ybSkgPT4ge1xuICAgICAgJGZvcm0uZmluZChgW25hbWU9XCIke2ZpZWxkTmFtZX1cIl1gKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMgIT09IHNraXBFbGVtZW50KSB7XG4gICAgICAgICAgc2V0VmFsdWVJbkZpZWxkKHRoaXMsIHNlbGZbZmllbGROYW1lXSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgc2V0VmFsdWVzKGRhdGEgPSB7fSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcInNldFZhbHVlcygpIG11c3QgYmUgaW1wbGVtZW50ZWQgYnkgc3ViY2xhc3NcIik7XG4gIH1cblxuICAvKipcbiAgICogQXR0YWNoIHRoZSBxdWVyeXNldCB0aGF0IG93bnMgdGhpcyBtb2RlbCBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHtTZGNRdWVyeVNldH0gcXVlcnlTZXRcbiAgICogQHBhcmFtIHtib29sZWFufSBpc0xvYWRlZFxuICAgKi9cbiAgX3NldFF1ZXJ5U2V0KHF1ZXJ5U2V0LCBpc0xvYWRlZCkge1xuICAgIHRoaXMuX3F1ZXJ5U2V0ID0gbmV3IFdlYWtSZWYocXVlcnlTZXQpO1xuICAgIHRoaXMubG9hZGVkID0gaXNMb2FkZWQ7XG4gIH1cblxuICBnZXQgcXVlcnlTZXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3F1ZXJ5U2V0LmRlcmVmKCk7XG4gIH1cblxuICBzYXZlKHsgZm9ybU5hbWUgPSBcImVkaXRfZm9ybVwiLCBkYXRhID0gbnVsbCB9ID0ge30pIHtcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlTZXQuZGVyZWYoKS5zYXZlKHsgcGs6IHRoaXMuaWQsIGZvcm1OYW1lLCBkYXRhIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSB0aGlzIGluc3RhbmNlIGluIHRoZSBEQi5cbiAgICpcbiAgICogQHBhcmFtIHt7ZGF0YT86IG9iamVjdH0gfCBvYmplY3QgfCBudWxsfSB2YWx1ZXNcbiAgICogICBFaXRoZXIgYHsgZGF0YSB9YCBvciBgZGF0YWAgZGlyZWN0bHkuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHVua25vd24+fVxuICAgKi9cbiAgY3JlYXRlKHZhbHVlcyA9IG51bGwpIHtcbiAgICBjb25zdCBkYXRhID0gaXNDcmVhdGVPcHRpb25zKHZhbHVlcykgPyAodmFsdWVzLmRhdGEgPz8gbnVsbCkgOiB2YWx1ZXM7XG4gICAgcmV0dXJuIHRoaXMuX3F1ZXJ5U2V0LmRlcmVmKCkuY3JlYXRlKHsgZWxlbTogdGhpcywgZGF0YSB9KTtcbiAgfVxuXG4gIGRlbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlTZXQuZGVyZWYoKS5kZWxldGUoeyBlbGVtOiB0aGlzIH0pO1xuICB9XG5cbiAgbG9hZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlTZXQuZGVyZWYoKS51cGRhdGUoeyBpdGVtOiB0aGlzIH0pO1xuICB9XG5cbiAgdXBkYXRlKCkge1xuICAgIHJldHVybiB0aGlzLmxvYWQoKTtcbiAgfVxuXG4gIGdldCBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5faWQ7XG4gIH1cblxuICBzZXQgaWQoZGF0YSkge1xuICAgIHRoaXMuX2lkID0gZGF0YTtcbiAgfVxuXG4gIHNldCBwayhkYXRhKSB7XG4gICAgdGhpcy5pZCA9IGRhdGE7XG4gIH1cblxuICBnZXQgcGsoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lkO1xuICB9XG5cbiAgY2xvc2UoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3F1ZXJ5U2V0LmRlcmVmKCkuY2xvc2UoKTtcbiAgfVxuXG4gIF9vbkNsb3NlKCkge1xuICAgIE9iamVjdC5rZXlzKHRoaXMuY29uc3RydWN0b3IuZmllbGRzKVxuICAgICAgLmZpbHRlcigoeCkgPT4gdGhpc1tgXyR7eH1gXSBpbnN0YW5jZW9mIFNkY1F1ZXJ5U2V0KVxuICAgICAgLmZvckVhY2goKHgpID0+IHRoaXNbYF8ke3h9YF0uY2xvc2UoKSk7XG4gIH1cblxuICAvKipcbiAgICogUmVxdWVzdCB0aGUgc2VydmVyLXJlbmRlcmVkIGRldGFpbCB2aWV3IGZvciB0aGlzIG1vZGVsIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIGRldGFpbFZpZXcoeyBjYlJlc29sdmUgPSBudWxsLCBjYlJlamVjdCA9IG51bGwsIHRlbXBsYXRlQ29udGV4dCA9IHt9IH0pIHtcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlTZXQuZGVyZWYoKS5kZXRhaWxWaWV3KHsgcGs6IHRoaXMuaWQsIGNiUmVzb2x2ZSwgY2JSZWplY3QsIHRlbXBsYXRlQ29udGV4dCB9KTtcbiAgfVxuXG4gIHNlcmlhbGl6ZSgpIHtcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXModGhpcy5jb25zdHJ1Y3Rvci5maWVsZHMpLnJlZHVjZSgoYWNjLCBba2V5LCB2YWxdKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHRoaXNba2V5XTtcbiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFNkY1F1ZXJ5U2V0KSB7XG4gICAgICAgIGlmICh2YWwubWFueV90b19tYW55IHx8IHZhbC5vbmVfdG9fbWFueSkge1xuICAgICAgICAgIGFjY1trZXldID0gdmFsdWUuZ2V0SWRzKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgYWxsSWRzID0gdmFsdWUuZ2V0SWRzKCk7XG4gICAgICAgICAgaWYgKGFsbElkcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBhY2Nba2V5XSA9IGFsbElkc1swXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWNjW2tleV0gPSBudWxsO1xuICAgICAgICAgIH1cblxuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHZhbC5pc19yZWxhdGlvbiAmJiB2YWx1ZSBpbnN0YW5jZW9mIFNkY01vZGVsKSB7XG4gICAgICAgIGFjY1trZXldID0gdmFsdWUuaWQgPz8gbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgIC8vIERqYW5nbydzIERhdGVGaWVsZCBkb2VzIG5vdCBhY2NlcHQgYSBmdWxsIElTTyBkYXRldGltZS5cbiAgICAgICAgYWNjW2tleV0gPSB2YWwudHlwZSA9PT0gXCJEYXRlRmllbGRcIiA/IGZvcm1hdERhdGUodmFsdWUpIDogdmFsdWUudG9JU09TdHJpbmcoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFjY1trZXldID0gdmFsdWU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhY2NcbiAgICB9LCB7fSk7XG4gIH1cblxuICB0b0pzb24oKSB7XG4gICAgY29uc3QgcmVzID0ge31cbiAgICBmb3IgKGxldCBrZXkgaW4gdGhpcy5jb25zdHJ1Y3Rvci5maWVsZHMpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gdGhpc1trZXldO1xuXG4gICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBGaWxlKSB7XG4gICAgICAgIHJlc1trZXldID0gdmFsdWUubmFtZTtcbiAgICAgIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBTZGNNb2RlbCkge1xuICAgICAgICByZXNba2V5XSA9IHZhbHVlLmlkO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFNkY1F1ZXJ5U2V0KSB7XG4gICAgICAgIHJlc1trZXldID0gdmFsdWUuZ2V0SWRzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNba2V5XSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXM7XG4gIH1cblxuICAvKipcbiAgICogQmFja3dhcmRzLWNvbXBhdGlibGUgYWxpYXMgZm9yIHN5bmNpbmcgdmFsdWVzIGZyb20gYSBmb3JtIGludG8gdGhlIG1vZGVsLlxuICAgKlxuICAgKiBAcGFyYW0geyp9ICRmb3Jtc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHN5bmNGb3JtVG9Nb2RlbCgkZm9ybXMpIHtcbiAgICByZXR1cm4gdGhpcy5zeW5jRm9ybSgkZm9ybXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgdGhlIGZvcm0gY29sbGVjdGlvbiBhc3NvY2lhdGVkIHdpdGggdGhpcyBtb2RlbCBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHsqfSAkZm9ybXNcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICBfcmVzb2x2ZUZvcm1zKCRmb3Jtcykge1xuICAgIGlmICghJGZvcm1zIHx8ICEkZm9ybXMuaGFzQ2xhc3ModGhpcy5mb3JtSWQpKSB7XG4gICAgICByZXR1cm4gJChgLiR7dGhpcy5mb3JtSWR9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuICRmb3JtcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3B5IHRoZSBjdXJyZW50IG1vZGVsIHN0YXRlIGludG8gbWF0Y2hpbmcgZm9ybSBmaWVsZHMuXG4gICAqXG4gICAqIEBwYXJhbSB7Kn0gJGZvcm1zXG4gICAqL1xuICBzeW5jTW9kZWxUb0Zvcm0oJGZvcm1zKSB7XG4gICAgJGZvcm1zID0gdGhpcy5fcmVzb2x2ZUZvcm1zKCRmb3Jtcyk7XG5cbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCB7IGZpZWxkcyB9ID0gdGhpcy5jb25zdHJ1Y3RvcjtcbiAgICAkZm9ybXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwayA9IG5vcm1hbGl6ZVBrKCQodGhpcykuZGF0YShcIm1vZGVsX3BrXCIpKTtcbiAgICAgIC8vIENyZWF0ZSBmb3JtcyBjYXJyeSBtb2RlbF9wayAtMSB3aGlsZSB0aGUgbmV3IG1vZGVsJ3MgaWQgaXMgc3RpbGwgbnVsbC5cbiAgICAgIGlmIChub3JtYWxpemVQayhzZWxmLmlkKSAhPT0gcGspIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBmb3JtSXRlbSBvZiB0aGlzLmVsZW1lbnRzKSB7XG4gICAgICAgIGxldCB7IG5hbWUgfSA9IGZvcm1JdGVtO1xuICAgICAgICBpZiAobmFtZSAmJiBuYW1lICE9PSBcIlwiICYmICEhZmllbGRzW25hbWVdKSB7XG4gICAgICAgICAgc2V0VmFsdWVJbkZpZWxkKGZvcm1JdGVtLCBzZWxmW25hbWVdKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29weSBtYXRjaGluZyBmb3JtIHZhbHVlcyBiYWNrIG9udG8gdGhlIGN1cnJlbnQgbW9kZWwgaW5zdGFuY2UuXG4gICAqXG4gICAqIEhpZGRlbiBpbnB1dHMgYXJlIHBhcnNlZCB0byB0aGVpciBvcmlnaW5hbCBwcmltaXRpdmUgdHlwZSB3aGVuIHBvc3NpYmxlLlxuICAgKlxuICAgKiBAcGFyYW0geyp9ICRmb3Jtc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHN5bmNGb3JtKCRmb3Jtcykge1xuICAgICRmb3JtcyA9IHRoaXMuX3Jlc29sdmVGb3JtcygkZm9ybXMpO1xuXG4gICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgY29uc3QgeyBmaWVsZHMgfSA9IHRoaXMuY29uc3RydWN0b3I7XG4gICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fVxuXG4gICAgZnVuY3Rpb24gc2V0VmFsdWVJbkZvcm0obmFtZSwgdmFsdWUpIHtcbiAgICAgIGlmIChmaWVsZHNbbmFtZV0pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzZWxmW25hbWVdID0gdmFsdWU7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIEludmFsaWQgdmFsdWVzIGFyZSBzdGlsbCBzZW50IHRvIHRoZSBzZXJ2ZXIsIHdoaWNoIHJldHVybnMgdGhlIGZvcm1cbiAgICAgICAgICAvLyBlcnJvcnM7IHRoZSBtb2RlbCBrZWVwcyBpdHMgbGFzdCB2YWxpZCB2YWx1ZS5cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuVmFsdWVbbmFtZV0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICAkZm9ybXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBjb25zdCBwayA9IG5vcm1hbGl6ZVBrKCQodGhpcykuZGF0YShcIm1vZGVsX3BrXCIpKTtcbiAgICAgIGlmIChzZWxmLmlkICE9PSBwayAmJiAoc2VsZi5pZCAhPT0gbnVsbCB8fCBwayAhPT0gLTEpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgZm9ybUl0ZW0gb2YgdGhpcy5lbGVtZW50cykge1xuICAgICAgICBzZXRWYWx1ZUluRm9ybShmb3JtSXRlbS5uYW1lLCBnZXRWYWx1ZUZyb21GaWVsZChmb3JtSXRlbSkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gc2VsZjtcbiAgICB9KTtcblxuICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgdGhlIGNvcnJlY3Qgc2VydmVyLXNpZGUgZm9ybSBmb3IgdGhpcyBtb2RlbCBzdGF0ZS5cbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICBmb3JtKHsgY2JSZXNvbHZlID0gbnVsbCwgY2JSZWplY3QgPSBudWxsIH0gPSB7fSkge1xuICAgIGlmICh0aGlzLmlkID09PSBudWxsIHx8IHRoaXMuaWQgPT09IC0xKSB7XG4gICAgICByZXR1cm4gdGhpcy5fY3JlYXRlRm9ybSh7IGNiUmVqZWN0LCBjYlJlc29sdmUgfSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9lZGl0Rm9ybSh7IGNiUmVqZWN0LCBjYlJlc29sdmUgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIHRoZSBjcmVhdGUgZm9ybSBmb3IgYSBuZXcgbW9kZWwgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgX2NyZWF0ZUZvcm0oeyBjYlJlc29sdmUgPSBudWxsLCBjYlJlamVjdCA9IG51bGwgfSkge1xuICAgIGxldCAkZGl2Rm9ybSA9ICQoXCI8ZGl2PlwiKTtcbiAgICB0aGlzLl9xdWVyeVNldC5kZXJlZigpLmdldEZvcm0oe1xuICAgICAgbW9kZWxPYmo6IHRoaXMsXG4gICAgICBldmVudFR5cGU6IFwiY3JlYXRlX2Zvcm1cIixcbiAgICAgIGZvcm1OYW1lOiBudWxsLFxuICAgICAgJGRpdkZvcm0sXG4gICAgICBjYlJlc29sdmUsXG4gICAgICBjYlJlamVjdCxcbiAgICAgIGZvcm1JZDogdGhpcy5mb3JtSWQsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gJGRpdkZvcm07XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIHRoZSBlZGl0IGZvcm0gZm9yIGFuIGV4aXN0aW5nIG1vZGVsIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIF9lZGl0Rm9ybSh7IGNiUmVzb2x2ZSA9IG51bGwsIGNiUmVqZWN0ID0gbnVsbCB9KSB7XG4gICAgbGV0ICRkaXZGb3JtID0gJChcIjxkaXY+XCIpO1xuXG4gICAgdGhpcy5fcXVlcnlTZXQuZGVyZWYoKS5nZXRGb3JtKHtcbiAgICAgIG1vZGVsT2JqOiB0aGlzLFxuICAgICAgZXZlbnRUeXBlOiBcImVkaXRfZm9ybVwiLFxuICAgICAgZm9ybU5hbWU6IG51bGwsXG4gICAgICAkZGl2Rm9ybSxcbiAgICAgIGNiUmVzb2x2ZSxcbiAgICAgIGNiUmVqZWN0LFxuICAgICAgZm9ybUlkOiB0aGlzLmZvcm1JZCxcbiAgICB9KTtcblxuICAgIHJldHVybiAkZGl2Rm9ybTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgYSBuYW1lZCBzZXJ2ZXItc2lkZSBmb3JtIGZvciB0aGlzIG1vZGVsLlxuICAgKlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIG5hbWVkRm9ybSh7IGZvcm1OYW1lLCBjYlJlc29sdmUgPSBudWxsLCBjYlJlamVjdCA9IG51bGwgfSkge1xuICAgIGxldCAkZGl2Rm9ybSA9ICQoJzxkaXYgIGNsYXNzPVwiY29udGFpbmVyLWZsdWlkXCI+Jyk7XG5cbiAgICB0aGlzLl9xdWVyeVNldC5kZXJlZigpLmdldEZvcm0oe1xuICAgICAgbW9kZWxPYmo6IHRoaXMsXG4gICAgICBldmVudFR5cGU6IFwibmFtZWRfZm9ybVwiLFxuICAgICAgZm9ybU5hbWUsXG4gICAgICAkZGl2Rm9ybSxcbiAgICAgIGNiUmVzb2x2ZSxcbiAgICAgIGNiUmVqZWN0LFxuICAgICAgZm9ybUlkOiB0aGlzLmZvcm1JZCxcbiAgICB9KTtcblxuICAgIHJldHVybiAkZGl2Rm9ybTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBhIGZpZWxkIHZhbHVlIHVzaW5nIHRoZSBzdXBwbGllZCBmaWVsZCBjb25maWcuXG4gICAqXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAgICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZ1xuICAgKi9cbiAgdmFsaWRhdGUodmFsdWUsIGNvbmZpZykge1xuICAgIGNvbnN0IGVyciA9IHZhbGlkYXRlRmllbGQodmFsdWUsIGNvbmZpZyk7XG4gICAgaWYgKGVycikgdGhyb3cgbmV3IEVycm9yKGVycik7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBhIHJhdyBpbnB1dCB2YWx1ZSBpbnRvIHRoZSBzaGFwZSBleHBlY3RlZCBieSB0aGUgZmllbGQgY29uZmlnLlxuICAgKlxuICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBjb25maWdcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICBwYXJzZVZhbHVlKHZhbHVlLCBjb25maWcpIHtcbiAgICBjb25zdCB7XG4gICAgICB0eXBlLFxuICAgICAgbWFueV90b19tYW55OiBtYW55VG9NYW55LFxuICAgICAgb25lX3RvX21hbnk6IG9uZVRvTWFueSxcbiAgICAgIG1hbnlfdG9fb25lOiBtYW55VG9PbmUsXG4gICAgICBvbmVfdG9fb25lOiBvbmVUb09uZSxcbiAgICB9ID0gY29uZmlnO1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgaWYgKChtYW55VG9NYW55IHx8IG9uZVRvTWFueSB8fCBtYW55VG9PbmUgfHwgb25lVG9PbmUpICYmIHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgXCJDaGFyRmllbGRcIjpcbiAgICAgIGNhc2UgXCJUZXh0RmllbGRcIjpcbiAgICAgIGNhc2UgXCJTbHVnRmllbGRcIjpcbiAgICAgIGNhc2UgXCJVVUlERmllbGRcIjpcbiAgICAgIGNhc2UgXCJFbWFpbEZpZWxkXCI6XG4gICAgICAgIHJldHVybiBgJHt2YWx1ZX1gO1xuXG4gICAgICBjYXNlIFwiSW50ZWdlckZpZWxkXCI6XG4gICAgICBjYXNlIFwiU21hbGxJbnRlZ2VyRmllbGRcIjpcbiAgICAgIGNhc2UgXCJCaWdJbnRlZ2VyRmllbGRcIjpcbiAgICAgIGNhc2UgXCJQb3NpdGl2ZUludGVnZXJGaWVsZFwiOlxuICAgICAgY2FzZSBcIlBvc2l0aXZlU21hbGxJbnRlZ2VyRmllbGRcIjpcbiAgICAgIGNhc2UgXCJQb3NpdGl2ZUJpZ0ludGVnZXJGaWVsZFwiOlxuICAgICAgY2FzZSBcIkF1dG9GaWVsZFwiOlxuICAgICAgY2FzZSBcIlNtYWxsQXV0b0ZpZWxkXCI6XG4gICAgICBjYXNlIFwiQmlnQXV0b0ZpZWxkXCI6XG4gICAgICAgIHJldHVybiBwYXJzZUludCh2YWx1ZSwgMTApO1xuXG4gICAgICBjYXNlIFwiRmxvYXRGaWVsZFwiOlxuICAgICAgY2FzZSBcIkRlY2ltYWxGaWVsZFwiOlxuICAgICAgICByZXR1cm4gcGFyc2VGbG9hdCh2YWx1ZSk7XG5cbiAgICAgIGNhc2UgXCJCb29sZWFuRmllbGRcIjpcbiAgICAgICAgcmV0dXJuICEhdmFsdWU7XG5cbiAgICAgIGNhc2UgXCJEYXRlRmllbGRcIjpcbiAgICAgIGNhc2UgXCJEYXRlVGltZUZpZWxkXCI6XG4gICAgICAgIHJldHVybiB0b0RhdGUodmFsdWUpO1xuXG4gICAgICBjYXNlIFwiVVJMRmllbGRcIjpcbiAgICAgICAgcmV0dXJuIG5ldyBVUkwodmFsdWUpO1xuXG4gICAgICBjYXNlIFwiRmlsZUZpZWxkXCI6XG4gICAgICAgIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoRmlsZUxvYWRlZC5pc1ZhbGlkKHZhbHVlKSkge1xuICAgICAgICAgIHJldHVybiBuZXcgRmlsZUxvYWRlZCh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBGaWxlTG9hZGVkKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBGaWxlTG9hZGVkKHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgRmlsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiB2YWx1ZSBpbnN0YW5jZW9mIEZpbGUpIHtcbiAgICAgICAgICAvLyBTaXplIGFuZCB0eXBlIGFyZSBjaGVja2VkIGluIHZhbGlkYXRlKCkuXG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIFwiSlNPTkZpZWxkXCI6XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG59XG5cbi8qKlxuICogVmFsaWRhdGUgYSBmaWVsZCB2YWx1ZSBhZ2FpbnN0IHRoZSBmaWVsZCBtZXRhZGF0YSByZWNlaXZlZCBmcm9tIHRoZSBiYWNrZW5kLlxuICpcbiAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAqIEBwYXJhbSB7b2JqZWN0fSBjb25maWdcbiAqIEByZXR1cm5zIHs/c3RyaW5nfVxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZUZpZWxkKHZhbHVlLCBjb25maWcpIHtcbiAgY29uc3Qge1xuICAgIHR5cGUsXG4gICAgcmVxdWlyZWQsXG4gICAgbWF4X2xlbmd0aDogbWF4TGVuZ3RoLFxuICAgIGlzX3JlbGF0aW9uOiBpc1JlbGF0aW9uLFxuICAgIG1hbnlfdG9fbWFueTogbWFueVRvTWFueSxcbiAgICBvbmVfdG9fbWFueTogb25lVG9NYW55LFxuICAgIG1hbnlfdG9fb25lOiBtYW55VG9PbmUsXG4gICAgb25lX3RvX29uZTogb25lVG9PbmUsXG4gICAgcmVsYXRlZF9tb2RlbDogcmVsYXRlZE1vZGVsLFxuICB9ID0gY29uZmlnO1xuXG4gIHZvaWQgaXNSZWxhdGlvbjtcblxuICBpZiAocmVxdWlyZWQpIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gXCJcIikge1xuICAgICAgcmV0dXJuIFwiVGhpcyBmaWVsZCBpcyByZXF1aXJlZFwiO1xuICAgIH1cbiAgfVxuXG4gIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBcIlwiKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAobWFueVRvTWFueSB8fCBvbmVUb01hbnkgfHwgbWFueVRvT25lIHx8IG9uZVRvT25lKSB7XG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBTZGNRdWVyeVNldCkgfHwgdmFsdWUubW9kZWxOYW1lICE9PSByZWxhdGVkTW9kZWwpIHtcbiAgICAgIGlmKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFsdWUgPSBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgaWYgKChtYW55VG9NYW55IHx8IG1hbnlUb09uZSkgJiYgQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUuc29tZSgoeCkgPT4gIU51bWJlci5pc05hTihwYXJzZUludCh4KSkpKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIiAmJiBOdW1iZXIuaXNOYU4ocGFyc2VJbnQodmFsdWUpKSkge1xuICAgICAgICByZXR1cm4gXCJNdXN0IGJlIG9iamVjdCBvciBJRFwiO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSBcIkNoYXJGaWVsZFwiOlxuICAgIGNhc2UgXCJUZXh0RmllbGRcIjpcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgcmV0dXJuIFwiTXVzdCBiZSBhIHN0cmluZ1wiO1xuICAgICAgfVxuICAgICAgaWYgKG1heExlbmd0aCAmJiB2YWx1ZS5sZW5ndGggPiBtYXhMZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGBNYXggbGVuZ3RoIGlzICR7bWF4TGVuZ3RofWA7XG4gICAgICB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgXCJJbnRlZ2VyRmllbGRcIjpcbiAgICBjYXNlIFwiU21hbGxJbnRlZ2VyRmllbGRcIjpcbiAgICBjYXNlIFwiQmlnSW50ZWdlckZpZWxkXCI6XG4gICAgY2FzZSBcIlBvc2l0aXZlSW50ZWdlckZpZWxkXCI6XG4gICAgY2FzZSBcIlBvc2l0aXZlU21hbGxJbnRlZ2VyRmllbGRcIjpcbiAgICBjYXNlIFwiUG9zaXRpdmVCaWdJbnRlZ2VyRmllbGRcIjpcbiAgICBjYXNlIFwiQXV0b0ZpZWxkXCI6XG4gICAgY2FzZSBcIlNtYWxsQXV0b0ZpZWxkXCI6XG4gICAgY2FzZSBcIkJpZ0F1dG9GaWVsZFwiOlxuICAgICAgaWYgKCFpc0Zpbml0ZShwYXJzZUludCh2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiBcIk11c3QgYmUgYW4gaW50ZWdlclwiO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlIFwiRmxvYXRGaWVsZFwiOlxuICAgIGNhc2UgXCJEZWNpbWFsRmllbGRcIjpcbiAgICAgIGlmICghaXNGaW5pdGUocGFyc2VGbG9hdCh2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiBcIk11c3QgYmUgYSBudW1iZXJcIjtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBcIkJvb2xlYW5GaWVsZFwiOlxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgcmV0dXJuIFwiTXVzdCBiZSBhIGJvb2xlYW5cIjtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBcIkRhdGVGaWVsZFwiOlxuICAgIGNhc2UgXCJEYXRlVGltZUZpZWxkXCI6XG4gICAgICBpZiAoaXNOYU4oRGF0ZS5wYXJzZSh2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiBcIk11c3QgYmUgYSB2YWxpZCBkYXRlXCI7XG4gICAgICB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgXCJFbWFpbEZpZWxkXCI6XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcInN0cmluZ1wiIHx8ICEvXlteXFxzQF0rQFteXFxzQF0rXFwuW15cXHNAXSskLy50ZXN0KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gXCJJbnZhbGlkIGVtYWlsXCI7XG4gICAgICB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgXCJVUkxGaWVsZFwiOlxuICAgICAgdHJ5IHtcbiAgICAgICAgbmV3IFVSTCh2YWx1ZSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuIFwiSW52YWxpZCBVUkxcIjtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBcIlVVSURGaWVsZFwiOlxuICAgICAgaWYgKCEvXlswLTlhLWZdezh9LVswLTlhLWZdezR9LVsxLTVdWzAtOWEtZl17M30tWzg5YWJdWzAtOWEtZl17M30tWzAtOWEtZl17MTJ9JC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIFwiSW52YWxpZCBVVUlEXCI7XG4gICAgICB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgXCJKU09ORmllbGRcIjpcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgcmV0dXJuIFwiTXVzdCBiZSB2YWxpZCBKU09OXCI7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJGaWxlRmllbGRcIjpcbiAgICAgIGlmICghRmlsZUxvYWRlZC5pc1ZhbGlkKHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgRmlsZSkgJiYgISh2YWx1ZSBpbnN0YW5jZW9mIEZpbGVMb2FkZWQpKSB7XG4gICAgICAgIHJldHVybiBcIk11c3QgYmUgYSB2YWxpZCBmaWxlXCI7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIEZpbGUgIT09IFwidW5kZWZpbmVkXCIgJiYgdmFsdWUgaW5zdGFuY2VvZiBGaWxlKSB7XG4gICAgICAgIGlmIChjb25maWcubWF4X3NpemUgJiYgdmFsdWUuc2l6ZSA+IGNvbmZpZy5tYXhfc2l6ZSkge1xuICAgICAgICAgIHJldHVybiBgRmlsZSB0b28gbGFyZ2UgKG1heCAke2NvbmZpZy5tYXhfc2l6ZX0gYnl0ZXMpYDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29uZmlnLmFsbG93ZWRfdHlwZXMgJiYgIWNvbmZpZy5hbGxvd2VkX3R5cGVzLmluY2x1ZGVzKHZhbHVlLnR5cGUpKSB7XG4gICAgICAgICAgcmV0dXJuIGBJbnZhbGlkIGZpbGUgdHlwZSAoJHt2YWx1ZS50eXBlfSlgO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgYnJlYWs7XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/simpleDomControl/sdc_model.js\n\n}");
87
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ SdcQuerySet: () => (/* binding */ SdcQuerySet),\n/* harmony export */ \"default\": () => (/* binding */ SdcModel)\n/* harmony export */ });\n/* harmony import */ var _sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./sdc_utils.js */ \"./src/simpleDomControl/sdc_utils.js\");\n/* harmony import */ var _sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./sdc_socket.js */ \"./src/simpleDomControl/sdc_socket.js\");\n/* harmony import */ var _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./sdc_main.js */ \"./src/simpleDomControl/sdc_main.js\");\n/* harmony import */ var _sdc_events_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./sdc_events.js */ \"./src/simpleDomControl/sdc_events.js\");\n\n\n\n\n\nconst MAX_FILE_UPLOAD = 25000;\nconst CONNECTING_REQUEST_ID = \"_connecting_process\";\n\n/**\n * Copy a model instance for another queryset. A new instance of the same class is\n * created from the serialized field values (structuredClone cannot copy the\n * WeakRef/Proxy members of a model).\n */\nconst cloneModel = (original) => {\n const copy = new original.constructor({});\n copy.setValues(original.serialize());\n return copy;\n}\n\nclass SdcModelError extends Error {\n constructor(props) {\n if (typeof props === 'string') {\n props = {\n msg: props,\n is_error: true,\n header: 'Error'\n }\n }\n super(props.msg)\n this.msg = props.msg;\n this.header = props.header;\n this.is_error = props.is_error;\n this.html = props.html;\n }\n}\n\nclass FileLoaded {\n constructor({ name, url }) {\n this.name = name;\n this.url = url;\n this.content = null;\n }\n\n async load(force = false) {\n if (force || !this.content) {\n this.content = await new Promise((resolve, reject) => {\n $.get(this.url).then(resolve).catch(\n () => {\n resolve('');\n }\n );\n });\n }\n\n return this.content;\n }\n\n async text() {\n return this.load();\n }\n\n static isValid(value) {\n return (\n value !== null &&\n typeof value === \"object\" &&\n !Array.isArray(value) &&\n !(value instanceof File) &&\n typeof value.url === \"string\" &&\n typeof value.name === \"string\"\n );\n }\n\n\n}\n\n/**\n * Normalize an incoming primary key value.\n *\n * `-1` is used throughout this module as the sentinel for \"new object / no pk\".\n *\n * @param {*} pk\n * @returns {number}\n */\nfunction normalizePk(pk) {\n const normalizedPk = parseInt(pk ?? -1, 10);\n return Number.isNaN(normalizedPk) ? -1 : normalizedPk;\n}\n\n/**\n * Decide whether an argument of `create()` is an options object\n * (`{elem, data}`) or the data itself. It is treated as options if it is\n * a non-empty plain object whose keys are only `elem` and/or `data`, and\n * `elem` (if present) is an SdcModel.\n *\n * @param {*} arg\n * @returns {boolean}\n */\nfunction isCreateOptions(arg) {\n if (!arg || typeof arg !== \"object\" || arg instanceof SdcModel) {\n return false;\n }\n const keys = Object.keys(arg);\n if (keys.length === 0 || !keys.every((k) => k === \"elem\" || k === \"data\")) {\n return false;\n }\n if (\"elem\" in arg && arg.elem !== null && !(arg.elem instanceof SdcModel)) {\n return false;\n }\n return !(\"data\" in arg) || arg.data === null || typeof arg.data === \"object\";\n}\n\nclass SdcQuerySet {\n /**\n * Lightweight client-side collection wrapper around the SDC model websocket.\n *\n * The queryset exposes array-like access through a proxy while also keeping\n * track of socket state and outstanding requests for that model.\n *\n * @param {string} modelName\n * @param {object} modelQuery\n */\n constructor(modelName, modelQuery = {}) {\n this.valuesList = [];\n this.loaded = false;\n this.modelName = modelName;\n this.modelQuery = modelQuery ?? {};\n this._onNoOpenRequests = [];\n this._isConnected = false;\n this._isConnectingProcess = false;\n this._autoReconnect = true;\n this.socket = null;\n // Request resolvers are stored by websocket event id until the server responds.\n this.openRequest = {};\n this.modelId = 0;\n this.onUpdate = () => {\n };\n this.onCreate = () => {\n };\n // Called with the removed models when rows of this queryset are deleted on the\n // server. If not set, onUpdate is called instead.\n this.onDelete = null;\n\n return new Proxy(this, {\n get(target, prop) {\n if (typeof prop !== \"symbol\" && !isNaN(prop)) {\n return target.valuesList[prop];\n }\n return target[prop];\n },\n\n set(target, prop, value) {\n if (!isNaN(prop)) {\n target.valuesList[prop] = value;\n return true;\n }\n target[prop] = value;\n return true;\n }\n });\n }\n\n [Symbol.iterator]() {\n let idx = -1;\n return {\n next: () => {\n ++idx;\n if (idx < this.valuesList.length) {\n return { value: this.valuesList[idx], done: false };\n }\n return { value: null, done: true };\n },\n };\n }\n\n set on_create(handler) {\n this.onCreate = handler;\n }\n\n set on_update(handler) {\n this.onUpdate = handler;\n }\n\n set on_delete(handler) {\n this.onDelete = handler;\n }\n\n /**\n * Remove the models with the given ids from the local list.\n *\n * @param {Array<number>} ids\n * @returns {Array<SdcModel>} the removed models\n */\n _removeIds(ids) {\n const removed = this.valuesList.filter((item) => ids.includes(item.id));\n this.valuesList = this.valuesList.filter((item) => !ids.includes(item.id));\n return removed;\n }\n\n /**\n *\n *\n * @param {Array<integr|string>|integer|SdcModel|SdcQuerySet|string} ids\n */\n setIds(ids) {\n const vl = this._setIds(ids);\n const filter = {\n id__in: vl.map((x) => x.id)\n }\n\n this.setFilter(filter);\n return vl;\n }\n\n /**\n *\n *\n * @param {Array<integr|string>|integer|SdcModel|SdcQuerySet|string} ids\n */\n _setIds(ids) {\n\n if (ids === null || ids === \"\" || Array.isArray(ids) && ids.length === 0) {\n this.valuesList = [];\n return this.valuesList;\n } else if (ids instanceof SdcQuerySet || ids instanceof SdcModel) {\n // Models already in this queryset are kept (so references to them stay valid);\n // other models are copied into it.\n const sources = ids instanceof SdcModel ? [ids] : ids.valuesList;\n this.valuesList = sources.map((source) => {\n const existing = source.id !== null ? this.byId(source.id) : null;\n if (existing) {\n return existing;\n }\n const copy = cloneModel(source);\n copy._setQuerySet(this, true);\n return copy;\n });\n return this.valuesList;\n }\n\n let numList, numId = Number.NaN;\n if (Number.isInteger(ids)) {\n numId = ids;\n } else if (ids instanceof Array) {\n const tempNumList = ids.map((x) => parseInt(x));\n if (!tempNumList.some(Number.isNaN)) {\n numList = tempNumList;\n }\n } else if (typeof ids === \"string\") {\n const tempNumList = ids.split(',').map((x) => parseInt(x));\n if (!tempNumList.some(Number.isNaN)) {\n numList = tempNumList\n } else {\n numId = parseInt(ids);\n }\n }\n\n if (!Number.isNaN(numId)) {\n this.valuesList = this.valuesList.filter((item) => numId === item.id);\n if (this.valuesList.length === 0) {\n const newModel = this.new();\n newModel.id = numId;\n }\n } else if (numList) {\n this.valuesList = this.valuesList.filter((item) => numList.includes(item.id));\n const valueIds = this.getIds();\n numList.filter(x => !valueIds.includes(x)).forEach((id) => {\n this.valuesList.push(new ((0,_sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__.getModel)(this.modelName))({ id }));\n });\n }\n return this.valuesList;\n }\n\n getIds() {\n return this.valuesList.map(x => x.id);\n }\n\n /**\n * Number of model instances currently present in the queryset cache.\n *\n * @returns {number}\n */\n get length() {\n return this.valuesList.length;\n }\n\n /**\n * Resolve a model instance by id, loading the queryset first if needed.\n *\n * @param {*} id\n * @returns {SdcModel|null}\n */\n byId(id) {\n if (id !== null) {\n const normalizedId = normalizePk(id);\n return this.valuesList.find((elm) => elm.id === normalizedId) ?? null;\n }\n\n return null;\n }\n\n /**\n * Merge additional query constraints into the current queryset.\n *\n * @param {object} modelQuery\n * @returns {SdcQuerySet}\n */\n setFilter(modelQuery) {\n this.modelQuery = modelQuery;\n return this;\n }\n\n addFilter(modelQuery) {\n this.modelQuery = Object.assign({}, this.modelQuery, modelQuery);\n return this;\n }\n\n /**\n * @param {?object} values\n * @returns {SdcModel}\n */\n new(values = {}) {\n const newModel = new ((0,_sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__.getModel)(this.modelName))(values);\n newModel._setQuerySet(this, false);\n this.valuesList.push(newModel);\n return newModel;\n }\n\n /**\n * Load model instances matching the current query into the queryset cache.\n *\n * @param {?object} modelQuery\n * @param {object} [options]\n * @param {?number} [options.limit] load at most this many instances (the server slices the query)\n * @returns {Promise<SdcQuerySet>}\n */\n load(modelQuery = null, { limit = null } = {}) {\n this.valuesList = [];\n this.modelQuery = modelQuery ?? this.modelQuery;\n return this._sendLoad(null, limit);\n }\n\n /**\n * Load model instances matching the current query into the queryset cache.\n *\n * @param {?object} modelQuery\n * @param {?SdcModel} item\n * @returns {Promise<SdcQuerySet>}\n */\n update({ modelQuery = null, item = null }) {\n this.modelQuery = modelQuery ?? this.modelQuery;\n let loadQuery = item ? { id: item.id } : this.modelQuery;\n return this._sendLoad(loadQuery);\n }\n\n /**\n *\n * @param pk {integr}\n * @param elem {SdcModel}\n * @returns {Promise<unknown>}\n */\n delete({ pk = null, id = null, elem = null }) {\n pk ??= id;\n pk = !elem ? pk : elem.id;\n if (pk === null) {\n throw new Error(\"pk or elem must be set\");\n }\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n return this.isConnected().then(() => {\n return new Promise((resolve, reject) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"delete\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n id: pk,\n pk\n },\n }),\n );\n\n this.openRequest[event_id] = [(res) => {\n this._removeIds([normalizePk(pk)]);\n resolve(res);\n }, reject];\n });\n });\n }\n\n /**\n * Request the server-side queryset data over the model websocket.\n *\n * @returns {Promise<*>}\n */\n _sendLoad(loadQuery = null, limit = null) {\n return this.isConnected().then(() => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n const args = {\n model_name: this.modelName,\n model_query: loadQuery ?? this.modelQuery,\n };\n if (limit !== null) {\n args.limit = limit;\n }\n return new Promise((resolve, reject) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"load\",\n event_id,\n args,\n }),\n );\n\n this.openRequest[event_id] = [(data) => {\n this.loaded = true;\n resolve(data);\n }, reject];\n });\n });\n }\n\n /**\n * Render the list-view endpoint for the current model.\n *\n * @param {object} options\n * @returns {*}\n */\n _sendListView({\n modelQuery = {},\n cbResolve = null,\n cbReject = null,\n templateContext = {},\n }) {\n return this.view({\n modelQuery,\n cbResolve,\n cbReject,\n templateContext,\n eventType: \"list_view\",\n });\n }\n\n /**\n * Render a named model view and append its HTML to a container element.\n *\n * @param {object} options\n * @returns {*}\n */\n view({\n viewName = \"html_list_template\",\n modelQuery = {},\n cbResolve = null,\n cbReject = null,\n templateContext = {},\n eventType = \"named_view\",\n }) {\n let $divList = $('<div class=\"container-fluid\">');\n this.isConnected().then(() => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: eventType,\n event_id,\n args: {\n view_name: viewName,\n model_name: this.modelName,\n model_query: modelQuery,\n template_context: templateContext,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (data) => {\n $divList.append(data.html);\n _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__.app.refresh($divList);\n cbResolve && cbResolve(data);\n },\n (res) => {\n cbReject && cbReject(res);\n },\n ];\n });\n\n return $divList;\n }\n\n /**\n * Render the detail-view endpoint for a single model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n _sendDetailView({\n pk = null,\n id = null,\n cbResolve = null,\n cbReject = null,\n templateContext = {},\n }) {\n pk ??= id;\n pk = normalizePk(pk);\n let $divList = $('<div class=\"container-fluid\">');\n\n this.isConnected().then(() => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"detail_view\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n id: pk,\n pk,\n template_context: templateContext,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (data) => {\n $divList.append(data.html);\n _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__.app.refresh($divList);\n cbResolve && cbResolve(data);\n },\n (res) => {\n cbReject && cbReject(res);\n },\n ];\n });\n\n return $divList;\n }\n\n /**\n * Fetch a model form fragment and attach the SDC form metadata expected by\n * the rest of the client.\n *\n * @param {string} eventType\n * @param {SdcModel} modelObj\n * @param formName\n * @param $divForm\n * @param cbResolve\n * @param cbReject\n * @param formId\n */\n getForm({ modelObj, eventType, formName, $divForm, cbResolve, cbReject, formId }) {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n const pk = modelObj.id ?? -1;\n this.isConnected().then(() => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: eventType,\n event_id,\n args: {\n model_name: this.modelName,\n id: pk,\n pk,\n form_name: formName,\n },\n }),\n );\n });\n\n const className = pk === null || pk === -1 ? \"create\" : \"edit\";\n\n this.openRequest[event_id] = [\n (data) => {\n $divForm.append(data.html);\n let $form = $divForm\n .closest(\"form\")\n .addClass(\n `sdc-model-${className}-form sdc-model-form ${formId}`,\n )\n .data(\"model\", modelObj)\n .data(\"model_pk\", pk)\n .data(\"form_name\", formName)\n .attr('SdcModelName', this.modelName)\n .attr('SdcModelPK', pk);\n modelObj.addForm($form);\n if ($form.length > 0 && !$form[0].hasAttribute(\"sdc_submit\")) {\n $form.attr(\"sdc_submit\", \"submitModelFormDistributor\");\n }\n\n _sdc_main_js__WEBPACK_IMPORTED_MODULE_2__.app.refresh($divForm).then(() => null);\n cbResolve && cbResolve(data);\n },\n (res) => {\n cbReject && cbReject(res);\n },\n ];\n }\n\n /**\n * Fetch a single model instance matching the current query.\n *\n * @param {?object} modelQuery\n * @param {?boolean} doNotLoad true if modelQuery contains id or pk and object does not need to be loaded.\n * @returns {Promise<SdcModel>}\n */\n async get(modelQuery = null, doNotLoad = false) {\n if (doNotLoad) {\n const id = modelQuery?.id ?? this.modelQuery?.id;\n if(modelQuery) {\n this.setFilter(modelQuery);\n }\n return this.byId(id) ?? this.new(modelQuery || this.modelQuery);\n }\n await this.load(modelQuery);\n if (this.length !== 1) {\n throw new Error(`model query returns ${this.length} but only 1 expected.`);\n }\n\n this.addFilter({ id: this.valuesList[0].id });\n\n return this.valuesList[0];\n }\n\n detailView({ pk, cbResolve = null, cbReject = null, templateContext = {} }) {\n return this._sendDetailView({\n id: pk,\n cbResolve,\n cbReject,\n templateContext,\n });\n }\n\n listView({ modelQuery = {}, searchValues = {}, cbResolve = null, cbReject = null, templateContext = {} }) {\n return this._sendListView({\n modelQuery: Object.assign({}, this.modelQuery, modelQuery, { '__search_values': searchValues }),\n cbResolve,\n cbReject,\n templateContext,\n });\n }\n\n save({ pk = null, id = null, formName = \"edit_form\", data = null } = {}) {\n pk ??= id;\n const normPk = normalizePk(pk);\n return this.isConnected().then(() => {\n let elemList;\n if (normPk > -1) {\n const elem = this.byId(normPk);\n if (!elem) {\n return Promise.reject(new SdcModelError(`Element not found with ID: ${normPk}`));\n }\n elemList = [elem];\n } else {\n elemList = this.valuesList;\n }\n let pList = [];\n elemList.forEach((elem) => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n pList.push(\n new Promise((resolve, reject) => {\n this._readFiles(elem).then((files) => {\n const sendData = data ? { ...data } : elem.serialize();\n sendData.id = elem.id;\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"save\",\n event_id,\n args: {\n form_name: formName,\n model_name: this.modelName,\n model_query: this.modelQuery,\n data: sendData,\n id: sendData.id,\n pk: sendData.id,\n files: files,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (res) => {\n let data =\n typeof res.data.instance === \"string\"\n ? JSON.parse(res.data.instance)\n : res.data.instance;\n res.data.instance = this._parseServerRes(data);\n resolve(res);\n },\n reject,\n ];\n });\n }),\n );\n });\n\n return Promise.all(pList);\n });\n }\n\n /**\n * Create a new instance in the DB.\n *\n * @param {{elem?: SdcModel, data?: object} | object} arg\n * Either an options object containing `elem` and/or `data`,\n * or `data` directly.\n *\n * @example\n * create({ elem, data });\n * create({ elem });\n * create(data);\n * @returns {Promise<unknown>}\n */\n create(arg = null) {\n let { elem = null, data = null } = isCreateOptions(arg) ? arg : { data: arg };\n if (data && typeof data === \"object\" && Object.keys(data).length === 0) {\n data = null;\n }\n\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n if (!elem) {\n elem = this.new(data);\n }\n return this.isConnected().then(() => {\n return new Promise((resolve, reject) => {\n this._readFiles(elem).then((files) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"create\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n data: data ?? elem?.serialize() ?? {},\n files: files,\n },\n }),\n );\n\n this.openRequest[event_id] = [\n (res) => {\n let data =\n typeof res.data.instance === \"string\"\n ? JSON.parse(res.data.instance)\n : res.data.instance;\n if (elem) {\n elem.id = data[0]?.id || data[0]?.pk;\n }\n res.data.instance = this._parseServerRes(data)[0];\n resolve(res);\n },\n reject,\n ];\n });\n });\n });\n }\n\n /**\n * Ensure the websocket is open and has completed the server-side connect\n * handshake before issuing model requests.\n *\n * Multiple callers can arrive while a connection attempt is already in\n * progress. In that case they are queued behind the same synthetic request id.\n *\n * @returns {Promise<void>}\n */\n isConnected() {\n return new Promise((resolve, reject) => {\n if (this._isConnected) {\n resolve();\n } else if (\n !this._isConnectingProcess ||\n !this.openRequest[CONNECTING_REQUEST_ID]\n ) {\n this._isConnectingProcess = true;\n this.openRequest[CONNECTING_REQUEST_ID] = [() => {\n }, () => {\n }];\n this._connectToServer().then(() => {\n resolve(this._checkConnection());\n });\n } else {\n const [resolveOrigin, rejectOrigin] =\n this.openRequest[CONNECTING_REQUEST_ID];\n this.openRequest[CONNECTING_REQUEST_ID] = [\n () => {\n resolveOrigin();\n resolve();\n },\n () => {\n rejectOrigin();\n reject();\n },\n ];\n }\n });\n }\n\n /**\n * Close the websocket and disable automatic reconnect for this queryset.\n */\n close() {\n if (this.socket) {\n this._autoReconnect = false;\n this.socket.onclose = () => {\n };\n this.socket.close();\n delete this[\"socket\"];\n }\n\n this.valuesList.forEach((elem) => {\n elem._onClose()\n });\n }\n\n /**\n * Upload attached `File` values in fixed-size chunks before save/create calls.\n *\n * @param {SdcModel} elem\n * @returns {Promise<object>}\n */\n _readFiles(elem) {\n let toSolve = [];\n let files = {};\n if (!elem) {\n return Promise.resolve(files);\n }\n Object.keys(elem.constructor.fields).forEach((key) => {\n const value = elem[key];\n if (value instanceof File) {\n toSolve.push(\n new Promise((resolve, reject) => {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.openRequest[event_id] = [resolve, reject];\n\n value.arrayBuffer().then((buffer) => {\n let result = new Uint8Array(buffer);\n let numberOfChunks = Math.ceil(result.length / MAX_FILE_UPLOAD);\n files[key] = {\n id: event_id,\n file_name: value.name,\n field_name: key,\n content_length: value.size,\n };\n for (let i = 0; i < numberOfChunks; ++i) {\n const chunk = Array.from(result.slice(\n MAX_FILE_UPLOAD * i,\n MAX_FILE_UPLOAD * (i + 1),\n ));\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"upload\",\n event_id,\n args: {\n chunk,\n idx: i,\n number_of_chunks: numberOfChunks,\n file_name: value.name,\n field_name: key,\n content_length: value.size,\n content_type: value.type,\n model_name: this.modelName,\n model_query: this.modelQuery,\n },\n }),\n );\n }\n }).catch((err) => {\n this._closeOpenRequest(event_id);\n reject(err);\n });\n }),\n );\n }\n });\n\n return Promise.all(toSolve).then(() => {\n return files;\n });\n }\n\n /**\n * Route websocket responses to the matching pending request and update local\n * state when the server sends model payloads.\n *\n * @param {MessageEvent} e\n */\n async _onMessage(e) {\n let data = JSON.parse(e.data);\n if (data.is_error) {\n if (Object.hasOwn(this.openRequest, data.event_id)) {\n this.openRequest[data.event_id][1](new SdcModelError(data));\n this._closeOpenRequest(data.event_id);\n }\n if (data.msg || data.header) {\n (0,_sdc_events_js__WEBPACK_IMPORTED_MODULE_3__.trigger)(\"pushErrorMsg\", data.header || \"\", data.msg || \"\");\n }\n\n if (data.type === \"connect\") {\n this.openRequest[CONNECTING_REQUEST_ID][1](new SdcModelError(data));\n this._closeOpenRequest(CONNECTING_REQUEST_ID);\n this._autoReconnect = false;\n this.socket.close();\n }\n } else {\n if (data.msg || data.header) {\n (0,_sdc_events_js__WEBPACK_IMPORTED_MODULE_3__.trigger)(\"pushMsg\", data.header || \"\", data.msg || \"\");\n }\n\n if (data.type === \"connect\") {\n this._isConnected = true;\n this._isConnectingProcess = false;\n this.openRequest[CONNECTING_REQUEST_ID][0](data);\n this._closeOpenRequest(CONNECTING_REQUEST_ID);\n } else if ([\"load\", \"list_view\", \"named_view\", \"detail_view\"].includes(data.type)) {\n const jsonRes = JSON.parse(data.args.data);\n data.args.data = await this._parseServerRes(jsonRes);\n } else if (data.type === \"on_update\" || data.type === \"on_create\") {\n const jsonRes = JSON.parse(data.args.data);\n\n let obj = await this._parseServerRes(jsonRes);\n let cb;\n\n if (data.type === \"on_create\") {\n cb = this.onCreate;\n } else {\n cb = this.onUpdate;\n }\n\n cb(obj);\n data.args.data = obj;\n } else if (data.type === \"on_delete\") {\n const ids = JSON.parse(data.args.data).map((x) => normalizePk(x.id ?? x.pk));\n const removed = this._removeIds(ids);\n (this.onDelete ?? this.onUpdate)(removed);\n data.args.data = removed;\n }\n\n let instance = data.data?.instance;\n if (instance) {\n data.data.instance = JSON.parse(data.data.instance);\n }\n\n if (Object.hasOwn(this.openRequest, data.event_id)) {\n this.openRequest[data.event_id][0](data);\n this._closeOpenRequest(data.event_id);\n }\n }\n }\n\n /**\n * Wait until all in-flight websocket requests for this queryset are resolved.\n *\n * @returns {Promise<void>}\n */\n noOpenRequests() {\n return new Promise((resolve) => {\n if (Object.keys(this.openRequest).length === 0) {\n return resolve();\n }\n\n this._onNoOpenRequests.push(resolve);\n });\n }\n\n /**\n * Remove a completed request and wake any `noOpenRequests()` waiters when the\n * request map becomes empty.\n *\n * @param {string} eventId\n */\n _closeOpenRequest(eventId) {\n delete this.openRequest[eventId];\n if (Object.keys(this.openRequest).length === 0) {\n this._onNoOpenRequests.forEach((x) => x());\n this._onNoOpenRequests = [];\n }\n }\n\n /**\n * Establish the raw websocket connection for this queryset.\n *\n * @returns {Promise<void>}\n */\n _connectToServer() {\n return new Promise((resolve) => {\n const modelIdentifier =\n `${this.modelName}` + (this.modelId > 0 ? `/${this.modelId}` : \"\");\n if (window.location.protocol === \"https:\") {\n this.socket = new WebSocket(\n `wss://${window.location.host}/sdc_ws/model/${modelIdentifier}`,\n );\n } else {\n this.socket = new WebSocket(\n `ws://${window.location.host}/sdc_ws/model/${modelIdentifier}`,\n );\n }\n\n this.socket.onmessage = this._onMessage.bind(this);\n\n this.socket.onclose = (e) => {\n console.error(\n `SDC Model (${this.modelName}, ${this.modelId}) Socket closed unexpectedly`,\n );\n this._isConnected = false;\n for (const value of Object.values(this.openRequest)) {\n value[1](e);\n }\n this.openRequest = {};\n\n this._isConnectingProcess = false;\n setTimeout(() => {\n if (this._autoReconnect && !this._isConnected) {\n // isConnected() opens the socket and sends the connect handshake, so\n // live updates work again and later requests reuse this connection.\n this.isConnected().catch(() => {\n });\n }\n }, 1000);\n };\n\n this.socket.onerror = (err) => {\n console.error(`Model Socket encountered error: ${err} Closing socket`);\n if (this._isConnected) {\n try {\n this.socket.close();\n } catch (e) {\n }\n }\n };\n\n this.socket.onopen = () => {\n resolve();\n };\n });\n }\n\n /**\n * Perform the application-level connect handshake once the websocket opens.\n *\n * @returns {Promise<*>}\n */\n _checkConnection() {\n const event_id = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n return new Promise((resolve, reject) => {\n this.socket.send(\n JSON.stringify({\n event: \"model\",\n event_type: \"connect\",\n event_id,\n args: {\n model_name: this.modelName,\n model_query: this.modelQuery,\n },\n }),\n );\n\n this.openRequest[event_id] = [resolve, reject];\n });\n }\n\n /**\n * Convert the backend model payload into locally tracked model objects.\n *\n * @param {Array<object>} results\n */\n _parseServerRes(results) {\n const newModels = []\n for (const x of results) {\n const ModelClass = (0,_sdc_socket_js__WEBPACK_IMPORTED_MODULE_1__.getModel)(this.modelName);\n if (!ModelClass) {\n throw new Error(`${this.modelName} is no SdcModel. mybe the models ar not importad.`);\n }\n const newModel = new ModelClass({ 'id': x.id ?? x.pk, ...x.fields });\n const currentModel = this.byId(newModel.id);\n if (currentModel) {\n currentModel.setValues(newModel);\n newModels.push(currentModel);\n } else {\n this.valuesList.push(newModel);\n newModel._setQuerySet(this, true);\n newModels.push(newModel);\n }\n }\n this.valuesList.sort((a, b) => a._id - b._id);\n return newModels;\n }\n}\n\nclass SdcModel {\n static fields = {};\n\n /**\n * Base model wrapper used by SDC model registrations.\n *\n * @param {string} modelName\n */\n constructor(modelName) {\n this._id = null;\n this._forms = [];\n this.loaded = false;\n this.formId = (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.uuidv4)();\n this.modelName = modelName;\n }\n\n /**\n *\n * @param {object?} modelQuerySet\n * @param {AbstractSDC} parent\n * @returns {SdcQuerySet}\n */\n static querySet(modelQuerySet = null, parent = null) {\n const { modelName } = new this({});\n if (!parent) {\n return new SdcQuerySet(modelName, modelQuerySet);\n }\n\n return parent.querySet(modelName, modelQuerySet);\n }\n\n addForm($form) {\n // Remove old listeners if form already set\n const onChange = this._onChange.bind(this);\n\n this._forms.push($form);\n\n if ($form) {\n // Attach delegated event handler to all inputs\n $form.on(\n \"input.formWatcher change.formWatcher\",\n \"input, select, textarea\",\n onChange\n );\n }\n }\n\n _onChange(event) {\n const { name } = event.target;\n if (this.constructor.fields[name]) {\n try {\n this[`set${name}`]((0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.getValueFromField)(event.target));\n } catch {\n // Invalid input (e.g. an empty required field) is kept in the form and\n // validated by the server on submit.\n return;\n }\n // Show the new value in the other forms of this model, not in the input being edited.\n this._updateForm(name, event.target);\n }\n }\n\n _updateForm(fieldName, skipElement = null) {\n const self = this;\n this._forms.forEach(($form) => {\n $form.find(`[name=\"${fieldName}\"]`).each(function () {\n if (this !== skipElement) {\n (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.setValueInField)(this, self[fieldName]);\n }\n });\n });\n }\n\n setValues(data = {}) {\n throw new Error(\"setValues() must be implemented by subclass\");\n }\n\n /**\n * Attach the queryset that owns this model instance.\n *\n * @param {SdcQuerySet} querySet\n * @param {boolean} isLoaded\n */\n _setQuerySet(querySet, isLoaded) {\n this._querySet = new WeakRef(querySet);\n this.loaded = isLoaded;\n }\n\n get querySet() {\n return this._querySet.deref();\n }\n\n save({ formName = \"edit_form\", data = null } = {}) {\n return this._querySet.deref().save({ pk: this.id, formName, data });\n }\n\n /**\n * Create this instance in the DB.\n *\n * @param {{data?: object} | object | null} values\n * Either `{ data }` or `data` directly.\n * @returns {Promise<unknown>}\n */\n create(values = null) {\n const data = isCreateOptions(values) ? (values.data ?? null) : values;\n return this._querySet.deref().create({ elem: this, data });\n }\n\n delete() {\n return this._querySet.deref().delete({ elem: this });\n }\n\n load() {\n return this._querySet.deref().update({ item: this });\n }\n\n update() {\n return this.load();\n }\n\n get id() {\n return this._id;\n }\n\n set id(data) {\n this._id = data;\n }\n\n set pk(data) {\n this.id = data;\n }\n\n get pk() {\n return this._id;\n }\n\n close() {\n return this._querySet.deref().close();\n }\n\n _onClose() {\n Object.keys(this.constructor.fields)\n .filter((x) => this[`_${x}`] instanceof SdcQuerySet)\n .forEach((x) => this[`_${x}`].close());\n }\n\n /**\n * Request the server-rendered detail view for this model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n detailView({ cbResolve = null, cbReject = null, templateContext = {} }) {\n return this._querySet.deref().detailView({ pk: this.id, cbResolve, cbReject, templateContext });\n }\n\n serialize() {\n return Object.entries(this.constructor.fields).reduce((acc, [key, val]) => {\n const value = this[key];\n if (value instanceof SdcQuerySet) {\n if (val.many_to_many || val.one_to_many) {\n acc[key] = value.getIds();\n } else {\n const allIds = value.getIds();\n if (allIds.length > 0) {\n acc[key] = allIds[0];\n } else {\n acc[key] = null;\n }\n\n }\n } else if (val.is_relation && value instanceof SdcModel) {\n acc[key] = value.id ?? null;\n } else if (value instanceof Date) {\n // Django's DateField does not accept a full ISO datetime.\n acc[key] = val.type === \"DateField\" ? (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.formatDate)(value) : value.toISOString();\n } else {\n acc[key] = value;\n }\n\n return acc\n }, {});\n }\n\n toJson() {\n const res = {}\n for (let key in this.constructor.fields) {\n const value = this[key];\n\n if (value instanceof File) {\n res[key] = value.name;\n } else if (value instanceof SdcModel) {\n res[key] = value.id;\n } else if (value instanceof SdcQuerySet) {\n res[key] = value.getIds();\n } else {\n res[key] = value;\n }\n }\n\n return res;\n }\n\n /**\n * Backwards-compatible alias for syncing values from a form into the model.\n *\n * @param {*} $forms\n * @returns {*}\n */\n syncFormToModel($forms) {\n return this.syncForm($forms);\n }\n\n /**\n * Resolve the form collection associated with this model instance.\n *\n * @param {*} $forms\n * @returns {*}\n */\n _resolveForms($forms) {\n if (!$forms || !$forms.hasClass(this.formId)) {\n return $(`.${this.formId}`);\n }\n\n return $forms;\n }\n\n /**\n * Copy the current model state into matching form fields.\n *\n * @param {*} $forms\n */\n syncModelToForm($forms) {\n $forms = this._resolveForms($forms);\n\n const self = this;\n const { fields } = this.constructor;\n $forms.each(function () {\n const pk = normalizePk($(this).data(\"model_pk\"));\n // Create forms carry model_pk -1 while the new model's id is still null.\n if (normalizePk(self.id) !== pk) {\n return;\n }\n\n for (let formItem of this.elements) {\n let { name } = formItem;\n if (name && name !== \"\" && !!fields[name]) {\n (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.setValueInField)(formItem, self[name])\n }\n }\n });\n }\n\n /**\n * Copy matching form values back onto the current model instance.\n *\n * Hidden inputs are parsed to their original primitive type when possible.\n *\n * @param {*} $forms\n * @returns {*}\n */\n syncForm($forms) {\n $forms = this._resolveForms($forms);\n\n const self = this;\n const { fields } = this.constructor;\n const returnValue = {}\n\n function setValueInForm(name, value) {\n if (fields[name]) {\n try {\n self[name] = value;\n } catch {\n // Invalid values are still sent to the server, which returns the form\n // errors; the model keeps its last valid value.\n }\n }\n returnValue[name] = value;\n }\n\n $forms.each(function () {\n const pk = normalizePk($(this).data(\"model_pk\"));\n if (self.id !== pk && (self.id !== null || pk !== -1)) {\n return;\n }\n\n for (let formItem of this.elements) {\n setValueInForm(formItem.name, (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.getValueFromField)(formItem));\n }\n\n return self;\n });\n\n return returnValue;\n }\n\n /**\n * Render the correct server-side form for this model state.\n *\n * @param {object} options\n * @returns {*}\n */\n form({ cbResolve = null, cbReject = null } = {}) {\n if (this.id === null || this.id === -1) {\n return this._createForm({ cbReject, cbResolve });\n }\n return this._editForm({ cbReject, cbResolve });\n }\n\n /**\n * Render the create form for a new model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n _createForm({ cbResolve = null, cbReject = null }) {\n let $divForm = $(\"<div>\");\n this._querySet.deref().getForm({\n modelObj: this,\n eventType: \"create_form\",\n formName: null,\n $divForm,\n cbResolve,\n cbReject,\n formId: this.formId,\n });\n\n return $divForm;\n }\n\n /**\n * Render the edit form for an existing model instance.\n *\n * @param {object} options\n * @returns {*}\n */\n _editForm({ cbResolve = null, cbReject = null }) {\n let $divForm = $(\"<div>\");\n\n this._querySet.deref().getForm({\n modelObj: this,\n eventType: \"edit_form\",\n formName: null,\n $divForm,\n cbResolve,\n cbReject,\n formId: this.formId,\n });\n\n return $divForm;\n }\n\n /**\n * Render a named server-side form for this model.\n *\n * @param {object} options\n * @returns {*}\n */\n namedForm({ formName, cbResolve = null, cbReject = null }) {\n let $divForm = $('<div class=\"container-fluid\">');\n\n this._querySet.deref().getForm({\n modelObj: this,\n eventType: \"named_form\",\n formName,\n $divForm,\n cbResolve,\n cbReject,\n formId: this.formId,\n });\n\n return $divForm;\n }\n\n /**\n * Validate a field value using the supplied field config.\n *\n * @param {*} value\n * @param {object} config\n */\n validate(value, config) {\n const err = validateField(value, config);\n if (err) throw new Error(err);\n }\n\n /**\n * Convert a raw input value into the shape expected by the field config.\n *\n * @param {*} value\n * @param {object} config\n * @returns {*}\n */\n parseValue(value, config) {\n const {\n type,\n many_to_many: manyToMany,\n one_to_many: oneToMany,\n many_to_one: manyToOne,\n one_to_one: oneToOne,\n } = config;\n if (value === null) {\n return null;\n }\n\n if ((manyToMany || oneToMany || manyToOne || oneToOne) && value && typeof value === 'string') {\n return JSON.parse(value);\n }\n\n switch (type) {\n case \"CharField\":\n case \"TextField\":\n case \"SlugField\":\n case \"UUIDField\":\n case \"EmailField\":\n return `${value}`;\n\n case \"IntegerField\":\n case \"SmallIntegerField\":\n case \"BigIntegerField\":\n case \"PositiveIntegerField\":\n case \"PositiveSmallIntegerField\":\n case \"PositiveBigIntegerField\":\n case \"AutoField\":\n case \"SmallAutoField\":\n case \"BigAutoField\":\n return parseInt(value, 10);\n\n case \"FloatField\":\n case \"DecimalField\":\n return parseFloat(value);\n\n case \"BooleanField\":\n return !!value;\n\n case \"DateField\":\n case \"DateTimeField\":\n return (0,_sdc_utils_js__WEBPACK_IMPORTED_MODULE_0__.toDate)(value);\n\n case \"URLField\":\n return new URL(value);\n\n case \"FileField\":\n if (value == null) {\n return null;\n }\n\n if (typeof value === \"string\") {\n return null;\n }\n\n if (FileLoaded.isValid(value)) {\n return new FileLoaded(value);\n }\n\n if (value instanceof FileLoaded) {\n return new FileLoaded(value);\n }\n\n if (typeof File !== \"undefined\" && value instanceof File) {\n // Size and type are checked in validate().\n return value;\n }\n break;\n\n case \"JSONField\":\n if (typeof value === \"object\") {\n return value;\n }\n if (typeof value === \"string\") {\n return JSON.parse(value);\n }\n break;\n\n default:\n break;\n }\n\n return value;\n }\n}\n\n/**\n * Validate a field value against the field metadata received from the backend.\n *\n * @param {*} value\n * @param {object} config\n * @returns {?string}\n */\nfunction validateField(value, config) {\n const {\n type,\n required,\n max_length: maxLength,\n is_relation: isRelation,\n many_to_many: manyToMany,\n one_to_many: oneToMany,\n many_to_one: manyToOne,\n one_to_one: oneToOne,\n related_model: relatedModel,\n } = config;\n\n void isRelation;\n\n if (required) {\n if (value === null || value === undefined || value === \"\") {\n return \"This field is required\";\n }\n }\n\n if (value === null || value === undefined || value === \"\") {\n return null;\n }\n\n if (manyToMany || oneToMany || manyToOne || oneToOne) {\n if (!(value instanceof SdcQuerySet) || value.modelName !== relatedModel) {\n if(typeof value === 'string') {\n value = JSON.parse(value);\n }\n\n if ((manyToMany || manyToOne) && Array.isArray(value) && value.some((x) => !Number.isNaN(parseInt(x)))) {\n return null;\n }\n if (typeof value !== \"object\" && Number.isNaN(parseInt(value))) {\n return \"Must be object or ID\";\n }\n return null;\n }\n }\n\n switch (type) {\n case \"CharField\":\n case \"TextField\":\n if (typeof value !== \"string\") {\n return \"Must be a string\";\n }\n if (maxLength && value.length > maxLength) {\n return `Max length is ${maxLength}`;\n }\n break;\n\n case \"IntegerField\":\n case \"SmallIntegerField\":\n case \"BigIntegerField\":\n case \"PositiveIntegerField\":\n case \"PositiveSmallIntegerField\":\n case \"PositiveBigIntegerField\":\n case \"AutoField\":\n case \"SmallAutoField\":\n case \"BigAutoField\":\n if (!isFinite(parseInt(value))) {\n return \"Must be an integer\";\n }\n break;\n\n case \"FloatField\":\n case \"DecimalField\":\n if (!isFinite(parseFloat(value))) {\n return \"Must be a number\";\n }\n break;\n\n case \"BooleanField\":\n if (typeof value !== \"boolean\") {\n return \"Must be a boolean\";\n }\n break;\n\n case \"DateField\":\n case \"DateTimeField\":\n if (isNaN(Date.parse(value))) {\n return \"Must be a valid date\";\n }\n break;\n\n case \"EmailField\":\n if (typeof value !== \"string\" || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {\n return \"Invalid email\";\n }\n break;\n\n case \"URLField\":\n try {\n new URL(value);\n } catch {\n return \"Invalid URL\";\n }\n break;\n\n case \"UUIDField\":\n if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(value)) {\n return \"Invalid UUID\";\n }\n break;\n\n case \"JSONField\":\n if (typeof value === \"string\") {\n try {\n JSON.parse(value);\n } catch {\n return \"Must be valid JSON\";\n }\n }\n break;\n case \"FileField\":\n if (!FileLoaded.isValid(value) && !(value instanceof File) && !(value instanceof FileLoaded)) {\n return \"Must be a valid file\";\n }\n if (typeof File !== \"undefined\" && value instanceof File) {\n if (config.max_size && value.size > config.max_size) {\n return `File too large (max ${config.max_size} bytes)`;\n }\n if (config.allowed_types && !config.allowed_types.includes(value.type)) {\n return `Invalid file type (${value.type})`;\n }\n }\n break;\n default:\n break;\n }\n\n return null;\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDLFVBQVU7QUFDMUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0Esc0JBQXNCLEVBQUUsVUFBVSxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEdBQUc7QUFDcEY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLGlCQUFpQjtBQUN6RDtBQUNBO0FBQ0EsdUNBQXVDLFdBQVc7QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9zZGNfY2xpZW50Ly4vc3JjL3NpbXBsZURvbUNvbnRyb2wvc2RjX21vZGVsLmpzPzk5MWIiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZm9ybWF0RGF0ZSwgZ2V0VmFsdWVGcm9tRmllbGQsIHNldFZhbHVlSW5GaWVsZCwgdG9EYXRlLCB1dWlkdjQgfSBmcm9tIFwiLi9zZGNfdXRpbHMuanNcIjtcbmltcG9ydCB7IGdldE1vZGVsIH0gZnJvbSBcIi4vc2RjX3NvY2tldC5qc1wiXG5pbXBvcnQgeyBhcHAgfSBmcm9tIFwiLi9zZGNfbWFpbi5qc1wiO1xuaW1wb3J0IHsgdHJpZ2dlciB9IGZyb20gXCIuL3NkY19ldmVudHMuanNcIjtcblxuY29uc3QgTUFYX0ZJTEVfVVBMT0FEID0gMjUwMDA7XG5jb25zdCBDT05ORUNUSU5HX1JFUVVFU1RfSUQgPSBcIl9jb25uZWN0aW5nX3Byb2Nlc3NcIjtcblxuLyoqXG4gKiBDb3B5IGEgbW9kZWwgaW5zdGFuY2UgZm9yIGFub3RoZXIgcXVlcnlzZXQuIEEgbmV3IGluc3RhbmNlIG9mIHRoZSBzYW1lIGNsYXNzIGlzXG4gKiBjcmVhdGVkIGZyb20gdGhlIHNlcmlhbGl6ZWQgZmllbGQgdmFsdWVzIChzdHJ1Y3R1cmVkQ2xvbmUgY2Fubm90IGNvcHkgdGhlXG4gKiBXZWFrUmVmL1Byb3h5IG1lbWJlcnMgb2YgYSBtb2RlbCkuXG4gKi9cbmNvbnN0IGNsb25lTW9kZWwgPSAob3JpZ2luYWwpID0+IHtcbiAgY29uc3QgY29weSA9IG5ldyBvcmlnaW5hbC5jb25zdHJ1Y3Rvcih7fSk7XG4gIGNvcHkuc2V0VmFsdWVzKG9yaWdpbmFsLnNlcmlhbGl6ZSgpKTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbmNsYXNzIFNkY01vZGVsRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgaWYgKHR5cGVvZiBwcm9wcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHByb3BzID0ge1xuICAgICAgICBtc2c6IHByb3BzLFxuICAgICAgICBpc19lcnJvcjogdHJ1ZSxcbiAgICAgICAgaGVhZGVyOiAnRXJyb3InXG4gICAgICB9XG4gICAgfVxuICAgIHN1cGVyKHByb3BzLm1zZylcbiAgICB0aGlzLm1zZyA9IHByb3BzLm1zZztcbiAgICB0aGlzLmhlYWRlciA9IHByb3BzLmhlYWRlcjtcbiAgICB0aGlzLmlzX2Vycm9yID0gcHJvcHMuaXNfZXJyb3I7XG4gICAgdGhpcy5odG1sID0gcHJvcHMuaHRtbDtcbiAgfVxufVxuXG5jbGFzcyBGaWxlTG9hZGVkIHtcbiAgY29uc3RydWN0b3IoeyBuYW1lLCB1cmwgfSkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgdGhpcy51cmwgPSB1cmw7XG4gICAgdGhpcy5jb250ZW50ID0gbnVsbDtcbiAgfVxuXG4gIGFzeW5jIGxvYWQoZm9yY2UgPSBmYWxzZSkge1xuICAgIGlmIChmb3JjZSB8fCAhdGhpcy5jb250ZW50KSB7XG4gICAgICB0aGlzLmNvbnRlbnQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICQuZ2V0KHRoaXMudXJsKS50aGVuKHJlc29sdmUpLmNhdGNoKFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmUoJycpO1xuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNvbnRlbnQ7XG4gIH1cblxuICBhc3luYyB0ZXh0KCkge1xuICAgIHJldHVybiB0aGlzLmxvYWQoKTtcbiAgfVxuXG4gIHN0YXRpYyBpc1ZhbGlkKHZhbHVlKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHZhbHVlICE9PSBudWxsICYmXG4gICAgICB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCIgJiZcbiAgICAgICFBcnJheS5pc0FycmF5KHZhbHVlKSAmJlxuICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIEZpbGUpICYmXG4gICAgICB0eXBlb2YgdmFsdWUudXJsID09PSBcInN0cmluZ1wiICYmXG4gICAgICB0eXBlb2YgdmFsdWUubmFtZSA9PT0gXCJzdHJpbmdcIlxuICAgICk7XG4gIH1cblxuXG59XG5cbi8qKlxuICogTm9ybWFsaXplIGFuIGluY29taW5nIHByaW1hcnkga2V5IHZhbHVlLlxuICpcbiAqIGAtMWAgaXMgdXNlZCB0aHJvdWdob3V0IHRoaXMgbW9kdWxlIGFzIHRoZSBzZW50aW5lbCBmb3IgXCJuZXcgb2JqZWN0IC8gbm8gcGtcIi5cbiAqXG4gKiBAcGFyYW0geyp9IHBrXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mdW5jdGlvbiBub3JtYWxpemVQayhwaykge1xuICBjb25zdCBub3JtYWxpemVkUGsgPSBwYXJzZUludChwayA/PyAtMSwgMTApO1xuICByZXR1cm4gTnVtYmVyLmlzTmFOKG5vcm1hbGl6ZWRQaykgPyAtMSA6IG5vcm1hbGl6ZWRQaztcbn1cblxuLyoqXG4gKiBEZWNpZGUgd2hldGhlciBhbiBhcmd1bWVudCBvZiBgY3JlYXRlKClgIGlzIGFuIG9wdGlvbnMgb2JqZWN0XG4gKiAoYHtlbGVtLCBkYXRhfWApIG9yIHRoZSBkYXRhIGl0c2VsZi4gSXQgaXMgdHJlYXRlZCBhcyBvcHRpb25zIGlmIGl0IGlzXG4gKiBhIG5vbi1lbXB0eSBwbGFpbiBvYmplY3Qgd2hvc2Uga2V5cyBhcmUgb25seSBgZWxlbWAgYW5kL29yIGBkYXRhYCwgYW5kXG4gKiBgZWxlbWAgKGlmIHByZXNlbnQpIGlzIGFuIFNkY01vZGVsLlxuICpcbiAqIEBwYXJhbSB7Kn0gYXJnXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gaXNDcmVhdGVPcHRpb25zKGFyZykge1xuICBpZiAoIWFyZyB8fCB0eXBlb2YgYXJnICE9PSBcIm9iamVjdFwiIHx8IGFyZyBpbnN0YW5jZW9mIFNkY01vZGVsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGNvbnN0IGtleXMgPSBPYmplY3Qua2V5cyhhcmcpO1xuICBpZiAoa2V5cy5sZW5ndGggPT09IDAgfHwgIWtleXMuZXZlcnkoKGspID0+IGsgPT09IFwiZWxlbVwiIHx8IGsgPT09IFwiZGF0YVwiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoXCJlbGVtXCIgaW4gYXJnICYmIGFyZy5lbGVtICE9PSBudWxsICYmICEoYXJnLmVsZW0gaW5zdGFuY2VvZiBTZGNNb2RlbCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuICEoXCJkYXRhXCIgaW4gYXJnKSB8fCBhcmcuZGF0YSA9PT0gbnVsbCB8fCB0eXBlb2YgYXJnLmRhdGEgPT09IFwib2JqZWN0XCI7XG59XG5cbmV4cG9ydCBjbGFzcyBTZGNRdWVyeVNldCB7XG4gIC8qKlxuICAgKiBMaWdodHdlaWdodCBjbGllbnQtc2lkZSBjb2xsZWN0aW9uIHdyYXBwZXIgYXJvdW5kIHRoZSBTREMgbW9kZWwgd2Vic29ja2V0LlxuICAgKlxuICAgKiBUaGUgcXVlcnlzZXQgZXhwb3NlcyBhcnJheS1saWtlIGFjY2VzcyB0aHJvdWdoIGEgcHJveHkgd2hpbGUgYWxzbyBrZWVwaW5nXG4gICAqIHRyYWNrIG9mIHNvY2tldCBzdGF0ZSBhbmQgb3V0c3RhbmRpbmcgcmVxdWVzdHMgZm9yIHRoYXQgbW9kZWwuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtb2RlbE5hbWVcbiAgICogQHBhcmFtIHtvYmplY3R9IG1vZGVsUXVlcnlcbiAgICovXG4gIGNvbnN0cnVjdG9yKG1vZGVsTmFtZSwgbW9kZWxRdWVyeSA9IHt9KSB7XG4gICAgdGhpcy52YWx1ZXNMaXN0ID0gW107XG4gICAgdGhpcy5sb2FkZWQgPSBmYWxzZTtcbiAgICB0aGlzLm1vZGVsTmFtZSA9IG1vZGVsTmFtZTtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBtb2RlbFF1ZXJ5ID8/IHt9O1xuICAgIHRoaXMuX29uTm9PcGVuUmVxdWVzdHMgPSBbXTtcbiAgICB0aGlzLl9pc0Nvbm5lY3RlZCA9IGZhbHNlO1xuICAgIHRoaXMuX2lzQ29ubmVjdGluZ1Byb2Nlc3MgPSBmYWxzZTtcbiAgICB0aGlzLl9hdXRvUmVjb25uZWN0ID0gdHJ1ZTtcbiAgICB0aGlzLnNvY2tldCA9IG51bGw7XG4gICAgLy8gUmVxdWVzdCByZXNvbHZlcnMgYXJlIHN0b3JlZCBieSB3ZWJzb2NrZXQgZXZlbnQgaWQgdW50aWwgdGhlIHNlcnZlciByZXNwb25kcy5cbiAgICB0aGlzLm9wZW5SZXF1ZXN0ID0ge307XG4gICAgdGhpcy5tb2RlbElkID0gMDtcbiAgICB0aGlzLm9uVXBkYXRlID0gKCkgPT4ge1xuICAgIH07XG4gICAgdGhpcy5vbkNyZWF0ZSA9ICgpID0+IHtcbiAgICB9O1xuICAgIC8vIENhbGxlZCB3aXRoIHRoZSByZW1vdmVkIG1vZGVscyB3aGVuIHJvd3Mgb2YgdGhpcyBxdWVyeXNldCBhcmUgZGVsZXRlZCBvbiB0aGVcbiAgICAvLyBzZXJ2ZXIuIElmIG5vdCBzZXQsIG9uVXBkYXRlIGlzIGNhbGxlZCBpbnN0ZWFkLlxuICAgIHRoaXMub25EZWxldGUgPSBudWxsO1xuXG4gICAgcmV0dXJuIG5ldyBQcm94eSh0aGlzLCB7XG4gICAgICBnZXQodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJvcCAhPT0gXCJzeW1ib2xcIiAmJiAhaXNOYU4ocHJvcCkpIHtcbiAgICAgICAgICByZXR1cm4gdGFyZ2V0LnZhbHVlc0xpc3RbcHJvcF07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRhcmdldFtwcm9wXTtcbiAgICAgIH0sXG5cbiAgICAgIHNldCh0YXJnZXQsIHByb3AsIHZhbHVlKSB7XG4gICAgICAgIGlmICghaXNOYU4ocHJvcCkpIHtcbiAgICAgICAgICB0YXJnZXQudmFsdWVzTGlzdFtwcm9wXSA9IHZhbHVlO1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHRhcmdldFtwcm9wXSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIGxldCBpZHggPSAtMTtcbiAgICByZXR1cm4ge1xuICAgICAgbmV4dDogKCkgPT4ge1xuICAgICAgICArK2lkeDtcbiAgICAgICAgaWYgKGlkeCA8IHRoaXMudmFsdWVzTGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICByZXR1cm4geyB2YWx1ZTogdGhpcy52YWx1ZXNMaXN0W2lkeF0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHsgdmFsdWU6IG51bGwsIGRvbmU6IHRydWUgfTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHNldCBvbl9jcmVhdGUoaGFuZGxlcikge1xuICAgIHRoaXMub25DcmVhdGUgPSBoYW5kbGVyO1xuICB9XG5cbiAgc2V0IG9uX3VwZGF0ZShoYW5kbGVyKSB7XG4gICAgdGhpcy5vblVwZGF0ZSA9IGhhbmRsZXI7XG4gIH1cblxuICBzZXQgb25fZGVsZXRlKGhhbmRsZXIpIHtcbiAgICB0aGlzLm9uRGVsZXRlID0gaGFuZGxlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgdGhlIG1vZGVscyB3aXRoIHRoZSBnaXZlbiBpZHMgZnJvbSB0aGUgbG9jYWwgbGlzdC5cbiAgICpcbiAgICogQHBhcmFtIHtBcnJheTxudW1iZXI+fSBpZHNcbiAgICogQHJldHVybnMge0FycmF5PFNkY01vZGVsPn0gdGhlIHJlbW92ZWQgbW9kZWxzXG4gICAqL1xuICBfcmVtb3ZlSWRzKGlkcykge1xuICAgIGNvbnN0IHJlbW92ZWQgPSB0aGlzLnZhbHVlc0xpc3QuZmlsdGVyKChpdGVtKSA9PiBpZHMuaW5jbHVkZXMoaXRlbS5pZCkpO1xuICAgIHRoaXMudmFsdWVzTGlzdCA9IHRoaXMudmFsdWVzTGlzdC5maWx0ZXIoKGl0ZW0pID0+ICFpZHMuaW5jbHVkZXMoaXRlbS5pZCkpO1xuICAgIHJldHVybiByZW1vdmVkO1xuICB9XG5cbiAgLyoqXG4gICAqXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXk8aW50ZWdyfHN0cmluZz58aW50ZWdlcnxTZGNNb2RlbHxTZGNRdWVyeVNldHxzdHJpbmd9IGlkc1xuICAgKi9cbiAgc2V0SWRzKGlkcykge1xuICAgIGNvbnN0IHZsID0gdGhpcy5fc2V0SWRzKGlkcyk7XG4gICAgY29uc3QgZmlsdGVyID0ge1xuICAgICAgaWRfX2luOiB2bC5tYXAoKHgpID0+IHguaWQpXG4gICAgfVxuXG4gICAgdGhpcy5zZXRGaWx0ZXIoZmlsdGVyKTtcbiAgICByZXR1cm4gdmw7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICpcbiAgICogQHBhcmFtIHtBcnJheTxpbnRlZ3J8c3RyaW5nPnxpbnRlZ2VyfFNkY01vZGVsfFNkY1F1ZXJ5U2V0fHN0cmluZ30gaWRzXG4gICAqL1xuICBfc2V0SWRzKGlkcykge1xuXG4gICAgaWYgKGlkcyA9PT0gbnVsbCB8fCBpZHMgPT09IFwiXCIgfHwgQXJyYXkuaXNBcnJheShpZHMpICYmIGlkcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IFtdO1xuICAgICAgcmV0dXJuIHRoaXMudmFsdWVzTGlzdDtcbiAgICB9IGVsc2UgaWYgKGlkcyBpbnN0YW5jZW9mIFNkY1F1ZXJ5U2V0IHx8IGlkcyBpbnN0YW5jZW9mIFNkY01vZGVsKSB7XG4gICAgICAvLyBNb2RlbHMgYWxyZWFkeSBpbiB0aGlzIHF1ZXJ5c2V0IGFyZSBrZXB0IChzbyByZWZlcmVuY2VzIHRvIHRoZW0gc3RheSB2YWxpZCk7XG4gICAgICAvLyBvdGhlciBtb2RlbHMgYXJlIGNvcGllZCBpbnRvIGl0LlxuICAgICAgY29uc3Qgc291cmNlcyA9IGlkcyBpbnN0YW5jZW9mIFNkY01vZGVsID8gW2lkc10gOiBpZHMudmFsdWVzTGlzdDtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IHNvdXJjZXMubWFwKChzb3VyY2UpID0+IHtcbiAgICAgICAgY29uc3QgZXhpc3RpbmcgPSBzb3VyY2UuaWQgIT09IG51bGwgPyB0aGlzLmJ5SWQoc291cmNlLmlkKSA6IG51bGw7XG4gICAgICAgIGlmIChleGlzdGluZykge1xuICAgICAgICAgIHJldHVybiBleGlzdGluZztcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb3B5ID0gY2xvbmVNb2RlbChzb3VyY2UpO1xuICAgICAgICBjb3B5Ll9zZXRRdWVyeVNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIGNvcHk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiB0aGlzLnZhbHVlc0xpc3Q7XG4gICAgfVxuXG4gICAgbGV0IG51bUxpc3QsIG51bUlkID0gTnVtYmVyLk5hTjtcbiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihpZHMpKSB7XG4gICAgICBudW1JZCA9IGlkcztcbiAgICB9IGVsc2UgaWYgKGlkcyBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBjb25zdCB0ZW1wTnVtTGlzdCA9IGlkcy5tYXAoKHgpID0+IHBhcnNlSW50KHgpKTtcbiAgICAgIGlmICghdGVtcE51bUxpc3Quc29tZShOdW1iZXIuaXNOYU4pKSB7XG4gICAgICAgIG51bUxpc3QgPSB0ZW1wTnVtTGlzdDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBpZHMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIGNvbnN0IHRlbXBOdW1MaXN0ID0gaWRzLnNwbGl0KCcsJykubWFwKCh4KSA9PiBwYXJzZUludCh4KSk7XG4gICAgICBpZiAoIXRlbXBOdW1MaXN0LnNvbWUoTnVtYmVyLmlzTmFOKSkge1xuICAgICAgICBudW1MaXN0ID0gdGVtcE51bUxpc3RcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG51bUlkID0gcGFyc2VJbnQoaWRzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIU51bWJlci5pc05hTihudW1JZCkpIHtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IHRoaXMudmFsdWVzTGlzdC5maWx0ZXIoKGl0ZW0pID0+IG51bUlkID09PSBpdGVtLmlkKTtcbiAgICAgIGlmICh0aGlzLnZhbHVlc0xpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnN0IG5ld01vZGVsID0gdGhpcy5uZXcoKTtcbiAgICAgICAgbmV3TW9kZWwuaWQgPSBudW1JZDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKG51bUxpc3QpIHtcbiAgICAgIHRoaXMudmFsdWVzTGlzdCA9IHRoaXMudmFsdWVzTGlzdC5maWx0ZXIoKGl0ZW0pID0+IG51bUxpc3QuaW5jbHVkZXMoaXRlbS5pZCkpO1xuICAgICAgY29uc3QgdmFsdWVJZHMgPSB0aGlzLmdldElkcygpO1xuICAgICAgbnVtTGlzdC5maWx0ZXIoeCA9PiAhdmFsdWVJZHMuaW5jbHVkZXMoeCkpLmZvckVhY2goKGlkKSA9PiB7XG4gICAgICAgIHRoaXMudmFsdWVzTGlzdC5wdXNoKG5ldyAoZ2V0TW9kZWwodGhpcy5tb2RlbE5hbWUpKSh7IGlkIH0pKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWx1ZXNMaXN0O1xuICB9XG5cbiAgZ2V0SWRzKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc0xpc3QubWFwKHggPT4geC5pZCk7XG4gIH1cblxuICAvKipcbiAgICogTnVtYmVyIG9mIG1vZGVsIGluc3RhbmNlcyBjdXJyZW50bHkgcHJlc2VudCBpbiB0aGUgcXVlcnlzZXQgY2FjaGUuXG4gICAqXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgbGVuZ3RoKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc0xpc3QubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgYSBtb2RlbCBpbnN0YW5jZSBieSBpZCwgbG9hZGluZyB0aGUgcXVlcnlzZXQgZmlyc3QgaWYgbmVlZGVkLlxuICAgKlxuICAgKiBAcGFyYW0geyp9IGlkXG4gICAqIEByZXR1cm5zIHtTZGNNb2RlbHxudWxsfVxuICAgKi9cbiAgYnlJZChpZCkge1xuICAgIGlmIChpZCAhPT0gbnVsbCkge1xuICAgICAgY29uc3Qgbm9ybWFsaXplZElkID0gbm9ybWFsaXplUGsoaWQpO1xuICAgICAgcmV0dXJuIHRoaXMudmFsdWVzTGlzdC5maW5kKChlbG0pID0+IGVsbS5pZCA9PT0gbm9ybWFsaXplZElkKSA/PyBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIE1lcmdlIGFkZGl0aW9uYWwgcXVlcnkgY29uc3RyYWludHMgaW50byB0aGUgY3VycmVudCBxdWVyeXNldC5cbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IG1vZGVsUXVlcnlcbiAgICogQHJldHVybnMge1NkY1F1ZXJ5U2V0fVxuICAgKi9cbiAgc2V0RmlsdGVyKG1vZGVsUXVlcnkpIHtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBtb2RlbFF1ZXJ5O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgYWRkRmlsdGVyKG1vZGVsUXVlcnkpIHtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLm1vZGVsUXVlcnksIG1vZGVsUXVlcnkpO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSB7P29iamVjdH0gdmFsdWVzXG4gICAqIEByZXR1cm5zIHtTZGNNb2RlbH1cbiAgICovXG4gIG5ldyh2YWx1ZXMgPSB7fSkge1xuICAgIGNvbnN0IG5ld01vZGVsID0gbmV3IChnZXRNb2RlbCh0aGlzLm1vZGVsTmFtZSkpKHZhbHVlcyk7XG4gICAgbmV3TW9kZWwuX3NldFF1ZXJ5U2V0KHRoaXMsIGZhbHNlKTtcbiAgICB0aGlzLnZhbHVlc0xpc3QucHVzaChuZXdNb2RlbCk7XG4gICAgcmV0dXJuIG5ld01vZGVsO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWQgbW9kZWwgaW5zdGFuY2VzIG1hdGNoaW5nIHRoZSBjdXJyZW50IHF1ZXJ5IGludG8gdGhlIHF1ZXJ5c2V0IGNhY2hlLlxuICAgKlxuICAgKiBAcGFyYW0gez9vYmplY3R9IG1vZGVsUXVlcnlcbiAgICogQHBhcmFtIHtvYmplY3R9IFtvcHRpb25zXVxuICAgKiBAcGFyYW0gez9udW1iZXJ9IFtvcHRpb25zLmxpbWl0XSBsb2FkIGF0IG1vc3QgdGhpcyBtYW55IGluc3RhbmNlcyAodGhlIHNlcnZlciBzbGljZXMgdGhlIHF1ZXJ5KVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxTZGNRdWVyeVNldD59XG4gICAqL1xuICBsb2FkKG1vZGVsUXVlcnkgPSBudWxsLCB7IGxpbWl0ID0gbnVsbCB9ID0ge30pIHtcbiAgICB0aGlzLnZhbHVlc0xpc3QgPSBbXTtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBtb2RlbFF1ZXJ5ID8/IHRoaXMubW9kZWxRdWVyeTtcbiAgICByZXR1cm4gdGhpcy5fc2VuZExvYWQobnVsbCwgbGltaXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWQgbW9kZWwgaW5zdGFuY2VzIG1hdGNoaW5nIHRoZSBjdXJyZW50IHF1ZXJ5IGludG8gdGhlIHF1ZXJ5c2V0IGNhY2hlLlxuICAgKlxuICAgKiBAcGFyYW0gez9vYmplY3R9IG1vZGVsUXVlcnlcbiAgICogQHBhcmFtIHs/U2RjTW9kZWx9IGl0ZW1cbiAgICogQHJldHVybnMge1Byb21pc2U8U2RjUXVlcnlTZXQ+fVxuICAgKi9cbiAgdXBkYXRlKHsgbW9kZWxRdWVyeSA9IG51bGwsIGl0ZW0gPSBudWxsIH0pIHtcbiAgICB0aGlzLm1vZGVsUXVlcnkgPSBtb2RlbFF1ZXJ5ID8/IHRoaXMubW9kZWxRdWVyeTtcbiAgICBsZXQgbG9hZFF1ZXJ5ID0gaXRlbSA/IHsgaWQ6IGl0ZW0uaWQgfSA6IHRoaXMubW9kZWxRdWVyeTtcbiAgICByZXR1cm4gdGhpcy5fc2VuZExvYWQobG9hZFF1ZXJ5KTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBAcGFyYW0gcGsge2ludGVncn1cbiAgICogQHBhcmFtIGVsZW0ge1NkY01vZGVsfVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx1bmtub3duPn1cbiAgICovXG4gIGRlbGV0ZSh7IHBrID0gbnVsbCwgaWQgPSBudWxsLCBlbGVtID0gbnVsbCB9KSB7XG4gICAgcGsgPz89IGlkO1xuICAgIHBrID0gIWVsZW0gPyBwayA6IGVsZW0uaWQ7XG4gICAgaWYgKHBrID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJwayBvciBlbGVtIG11c3QgYmUgc2V0XCIpO1xuICAgIH1cbiAgICBjb25zdCBldmVudF9pZCA9IHV1aWR2NCgpO1xuICAgIHJldHVybiB0aGlzLmlzQ29ubmVjdGVkKCkudGhlbigoKSA9PiB7XG4gICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgICBldmVudF90eXBlOiBcImRlbGV0ZVwiLFxuICAgICAgICAgICAgZXZlbnRfaWQsXG4gICAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICAgICAgICBtb2RlbF9xdWVyeTogdGhpcy5tb2RlbFF1ZXJ5LFxuICAgICAgICAgICAgICBpZDogcGssXG4gICAgICAgICAgICAgIHBrXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gWyhyZXMpID0+IHtcbiAgICAgICAgICB0aGlzLl9yZW1vdmVJZHMoW25vcm1hbGl6ZVBrKHBrKV0pO1xuICAgICAgICAgIHJlc29sdmUocmVzKTtcbiAgICAgICAgfSwgcmVqZWN0XTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIHNlcnZlci1zaWRlIHF1ZXJ5c2V0IGRhdGEgb3ZlciB0aGUgbW9kZWwgd2Vic29ja2V0LlxuICAgKlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTwqPn1cbiAgICovXG4gIF9zZW5kTG9hZChsb2FkUXVlcnkgPSBudWxsLCBsaW1pdCA9IG51bGwpIHtcbiAgICByZXR1cm4gdGhpcy5pc0Nvbm5lY3RlZCgpLnRoZW4oKCkgPT4ge1xuICAgICAgY29uc3QgZXZlbnRfaWQgPSB1dWlkdjQoKTtcbiAgICAgIGNvbnN0IGFyZ3MgPSB7XG4gICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICBtb2RlbF9xdWVyeTogbG9hZFF1ZXJ5ID8/IHRoaXMubW9kZWxRdWVyeSxcbiAgICAgIH07XG4gICAgICBpZiAobGltaXQgIT09IG51bGwpIHtcbiAgICAgICAgYXJncy5saW1pdCA9IGxpbWl0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgdGhpcy5zb2NrZXQuc2VuZChcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBldmVudDogXCJtb2RlbFwiLFxuICAgICAgICAgICAgZXZlbnRfdHlwZTogXCJsb2FkXCIsXG4gICAgICAgICAgICBldmVudF9pZCxcbiAgICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtldmVudF9pZF0gPSBbKGRhdGEpID0+IHtcbiAgICAgICAgICB0aGlzLmxvYWRlZCA9IHRydWU7XG4gICAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgICAgfSwgcmVqZWN0XTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgbGlzdC12aWV3IGVuZHBvaW50IGZvciB0aGUgY3VycmVudCBtb2RlbC5cbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICBfc2VuZExpc3RWaWV3KHtcbiAgICAgICAgICAgICAgICAgIG1vZGVsUXVlcnkgPSB7fSxcbiAgICAgICAgICAgICAgICAgIGNiUmVzb2x2ZSA9IG51bGwsXG4gICAgICAgICAgICAgICAgICBjYlJlamVjdCA9IG51bGwsXG4gICAgICAgICAgICAgICAgICB0ZW1wbGF0ZUNvbnRleHQgPSB7fSxcbiAgICAgICAgICAgICAgICB9KSB7XG4gICAgcmV0dXJuIHRoaXMudmlldyh7XG4gICAgICBtb2RlbFF1ZXJ5LFxuICAgICAgY2JSZXNvbHZlLFxuICAgICAgY2JSZWplY3QsXG4gICAgICB0ZW1wbGF0ZUNvbnRleHQsXG4gICAgICBldmVudFR5cGU6IFwibGlzdF92aWV3XCIsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIGEgbmFtZWQgbW9kZWwgdmlldyBhbmQgYXBwZW5kIGl0cyBIVE1MIHRvIGEgY29udGFpbmVyIGVsZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgdmlldyh7XG4gICAgICAgICB2aWV3TmFtZSA9IFwiaHRtbF9saXN0X3RlbXBsYXRlXCIsXG4gICAgICAgICBtb2RlbFF1ZXJ5ID0ge30sXG4gICAgICAgICBjYlJlc29sdmUgPSBudWxsLFxuICAgICAgICAgY2JSZWplY3QgPSBudWxsLFxuICAgICAgICAgdGVtcGxhdGVDb250ZXh0ID0ge30sXG4gICAgICAgICBldmVudFR5cGUgPSBcIm5hbWVkX3ZpZXdcIixcbiAgICAgICB9KSB7XG4gICAgbGV0ICRkaXZMaXN0ID0gJCgnPGRpdiBjbGFzcz1cImNvbnRhaW5lci1mbHVpZFwiPicpO1xuICAgIHRoaXMuaXNDb25uZWN0ZWQoKS50aGVuKCgpID0+IHtcbiAgICAgIGNvbnN0IGV2ZW50X2lkID0gdXVpZHY0KCk7XG4gICAgICB0aGlzLnNvY2tldC5zZW5kKFxuICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgZXZlbnQ6IFwibW9kZWxcIixcbiAgICAgICAgICBldmVudF90eXBlOiBldmVudFR5cGUsXG4gICAgICAgICAgZXZlbnRfaWQsXG4gICAgICAgICAgYXJnczoge1xuICAgICAgICAgICAgdmlld19uYW1lOiB2aWV3TmFtZSxcbiAgICAgICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICAgICAgbW9kZWxfcXVlcnk6IG1vZGVsUXVlcnksXG4gICAgICAgICAgICB0ZW1wbGF0ZV9jb250ZXh0OiB0ZW1wbGF0ZUNvbnRleHQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICApO1xuXG4gICAgICB0aGlzLm9wZW5SZXF1ZXN0W2V2ZW50X2lkXSA9IFtcbiAgICAgICAgKGRhdGEpID0+IHtcbiAgICAgICAgICAkZGl2TGlzdC5hcHBlbmQoZGF0YS5odG1sKTtcbiAgICAgICAgICBhcHAucmVmcmVzaCgkZGl2TGlzdCk7XG4gICAgICAgICAgY2JSZXNvbHZlICYmIGNiUmVzb2x2ZShkYXRhKTtcbiAgICAgICAgfSxcbiAgICAgICAgKHJlcykgPT4ge1xuICAgICAgICAgIGNiUmVqZWN0ICYmIGNiUmVqZWN0KHJlcyk7XG4gICAgICAgIH0sXG4gICAgICBdO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuICRkaXZMaXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgZGV0YWlsLXZpZXcgZW5kcG9pbnQgZm9yIGEgc2luZ2xlIG1vZGVsIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIF9zZW5kRGV0YWlsVmlldyh7XG4gICAgICAgICAgICAgICAgICAgIHBrID0gbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgaWQgPSBudWxsLFxuICAgICAgICAgICAgICAgICAgICBjYlJlc29sdmUgPSBudWxsLFxuICAgICAgICAgICAgICAgICAgICBjYlJlamVjdCA9IG51bGwsXG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlQ29udGV4dCA9IHt9LFxuICAgICAgICAgICAgICAgICAgfSkge1xuICAgIHBrID8/PSBpZDtcbiAgICBwayA9IG5vcm1hbGl6ZVBrKHBrKTtcbiAgICBsZXQgJGRpdkxpc3QgPSAkKCc8ZGl2IGNsYXNzPVwiY29udGFpbmVyLWZsdWlkXCI+Jyk7XG5cbiAgICB0aGlzLmlzQ29ubmVjdGVkKCkudGhlbigoKSA9PiB7XG4gICAgICBjb25zdCBldmVudF9pZCA9IHV1aWR2NCgpO1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgZXZlbnRfdHlwZTogXCJkZXRhaWxfdmlld1wiLFxuICAgICAgICAgIGV2ZW50X2lkLFxuICAgICAgICAgIGFyZ3M6IHtcbiAgICAgICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICAgICAgbW9kZWxfcXVlcnk6IHRoaXMubW9kZWxRdWVyeSxcbiAgICAgICAgICAgIGlkOiBwayxcbiAgICAgICAgICAgIHBrLFxuICAgICAgICAgICAgdGVtcGxhdGVfY29udGV4dDogdGVtcGxhdGVDb250ZXh0LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgdGhpcy5vcGVuUmVxdWVzdFtldmVudF9pZF0gPSBbXG4gICAgICAgIChkYXRhKSA9PiB7XG4gICAgICAgICAgJGRpdkxpc3QuYXBwZW5kKGRhdGEuaHRtbCk7XG4gICAgICAgICAgYXBwLnJlZnJlc2goJGRpdkxpc3QpO1xuICAgICAgICAgIGNiUmVzb2x2ZSAmJiBjYlJlc29sdmUoZGF0YSk7XG4gICAgICAgIH0sXG4gICAgICAgIChyZXMpID0+IHtcbiAgICAgICAgICBjYlJlamVjdCAmJiBjYlJlamVjdChyZXMpO1xuICAgICAgICB9LFxuICAgICAgXTtcbiAgICB9KTtcblxuICAgIHJldHVybiAkZGl2TGlzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaCBhIG1vZGVsIGZvcm0gZnJhZ21lbnQgYW5kIGF0dGFjaCB0aGUgU0RDIGZvcm0gbWV0YWRhdGEgZXhwZWN0ZWQgYnlcbiAgICogdGhlIHJlc3Qgb2YgdGhlIGNsaWVudC5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50VHlwZVxuICAgKiBAcGFyYW0ge1NkY01vZGVsfSBtb2RlbE9ialxuICAgKiBAcGFyYW0gZm9ybU5hbWVcbiAgICogQHBhcmFtICRkaXZGb3JtXG4gICAqIEBwYXJhbSBjYlJlc29sdmVcbiAgICogQHBhcmFtIGNiUmVqZWN0XG4gICAqIEBwYXJhbSBmb3JtSWRcbiAgICovXG4gIGdldEZvcm0oeyBtb2RlbE9iaiwgZXZlbnRUeXBlLCBmb3JtTmFtZSwgJGRpdkZvcm0sIGNiUmVzb2x2ZSwgY2JSZWplY3QsIGZvcm1JZCB9KSB7XG4gICAgY29uc3QgZXZlbnRfaWQgPSB1dWlkdjQoKTtcbiAgICBjb25zdCBwayA9IG1vZGVsT2JqLmlkID8/IC0xO1xuICAgIHRoaXMuaXNDb25uZWN0ZWQoKS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBldmVudDogXCJtb2RlbFwiLFxuICAgICAgICAgIGV2ZW50X3R5cGU6IGV2ZW50VHlwZSxcbiAgICAgICAgICBldmVudF9pZCxcbiAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgIGlkOiBwayxcbiAgICAgICAgICAgIHBrLFxuICAgICAgICAgICAgZm9ybV9uYW1lOiBmb3JtTmFtZSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBjbGFzc05hbWUgPSBwayA9PT0gbnVsbCB8fCBwayA9PT0gLTEgPyBcImNyZWF0ZVwiIDogXCJlZGl0XCI7XG5cbiAgICB0aGlzLm9wZW5SZXF1ZXN0W2V2ZW50X2lkXSA9IFtcbiAgICAgIChkYXRhKSA9PiB7XG4gICAgICAgICRkaXZGb3JtLmFwcGVuZChkYXRhLmh0bWwpO1xuICAgICAgICBsZXQgJGZvcm0gPSAkZGl2Rm9ybVxuICAgICAgICAgIC5jbG9zZXN0KFwiZm9ybVwiKVxuICAgICAgICAgIC5hZGRDbGFzcyhcbiAgICAgICAgICAgIGBzZGMtbW9kZWwtJHtjbGFzc05hbWV9LWZvcm0gc2RjLW1vZGVsLWZvcm0gJHtmb3JtSWR9YCxcbiAgICAgICAgICApXG4gICAgICAgICAgLmRhdGEoXCJtb2RlbFwiLCBtb2RlbE9iailcbiAgICAgICAgICAuZGF0YShcIm1vZGVsX3BrXCIsIHBrKVxuICAgICAgICAgIC5kYXRhKFwiZm9ybV9uYW1lXCIsIGZvcm1OYW1lKVxuICAgICAgICAgIC5hdHRyKCdTZGNNb2RlbE5hbWUnLCB0aGlzLm1vZGVsTmFtZSlcbiAgICAgICAgICAuYXR0cignU2RjTW9kZWxQSycsIHBrKTtcbiAgICAgICAgbW9kZWxPYmouYWRkRm9ybSgkZm9ybSk7XG4gICAgICAgIGlmICgkZm9ybS5sZW5ndGggPiAwICYmICEkZm9ybVswXS5oYXNBdHRyaWJ1dGUoXCJzZGNfc3VibWl0XCIpKSB7XG4gICAgICAgICAgJGZvcm0uYXR0cihcInNkY19zdWJtaXRcIiwgXCJzdWJtaXRNb2RlbEZvcm1EaXN0cmlidXRvclwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFwcC5yZWZyZXNoKCRkaXZGb3JtKS50aGVuKCgpID0+IG51bGwpO1xuICAgICAgICBjYlJlc29sdmUgJiYgY2JSZXNvbHZlKGRhdGEpO1xuICAgICAgfSxcbiAgICAgIChyZXMpID0+IHtcbiAgICAgICAgY2JSZWplY3QgJiYgY2JSZWplY3QocmVzKTtcbiAgICAgIH0sXG4gICAgXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaCBhIHNpbmdsZSBtb2RlbCBpbnN0YW5jZSBtYXRjaGluZyB0aGUgY3VycmVudCBxdWVyeS5cbiAgICpcbiAgICogQHBhcmFtIHs/b2JqZWN0fSBtb2RlbFF1ZXJ5XG4gICAqIEBwYXJhbSB7P2Jvb2xlYW59IGRvTm90TG9hZCB0cnVlIGlmIG1vZGVsUXVlcnkgY29udGFpbnMgaWQgb3IgcGsgYW5kIG9iamVjdCBkb2VzIG5vdCBuZWVkIHRvIGJlIGxvYWRlZC5cbiAgICogQHJldHVybnMge1Byb21pc2U8U2RjTW9kZWw+fVxuICAgKi9cbiAgYXN5bmMgZ2V0KG1vZGVsUXVlcnkgPSBudWxsLCBkb05vdExvYWQgPSBmYWxzZSkge1xuICAgIGlmIChkb05vdExvYWQpIHtcbiAgICAgIGNvbnN0IGlkID0gbW9kZWxRdWVyeT8uaWQgPz8gdGhpcy5tb2RlbFF1ZXJ5Py5pZDtcbiAgICAgIGlmKG1vZGVsUXVlcnkpIHtcbiAgICAgICAgdGhpcy5zZXRGaWx0ZXIobW9kZWxRdWVyeSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5ieUlkKGlkKSA/PyB0aGlzLm5ldyhtb2RlbFF1ZXJ5IHx8IHRoaXMubW9kZWxRdWVyeSk7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMubG9hZChtb2RlbFF1ZXJ5KTtcbiAgICBpZiAodGhpcy5sZW5ndGggIT09IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgbW9kZWwgcXVlcnkgcmV0dXJucyAke3RoaXMubGVuZ3RofSBidXQgb25seSAxIGV4cGVjdGVkLmApO1xuICAgIH1cblxuICAgIHRoaXMuYWRkRmlsdGVyKHsgaWQ6IHRoaXMudmFsdWVzTGlzdFswXS5pZCB9KTtcblxuICAgIHJldHVybiB0aGlzLnZhbHVlc0xpc3RbMF07XG4gIH1cblxuICBkZXRhaWxWaWV3KHsgcGssIGNiUmVzb2x2ZSA9IG51bGwsIGNiUmVqZWN0ID0gbnVsbCwgdGVtcGxhdGVDb250ZXh0ID0ge30gfSkge1xuICAgIHJldHVybiB0aGlzLl9zZW5kRGV0YWlsVmlldyh7XG4gICAgICBpZDogcGssXG4gICAgICBjYlJlc29sdmUsXG4gICAgICBjYlJlamVjdCxcbiAgICAgIHRlbXBsYXRlQ29udGV4dCxcbiAgICB9KTtcbiAgfVxuXG4gIGxpc3RWaWV3KHsgbW9kZWxRdWVyeSA9IHt9LCBzZWFyY2hWYWx1ZXMgPSB7fSwgY2JSZXNvbHZlID0gbnVsbCwgY2JSZWplY3QgPSBudWxsLCB0ZW1wbGF0ZUNvbnRleHQgPSB7fSB9KSB7XG4gICAgcmV0dXJuIHRoaXMuX3NlbmRMaXN0Vmlldyh7XG4gICAgICBtb2RlbFF1ZXJ5OiBPYmplY3QuYXNzaWduKHt9LCB0aGlzLm1vZGVsUXVlcnksIG1vZGVsUXVlcnksIHsgJ19fc2VhcmNoX3ZhbHVlcyc6IHNlYXJjaFZhbHVlcyB9KSxcbiAgICAgIGNiUmVzb2x2ZSxcbiAgICAgIGNiUmVqZWN0LFxuICAgICAgdGVtcGxhdGVDb250ZXh0LFxuICAgIH0pO1xuICB9XG5cbiAgc2F2ZSh7IHBrID0gbnVsbCwgaWQgPSBudWxsLCBmb3JtTmFtZSA9IFwiZWRpdF9mb3JtXCIsIGRhdGEgPSBudWxsIH0gPSB7fSkge1xuICAgIHBrID8/PSBpZDtcbiAgICBjb25zdCBub3JtUGsgPSBub3JtYWxpemVQayhwayk7XG4gICAgcmV0dXJuIHRoaXMuaXNDb25uZWN0ZWQoKS50aGVuKCgpID0+IHtcbiAgICAgIGxldCBlbGVtTGlzdDtcbiAgICAgIGlmIChub3JtUGsgPiAtMSkge1xuICAgICAgICBjb25zdCBlbGVtID0gdGhpcy5ieUlkKG5vcm1Qayk7XG4gICAgICAgIGlmICghZWxlbSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgU2RjTW9kZWxFcnJvcihgRWxlbWVudCBub3QgZm91bmQgd2l0aCBJRDogJHtub3JtUGt9YCkpO1xuICAgICAgICB9XG4gICAgICAgIGVsZW1MaXN0ID0gW2VsZW1dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZWxlbUxpc3QgPSB0aGlzLnZhbHVlc0xpc3Q7XG4gICAgICB9XG4gICAgICBsZXQgcExpc3QgPSBbXTtcbiAgICAgIGVsZW1MaXN0LmZvckVhY2goKGVsZW0pID0+IHtcbiAgICAgICAgY29uc3QgZXZlbnRfaWQgPSB1dWlkdjQoKTtcbiAgICAgICAgcExpc3QucHVzaChcbiAgICAgICAgICBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9yZWFkRmlsZXMoZWxlbSkudGhlbigoZmlsZXMpID0+IHtcbiAgICAgICAgICAgICAgY29uc3Qgc2VuZERhdGEgPSBkYXRhID8geyAuLi5kYXRhIH0gOiBlbGVtLnNlcmlhbGl6ZSgpO1xuICAgICAgICAgICAgICBzZW5kRGF0YS5pZCA9IGVsZW0uaWQ7XG4gICAgICAgICAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICAgZXZlbnQ6IFwibW9kZWxcIixcbiAgICAgICAgICAgICAgICAgIGV2ZW50X3R5cGU6IFwic2F2ZVwiLFxuICAgICAgICAgICAgICAgICAgZXZlbnRfaWQsXG4gICAgICAgICAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1fbmFtZTogZm9ybU5hbWUsXG4gICAgICAgICAgICAgICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICAgICAgICAgICAgICBtb2RlbF9xdWVyeTogdGhpcy5tb2RlbFF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICBkYXRhOiBzZW5kRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgaWQ6IHNlbmREYXRhLmlkLFxuICAgICAgICAgICAgICAgICAgICBwazogc2VuZERhdGEuaWQsXG4gICAgICAgICAgICAgICAgICAgIGZpbGVzOiBmaWxlcyxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtldmVudF9pZF0gPSBbXG4gICAgICAgICAgICAgICAgKHJlcykgPT4ge1xuICAgICAgICAgICAgICAgICAgbGV0IGRhdGEgPVxuICAgICAgICAgICAgICAgICAgICB0eXBlb2YgcmVzLmRhdGEuaW5zdGFuY2UgPT09IFwic3RyaW5nXCJcbiAgICAgICAgICAgICAgICAgICAgICA/IEpTT04ucGFyc2UocmVzLmRhdGEuaW5zdGFuY2UpXG4gICAgICAgICAgICAgICAgICAgICAgOiByZXMuZGF0YS5pbnN0YW5jZTtcbiAgICAgICAgICAgICAgICAgIHJlcy5kYXRhLmluc3RhbmNlID0gdGhpcy5fcGFyc2VTZXJ2ZXJSZXMoZGF0YSk7XG4gICAgICAgICAgICAgICAgICByZXNvbHZlKHJlcyk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZWplY3QsXG4gICAgICAgICAgICAgIF07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwocExpc3QpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBpbnN0YW5jZSBpbiB0aGUgREIuXG4gICAqXG4gICAqIEBwYXJhbSB7e2VsZW0/OiBTZGNNb2RlbCwgZGF0YT86IG9iamVjdH0gfCBvYmplY3R9IGFyZ1xuICAgKiAgIEVpdGhlciBhbiBvcHRpb25zIG9iamVjdCBjb250YWluaW5nIGBlbGVtYCBhbmQvb3IgYGRhdGFgLFxuICAgKiAgIG9yIGBkYXRhYCBkaXJlY3RseS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogY3JlYXRlKHsgZWxlbSwgZGF0YSB9KTtcbiAgICogY3JlYXRlKHsgZWxlbSB9KTtcbiAgICogY3JlYXRlKGRhdGEpO1xuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx1bmtub3duPn1cbiAgICovXG4gIGNyZWF0ZShhcmcgPSBudWxsKSB7XG4gICAgbGV0IHsgZWxlbSA9IG51bGwsIGRhdGEgPSBudWxsIH0gPSBpc0NyZWF0ZU9wdGlvbnMoYXJnKSA/IGFyZyA6IHsgZGF0YTogYXJnIH07XG4gICAgaWYgKGRhdGEgJiYgdHlwZW9mIGRhdGEgPT09IFwib2JqZWN0XCIgJiYgT2JqZWN0LmtleXMoZGF0YSkubGVuZ3RoID09PSAwKSB7XG4gICAgICBkYXRhID0gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCBldmVudF9pZCA9IHV1aWR2NCgpO1xuICAgIGlmICghZWxlbSkge1xuICAgICAgZWxlbSA9IHRoaXMubmV3KGRhdGEpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5pc0Nvbm5lY3RlZCgpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgdGhpcy5fcmVhZEZpbGVzKGVsZW0pLnRoZW4oKGZpbGVzKSA9PiB7XG4gICAgICAgICAgdGhpcy5zb2NrZXQuc2VuZChcbiAgICAgICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgZXZlbnQ6IFwibW9kZWxcIixcbiAgICAgICAgICAgICAgZXZlbnRfdHlwZTogXCJjcmVhdGVcIixcbiAgICAgICAgICAgICAgZXZlbnRfaWQsXG4gICAgICAgICAgICAgIGFyZ3M6IHtcbiAgICAgICAgICAgICAgICBtb2RlbF9uYW1lOiB0aGlzLm1vZGVsTmFtZSxcbiAgICAgICAgICAgICAgICBtb2RlbF9xdWVyeTogdGhpcy5tb2RlbFF1ZXJ5LFxuICAgICAgICAgICAgICAgIGRhdGE6IGRhdGEgPz8gZWxlbT8uc2VyaWFsaXplKCkgPz8ge30sXG4gICAgICAgICAgICAgICAgZmlsZXM6IGZpbGVzLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gW1xuICAgICAgICAgICAgKHJlcykgPT4ge1xuICAgICAgICAgICAgICBsZXQgZGF0YSA9XG4gICAgICAgICAgICAgICAgdHlwZW9mIHJlcy5kYXRhLmluc3RhbmNlID09PSBcInN0cmluZ1wiXG4gICAgICAgICAgICAgICAgICA/IEpTT04ucGFyc2UocmVzLmRhdGEuaW5zdGFuY2UpXG4gICAgICAgICAgICAgICAgICA6IHJlcy5kYXRhLmluc3RhbmNlO1xuICAgICAgICAgICAgICBpZiAoZWxlbSkge1xuICAgICAgICAgICAgICAgIGVsZW0uaWQgPSBkYXRhWzBdPy5pZCB8fCBkYXRhWzBdPy5waztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXMuZGF0YS5pbnN0YW5jZSA9IHRoaXMuX3BhcnNlU2VydmVyUmVzKGRhdGEpWzBdO1xuICAgICAgICAgICAgICByZXNvbHZlKHJlcyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVqZWN0LFxuICAgICAgICAgIF07XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRW5zdXJlIHRoZSB3ZWJzb2NrZXQgaXMgb3BlbiBhbmQgaGFzIGNvbXBsZXRlZCB0aGUgc2VydmVyLXNpZGUgY29ubmVjdFxuICAgKiBoYW5kc2hha2UgYmVmb3JlIGlzc3VpbmcgbW9kZWwgcmVxdWVzdHMuXG4gICAqXG4gICAqIE11bHRpcGxlIGNhbGxlcnMgY2FuIGFycml2ZSB3aGlsZSBhIGNvbm5lY3Rpb24gYXR0ZW1wdCBpcyBhbHJlYWR5IGluXG4gICAqIHByb2dyZXNzLiBJbiB0aGF0IGNhc2UgdGhleSBhcmUgcXVldWVkIGJlaGluZCB0aGUgc2FtZSBzeW50aGV0aWMgcmVxdWVzdCBpZC5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBpc0Nvbm5lY3RlZCgpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgaWYgKHRoaXMuX2lzQ29ubmVjdGVkKSB7XG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICF0aGlzLl9pc0Nvbm5lY3RpbmdQcm9jZXNzIHx8XG4gICAgICAgICF0aGlzLm9wZW5SZXF1ZXN0W0NPTk5FQ1RJTkdfUkVRVUVTVF9JRF1cbiAgICAgICkge1xuICAgICAgICB0aGlzLl9pc0Nvbm5lY3RpbmdQcm9jZXNzID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtDT05ORUNUSU5HX1JFUVVFU1RfSURdID0gWygpID0+IHtcbiAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICB9XTtcbiAgICAgICAgdGhpcy5fY29ubmVjdFRvU2VydmVyKCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgcmVzb2x2ZSh0aGlzLl9jaGVja0Nvbm5lY3Rpb24oKSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgW3Jlc29sdmVPcmlnaW4sIHJlamVjdE9yaWdpbl0gPVxuICAgICAgICAgIHRoaXMub3BlblJlcXVlc3RbQ09OTkVDVElOR19SRVFVRVNUX0lEXTtcbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtDT05ORUNUSU5HX1JFUVVFU1RfSURdID0gW1xuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIHJlc29sdmVPcmlnaW4oKTtcbiAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgIHJlamVjdE9yaWdpbigpO1xuICAgICAgICAgICAgcmVqZWN0KCk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZSB0aGUgd2Vic29ja2V0IGFuZCBkaXNhYmxlIGF1dG9tYXRpYyByZWNvbm5lY3QgZm9yIHRoaXMgcXVlcnlzZXQuXG4gICAqL1xuICBjbG9zZSgpIHtcbiAgICBpZiAodGhpcy5zb2NrZXQpIHtcbiAgICAgIHRoaXMuX2F1dG9SZWNvbm5lY3QgPSBmYWxzZTtcbiAgICAgIHRoaXMuc29ja2V0Lm9uY2xvc2UgPSAoKSA9PiB7XG4gICAgICB9O1xuICAgICAgdGhpcy5zb2NrZXQuY2xvc2UoKTtcbiAgICAgIGRlbGV0ZSB0aGlzW1wic29ja2V0XCJdO1xuICAgIH1cblxuICAgIHRoaXMudmFsdWVzTGlzdC5mb3JFYWNoKChlbGVtKSA9PiB7XG4gICAgICBlbGVtLl9vbkNsb3NlKClcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGxvYWQgYXR0YWNoZWQgYEZpbGVgIHZhbHVlcyBpbiBmaXhlZC1zaXplIGNodW5rcyBiZWZvcmUgc2F2ZS9jcmVhdGUgY2FsbHMuXG4gICAqXG4gICAqIEBwYXJhbSB7U2RjTW9kZWx9IGVsZW1cbiAgICogQHJldHVybnMge1Byb21pc2U8b2JqZWN0Pn1cbiAgICovXG4gIF9yZWFkRmlsZXMoZWxlbSkge1xuICAgIGxldCB0b1NvbHZlID0gW107XG4gICAgbGV0IGZpbGVzID0ge307XG4gICAgaWYgKCFlbGVtKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZpbGVzKTtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoZWxlbS5jb25zdHJ1Y3Rvci5maWVsZHMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgY29uc3QgdmFsdWUgPSBlbGVtW2tleV07XG4gICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBGaWxlKSB7XG4gICAgICAgIHRvU29sdmUucHVzaChcbiAgICAgICAgICBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBldmVudF9pZCA9IHV1aWR2NCgpO1xuICAgICAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtldmVudF9pZF0gPSBbcmVzb2x2ZSwgcmVqZWN0XTtcblxuICAgICAgICAgICAgdmFsdWUuYXJyYXlCdWZmZXIoKS50aGVuKChidWZmZXIpID0+IHtcbiAgICAgICAgICAgICAgbGV0IHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlcik7XG4gICAgICAgICAgICAgIGxldCBudW1iZXJPZkNodW5rcyA9IE1hdGguY2VpbChyZXN1bHQubGVuZ3RoIC8gTUFYX0ZJTEVfVVBMT0FEKTtcbiAgICAgICAgICAgICAgZmlsZXNba2V5XSA9IHtcbiAgICAgICAgICAgICAgICBpZDogZXZlbnRfaWQsXG4gICAgICAgICAgICAgICAgZmlsZV9uYW1lOiB2YWx1ZS5uYW1lLFxuICAgICAgICAgICAgICAgIGZpZWxkX25hbWU6IGtleSxcbiAgICAgICAgICAgICAgICBjb250ZW50X2xlbmd0aDogdmFsdWUuc2l6ZSxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZkNodW5rczsgKytpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2h1bmsgPSBBcnJheS5mcm9tKHJlc3VsdC5zbGljZShcbiAgICAgICAgICAgICAgICAgIE1BWF9GSUxFX1VQTE9BRCAqIGksXG4gICAgICAgICAgICAgICAgICBNQVhfRklMRV9VUExPQUQgKiAoaSArIDEpLFxuICAgICAgICAgICAgICAgICkpO1xuICAgICAgICAgICAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50OiBcIm1vZGVsXCIsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50X3R5cGU6IFwidXBsb2FkXCIsXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50X2lkLFxuICAgICAgICAgICAgICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgY2h1bmssXG4gICAgICAgICAgICAgICAgICAgICAgaWR4OiBpLFxuICAgICAgICAgICAgICAgICAgICAgIG51bWJlcl9vZl9jaHVua3M6IG51bWJlck9mQ2h1bmtzLFxuICAgICAgICAgICAgICAgICAgICAgIGZpbGVfbmFtZTogdmFsdWUubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICBmaWVsZF9uYW1lOiBrZXksXG4gICAgICAgICAgICAgICAgICAgICAgY29udGVudF9sZW5ndGg6IHZhbHVlLnNpemUsXG4gICAgICAgICAgICAgICAgICAgICAgY29udGVudF90eXBlOiB2YWx1ZS50eXBlLFxuICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICAgICAgICAgICAgICAgIG1vZGVsX3F1ZXJ5OiB0aGlzLm1vZGVsUXVlcnksXG4gICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMuX2Nsb3NlT3BlblJlcXVlc3QoZXZlbnRfaWQpO1xuICAgICAgICAgICAgICByZWplY3QoZXJyKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHRvU29sdmUpLnRoZW4oKCkgPT4ge1xuICAgICAgcmV0dXJuIGZpbGVzO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJvdXRlIHdlYnNvY2tldCByZXNwb25zZXMgdG8gdGhlIG1hdGNoaW5nIHBlbmRpbmcgcmVxdWVzdCBhbmQgdXBkYXRlIGxvY2FsXG4gICAqIHN0YXRlIHdoZW4gdGhlIHNlcnZlciBzZW5kcyBtb2RlbCBwYXlsb2Fkcy5cbiAgICpcbiAgICogQHBhcmFtIHtNZXNzYWdlRXZlbnR9IGVcbiAgICovXG4gIGFzeW5jIF9vbk1lc3NhZ2UoZSkge1xuICAgIGxldCBkYXRhID0gSlNPTi5wYXJzZShlLmRhdGEpO1xuICAgIGlmIChkYXRhLmlzX2Vycm9yKSB7XG4gICAgICBpZiAoT2JqZWN0Lmhhc093bih0aGlzLm9wZW5SZXF1ZXN0LCBkYXRhLmV2ZW50X2lkKSkge1xuICAgICAgICB0aGlzLm9wZW5SZXF1ZXN0W2RhdGEuZXZlbnRfaWRdWzFdKG5ldyBTZGNNb2RlbEVycm9yKGRhdGEpKTtcbiAgICAgICAgdGhpcy5fY2xvc2VPcGVuUmVxdWVzdChkYXRhLmV2ZW50X2lkKTtcbiAgICAgIH1cbiAgICAgIGlmIChkYXRhLm1zZyB8fCBkYXRhLmhlYWRlcikge1xuICAgICAgICB0cmlnZ2VyKFwicHVzaEVycm9yTXNnXCIsIGRhdGEuaGVhZGVyIHx8IFwiXCIsIGRhdGEubXNnIHx8IFwiXCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZGF0YS50eXBlID09PSBcImNvbm5lY3RcIikge1xuICAgICAgICB0aGlzLm9wZW5SZXF1ZXN0W0NPTk5FQ1RJTkdfUkVRVUVTVF9JRF1bMV0obmV3IFNkY01vZGVsRXJyb3IoZGF0YSkpO1xuICAgICAgICB0aGlzLl9jbG9zZU9wZW5SZXF1ZXN0KENPTk5FQ1RJTkdfUkVRVUVTVF9JRCk7XG4gICAgICAgIHRoaXMuX2F1dG9SZWNvbm5lY3QgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zb2NrZXQuY2xvc2UoKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGRhdGEubXNnIHx8IGRhdGEuaGVhZGVyKSB7XG4gICAgICAgIHRyaWdnZXIoXCJwdXNoTXNnXCIsIGRhdGEuaGVhZGVyIHx8IFwiXCIsIGRhdGEubXNnIHx8IFwiXCIpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZGF0YS50eXBlID09PSBcImNvbm5lY3RcIikge1xuICAgICAgICB0aGlzLl9pc0Nvbm5lY3RlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuX2lzQ29ubmVjdGluZ1Byb2Nlc3MgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5vcGVuUmVxdWVzdFtDT05ORUNUSU5HX1JFUVVFU1RfSURdWzBdKGRhdGEpO1xuICAgICAgICB0aGlzLl9jbG9zZU9wZW5SZXF1ZXN0KENPTk5FQ1RJTkdfUkVRVUVTVF9JRCk7XG4gICAgICB9IGVsc2UgaWYgKFtcImxvYWRcIiwgXCJsaXN0X3ZpZXdcIiwgXCJuYW1lZF92aWV3XCIsIFwiZGV0YWlsX3ZpZXdcIl0uaW5jbHVkZXMoZGF0YS50eXBlKSkge1xuICAgICAgICBjb25zdCBqc29uUmVzID0gSlNPTi5wYXJzZShkYXRhLmFyZ3MuZGF0YSk7XG4gICAgICAgIGRhdGEuYXJncy5kYXRhID0gYXdhaXQgdGhpcy5fcGFyc2VTZXJ2ZXJSZXMoanNvblJlcyk7XG4gICAgICB9IGVsc2UgaWYgKGRhdGEudHlwZSA9PT0gXCJvbl91cGRhdGVcIiB8fCBkYXRhLnR5cGUgPT09IFwib25fY3JlYXRlXCIpIHtcbiAgICAgICAgY29uc3QganNvblJlcyA9IEpTT04ucGFyc2UoZGF0YS5hcmdzLmRhdGEpO1xuXG4gICAgICAgIGxldCBvYmogPSBhd2FpdCB0aGlzLl9wYXJzZVNlcnZlclJlcyhqc29uUmVzKTtcbiAgICAgICAgbGV0IGNiO1xuXG4gICAgICAgIGlmIChkYXRhLnR5cGUgPT09IFwib25fY3JlYXRlXCIpIHtcbiAgICAgICAgICBjYiA9IHRoaXMub25DcmVhdGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2IgPSB0aGlzLm9uVXBkYXRlO1xuICAgICAgICB9XG5cbiAgICAgICAgY2Iob2JqKTtcbiAgICAgICAgZGF0YS5hcmdzLmRhdGEgPSBvYmo7XG4gICAgICB9IGVsc2UgaWYgKGRhdGEudHlwZSA9PT0gXCJvbl9kZWxldGVcIikge1xuICAgICAgICBjb25zdCBpZHMgPSBKU09OLnBhcnNlKGRhdGEuYXJncy5kYXRhKS5tYXAoKHgpID0+IG5vcm1hbGl6ZVBrKHguaWQgPz8geC5waykpO1xuICAgICAgICBjb25zdCByZW1vdmVkID0gdGhpcy5fcmVtb3ZlSWRzKGlkcyk7XG4gICAgICAgICh0aGlzLm9uRGVsZXRlID8/IHRoaXMub25VcGRhdGUpKHJlbW92ZWQpO1xuICAgICAgICBkYXRhLmFyZ3MuZGF0YSA9IHJlbW92ZWQ7XG4gICAgICB9XG5cbiAgICAgIGxldCBpbnN0YW5jZSA9IGRhdGEuZGF0YT8uaW5zdGFuY2U7XG4gICAgICBpZiAoaW5zdGFuY2UpIHtcbiAgICAgICAgZGF0YS5kYXRhLmluc3RhbmNlID0gSlNPTi5wYXJzZShkYXRhLmRhdGEuaW5zdGFuY2UpO1xuICAgICAgfVxuXG4gICAgICBpZiAoT2JqZWN0Lmhhc093bih0aGlzLm9wZW5SZXF1ZXN0LCBkYXRhLmV2ZW50X2lkKSkge1xuICAgICAgICB0aGlzLm9wZW5SZXF1ZXN0W2RhdGEuZXZlbnRfaWRdWzBdKGRhdGEpO1xuICAgICAgICB0aGlzLl9jbG9zZU9wZW5SZXF1ZXN0KGRhdGEuZXZlbnRfaWQpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXYWl0IHVudGlsIGFsbCBpbi1mbGlnaHQgd2Vic29ja2V0IHJlcXVlc3RzIGZvciB0aGlzIHF1ZXJ5c2V0IGFyZSByZXNvbHZlZC5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59XG4gICAqL1xuICBub09wZW5SZXF1ZXN0cygpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLm9wZW5SZXF1ZXN0KS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fb25Ob09wZW5SZXF1ZXN0cy5wdXNoKHJlc29sdmUpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZSBhIGNvbXBsZXRlZCByZXF1ZXN0IGFuZCB3YWtlIGFueSBgbm9PcGVuUmVxdWVzdHMoKWAgd2FpdGVycyB3aGVuIHRoZVxuICAgKiByZXF1ZXN0IG1hcCBiZWNvbWVzIGVtcHR5LlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnRJZFxuICAgKi9cbiAgX2Nsb3NlT3BlblJlcXVlc3QoZXZlbnRJZCkge1xuICAgIGRlbGV0ZSB0aGlzLm9wZW5SZXF1ZXN0W2V2ZW50SWRdO1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLm9wZW5SZXF1ZXN0KS5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMuX29uTm9PcGVuUmVxdWVzdHMuZm9yRWFjaCgoeCkgPT4geCgpKTtcbiAgICAgIHRoaXMuX29uTm9PcGVuUmVxdWVzdHMgPSBbXTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXN0YWJsaXNoIHRoZSByYXcgd2Vic29ja2V0IGNvbm5lY3Rpb24gZm9yIHRoaXMgcXVlcnlzZXQuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICAgKi9cbiAgX2Nvbm5lY3RUb1NlcnZlcigpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIGNvbnN0IG1vZGVsSWRlbnRpZmllciA9XG4gICAgICAgIGAke3RoaXMubW9kZWxOYW1lfWAgKyAodGhpcy5tb2RlbElkID4gMCA/IGAvJHt0aGlzLm1vZGVsSWR9YCA6IFwiXCIpO1xuICAgICAgaWYgKHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCA9PT0gXCJodHRwczpcIikge1xuICAgICAgICB0aGlzLnNvY2tldCA9IG5ldyBXZWJTb2NrZXQoXG4gICAgICAgICAgYHdzczovLyR7d2luZG93LmxvY2F0aW9uLmhvc3R9L3NkY193cy9tb2RlbC8ke21vZGVsSWRlbnRpZmllcn1gLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zb2NrZXQgPSBuZXcgV2ViU29ja2V0KFxuICAgICAgICAgIGB3czovLyR7d2luZG93LmxvY2F0aW9uLmhvc3R9L3NkY193cy9tb2RlbC8ke21vZGVsSWRlbnRpZmllcn1gLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNvY2tldC5vbm1lc3NhZ2UgPSB0aGlzLl9vbk1lc3NhZ2UuYmluZCh0aGlzKTtcblxuICAgICAgdGhpcy5zb2NrZXQub25jbG9zZSA9IChlKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgYFNEQyBNb2RlbCAoJHt0aGlzLm1vZGVsTmFtZX0sICR7dGhpcy5tb2RlbElkfSkgU29ja2V0IGNsb3NlZCB1bmV4cGVjdGVkbHlgLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLl9pc0Nvbm5lY3RlZCA9IGZhbHNlO1xuICAgICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIE9iamVjdC52YWx1ZXModGhpcy5vcGVuUmVxdWVzdCkpIHtcbiAgICAgICAgICB2YWx1ZVsxXShlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9wZW5SZXF1ZXN0ID0ge307XG5cbiAgICAgICAgdGhpcy5faXNDb25uZWN0aW5nUHJvY2VzcyA9IGZhbHNlO1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5fYXV0b1JlY29ubmVjdCAmJiAhdGhpcy5faXNDb25uZWN0ZWQpIHtcbiAgICAgICAgICAgIC8vIGlzQ29ubmVjdGVkKCkgb3BlbnMgdGhlIHNvY2tldCBhbmQgc2VuZHMgdGhlIGNvbm5lY3QgaGFuZHNoYWtlLCBzb1xuICAgICAgICAgICAgLy8gbGl2ZSB1cGRhdGVzIHdvcmsgYWdhaW4gYW5kIGxhdGVyIHJlcXVlc3RzIHJldXNlIHRoaXMgY29ubmVjdGlvbi5cbiAgICAgICAgICAgIHRoaXMuaXNDb25uZWN0ZWQoKS5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIDEwMDApO1xuICAgICAgfTtcblxuICAgICAgdGhpcy5zb2NrZXQub25lcnJvciA9IChlcnIpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgTW9kZWwgU29ja2V0IGVuY291bnRlcmVkIGVycm9yOiAke2Vycn0gQ2xvc2luZyBzb2NrZXRgKTtcbiAgICAgICAgaWYgKHRoaXMuX2lzQ29ubmVjdGVkKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuc29ja2V0LmNsb3NlKCk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgdGhpcy5zb2NrZXQub25vcGVuID0gKCkgPT4ge1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gdGhlIGFwcGxpY2F0aW9uLWxldmVsIGNvbm5lY3QgaGFuZHNoYWtlIG9uY2UgdGhlIHdlYnNvY2tldCBvcGVucy5cbiAgICpcbiAgICogQHJldHVybnMge1Byb21pc2U8Kj59XG4gICAqL1xuICBfY2hlY2tDb25uZWN0aW9uKCkge1xuICAgIGNvbnN0IGV2ZW50X2lkID0gdXVpZHY0KCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICBldmVudDogXCJtb2RlbFwiLFxuICAgICAgICAgIGV2ZW50X3R5cGU6IFwiY29ubmVjdFwiLFxuICAgICAgICAgIGV2ZW50X2lkLFxuICAgICAgICAgIGFyZ3M6IHtcbiAgICAgICAgICAgIG1vZGVsX25hbWU6IHRoaXMubW9kZWxOYW1lLFxuICAgICAgICAgICAgbW9kZWxfcXVlcnk6IHRoaXMubW9kZWxRdWVyeSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIHRoaXMub3BlblJlcXVlc3RbZXZlbnRfaWRdID0gW3Jlc29sdmUsIHJlamVjdF07XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB0aGUgYmFja2VuZCBtb2RlbCBwYXlsb2FkIGludG8gbG9jYWxseSB0cmFja2VkIG1vZGVsIG9iamVjdHMuXG4gICAqXG4gICAqIEBwYXJhbSB7QXJyYXk8b2JqZWN0Pn0gcmVzdWx0c1xuICAgKi9cbiAgX3BhcnNlU2VydmVyUmVzKHJlc3VsdHMpIHtcbiAgICBjb25zdCBuZXdNb2RlbHMgPSBbXVxuICAgIGZvciAoY29uc3QgeCBvZiByZXN1bHRzKSB7XG4gICAgICBjb25zdCBNb2RlbENsYXNzID0gZ2V0TW9kZWwodGhpcy5tb2RlbE5hbWUpO1xuICAgICAgaWYgKCFNb2RlbENsYXNzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aGlzLm1vZGVsTmFtZX0gaXMgbm8gU2RjTW9kZWwuIG15YmUgdGhlIG1vZGVscyBhciBub3QgaW1wb3J0YWQuYCk7XG4gICAgICB9XG4gICAgICBjb25zdCBuZXdNb2RlbCA9IG5ldyBNb2RlbENsYXNzKHsgJ2lkJzogeC5pZCA/PyB4LnBrLCAuLi54LmZpZWxkcyB9KTtcbiAgICAgIGNvbnN0IGN1cnJlbnRNb2RlbCA9IHRoaXMuYnlJZChuZXdNb2RlbC5pZCk7XG4gICAgICBpZiAoY3VycmVudE1vZGVsKSB7XG4gICAgICAgIGN1cnJlbnRNb2RlbC5zZXRWYWx1ZXMobmV3TW9kZWwpO1xuICAgICAgICBuZXdNb2RlbHMucHVzaChjdXJyZW50TW9kZWwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy52YWx1ZXNMaXN0LnB1c2gobmV3TW9kZWwpO1xuICAgICAgICBuZXdNb2RlbC5fc2V0UXVlcnlTZXQodGhpcywgdHJ1ZSk7XG4gICAgICAgIG5ld01vZGVscy5wdXNoKG5ld01vZGVsKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy52YWx1ZXNMaXN0LnNvcnQoKGEsIGIpID0+IGEuX2lkIC0gYi5faWQpO1xuICAgIHJldHVybiBuZXdNb2RlbHM7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2RjTW9kZWwge1xuICBzdGF0aWMgZmllbGRzID0ge307XG5cbiAgLyoqXG4gICAqIEJhc2UgbW9kZWwgd3JhcHBlciB1c2VkIGJ5IFNEQyBtb2RlbCByZWdpc3RyYXRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbW9kZWxOYW1lXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihtb2RlbE5hbWUpIHtcbiAgICB0aGlzLl9pZCA9IG51bGw7XG4gICAgdGhpcy5fZm9ybXMgPSBbXTtcbiAgICB0aGlzLmxvYWRlZCA9IGZhbHNlO1xuICAgIHRoaXMuZm9ybUlkID0gdXVpZHY0KCk7XG4gICAgdGhpcy5tb2RlbE5hbWUgPSBtb2RlbE5hbWU7XG4gIH1cblxuICAvKipcbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3Q/fSBtb2RlbFF1ZXJ5U2V0XG4gICAqIEBwYXJhbSB7QWJzdHJhY3RTREN9IHBhcmVudFxuICAgKiBAcmV0dXJucyB7U2RjUXVlcnlTZXR9XG4gICAqL1xuICBzdGF0aWMgcXVlcnlTZXQobW9kZWxRdWVyeVNldCA9IG51bGwsIHBhcmVudCA9IG51bGwpIHtcbiAgICBjb25zdCB7IG1vZGVsTmFtZSB9ID0gbmV3IHRoaXMoe30pO1xuICAgIGlmICghcGFyZW50KSB7XG4gICAgICByZXR1cm4gbmV3IFNkY1F1ZXJ5U2V0KG1vZGVsTmFtZSwgbW9kZWxRdWVyeVNldCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmVudC5xdWVyeVNldChtb2RlbE5hbWUsIG1vZGVsUXVlcnlTZXQpO1xuICB9XG5cbiAgYWRkRm9ybSgkZm9ybSkge1xuICAgIC8vIFJlbW92ZSBvbGQgbGlzdGVuZXJzIGlmIGZvcm0gYWxyZWFkeSBzZXRcbiAgICBjb25zdCBvbkNoYW5nZSA9IHRoaXMuX29uQ2hhbmdlLmJpbmQodGhpcyk7XG5cbiAgICB0aGlzLl9mb3Jtcy5wdXNoKCRmb3JtKTtcblxuICAgIGlmICgkZm9ybSkge1xuICAgICAgLy8gQXR0YWNoIGRlbGVnYXRlZCBldmVudCBoYW5kbGVyIHRvIGFsbCBpbnB1dHNcbiAgICAgICRmb3JtLm9uKFxuICAgICAgICBcImlucHV0LmZvcm1XYXRjaGVyIGNoYW5nZS5mb3JtV2F0Y2hlclwiLFxuICAgICAgICBcImlucHV0LCBzZWxlY3QsIHRleHRhcmVhXCIsXG4gICAgICAgIG9uQ2hhbmdlXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIF9vbkNoYW5nZShldmVudCkge1xuICAgIGNvbnN0IHsgbmFtZSB9ID0gZXZlbnQudGFyZ2V0O1xuICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yLmZpZWxkc1tuYW1lXSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpc1tgc2V0JHtuYW1lfWBdKGdldFZhbHVlRnJvbUZpZWxkKGV2ZW50LnRhcmdldCkpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIC8vIEludmFsaWQgaW5wdXQgKGUuZy4gYW4gZW1wdHkgcmVxdWlyZWQgZmllbGQpIGlzIGtlcHQgaW4gdGhlIGZvcm0gYW5kXG4gICAgICAgIC8vIHZhbGlkYXRlZCBieSB0aGUgc2VydmVyIG9uIHN1Ym1pdC5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLy8gU2hvdyB0aGUgbmV3IHZhbHVlIGluIHRoZSBvdGhlciBmb3JtcyBvZiB0aGlzIG1vZGVsLCBub3QgaW4gdGhlIGlucHV0IGJlaW5nIGVkaXRlZC5cbiAgICAgIHRoaXMuX3VwZGF0ZUZvcm0obmFtZSwgZXZlbnQudGFyZ2V0KTtcbiAgICB9XG4gIH1cblxuICBfdXBkYXRlRm9ybShmaWVsZE5hbWUsIHNraXBFbGVtZW50ID0gbnVsbCkge1xuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIHRoaXMuX2Zvcm1zLmZvckVhY2goKCRmb3JtKSA9PiB7XG4gICAgICAkZm9ybS5maW5kKGBbbmFtZT1cIiR7ZmllbGROYW1lfVwiXWApLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcyAhPT0gc2tpcEVsZW1lbnQpIHtcbiAgICAgICAgICBzZXRWYWx1ZUluRmllbGQodGhpcywgc2VsZltmaWVsZE5hbWVdKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBzZXRWYWx1ZXMoZGF0YSA9IHt9KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwic2V0VmFsdWVzKCkgbXVzdCBiZSBpbXBsZW1lbnRlZCBieSBzdWJjbGFzc1wiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRhY2ggdGhlIHF1ZXJ5c2V0IHRoYXQgb3ducyB0aGlzIG1vZGVsIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0ge1NkY1F1ZXJ5U2V0fSBxdWVyeVNldFxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzTG9hZGVkXG4gICAqL1xuICBfc2V0UXVlcnlTZXQocXVlcnlTZXQsIGlzTG9hZGVkKSB7XG4gICAgdGhpcy5fcXVlcnlTZXQgPSBuZXcgV2Vha1JlZihxdWVyeVNldCk7XG4gICAgdGhpcy5sb2FkZWQgPSBpc0xvYWRlZDtcbiAgfVxuXG4gIGdldCBxdWVyeVNldCgpIHtcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlTZXQuZGVyZWYoKTtcbiAgfVxuXG4gIHNhdmUoeyBmb3JtTmFtZSA9IFwiZWRpdF9mb3JtXCIsIGRhdGEgPSBudWxsIH0gPSB7fSkge1xuICAgIHJldHVybiB0aGlzLl9xdWVyeVNldC5kZXJlZigpLnNhdmUoeyBwazogdGhpcy5pZCwgZm9ybU5hbWUsIGRhdGEgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIHRoaXMgaW5zdGFuY2UgaW4gdGhlIERCLlxuICAgKlxuICAgKiBAcGFyYW0ge3tkYXRhPzogb2JqZWN0fSB8IG9iamVjdCB8IG51bGx9IHZhbHVlc1xuICAgKiAgIEVpdGhlciBgeyBkYXRhIH1gIG9yIGBkYXRhYCBkaXJlY3RseS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dW5rbm93bj59XG4gICAqL1xuICBjcmVhdGUodmFsdWVzID0gbnVsbCkge1xuICAgIGNvbnN0IGRhdGEgPSBpc0NyZWF0ZU9wdGlvbnModmFsdWVzKSA/ICh2YWx1ZXMuZGF0YSA/PyBudWxsKSA6IHZhbHVlcztcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlTZXQuZGVyZWYoKS5jcmVhdGUoeyBlbGVtOiB0aGlzLCBkYXRhIH0pO1xuICB9XG5cbiAgZGVsZXRlKCkge1xuICAgIHJldHVybiB0aGlzLl9xdWVyeVNldC5kZXJlZigpLmRlbGV0ZSh7IGVsZW06IHRoaXMgfSk7XG4gIH1cblxuICBsb2FkKCkge1xuICAgIHJldHVybiB0aGlzLl9xdWVyeVNldC5kZXJlZigpLnVwZGF0ZSh7IGl0ZW06IHRoaXMgfSk7XG4gIH1cblxuICB1cGRhdGUoKSB7XG4gICAgcmV0dXJuIHRoaXMubG9hZCgpO1xuICB9XG5cbiAgZ2V0IGlkKCkge1xuICAgIHJldHVybiB0aGlzLl9pZDtcbiAgfVxuXG4gIHNldCBpZChkYXRhKSB7XG4gICAgdGhpcy5faWQgPSBkYXRhO1xuICB9XG5cbiAgc2V0IHBrKGRhdGEpIHtcbiAgICB0aGlzLmlkID0gZGF0YTtcbiAgfVxuXG4gIGdldCBwaygpIHtcbiAgICByZXR1cm4gdGhpcy5faWQ7XG4gIH1cblxuICBjbG9zZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fcXVlcnlTZXQuZGVyZWYoKS5jbG9zZSgpO1xuICB9XG5cbiAgX29uQ2xvc2UoKSB7XG4gICAgT2JqZWN0LmtleXModGhpcy5jb25zdHJ1Y3Rvci5maWVsZHMpXG4gICAgICAuZmlsdGVyKCh4KSA9PiB0aGlzW2BfJHt4fWBdIGluc3RhbmNlb2YgU2RjUXVlcnlTZXQpXG4gICAgICAuZm9yRWFjaCgoeCkgPT4gdGhpc1tgXyR7eH1gXS5jbG9zZSgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1ZXN0IHRoZSBzZXJ2ZXItcmVuZGVyZWQgZGV0YWlsIHZpZXcgZm9yIHRoaXMgbW9kZWwgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgZGV0YWlsVmlldyh7IGNiUmVzb2x2ZSA9IG51bGwsIGNiUmVqZWN0ID0gbnVsbCwgdGVtcGxhdGVDb250ZXh0ID0ge30gfSkge1xuICAgIHJldHVybiB0aGlzLl9xdWVyeVNldC5kZXJlZigpLmRldGFpbFZpZXcoeyBwazogdGhpcy5pZCwgY2JSZXNvbHZlLCBjYlJlamVjdCwgdGVtcGxhdGVDb250ZXh0IH0pO1xuICB9XG5cbiAgc2VyaWFsaXplKCkge1xuICAgIHJldHVybiBPYmplY3QuZW50cmllcyh0aGlzLmNvbnN0cnVjdG9yLmZpZWxkcykucmVkdWNlKChhY2MsIFtrZXksIHZhbF0pID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlID0gdGhpc1trZXldO1xuICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgU2RjUXVlcnlTZXQpIHtcbiAgICAgICAgaWYgKHZhbC5tYW55X3RvX21hbnkgfHwgdmFsLm9uZV90b19tYW55KSB7XG4gICAgICAgICAgYWNjW2tleV0gPSB2YWx1ZS5nZXRJZHMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBhbGxJZHMgPSB2YWx1ZS5nZXRJZHMoKTtcbiAgICAgICAgICBpZiAoYWxsSWRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGFjY1trZXldID0gYWxsSWRzWzBdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhY2Nba2V5XSA9IG51bGw7XG4gICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAodmFsLmlzX3JlbGF0aW9uICYmIHZhbHVlIGluc3RhbmNlb2YgU2RjTW9kZWwpIHtcbiAgICAgICAgYWNjW2tleV0gPSB2YWx1ZS5pZCA/PyBudWxsO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgLy8gRGphbmdvJ3MgRGF0ZUZpZWxkIGRvZXMgbm90IGFjY2VwdCBhIGZ1bGwgSVNPIGRhdGV0aW1lLlxuICAgICAgICBhY2Nba2V5XSA9IHZhbC50eXBlID09PSBcIkRhdGVGaWVsZFwiID8gZm9ybWF0RGF0ZSh2YWx1ZSkgOiB2YWx1ZS50b0lTT1N0cmluZygpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYWNjW2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGFjY1xuICAgIH0sIHt9KTtcbiAgfVxuXG4gIHRvSnNvbigpIHtcbiAgICBjb25zdCByZXMgPSB7fVxuICAgIGZvciAobGV0IGtleSBpbiB0aGlzLmNvbnN0cnVjdG9yLmZpZWxkcykge1xuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzW2tleV07XG5cbiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEZpbGUpIHtcbiAgICAgICAgcmVzW2tleV0gPSB2YWx1ZS5uYW1lO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFNkY01vZGVsKSB7XG4gICAgICAgIHJlc1trZXldID0gdmFsdWUuaWQ7XG4gICAgICB9IGVsc2UgaWYgKHZhbHVlIGluc3RhbmNlb2YgU2RjUXVlcnlTZXQpIHtcbiAgICAgICAgcmVzW2tleV0gPSB2YWx1ZS5nZXRJZHMoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc1trZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBCYWNrd2FyZHMtY29tcGF0aWJsZSBhbGlhcyBmb3Igc3luY2luZyB2YWx1ZXMgZnJvbSBhIGZvcm0gaW50byB0aGUgbW9kZWwuXG4gICAqXG4gICAqIEBwYXJhbSB7Kn0gJGZvcm1zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgc3luY0Zvcm1Ub01vZGVsKCRmb3Jtcykge1xuICAgIHJldHVybiB0aGlzLnN5bmNGb3JtKCRmb3Jtcyk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGUgZm9ybSBjb2xsZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGlzIG1vZGVsIGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0geyp9ICRmb3Jtc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIF9yZXNvbHZlRm9ybXMoJGZvcm1zKSB7XG4gICAgaWYgKCEkZm9ybXMgfHwgISRmb3Jtcy5oYXNDbGFzcyh0aGlzLmZvcm1JZCkpIHtcbiAgICAgIHJldHVybiAkKGAuJHt0aGlzLmZvcm1JZH1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gJGZvcm1zO1xuICB9XG5cbiAgLyoqXG4gICAqIENvcHkgdGhlIGN1cnJlbnQgbW9kZWwgc3RhdGUgaW50byBtYXRjaGluZyBmb3JtIGZpZWxkcy5cbiAgICpcbiAgICogQHBhcmFtIHsqfSAkZm9ybXNcbiAgICovXG4gIHN5bmNNb2RlbFRvRm9ybSgkZm9ybXMpIHtcbiAgICAkZm9ybXMgPSB0aGlzLl9yZXNvbHZlRm9ybXMoJGZvcm1zKTtcblxuICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgIGNvbnN0IHsgZmllbGRzIH0gPSB0aGlzLmNvbnN0cnVjdG9yO1xuICAgICRmb3Jtcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBrID0gbm9ybWFsaXplUGsoJCh0aGlzKS5kYXRhKFwibW9kZWxfcGtcIikpO1xuICAgICAgLy8gQ3JlYXRlIGZvcm1zIGNhcnJ5IG1vZGVsX3BrIC0xIHdoaWxlIHRoZSBuZXcgbW9kZWwncyBpZCBpcyBzdGlsbCBudWxsLlxuICAgICAgaWYgKG5vcm1hbGl6ZVBrKHNlbGYuaWQpICE9PSBwaykge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGZvciAobGV0IGZvcm1JdGVtIG9mIHRoaXMuZWxlbWVudHMpIHtcbiAgICAgICAgbGV0IHsgbmFtZSB9ID0gZm9ybUl0ZW07XG4gICAgICAgIGlmIChuYW1lICYmIG5hbWUgIT09IFwiXCIgJiYgISFmaWVsZHNbbmFtZV0pIHtcbiAgICAgICAgICBzZXRWYWx1ZUluRmllbGQoZm9ybUl0ZW0sIHNlbGZbbmFtZV0pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3B5IG1hdGNoaW5nIGZvcm0gdmFsdWVzIGJhY2sgb250byB0aGUgY3VycmVudCBtb2RlbCBpbnN0YW5jZS5cbiAgICpcbiAgICogSGlkZGVuIGlucHV0cyBhcmUgcGFyc2VkIHRvIHRoZWlyIG9yaWdpbmFsIHByaW1pdGl2ZSB0eXBlIHdoZW4gcG9zc2libGUuXG4gICAqXG4gICAqIEBwYXJhbSB7Kn0gJGZvcm1zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgc3luY0Zvcm0oJGZvcm1zKSB7XG4gICAgJGZvcm1zID0gdGhpcy5fcmVzb2x2ZUZvcm1zKCRmb3Jtcyk7XG5cbiAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICBjb25zdCB7IGZpZWxkcyB9ID0gdGhpcy5jb25zdHJ1Y3RvcjtcbiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IHt9XG5cbiAgICBmdW5jdGlvbiBzZXRWYWx1ZUluRm9ybShuYW1lLCB2YWx1ZSkge1xuICAgICAgaWYgKGZpZWxkc1tuYW1lXSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHNlbGZbbmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgfSBjYXRjaCB7XG4gICAgICAgICAgLy8gSW52YWxpZCB2YWx1ZXMgYXJlIHN0aWxsIHNlbnQgdG8gdGhlIHNlcnZlciwgd2hpY2ggcmV0dXJucyB0aGUgZm9ybVxuICAgICAgICAgIC8vIGVycm9yczsgdGhlIG1vZGVsIGtlZXBzIGl0cyBsYXN0IHZhbGlkIHZhbHVlLlxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm5WYWx1ZVtuYW1lXSA9IHZhbHVlO1xuICAgIH1cblxuICAgICRmb3Jtcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IHBrID0gbm9ybWFsaXplUGsoJCh0aGlzKS5kYXRhKFwibW9kZWxfcGtcIikpO1xuICAgICAgaWYgKHNlbGYuaWQgIT09IHBrICYmIChzZWxmLmlkICE9PSBudWxsIHx8IHBrICE9PSAtMSkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBmb3JtSXRlbSBvZiB0aGlzLmVsZW1lbnRzKSB7XG4gICAgICAgIHNldFZhbHVlSW5Gb3JtKGZvcm1JdGVtLm5hbWUsIGdldFZhbHVlRnJvbUZpZWxkKGZvcm1JdGVtKSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBzZWxmO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciB0aGUgY29ycmVjdCBzZXJ2ZXItc2lkZSBmb3JtIGZvciB0aGlzIG1vZGVsIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIGZvcm0oeyBjYlJlc29sdmUgPSBudWxsLCBjYlJlamVjdCA9IG51bGwgfSA9IHt9KSB7XG4gICAgaWYgKHRoaXMuaWQgPT09IG51bGwgfHwgdGhpcy5pZCA9PT0gLTEpIHtcbiAgICAgIHJldHVybiB0aGlzLl9jcmVhdGVGb3JtKHsgY2JSZWplY3QsIGNiUmVzb2x2ZSB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2VkaXRGb3JtKHsgY2JSZWplY3QsIGNiUmVzb2x2ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgdGhlIGNyZWF0ZSBmb3JtIGZvciBhIG5ldyBtb2RlbCBpbnN0YW5jZS5cbiAgICpcbiAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICogQHJldHVybnMgeyp9XG4gICAqL1xuICBfY3JlYXRlRm9ybSh7IGNiUmVzb2x2ZSA9IG51bGwsIGNiUmVqZWN0ID0gbnVsbCB9KSB7XG4gICAgbGV0ICRkaXZGb3JtID0gJChcIjxkaXY+XCIpO1xuICAgIHRoaXMuX3F1ZXJ5U2V0LmRlcmVmKCkuZ2V0Rm9ybSh7XG4gICAgICBtb2RlbE9iajogdGhpcyxcbiAgICAgIGV2ZW50VHlwZTogXCJjcmVhdGVfZm9ybVwiLFxuICAgICAgZm9ybU5hbWU6IG51bGwsXG4gICAgICAkZGl2Rm9ybSxcbiAgICAgIGNiUmVzb2x2ZSxcbiAgICAgIGNiUmVqZWN0LFxuICAgICAgZm9ybUlkOiB0aGlzLmZvcm1JZCxcbiAgICB9KTtcblxuICAgIHJldHVybiAkZGl2Rm9ybTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW5kZXIgdGhlIGVkaXQgZm9ybSBmb3IgYW4gZXhpc3RpbmcgbW9kZWwgaW5zdGFuY2UuXG4gICAqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgX2VkaXRGb3JtKHsgY2JSZXNvbHZlID0gbnVsbCwgY2JSZWplY3QgPSBudWxsIH0pIHtcbiAgICBsZXQgJGRpdkZvcm0gPSAkKFwiPGRpdj5cIik7XG5cbiAgICB0aGlzLl9xdWVyeVNldC5kZXJlZigpLmdldEZvcm0oe1xuICAgICAgbW9kZWxPYmo6IHRoaXMsXG4gICAgICBldmVudFR5cGU6IFwiZWRpdF9mb3JtXCIsXG4gICAgICBmb3JtTmFtZTogbnVsbCxcbiAgICAgICRkaXZGb3JtLFxuICAgICAgY2JSZXNvbHZlLFxuICAgICAgY2JSZWplY3QsXG4gICAgICBmb3JtSWQ6IHRoaXMuZm9ybUlkLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuICRkaXZGb3JtO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbmRlciBhIG5hbWVkIHNlcnZlci1zaWRlIGZvcm0gZm9yIHRoaXMgbW9kZWwuXG4gICAqXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgbmFtZWRGb3JtKHsgZm9ybU5hbWUsIGNiUmVzb2x2ZSA9IG51bGwsIGNiUmVqZWN0ID0gbnVsbCB9KSB7XG4gICAgbGV0ICRkaXZGb3JtID0gJCgnPGRpdiAgY2xhc3M9XCJjb250YWluZXItZmx1aWRcIj4nKTtcblxuICAgIHRoaXMuX3F1ZXJ5U2V0LmRlcmVmKCkuZ2V0Rm9ybSh7XG4gICAgICBtb2RlbE9iajogdGhpcyxcbiAgICAgIGV2ZW50VHlwZTogXCJuYW1lZF9mb3JtXCIsXG4gICAgICBmb3JtTmFtZSxcbiAgICAgICRkaXZGb3JtLFxuICAgICAgY2JSZXNvbHZlLFxuICAgICAgY2JSZWplY3QsXG4gICAgICBmb3JtSWQ6IHRoaXMuZm9ybUlkLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuICRkaXZGb3JtO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIGEgZmllbGQgdmFsdWUgdXNpbmcgdGhlIHN1cHBsaWVkIGZpZWxkIGNvbmZpZy5cbiAgICpcbiAgICogQHBhcmFtIHsqfSB2YWx1ZVxuICAgKiBAcGFyYW0ge29iamVjdH0gY29uZmlnXG4gICAqL1xuICB2YWxpZGF0ZSh2YWx1ZSwgY29uZmlnKSB7XG4gICAgY29uc3QgZXJyID0gdmFsaWRhdGVGaWVsZCh2YWx1ZSwgY29uZmlnKTtcbiAgICBpZiAoZXJyKSB0aHJvdyBuZXcgRXJyb3IoZXJyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IGEgcmF3IGlucHV0IHZhbHVlIGludG8gdGhlIHNoYXBlIGV4cGVjdGVkIGJ5IHRoZSBmaWVsZCBjb25maWcuXG4gICAqXG4gICAqIEBwYXJhbSB7Kn0gdmFsdWVcbiAgICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZ1xuICAgKiBAcmV0dXJucyB7Kn1cbiAgICovXG4gIHBhcnNlVmFsdWUodmFsdWUsIGNvbmZpZykge1xuICAgIGNvbnN0IHtcbiAgICAgIHR5cGUsXG4gICAgICBtYW55X3RvX21hbnk6IG1hbnlUb01hbnksXG4gICAgICBvbmVfdG9fbWFueTogb25lVG9NYW55LFxuICAgICAgbWFueV90b19vbmU6IG1hbnlUb09uZSxcbiAgICAgIG9uZV90b19vbmU6IG9uZVRvT25lLFxuICAgIH0gPSBjb25maWc7XG4gICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoKG1hbnlUb01hbnkgfHwgb25lVG9NYW55IHx8IG1hbnlUb09uZSB8fCBvbmVUb09uZSkgJiYgdmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIEpTT04ucGFyc2UodmFsdWUpO1xuICAgIH1cblxuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBcIkNoYXJGaWVsZFwiOlxuICAgICAgY2FzZSBcIlRleHRGaWVsZFwiOlxuICAgICAgY2FzZSBcIlNsdWdGaWVsZFwiOlxuICAgICAgY2FzZSBcIlVVSURGaWVsZFwiOlxuICAgICAgY2FzZSBcIkVtYWlsRmllbGRcIjpcbiAgICAgICAgcmV0dXJuIGAke3ZhbHVlfWA7XG5cbiAgICAgIGNhc2UgXCJJbnRlZ2VyRmllbGRcIjpcbiAgICAgIGNhc2UgXCJTbWFsbEludGVnZXJGaWVsZFwiOlxuICAgICAgY2FzZSBcIkJpZ0ludGVnZXJGaWVsZFwiOlxuICAgICAgY2FzZSBcIlBvc2l0aXZlSW50ZWdlckZpZWxkXCI6XG4gICAgICBjYXNlIFwiUG9zaXRpdmVTbWFsbEludGVnZXJGaWVsZFwiOlxuICAgICAgY2FzZSBcIlBvc2l0aXZlQmlnSW50ZWdlckZpZWxkXCI6XG4gICAgICBjYXNlIFwiQXV0b0ZpZWxkXCI6XG4gICAgICBjYXNlIFwiU21hbGxBdXRvRmllbGRcIjpcbiAgICAgIGNhc2UgXCJCaWdBdXRvRmllbGRcIjpcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHZhbHVlLCAxMCk7XG5cbiAgICAgIGNhc2UgXCJGbG9hdEZpZWxkXCI6XG4gICAgICBjYXNlIFwiRGVjaW1hbEZpZWxkXCI6XG4gICAgICAgIHJldHVybiBwYXJzZUZsb2F0KHZhbHVlKTtcblxuICAgICAgY2FzZSBcIkJvb2xlYW5GaWVsZFwiOlxuICAgICAgICByZXR1cm4gISF2YWx1ZTtcblxuICAgICAgY2FzZSBcIkRhdGVGaWVsZFwiOlxuICAgICAgY2FzZSBcIkRhdGVUaW1lRmllbGRcIjpcbiAgICAgICAgcmV0dXJuIHRvRGF0ZSh2YWx1ZSk7XG5cbiAgICAgIGNhc2UgXCJVUkxGaWVsZFwiOlxuICAgICAgICByZXR1cm4gbmV3IFVSTCh2YWx1ZSk7XG5cbiAgICAgIGNhc2UgXCJGaWxlRmllbGRcIjpcbiAgICAgICAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChGaWxlTG9hZGVkLmlzVmFsaWQodmFsdWUpKSB7XG4gICAgICAgICAgcmV0dXJuIG5ldyBGaWxlTG9hZGVkKHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIEZpbGVMb2FkZWQpIHtcbiAgICAgICAgICByZXR1cm4gbmV3IEZpbGVMb2FkZWQodmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBGaWxlICE9PSBcInVuZGVmaW5lZFwiICYmIHZhbHVlIGluc3RhbmNlb2YgRmlsZSkge1xuICAgICAgICAgIC8vIFNpemUgYW5kIHR5cGUgYXJlIGNoZWNrZWQgaW4gdmFsaWRhdGUoKS5cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJKU09ORmllbGRcIjpcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSBhIGZpZWxkIHZhbHVlIGFnYWluc3QgdGhlIGZpZWxkIG1ldGFkYXRhIHJlY2VpdmVkIGZyb20gdGhlIGJhY2tlbmQuXG4gKlxuICogQHBhcmFtIHsqfSB2YWx1ZVxuICogQHBhcmFtIHtvYmplY3R9IGNvbmZpZ1xuICogQHJldHVybnMgez9zdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlRmllbGQodmFsdWUsIGNvbmZpZykge1xuICBjb25zdCB7XG4gICAgdHlwZSxcbiAgICByZXF1aXJlZCxcbiAgICBtYXhfbGVuZ3RoOiBtYXhMZW5ndGgsXG4gICAgaXNfcmVsYXRpb246IGlzUmVsYXRpb24sXG4gICAgbWFueV90b19tYW55OiBtYW55VG9NYW55LFxuICAgIG9uZV90b19tYW55OiBvbmVUb01hbnksXG4gICAgbWFueV90b19vbmU6IG1hbnlUb09uZSxcbiAgICBvbmVfdG9fb25lOiBvbmVUb09uZSxcbiAgICByZWxhdGVkX21vZGVsOiByZWxhdGVkTW9kZWwsXG4gIH0gPSBjb25maWc7XG5cbiAgdm9pZCBpc1JlbGF0aW9uO1xuXG4gIGlmIChyZXF1aXJlZCkge1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBcIlwiKSB7XG4gICAgICByZXR1cm4gXCJUaGlzIGZpZWxkIGlzIHJlcXVpcmVkXCI7XG4gICAgfVxuICB9XG5cbiAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IFwiXCIpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmIChtYW55VG9NYW55IHx8IG9uZVRvTWFueSB8fCBtYW55VG9PbmUgfHwgb25lVG9PbmUpIHtcbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIFNkY1F1ZXJ5U2V0KSB8fCB2YWx1ZS5tb2RlbE5hbWUgIT09IHJlbGF0ZWRNb2RlbCkge1xuICAgICAgaWYodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YWx1ZSA9IEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoKG1hbnlUb01hbnkgfHwgbWFueVRvT25lKSAmJiBBcnJheS5pc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5zb21lKCh4KSA9PiAhTnVtYmVyLmlzTmFOKHBhcnNlSW50KHgpKSkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcIm9iamVjdFwiICYmIE51bWJlci5pc05hTihwYXJzZUludCh2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiBcIk11c3QgYmUgb2JqZWN0IG9yIElEXCI7XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlIFwiQ2hhckZpZWxkXCI6XG4gICAgY2FzZSBcIlRleHRGaWVsZFwiOlxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICByZXR1cm4gXCJNdXN0IGJlIGEgc3RyaW5nXCI7XG4gICAgICB9XG4gICAgICBpZiAobWF4TGVuZ3RoICYmIHZhbHVlLmxlbmd0aCA+IG1heExlbmd0aCkge1xuICAgICAgICByZXR1cm4gYE1heCBsZW5ndGggaXMgJHttYXhMZW5ndGh9YDtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBcIkludGVnZXJGaWVsZFwiOlxuICAgIGNhc2UgXCJTbWFsbEludGVnZXJGaWVsZFwiOlxuICAgIGNhc2UgXCJCaWdJbnRlZ2VyRmllbGRcIjpcbiAgICBjYXNlIFwiUG9zaXRpdmVJbnRlZ2VyRmllbGRcIjpcbiAgICBjYXNlIFwiUG9zaXRpdmVTbWFsbEludGVnZXJGaWVsZFwiOlxuICAgIGNhc2UgXCJQb3NpdGl2ZUJpZ0ludGVnZXJGaWVsZFwiOlxuICAgIGNhc2UgXCJBdXRvRmllbGRcIjpcbiAgICBjYXNlIFwiU21hbGxBdXRvRmllbGRcIjpcbiAgICBjYXNlIFwiQmlnQXV0b0ZpZWxkXCI6XG4gICAgICBpZiAoIWlzRmluaXRlKHBhcnNlSW50KHZhbHVlKSkpIHtcbiAgICAgICAgcmV0dXJuIFwiTXVzdCBiZSBhbiBpbnRlZ2VyXCI7XG4gICAgICB9XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgXCJGbG9hdEZpZWxkXCI6XG4gICAgY2FzZSBcIkRlY2ltYWxGaWVsZFwiOlxuICAgICAgaWYgKCFpc0Zpbml0ZShwYXJzZUZsb2F0KHZhbHVlKSkpIHtcbiAgICAgICAgcmV0dXJuIFwiTXVzdCBiZSBhIG51bWJlclwiO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlIFwiQm9vbGVhbkZpZWxkXCI6XG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcImJvb2xlYW5cIikge1xuICAgICAgICByZXR1cm4gXCJNdXN0IGJlIGEgYm9vbGVhblwiO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlIFwiRGF0ZUZpZWxkXCI6XG4gICAgY2FzZSBcIkRhdGVUaW1lRmllbGRcIjpcbiAgICAgIGlmIChpc05hTihEYXRlLnBhcnNlKHZhbHVlKSkpIHtcbiAgICAgICAgcmV0dXJuIFwiTXVzdCBiZSBhIHZhbGlkIGRhdGVcIjtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBcIkVtYWlsRmllbGRcIjpcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwic3RyaW5nXCIgfHwgIS9eW15cXHNAXStAW15cXHNAXStcXC5bXlxcc0BdKyQvLnRlc3QodmFsdWUpKSB7XG4gICAgICAgIHJldHVybiBcIkludmFsaWQgZW1haWxcIjtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBcIlVSTEZpZWxkXCI6XG4gICAgICB0cnkge1xuICAgICAgICBuZXcgVVJMKHZhbHVlKTtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gXCJJbnZhbGlkIFVSTFwiO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG5cbiAgICBjYXNlIFwiVVVJREZpZWxkXCI6XG4gICAgICBpZiAoIS9eWzAtOWEtZl17OH0tWzAtOWEtZl17NH0tWzEtNV1bMC05YS1mXXszfS1bODlhYl1bMC05YS1mXXszfS1bMC05YS1mXXsxMn0kLy50ZXN0KHZhbHVlKSkge1xuICAgICAgICByZXR1cm4gXCJJbnZhbGlkIFVVSURcIjtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBcIkpTT05GaWVsZFwiOlxuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICByZXR1cm4gXCJNdXN0IGJlIHZhbGlkIEpTT05cIjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSBcIkZpbGVGaWVsZFwiOlxuICAgICAgaWYgKCFGaWxlTG9hZGVkLmlzVmFsaWQodmFsdWUpICYmICEodmFsdWUgaW5zdGFuY2VvZiBGaWxlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgRmlsZUxvYWRlZCkpIHtcbiAgICAgICAgcmV0dXJuIFwiTXVzdCBiZSBhIHZhbGlkIGZpbGVcIjtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgRmlsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiB2YWx1ZSBpbnN0YW5jZW9mIEZpbGUpIHtcbiAgICAgICAgaWYgKGNvbmZpZy5tYXhfc2l6ZSAmJiB2YWx1ZS5zaXplID4gY29uZmlnLm1heF9zaXplKSB7XG4gICAgICAgICAgcmV0dXJuIGBGaWxlIHRvbyBsYXJnZSAobWF4ICR7Y29uZmlnLm1heF9zaXplfSBieXRlcylgO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb25maWcuYWxsb3dlZF90eXBlcyAmJiAhY29uZmlnLmFsbG93ZWRfdHlwZXMuaW5jbHVkZXModmFsdWUudHlwZSkpIHtcbiAgICAgICAgICByZXR1cm4gYEludmFsaWQgZmlsZSB0eXBlICgke3ZhbHVlLnR5cGV9KWA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBicmVhaztcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuIl0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/simpleDomControl/sdc_model.js\n\n}");
88
88
 
89
89
  /***/ },
90
90
 
@@ -1,2 +1,2 @@
1
1
  /*! For license information please see ugly.index.js.LICENSE.txt */
2
- let e;function t(){return new Promise(function(e){e()})}function n(e){return(e=(e=e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)).replace(/[0-9]+/g,e=>`-${e}`)).replace(/^[-]/g,"")}function r(e){return e.replace(/-./g,e=>`${e[1].toUpperCase()}`)}const s=(e,t)=>{let n=t,r=Object.getOwnPropertyNames(e.prototype).concat(Object.getOwnPropertySymbols(e.prototype));for(;""!==n.name;)Object.getOwnPropertyNames(n.prototype).concat(Object.getOwnPropertySymbols(n.prototype)).forEach(t=>{t.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/)||r.includes(t)||(r.push(t),Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(n.prototype,t)))}),n=Object.getPrototypeOf(n)};function o(e,t,n){return $.ajax({url:t,type:n||"POST",xhr:function(){var e=$.ajaxSettings.xhr();return e.upload&&e.upload.addEventListener("progress",i,!1),e},data:e,cache:!1,contentType:!1,processData:!1,beforeSend:function(e,t){(function(e){return/^(GET|HEAD|OPTIONS|TRACE)$/.test(e)})(t.type)||this.crossDomain||e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}})}function i(e){if(e.lengthComputable){var t=Math.round(e.loaded/e.total*100),n=$(".progress-container");100===t?n.hide():n.show(),t+="%",n.find(".progress-bar").css({width:t}).text(t)}}function l(e,t=null){return"string"!=typeof e?e:t&&void 0!==t[e]?"function"==typeof t[e]?t[e].bind(t):t[e]:e.match(/^(true|false)$/)?"true"===e:"undefined"!==e?"none"===e.toLowerCase()?null:e.match(/^-?\d+$/)?parseInt(e):e.match(/^-?\d+\.?\d+$/)?parseFloat(e):e.match(/^(['][^']*['])|(["][^"]*["])$/)?e.substr(1,e.length-2):e:void 0}function a(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}function c(e){e.find(".has-error").removeClass("has-error").find(".alert-danger").remove(),e.find(".non-field-errors").remove()}function u(e,t){t=$("<div>").append(t),e.find(".has-error").removeClass("has-error").find(".alert-danger").safeRemove(),e.find(".non-field-errors").safeRemove();let n=t.find("input[type=file]").parent();e.find("input[type=file]").parent().each(function(e){$(this).replaceWith(n[e])});let r=0===t.find(".non-field-errors").insertAfter(e.find(".hidden-form-fields")).length;return t.find(".has-error").each(function(){r=!1;let t=$(this),n=t.data("auto-id"),s=e.find(".form-group."+n);s.addClass("has-error"),s.find(".form-input-container").append(t.find(".alert-danger"))}),r}function d(e){let{type:t,name:n}=e;return n&&""!==n?"hidden"===t?(r=$(e).val()).toLowerCase().match(/^(true|false)$/)?"true"===r.toLowerCase():"undefined"!==r?"none"===r.toLowerCase()?null:r.match(/^-?\d+$/)?parseInt(r,10):r.match(/^-?\d+\.?\d+$/)?parseFloat(r):r.match(/^(['][^']*['])|(["][^"]*["])$/)?r.substring(1,r.length-1):r:void 0:"checkbox"===t?e.checked:"file"===t?e.files[0]:$(e).val():null;var r}const h=e=>String(e).padStart(2,"0");function f(e){if(null==e||""===e)return null;let t;if(e instanceof Date)t=e;else if("string"==typeof e&&/^\d{4}-\d{2}-\d{2}$/.test(e)){const[n,r,s]=e.split("-").map(Number);t=new Date(n,r-1,s)}else t=new Date(e);return isNaN(t.getTime())?null:t}function m(e){const t=f(e);return t?`${t.getFullYear()}-${h(t.getMonth()+1)}-${h(t.getDate())}`:""}function p(e,t){let{type:n,name:r}=e;if(r&&""!==r)if("datetime-local"===n)e.value=function(e){const t=f(e);return t?`${m(t)}T${h(t.getHours())}:${h(t.getMinutes())}`:""}(t);else if("date"===n)e.value=m(t);else if("checkbox"===n)e.checked=!!t;else if("file"===n){if(t instanceof File&&"undefined"!=typeof DataTransfer){let n=new DataTransfer;n.items.add(t),e.files=n}}else t instanceof ue?$(e).val(t.id):t instanceof ce?$(e).val(`[${t.getIds().join(",")}]`):(null===t&&(t=""),$(e).val(t));return null}function g(e,t=null){return Object.fromEntries(Object.entries(e).filter(([e,t])=>e!==U).map(([e,n])=>{if("string"==typeof n&&n.startsWith("SDC_JSON_MODEL=["))try{const{pk:t,fields:r}=JSON.parse(n.slice(16,-1));return[e,{...r,id:t}]}catch{}return[e,l(n,t)]}))}function y(e,t=null){return g(e.data(),t)}const v=["onbeforeunload","onunload"],w=Object.keys(window).filter(e=>/^on/.test(e)&&!v.includes(e)).map(e=>e.slice(2));function b(e,t,n){let r;switch(e){case"mouseleave":case"mouseout":case"mouseenter":return r=document.elementFromPoint(t.clientX,t.clientY),n!==r&&!n.contains(r);default:return!0}}function R(e){let t=e.type;Object.hasOwn(e,"namespace")&&e.namespace&&e.namespace.length&&(t+=`.${e.namespace}`);let n=$(e.target),r=null,s=!1,o=!1;for(e.stopImmediatePropagation=()=>o=!0,e.stopPropagation=()=>o=s=!0;n.length;){let i=n.attr(`sdc_${t}`);if(i&&b(t,e,n[0])){if(!r&&(r=W(n),!r))return;for(;r;){if(i.split(" ").forEach(o=>{if(s)return;let i=null;if("function"==typeof o)i=o;else if("function"==typeof r[o])i=r[o];else if("string"==typeof o&&o.startsWith("this.event_")){if(i=r.getEvents()[t],!i)return;if(i=i[o.slice(11)],!i)return}i&&i.call(r,n,e)}),o)return;r=r._parentController}}if(s)return;n=n.parent()}return{res:!0}}function C(e){const t=e.getEvents();for(let n in t)if(Object.hasOwn(t,n)){let r=t[n];for(let t in r)Object.hasOwn(r,t)&&e.find(t).each(function(){let e=$(this),r=e.attr(`sdc_${n}`)||null;r=r?r.split(" "):[];const s=`this.event_${t}`;-1===r.indexOf(s)&&(r.push(s),e.attr(`sdc_${n}`,r.join(" ")))})}}let N=[],O={};function S(e,t){if(e){let n=r(t._tagName);e._childController[n]||(e._childController[n]=[]),e._childController[n].push(t)}return t._parentController=e}function F(e,t,n,r){let o=[];r=function(e,t){e=(e=e.concat(O[t][1])).filter((e,t,n)=>n.indexOf(e)===t);let n=!0;for(;n;){n=!1;for(let t of e)for(let r of O[t][1])e.includes(r)||(e.push(r),n=!0)}return e}(r,n);for(let e of r)o.push(O[e][0]);let i=new(function(e,...t){let n={[e.name]:class{constructor(...n){let r={};t.forEach(e=>{let t;Object.assign(this,t=new e),t._tagName=e.prototype._tagName,t._isMixin=!0,r[e.name]=t}),Object.assign(this,new e),this._mixins=r}static get name(){return e.name}static className(){return this.name}get mixins(){return this._mixins}}}[e.name];return s(n,e),t.forEach(e=>{s(n,e)}),n}(O[n][0],...o));return i._tagName=n,S(e,i),i.$container=t,function(e,t){!function(e,t,n){if(!e)return!1;e.params=y(t,n._parentController)}(t,e,t)}(t,i),i}function k(e,t,n,s){if(N.includes(n)){let o=r(n);return window[o]||(window[o]=F(e,t,n,s)),window[o].$container=t,window[o]}return F(e,t,n,s)}function E(e,n){const r=function(e){return function(e){let t={args:{}};return e.contentUrl&&(t=B(e),e.contentUrl=t.url),Promise.all([V(e,t.args)]).then(function(e){let t=e[0];if(t)try{return $(t)}catch{return $("<div></div>").append(t)}return null})}(e).then(n=>!e.onLoad||e._onLoadDone?n:(e._onLoadDone=!0,(e.onLoad(n)||t()).then(()=>n)))}(e).then(function(t){return function(e,t){return z(e,t).then(function(t){if(t=t||!0,e.willShow){let n=e.willShow();if(n instanceof Promise)return n.then(function(){return t})}return t})}(e,t)}).then(()=>function(e,t){return Z(null,e,t)}(e,n)).catch(function(t){if("string"==typeof t||t instanceof $)return z(e,t);throw t});return e.load_async?Promise.resolve():r}function x(e){const t=function(e){let t=[];for(;e;)t.unshift(e),e=e._parentController;return t}(e.controller[0]),n=t.concat(e.controller.slice(1));for(let t of n)C(t),t.onRefresh(e.controller[0])}function I(e,t){let n=Boolean(e);return n?e.uuids.has(t._uuid)||(e.uuids.add(t._uuid),e.controller.push(t)):e={uuids:new Set([t._uuid]),controller:[t]},{isRunningProcess:n,refreshProcess:e}}let j={},P={};function L(e,t){return q(e),Object.hasOwn(P,e)?t[P[e]]?void j[e].push(t):console.log("No event handler: "+e,t):console.log("No event: "+e,t)}function q(e,t){t||(t=e),P[e]||(P[e]=t,j[e]=[])}function T(e){for(let t in j)if(Object.hasOwn(j,t))for(let n=j[t].length-1;n>=0;n--)e===j[t][n]&&j[t].splice(n,1)}function A(e){let n=Array.apply(null,arguments);if(e=n.shift(),!Object.hasOwn(j,e)||!Object.hasOwn(P,e))return t();let r=j[e],s=P[e],o=[];for(let e=0;e<r.length;e++){let t=r[e][s].apply(r[e],n);void 0!==t&&o.push(t)}return Promise.all(o)}let D={};const U="_controller_",M="_sdc_controller_";function J(e,t,n){if(!e)return[];let r=e.children(),s=[];return r.each(function(e,r){let o=$(r),i=o.prop("tagName").toLowerCase().split("_");$.inArray(i[0],t)>=0?s.push({tag:i[0],super:i.splice(1)||[],dom:o}):i[0].startsWith("this.")?o.addClass(`_bind_to_update_handler sdc_uuid_${n._uuid}`):s=s.concat(J(o,t,n))}),s}function V(e,t){const{contentUrl:n,_tagName:r,contentReload:s}=e;return n?D[r]?Promise.resolve(D[r]):(t.VERSION=$e.VERSION,t._method="content",$.get(n,t).then(function(e){return s||(D[r]=e),e}).catch(function(t){if(301===t.status){const n=t.responseJSON;return A("_RedirectOnView",n["url-link"]),s||(e.autoRedirect=n["url-link"]),"<p>Redirected</p>"}throw e.autoRedirect=null,"function"==typeof e.confirmPageLoaded&&A("navLoaded",{controller_name:()=>t.status}),`<sdc-error data-code="${t.status}">${t.responseText}</sdc-error>`})):Promise.resolve(!1)}function Q(e,t,n=null){return t=t||e.data(U),K($e.tagNames,e,t,n)}function B(e){let t=e.contentUrl;if(e&&0===e._urlParams.length){let n,r=/%\(([^)]+)\)\w/gm;for(e._urlParams=[];n=r.exec(t);)e._urlParams.push(n[1]),e.contentReload=!0}let{args:n,params:r}=function(e,t){const n=y(t,e),[r,s]=Object.entries(n).reduce(([t,n],[r,s])=>(e._urlParams.includes(r)?t[r]=s:n[r]=s,[t,n]),[{},{}]);return{params:r,args:s}}(e,e.$container);return e._urlParams.length&&(t=function(e,t,n){for(let r in e._urlParams)if(Object.hasOwn(e._urlParams,r)){let s=e._urlParams[r],o=RegExp("%\\("+s+"\\)\\w","gm");const i=n[s];i||console.warn(`${s} is not set for controller ${e._tagName}`),t=t.replace(o,i)}return t}(e,t,r)),e.parsedContentUrl=t,{url:t,args:n}}function W(e){return e.hasClass(M)?e.data(`${U}`):e.closest(`.${M}`).data(`${U}`)}function G(e,t,n,r,s){let o=e.data(U);return o?Q(e,o,s):(o=k(r,e,t,n),e.data(U,o),e.addClass(M),E(o,s))}function z(e,t,n=null){if(t&&t.length>0){e.$container.empty(),e.$container.attr(e._tagName,"");for(let t in e._mixins)e.$container.attr(e._mixins[t]._tagName,"");e.$container.append(t)}return Q(e.$container,e,n)}function K(e,t,n,r){return new Promise(s=>{let o=J(t,e,n),i=o.length;if(0===i)return s();for(let e=0;e<o.length;e++)G(o[e].dom,o[e].tag,o[e].super,n,r).then(()=>{if(i--,0===i)return s()})})}function H({$element:e,id:t=[],parent:n=null}){t.push(function(e){if(3===e[0].nodeType)return`TEXT__${e[0].nodeValue}`;const t=[e[0].tagName];return"INPUT"===e[0].nodeName&&[["name",""],["type","text"],["id",""]].forEach(([n,r])=>{const s=e.attr(n)??r;s&&t.push(s)}),t.join("__")}(e));const r={$element:e,id:t.join("::"),depth:t.length,idx:0,getRealParent:()=>n,getIdx:function(){return this.idx=Math.max(0,(this.getRealParent()?.getIdx()??-1)+e.index()+1),this.idx},op:null,parent:n};return r.getIdx.bind(r),[r].concat(e.contents().toArray().map(e=>H({$element:$(e),id:t.slice(),parent:r})).flat())}function X(e,t){const n=H({$element:t}),r=H({$element:e});n.map((e,t)=>e.idx=t),r.map((e,t)=>e.idx=t);const s=Math.max(...r.concat(n).map(e=>e.depth)),o=Y(n,r,s);let i=[];window.MAIN=t,window.OPS=o,o.forEach((e,t)=>{const{op:n,$element:r,idx:s}=e;if("keep_counterpart"===n.type){if(n.counterpart.getIdx()!==s){const t=e.getBefore();t?n.counterpart.$element.insertAfter(t.$element):e.getRealParent().$element.prepend(n.counterpart.$element)}!function(e,t){!function(e,t){if(!e||!t||!e._sdcListeners&&!t._sdcListeners)return;(e._sdcListeners??[]).forEach(([t,n])=>e.removeEventListener(t,n));const n=t._sdcListeners??[];n.forEach(([t,n])=>e.addEventListener(t,n)),e._sdcListeners=n}(e[0],t[0]);const n=e[0].attributes??[],r=t[0].attributes??[];[...n].forEach(n=>{t.is(`[${n.name}]`)||e.removeAttr(n.name)}),[...r].forEach(t=>{t.name.startsWith("data")||e.attr(t.name)===t.value||e.attr(t.name,t.value)}),e.removeData(),Object.entries(t.data()).forEach(([t,n])=>{e.data(t,n)})}(n.counterpart.$element,r),r.hasClass(M)&&(r.data(U).$container=n.counterpart.$element,r.data(U,null)),i.push(r)}else if("delete"===n.type)r.safeRemove();else if("insert"===n.type){const{after:t,target:n}=e.op;t?r.insertAfter(t.$element):n&&n.$element.prepend(r)}}),i.forEach(e=>e.safeRemove())}function Y(e,t,n){return t.filter(e=>e.depth===n&&!e.op).forEach(t=>{const n=e.find(e=>!e.op&&e.id===t.id);if(n){const e=(t,n)=>{t.op={type:"keep",idx:n.idx},n.op={type:"keep_counterpart",counterpart:t},t=t.parent,n=n.parent,!t||t.op||n?.op||e(t,n)};e(n,t)}}),n>1?Y(e,t,n-1):(e.forEach((t,n)=>{if(!t.op){const r=(e[n-1]?.op.idx??-1)+1;t.op={type:"delete",idx:r}}}),t.forEach((e,n)=>{if(e.getBefore=()=>function(e,n){const r=e.depth;for(;n>=1&&e.depth>=r;)if((e=t[n-=1]).depth===r)return"keep_counterpart"===e.op.type?e.op.counterpart:e;return null}(e,n),e.getRealParent=()=>{return(t=e).parent?"keep_counterpart"===t.parent.op.type?t.parent.op.counterpart:t.parent:null;var t},!e.op){const t=e.getRealParent(),n="insert"===t?.op.type?"insert_ignore":"insert";e.op={type:n,target:t,after:e.getBefore()}}}),[...e,...t].sort((e,t)=>(e.op?.idx??e.idx)-(t.op?.idx??t.idx)))}function Z(e,t,n=null){if(t||(t=W(e)),!t)return Promise.resolve();const{refreshProcess:r,isRunningProcess:s}=I(n,t);return e??=t.$container,K($e.tagNames,e,t,n).then(()=>function(e,t,n){return function(e,t,n){const r=[];return t.find(`._bind_to_update_handler.sdc_uuid_${e._uuid}`).each(function(){const t=$(this);let s;if(t.hasClass("_with_handler"))s=t.data("handler");else{let t=this.tagName.toLowerCase().replace(/^this./,"");e[t]&&(s=e[t])}if("function"==typeof s){const n=g(t.data(),e);s=s.bind(e)(n)}s&&r.push(Promise.resolve(s).then(r=>{let s=$("<div></div>");return s.append(r),""===t.html()&&t.append("<div></div>"),$e.reconcile(e,s,t.children(),n)}))}),Promise.all(r)}(e,t??e.$container,n)}(t,e,r).then(()=>{s||x(r)}))}const ee={};function te(e,t){ee[e]=t}function ne(e){return ee[e]}const re=25e3,se="_connecting_process";class oe extends Error{constructor(e){"string"==typeof e&&(e={msg:e,is_error:!0,header:"Error"}),super(e.msg),this.msg=e.msg,this.header=e.header,this.is_error=e.is_error,this.html=e.html}}class ie{constructor({name:e,url:t}){this.name=e,this.url=t,this.content=null}async load(e=!1){return!e&&this.content||(this.content=await new Promise((e,t)=>{$.get(this.url).then(e).catch(()=>{e("")})})),this.content}async text(){return this.load()}static isValid(e){return!(null===e||"object"!=typeof e||Array.isArray(e)||e instanceof File||"string"!=typeof e.url||"string"!=typeof e.name)}}function le(e){const t=parseInt(e??-1,10);return Number.isNaN(t)?-1:t}function ae(e){if(!e||"object"!=typeof e||e instanceof ue)return!1;const t=Object.keys(e);return!(0===t.length||!t.every(e=>"elem"===e||"data"===e)||"elem"in e&&null!==e.elem&&!(e.elem instanceof ue)||"data"in e&&null!==e.data&&"object"!=typeof e.data)}class ce{constructor(e,t={}){return this.valuesList=[],this.loaded=!1,this.modelName=e,this.modelQuery=t??{},this._onNoOpenRequests=[],this._isConnected=!1,this._isConnectingProcess=!1,this._autoReconnect=!0,this.socket=null,this.openRequest={},this.modelId=0,this.onUpdate=()=>{},this.onCreate=()=>{},this.onDelete=null,new Proxy(this,{get:(e,t)=>"symbol"==typeof t||isNaN(t)?e[t]:e.valuesList[t],set:(e,t,n)=>isNaN(t)?(e[t]=n,!0):(e.valuesList[t]=n,!0)})}[Symbol.iterator](){let e=-1;return{next:()=>(++e,e<this.valuesList.length?{value:this.valuesList[e],done:!1}:{value:null,done:!0})}}set on_create(e){this.onCreate=e}set on_update(e){this.onUpdate=e}set on_delete(e){this.onDelete=e}_removeIds(e){const t=this.valuesList.filter(t=>e.includes(t.id));return this.valuesList=this.valuesList.filter(t=>!e.includes(t.id)),t}setIds(e){const t=this._setIds(e),n={id__in:t.map(e=>e.id)};return this.setFilter(n),t}_setIds(e){if(null===e||""===e||Array.isArray(e)&&0===e.length)return this.valuesList=[],this.valuesList;if(e instanceof ce||e instanceof ue){const t=e instanceof ue?[e]:e.valuesList;return this.valuesList=t.map(e=>{const t=null!==e.id?this.byId(e.id):null;if(t)return t;const n=(e=>{const t=new e.constructor({});return t.setValues(e.serialize()),t})(e);return n._setQuerySet(this,!0),n}),this.valuesList}let t,n=Number.NaN;if(Number.isInteger(e))n=e;else if(e instanceof Array){const n=e.map(e=>parseInt(e));n.some(Number.isNaN)||(t=n)}else if("string"==typeof e){const r=e.split(",").map(e=>parseInt(e));r.some(Number.isNaN)?n=parseInt(e):t=r}if(Number.isNaN(n)){if(t){this.valuesList=this.valuesList.filter(e=>t.includes(e.id));const e=this.getIds();t.filter(t=>!e.includes(t)).forEach(e=>{this.valuesList.push(new(ne(this.modelName))({id:e}))})}}else this.valuesList=this.valuesList.filter(e=>n===e.id),0===this.valuesList.length&&(this.new().id=n);return this.valuesList}getIds(){return this.valuesList.map(e=>e.id)}get length(){return this.valuesList.length}byId(e){if(null!==e){const t=le(e);return this.valuesList.find(e=>e.id===t)??null}return null}setFilter(e){return this.modelQuery=e,this}addFilter(e){return this.modelQuery=Object.assign({},this.modelQuery,e),this}new(e={}){const t=new(ne(this.modelName))(e);return t._setQuerySet(this,!1),this.valuesList.push(t),t}load(e=null){return this.valuesList=[],this.modelQuery=e??this.modelQuery,this._sendLoad()}update({modelQuery:e=null,item:t=null}){this.modelQuery=e??this.modelQuery;let n=t?{id:t.id}:this.modelQuery;return this._sendLoad(n)}delete({pk:e=null,id:t=null,elem:n=null}){if(e??=t,null===(e=n?n.id:e))throw new Error("pk or elem must be set");const r=a();return this.isConnected().then(()=>new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"delete",event_id:r,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e}})),this.openRequest[r]=[n=>{this._removeIds([le(e)]),t(n)},n]}))}_sendLoad(e=null){return this.isConnected().then(()=>{const t=a();return new Promise((n,r)=>{this.socket.send(JSON.stringify({event:"model",event_type:"load",event_id:t,args:{model_name:this.modelName,model_query:e??this.modelQuery}})),this.openRequest[t]=[e=>{this.loaded=!0,n(e)},r]})})}_sendListView({modelQuery:e={},cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this.view({modelQuery:e,cbResolve:t,cbReject:n,templateContext:r,eventType:"list_view"})}view({viewName:e="html_list_template",modelQuery:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={},eventType:o="named_view"}){let i=$('<div class="container-fluid">');return this.isConnected().then(()=>{const l=a();this.socket.send(JSON.stringify({event:"model",event_type:o,event_id:l,args:{view_name:e,model_name:this.modelName,model_query:t,template_context:s}})),this.openRequest[l]=[e=>{i.append(e.html),$e.refresh(i),n&&n(e)},e=>{r&&r(e)}]}),i}_sendDetailView({pk:e=null,id:t=null,cbResolve:n=null,cbReject:r=null,templateContext:s={}}){e??=t,e=le(e);let o=$('<div class="container-fluid">');return this.isConnected().then(()=>{const t=a();this.socket.send(JSON.stringify({event:"model",event_type:"detail_view",event_id:t,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e,template_context:s}})),this.openRequest[t]=[e=>{o.append(e.html),$e.refresh(o),n&&n(e)},e=>{r&&r(e)}]}),o}getForm({modelObj:e,eventType:t,formName:n,$divForm:r,cbResolve:s,cbReject:o,formId:i}){const l=a(),c=e.id??-1;this.isConnected().then(()=>{this.socket.send(JSON.stringify({event:"model",event_type:t,event_id:l,args:{model_name:this.modelName,id:c,pk:c,form_name:n}}))});const u=null===c||-1===c?"create":"edit";this.openRequest[l]=[t=>{r.append(t.html);let o=r.closest("form").addClass(`sdc-model-${u}-form sdc-model-form ${i}`).data("model",e).data("model_pk",c).data("form_name",n);e.addForm(o),o.length>0&&!o[0].hasAttribute("sdc_submit")&&o.attr("sdc_submit","submitModelFormDistributor"),$e.refresh(r).then(()=>null),s&&s(t)},e=>{o&&o(e)}]}async get(e=null,t=!1){if(t){const t=e?.id??this.modelQuery?.id;return e&&this.setFilter(e),this.byId(t)??this.new(e||this.modelQuery)}if(await this.load(e),1!==this.length)throw new Error(`model query returns ${this.length} but only 1 expected.`);return this.addFilter({id:this.valuesList[0].id}),this.valuesList[0]}detailView({pk:e,cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this._sendDetailView({id:e,cbResolve:t,cbReject:n,templateContext:r})}listView({modelQuery:e={},searchValues:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={}}){return this._sendListView({modelQuery:Object.assign({},this.modelQuery,e,{__search_values:t}),cbResolve:n,cbReject:r,templateContext:s})}save({pk:e=null,id:t=null,formName:n="edit_form",data:r=null}={}){e??=t;const s=le(e);return this.isConnected().then(()=>{let e;if(s>-1){const t=this.byId(s);if(!t)return Promise.reject(new oe(`Element not found with ID: ${s}`));e=[t]}else e=this.valuesList;let t=[];return e.forEach(e=>{const s=a();t.push(new Promise((t,o)=>{this._readFiles(e).then(i=>{const l=r?{...r}:e.serialize();l.id=e.id,this.socket.send(JSON.stringify({event:"model",event_type:"save",event_id:s,args:{form_name:n,model_name:this.modelName,model_query:this.modelQuery,data:l,id:l.id,pk:l.id,files:i}})),this.openRequest[s]=[e=>{let n="string"==typeof e.data.instance?JSON.parse(e.data.instance):e.data.instance;e.data.instance=this._parseServerRes(n),t(e)},o]})}))}),Promise.all(t)})}create(e=null){let{elem:t=null,data:n=null}=ae(e)?e:{data:e};n&&"object"==typeof n&&0===Object.keys(n).length&&(n=null);const r=a();return t||(t=this.new(n)),this.isConnected().then(()=>new Promise((e,s)=>{this._readFiles(t).then(o=>{this.socket.send(JSON.stringify({event:"model",event_type:"create",event_id:r,args:{model_name:this.modelName,model_query:this.modelQuery,data:n??t?.serialize()??{},files:o}})),this.openRequest[r]=[n=>{let r="string"==typeof n.data.instance?JSON.parse(n.data.instance):n.data.instance;t&&(t.id=r[0]?.id||r[0]?.pk),n.data.instance=this._parseServerRes(r)[0],e(n)},s]})}))}isConnected(){return new Promise((e,t)=>{if(this._isConnected)e();else if(this._isConnectingProcess&&this.openRequest[se]){const[n,r]=this.openRequest[se];this.openRequest[se]=[()=>{n(),e()},()=>{r(),t()}]}else this._isConnectingProcess=!0,this.openRequest[se]=[()=>{},()=>{}],this._connectToServer().then(()=>{e(this._checkConnection())})})}close(){this.socket&&(this._autoReconnect=!1,this.socket.onclose=()=>{},this.socket.close(),delete this.socket),this.valuesList.forEach(e=>{e._onClose()})}_readFiles(e){let t=[],n={};return e?(Object.keys(e.constructor.fields).forEach(r=>{const s=e[r];s instanceof File&&t.push(new Promise((e,t)=>{const o=a();this.openRequest[o]=[e,t],s.arrayBuffer().then(e=>{let t=new Uint8Array(e),i=Math.ceil(t.length/re);n[r]={id:o,file_name:s.name,field_name:r,content_length:s.size};for(let e=0;e<i;++e){const n=Array.from(t.slice(re*e,re*(e+1)));this.socket.send(JSON.stringify({event:"model",event_type:"upload",event_id:o,args:{chunk:n,idx:e,number_of_chunks:i,file_name:s.name,field_name:r,content_length:s.size,content_type:s.type,model_name:this.modelName,model_query:this.modelQuery}}))}}).catch(e=>{this._closeOpenRequest(o),t(e)})}))}),Promise.all(t).then(()=>n)):Promise.resolve(n)}async _onMessage(e){let t=JSON.parse(e.data);if(t.is_error)Object.hasOwn(this.openRequest,t.event_id)&&(this.openRequest[t.event_id][1](new oe(t)),this._closeOpenRequest(t.event_id)),(t.msg||t.header)&&A("pushErrorMsg",t.header||"",t.msg||""),"connect"===t.type&&(this.openRequest[se][1](new oe(t)),this._closeOpenRequest(se),this._autoReconnect=!1,this.socket.close());else{if((t.msg||t.header)&&A("pushMsg",t.header||"",t.msg||""),"connect"===t.type)this._isConnected=!0,this._isConnectingProcess=!1,this.openRequest[se][0](t),this._closeOpenRequest(se);else if(["load","list_view","named_view","detail_view"].includes(t.type)){const e=JSON.parse(t.args.data);t.args.data=await this._parseServerRes(e)}else if("on_update"===t.type||"on_create"===t.type){const e=JSON.parse(t.args.data);let n,r=await this._parseServerRes(e);n="on_create"===t.type?this.onCreate:this.onUpdate,n(r),t.args.data=r}else if("on_delete"===t.type){const e=JSON.parse(t.args.data).map(e=>le(e.id??e.pk)),n=this._removeIds(e);(this.onDelete??this.onUpdate)(n),t.args.data=n}let e=t.data?.instance;e&&(t.data.instance=JSON.parse(t.data.instance)),Object.hasOwn(this.openRequest,t.event_id)&&(this.openRequest[t.event_id][0](t),this._closeOpenRequest(t.event_id))}}noOpenRequests(){return new Promise(e=>{if(0===Object.keys(this.openRequest).length)return e();this._onNoOpenRequests.push(e)})}_closeOpenRequest(e){delete this.openRequest[e],0===Object.keys(this.openRequest).length&&(this._onNoOpenRequests.forEach(e=>e()),this._onNoOpenRequests=[])}_connectToServer(){return new Promise(e=>{const t=`${this.modelName}`+(this.modelId>0?`/${this.modelId}`:"");"https:"===window.location.protocol?this.socket=new WebSocket(`wss://${window.location.host}/sdc_ws/model/${t}`):this.socket=new WebSocket(`ws://${window.location.host}/sdc_ws/model/${t}`),this.socket.onmessage=this._onMessage.bind(this),this.socket.onclose=e=>{console.error(`SDC Model (${this.modelName}, ${this.modelId}) Socket closed unexpectedly`),this._isConnected=!1;for(const t of Object.values(this.openRequest))t[1](e);this.openRequest={},this._isConnectingProcess=!1,setTimeout(()=>{this._autoReconnect&&!this._isConnected&&this.isConnected().catch(()=>{})},1e3)},this.socket.onerror=e=>{if(console.error(`Model Socket encountered error: ${e} Closing socket`),this._isConnected)try{this.socket.close()}catch(e){}},this.socket.onopen=()=>{e()}})}_checkConnection(){const e=a();return new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"connect",event_id:e,args:{model_name:this.modelName,model_query:this.modelQuery}})),this.openRequest[e]=[t,n]})}_parseServerRes(e){const t=[];for(const n of e){const e=ne(this.modelName);if(!e)throw new Error(`${this.modelName} is no SdcModel. mybe the models ar not importad.`);const r=new e({id:n.id??n.pk,...n.fields}),s=this.byId(r.id);s?(s.setValues(r),t.push(s)):(this.valuesList.push(r),r._setQuerySet(this,!0),t.push(r))}return this.valuesList.sort((e,t)=>e._id-t._id),t}}class ue{static fields={};constructor(e){this._id=null,this._forms=[],this.loaded=!1,this.formId=a(),this.modelName=e}static querySet(e=null,t=null){const{modelName:n}=new this({});return t?t.querySet(n,e):new ce(n,e)}addForm(e){const t=this._onChange.bind(this);this._forms.push(e),e&&e.on("input.formWatcher change.formWatcher","input, select, textarea",t)}_onChange(e){const{name:t}=e.target;if(this.constructor.fields[t]){try{this[`set${t}`](d(e.target))}catch{return}this._updateForm(t,e.target)}}_updateForm(e,t=null){const n=this;this._forms.forEach(r=>{r.find(`[name="${e}"]`).each(function(){this!==t&&p(this,n[e])})})}setValues(e={}){throw new Error("setValues() must be implemented by subclass")}_setQuerySet(e,t){this._querySet=new WeakRef(e),this.loaded=t}get querySet(){return this._querySet.deref()}save({formName:e="edit_form",data:t=null}={}){return this._querySet.deref().save({pk:this.id,formName:e,data:t})}create(e=null){const t=ae(e)?e.data??null:e;return this._querySet.deref().create({elem:this,data:t})}delete(){return this._querySet.deref().delete({elem:this})}load(){return this._querySet.deref().update({item:this})}update(){return this.load()}get id(){return this._id}set id(e){this._id=e}set pk(e){this.id=e}get pk(){return this._id}close(){return this._querySet.deref().close()}_onClose(){Object.keys(this.constructor.fields).filter(e=>this[`_${e}`]instanceof ce).forEach(e=>this[`_${e}`].close())}detailView({cbResolve:e=null,cbReject:t=null,templateContext:n={}}){return this._querySet.deref().detailView({pk:this.id,cbResolve:e,cbReject:t,templateContext:n})}serialize(){return Object.entries(this.constructor.fields).reduce((e,[t,n])=>{const r=this[t];if(r instanceof ce)if(n.many_to_many||n.one_to_many)e[t]=r.getIds();else{const n=r.getIds();n.length>0?e[t]=n[0]:e[t]=null}else n.is_relation&&r instanceof ue?e[t]=r.id??null:r instanceof Date?e[t]="DateField"===n.type?m(r):r.toISOString():e[t]=r;return e},{})}toJson(){const e={};for(let t in this.constructor.fields){const n=this[t];n instanceof File?e[t]=n.name:e[t]=n instanceof ue?n.id:n instanceof ce?n.getIds():n}return e}syncFormToModel(e){return this.syncForm(e)}_resolveForms(e){return e&&e.hasClass(this.formId)?e:$(`.${this.formId}`)}syncModelToForm(e){e=this._resolveForms(e);const t=this,{fields:n}=this.constructor;e.each(function(){const e=le($(this).data("model_pk"));if(le(t.id)===e)for(let e of this.elements){let{name:r}=e;r&&""!==r&&n[r]&&p(e,t[r])}})}syncForm(e){e=this._resolveForms(e);const t=this,{fields:n}=this.constructor,r={};function s(e,s){if(n[e])try{t[e]=s}catch{}r[e]=s}return e.each(function(){const e=le($(this).data("model_pk"));if(t.id===e||null===t.id&&-1===e){for(let e of this.elements)s(e.name,d(e));return t}}),r}form({cbResolve:e=null,cbReject:t=null}={}){return null===this.id||-1===this.id?this._createForm({cbReject:t,cbResolve:e}):this._editForm({cbReject:t,cbResolve:e})}_createForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"create_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}_editForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"edit_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}namedForm({formName:e,cbResolve:t=null,cbReject:n=null}){let r=$('<div class="container-fluid">');return this._querySet.deref().getForm({modelObj:this,eventType:"named_form",formName:e,$divForm:r,cbResolve:t,cbReject:n,formId:this.formId}),r}validate(e,t){const n=function(e,t){const{type:n,required:r,max_length:s,is_relation:o,many_to_many:i,one_to_many:l,many_to_one:a,one_to_one:c,related_model:u}=t;if(r&&(null==e||""===e))return"This field is required";if(null==e||""===e)return null;if((i||l||a||c)&&(!(e instanceof ce)||e.modelName!==u))return"string"==typeof e&&(e=JSON.parse(e)),(i||a)&&Array.isArray(e)&&e.some(e=>!Number.isNaN(parseInt(e)))?null:"object"!=typeof e&&Number.isNaN(parseInt(e))?"Must be object or ID":null;switch(n){case"CharField":case"TextField":if("string"!=typeof e)return"Must be a string";if(s&&e.length>s)return`Max length is ${s}`;break;case"IntegerField":case"SmallIntegerField":case"BigIntegerField":case"PositiveIntegerField":case"PositiveSmallIntegerField":case"PositiveBigIntegerField":case"AutoField":case"SmallAutoField":case"BigAutoField":if(!isFinite(parseInt(e)))return"Must be an integer";break;case"FloatField":case"DecimalField":if(!isFinite(parseFloat(e)))return"Must be a number";break;case"BooleanField":if("boolean"!=typeof e)return"Must be a boolean";break;case"DateField":case"DateTimeField":if(isNaN(Date.parse(e)))return"Must be a valid date";break;case"EmailField":if("string"!=typeof e||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))return"Invalid email";break;case"URLField":try{new URL(e)}catch{return"Invalid URL"}break;case"UUIDField":if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(e))return"Invalid UUID";break;case"JSONField":if("string"==typeof e)try{JSON.parse(e)}catch{return"Must be valid JSON"}break;case"FileField":if(!(ie.isValid(e)||e instanceof File||e instanceof ie))return"Must be a valid file";if("undefined"!=typeof File&&e instanceof File){if(t.max_size&&e.size>t.max_size)return`File too large (max ${t.max_size} bytes)`;if(t.allowed_types&&!t.allowed_types.includes(e.type))return`Invalid file type (${e.type})`}}return null}(e,t);if(n)throw new Error(n)}parseValue(e,t){const{type:n,many_to_many:r,one_to_many:s,many_to_one:o,one_to_one:i}=t;if(null===e)return null;if((r||s||o||i)&&e&&"string"==typeof e)return JSON.parse(e);switch(n){case"CharField":case"TextField":case"SlugField":case"UUIDField":case"EmailField":return`${e}`;case"IntegerField":case"SmallIntegerField":case"BigIntegerField":case"PositiveIntegerField":case"PositiveSmallIntegerField":case"PositiveBigIntegerField":case"AutoField":case"SmallAutoField":case"BigAutoField":return parseInt(e,10);case"FloatField":case"DecimalField":return parseFloat(e);case"BooleanField":return!!e;case"DateField":case"DateTimeField":return f(e);case"URLField":return new URL(e);case"FileField":if(null==e)return null;if("string"==typeof e)return null;if(ie.isValid(e))return new ie(e);if(e instanceof ie)return new ie(e);if("undefined"!=typeof File&&e instanceof File)return e;break;case"JSONField":if("object"==typeof e)return e;if("string"==typeof e)return JSON.parse(e)}return e}}let de=!1,he=!1,fe=null,me={};function pe(){return window.SERVER_CALL_VIA_WEB_SOCKET?new Promise(e=>de?e():he?void setTimeout(()=>{pe().then(()=>{e()})},200):e(ge())):Promise.resolve(!0)}function _e(){window.SERVER_CALL_VIA_WEB_SOCKET&&function(){if(de){de=!1;try{fe.close()}catch(e){}}}()}function ge(){return he=!0,new Promise(e=>{fe="https:"===window.location.protocol?new WebSocket(`wss://${window.location.host}/sdc_ws/ws/`):new WebSocket(`ws://${window.location.host}/sdc_ws/ws/`),fe.onmessage=function(e){ye(JSON.parse(e.data))},fe.onclose=function(){de&&console.error("SDC Socket closed unexpectedly"),de=!1;for(const[e,t]of Object.entries(me))t[1]({}),delete me[e];setTimeout(()=>{ge()},1e3)},fe.onerror=function(e){if(console.error("Socket encountered error: ",e.message,"Closing socket"),de)try{fe.close()}catch(e){}},fe.onopen=function(){de=!0,he=!1,e()}})}function ye(e){if(e||(e={}),e.is_error)(e.msg||e.header)&&A("pushErrorMsg",e.header||"",e.msg||""),e.id&&me[e.id]&&(me[e.id][1](e.data||null),delete me[e.id]);else if((e.msg||e.header)&&A("pushMsg",e.header||"",e.msg||""),e.type&&"sdc_recall"===e.type){const{data:t}=e;t&&"object"==typeof t&&(t.msg||t.header)&&A("pushMsg",t.header||"",t.msg||""),e.id&&me[e.id]&&(me[e.id][0](e.data),delete me[e.id])}else if(e.type&&"sdc_event"===e.type){let{event:t}=e;t&&A(t,e.payload)}else e.type&&"sdc_redirect"===e.type&&A("onNavLink",e.link)}class ve{constructor(){this._uuid=a(),this.contentUrl="",this.contentReload=!1,this.parsedContentUrl=null,this.events=[],this.load_async=!1,this._allEvents=null,this._autoRedirect=null,this._params={},this._urlParams=[],this._models=[],this._cssUrls=[],this.afterShow=()=>{console.warn("afterShow is deprecated!!")},this._mixins={},this._tagName=Object.getPrototypeOf(this)._tagName??"",this._childController={},this._parentController=null,this._onLoadDone=!1,this.$container=null,this._isMixin=!1}get params(){return this._params}set params(e){this._params=e}_runLifecycle(e,t){$e.DEBUG&&!this._isMixin&&console.debug(e,this._tagName);let n=[];if(!this._isMixin){this._isMixin=!0;for(let r in this._mixins){let s=this._mixins[r];"function"==typeof s[e]&&n.push(s[e].apply(this,t))}return Promise.all(n).then(()=>{this._isMixin=!1})}}onInit(){$e.DEBUG&&!this._isMixin&&console.debug(Array.apply(null,arguments),this._tagName)}set autoRedirect(e){this._autoRedirect=e}get autoRedirect(){return this._autoRedirect}get parentController(){return this._parentController}get childController(){return this._childController}onLoad(){return this._runLifecycle("onLoad",arguments)}willShow(){return this._runLifecycle("willShow",arguments)}onRefresh(){return this._runLifecycle("onRefresh",arguments)}onRemove(){return this._runLifecycle("onRemove",arguments),!0}noOpenModelRequests(){return Promise.all(this._models.map(e=>e.noOpenRequests()))}remove(){for(const e of this._models)e.close();const{_childController:e}=this;for(let t in e)if(Object.hasOwn(e,t))for(let n of e[t])if(!n.remove())return!1;if(!this.onRemove||this.onRemove()){T(this);const e=r(this._tagName);if(this._parentController._childController[e]){let t=this._parentController._childController[e];for(let e=0;e<t.length;e++)t[e]===this&&t.splice(e,1)}return this.$container.remove(),!0}return!1}controller_name(){return this._tagName.replace(/-./g,e=>` ${e[1].toUpperCase()}`).replace(/^./g,e=>`${e.toUpperCase()}`)}addEvent(e,t,n){this.getEvents(),this._allEvents[e]=this._allEvents[e]||{},this._allEvents[e][t]=n}getEvents(){if(this._allEvents)return this._allEvents;let e=[];e=e.concat(this.events);for(let t in this._mixins){let n=this._mixins[t];Array.isArray(n.events)&&(e=e.concat(n.events))}return this._allEvents=_.merge({},...e)}post(e,t){return $e.post(this,e,t)}get(e,t){return $e.get(this,e,t)}submitForm(e,t,n){return $e.submitFormAndUpdateView(this,e,t,n)}serverCall(e,t){let n=this.contentUrl.match(/sdc_view\/([^/]+)/i);if(n&&!(n.length<2))return function(e,t,n,r,s){return s=function(e){return null==e?{}:"object"!=typeof e||Array.isArray(e)?{arg0:e}:e}(s),window.SERVER_CALL_VIA_WEB_SOCKET?function(e,t,n,r){let s=a();return pe().then(()=>{fe.send(JSON.stringify({event:"sdc_call",id:s,controller:t,app:e,function:n,args:r}))}),new Promise((e,t)=>{me[s]=[e,t]})}(e,t,r,s):function(e,t,n){return n={data:JSON.stringify(n),_sdc_func_name:t,_method:"sdc_server_call"},$.post({url:e,data:n,beforeSend:function(e,t){e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}}).then(e=>{const t=e._return_data;return ye(t),t}).catch(e=>{const t=e.responseJSON||{};throw t.is_error=!0,ye(t),e})}(n,r,s)}(n[1],this._tagName,this.parsedContentUrl??this.contentUrl,e,t);console.error("To use the serverCall function the contentUrl must contain sdc_view/<app>: "+this._tagName)}querySet(e,t={}){const n=new ce(e,t);return this._models.push(n),n}newModel(e,t={}){return console.warn("newModel is deprecated and will soon be removed. Please use this.querySet(modelName, modelQuery)"),this.querySet(e,t)}find(e){return this.$container.find(e)}refresh(){return $e.refresh(this.$container,this)}reload(){return $e.reloadController(this)}reconcile(e,t=null){return $e.reconcile(this,e,t)}submitModelFormDistributor(e,t){return"function"==typeof this._submitModelForm?this._submitModelForm(e,t):"function"==typeof this.submitModelForm?this.submitModelForm(e,t):this.defaultSubmitModelForm(e,t)}iterateAllChildren(){const{_childController:e}=this;let t=[];for(let n in e)if(Object.hasOwn(e,n))for(let r of e[n])t.push(r),t.push(...r.iterateAllChildren());return t}defaultSubmitModelForm(e,t){if(!this._isMixin){t.stopPropagation(),t.preventDefault();let{model:n,form_name:r}=e.data(),s=n.syncForm(e);return new Promise((t,o)=>{let i;i=null!==n.id&&n.id>=0?n.save({formName:r,data:s}):n.create({data:s}),i.then(n=>{c(e);const r=Array.isArray(n)?n[0]:n;this.submit_model_form_success&&this.submit_model_form_success(r);for(const e of this.iterateAllChildren())e.submit_model_form_success&&e.submit_model_form_success(r);t(n)}).catch(t=>{this.reconcile($(`<div class="container-fluid">${t.html}</div>`),e.find(".container-fluid").first()),this.submit_model_form_error&&this.submit_model_form_error(t);for(const e of this.iterateAllChildren())e.submit_model_form_error&&e.submit_model_form_error(t);o(t)})})}return Promise.resolve()}}const we={classname:"class"};window.sdcDom=function(e,t,...n){if(!e)return"";const r=function(e,t){let n,r=!1;if("string"==typeof e)n=$(document.createElement(e));else{const t=`this.${e.name}`;n=$(document.createElement(t)),n.data("handler",e),r=!0}return t&&Object.entries(t).forEach(([e,t])=>{if(e.startsWith("on")){const r=e.substring(2).toLowerCase();n[0].addEventListener(r,t),(n[0]._sdcListeners??=[]).push([r,t])}else we[e.toLowerCase()]&&(e=we[e.toLowerCase()]),n[0].setAttribute(e,t)}),r&&n.addClass("_bind_to_update_handler _with_handler"),n}(e,t);for(const e of n)r.append(e);return r};const be=e=>{e["url-link"]?A("onNavLink",e["url-link"]):window.location.href=e.url};let $e={CSRF_TOKEN:window.CSRF_TOKEN||"",LANGUAGE_CODE:window.LANGUAGE_CODE||"en",DEBUG:window.DEBUG||!1,VERSION:window.VERSION||"0.0",tagNames:[],Global:N,rootController:null,globalRootController:null,_isInit:!1,_origin_trigger:null,_globalControllerClasses:[],_createdGlobals:[],init_sdc:()=>{$e._isInit||($e._isInit=!0,$e._origin_trigger?_e():($e._origin_trigger=$.fn.trigger,$.fn.trigger=function(e){const t={}.hasOwnProperty.call(e,"type")?e.type:e;return w.includes(t)||(w.push(t),$(window).on(t,R)),$e._origin_trigger.call(this,e)},$e.updateJquery()),pe(),function(){const e=$(window);w.forEach(t=>{e.off(t).on(t,R)})}(),$e.rootController=$e.rootController||new ve,$e.globalRootController=$e.globalRootController||new ve),$e.tagNames=Object.keys(O);const t=N.filter(e=>!$e._createdGlobals.includes(e));$e._createdGlobals.push(...t);const n=$("<div></div>");t.forEach(e=>{const t=O[e][0];n.append(`<${t.prototype._tagName}></${t.prototype._tagName}>`)});const{refreshProcess:r}=I(null,$e.rootController);return K($e.tagNames,n,$e.globalRootController,r).then(()=>K($e.tagNames,(e||(e=$("body")),e),$e.rootController,r).then(e=>(x(r),e)))},updateJquery:()=>{$.fn.safeReplace=function(e){return $e.safeReplace($(this),e)},$.fn.safeEmpty=function(){return $e.safeEmpty($(this))},$.fn.safeRemove=function(){return $e.safeRemove($(this))}},controllerToTag:e=>n(e.name).replace(/-controller$/,""),registerGlobal:e=>{const t=$e.register(e);let n=e.prototype._tagName;return N.includes(n)||N.push(n),t},cleanCache:()=>{D={}},register:(e,t=!1)=>{let r=$e.controllerToTag(e);return!O[r]||t?(O[r]=[e,[]],e.prototype._tagName=r,{addMixin:(...e)=>{for(let t of e){let e;"string"==typeof t?e=n(t):t&&(e=$e.controllerToTag(t)),O[r][1].push(e)}}}):{addMixin:(...e)=>{}}},post:(e,t,n)=>(n||(n={}),n.CSRF_TOKEN=$e.CSRF_TOKEN,$e.ajax(e,t,n,$.post)),get:(e,t,n)=>$e.ajax(e,t,n,$.get),ajax:(e,t,n,r)=>{n||(n={}),n.VERSION=$e.VERSION,n._method=n._method||"api";const s=new Promise((o,i)=>r(t,n).then((t,n,r)=>{o(t,n,r),"redirect"===t.status?be(t):s.then(()=>{$e.refresh(e.$container)})}).catch((e,t,n)=>{301===e.status&&e.responseJSON?(e=e.responseJSON,be(e),o(e,t,n)):i(e,t,n)}));return s},submitFormAndUpdateView:(e,t,n,r)=>{let s=new FormData(t);const i=new Promise((l,a)=>{o(s,n||t.action,r||t.method).then((t,n,r)=>{l(t,n,r),"redirect"===t.status?be(t):i.then(()=>{$e.refresh(e.$container,e)})}).catch((e,t,n)=>{301===e.status?(e=e.responseJSON,be(e),l(e,t,n)):a(e,t,n)})});return i},submitForm:(e,t,n)=>{let r=new FormData(e);return new Promise((s,i)=>{o(r,t||e.action,n||e.method).then(s).catch(i)})},getController:e=>W(e),safeEmpty:e=>(e.children().each(function(e,t){let n=$(t);$e.safeRemove(n)}),e),safeReplace:(e,t)=>(t.insertBefore(e),$e.safeRemove(e)),safeRemove:e=>(e.each(function(){let e=$(this);e.data(`${U}`)&&e.data(`${U}`).remove()}),e.find(`.${M}`).each(function(){const e=$(this).data(`${U}`);e&&e.remove()}),e.remove()),reloadController:e=>function(e){if(e.contentUrl){let t=B(e);return e.contentUrl=t.url,V(e,t.args)}return new Promise(e=>{e($())})}(e).then(t=>{let n=$(t);return $e.reconcile(e,n)}),reconcile:(e,t,n=null,r=null)=>{if(!n){let n=e.$container.clone().empty();n.data(U,null),n.removeClass(M),n.append(t),t=n}n=n??e.$container;const{refreshProcess:s,isRunningProcess:o}=I(r,e);return Z(t,e,s).then(()=>{var r;return X(t,n),(r=e)._childController={},r.find(`.${M}`).each(function(){const e=$(this),t=W(e);t&&W(e.parent())===r&&S(r,t)}),o||x(s),e})},refresh:(e,t=null)=>Z(e,t)};function Re(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)"__proto__"!==r&&(e[r]=n[r])}return e}var Ce=function e(t,n){function r(e,r,s){if("undefined"!=typeof document){"number"==typeof(s=Re({},n,s)).expires&&(s.expires=new Date(Date.now()+864e5*s.expires)),s.expires&&(s.expires=s.expires.toUTCString()),e=encodeURIComponent(e).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var o="";for(var i in s)s[i]&&(o+="; "+i,!0!==s[i]&&(o+="="+s[i].split(";")[0]));return document.cookie=e+"="+t.write(r,e)+o}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var n=document.cookie?document.cookie.split("; "):[],r={},s=0;s<n.length;s++){var o=n[s].split("="),i=o.slice(1).join("=");try{var l=decodeURIComponent(o[0]);if(l in r||(r[l]=t.read(i,l)),e===l)break}catch(e){}}return e?r[e]:r}},remove:function(e,t){r(e,"",Re({},t,{expires:-1}))},withAttributes:function(t){return e(this.converter,Re({},this.attributes,t))},withConverter:function(t){return e(Re({},this.converter,t),this.attributes)}},{attributes:{value:Object.freeze(n)},converter:{value:Object.freeze(t)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"});let Ne,Oe=[];function Se(){if(!jest)throw new Error("JEST is not defined");0===Oe.length&&(Ne=$.ajax.bind($),Oe.push(jest.spyOn($,"ajax")),Oe[0].mockImplementation(function(e){return Ne(e).then(e=>e).catch(e=>e)}))}const Fe=_e,ke={get_controller:async function(e,t={},n=""){Se();const r=$("body");$e.updateJquery(),r.safeEmpty();const s=$(`<${e}>${n}</${e}>`);for(const[e,n]of Object.entries(t))s.data(e,n);const o=$("<div></div>").append(s);r.append(o),$e._isInit=!1,$e.cleanCache(),await $e.init_sdc();const i=$e.getController(s);return i.navControllerPath=[e],i},getCsrfToken:function(){return function(e){if(document.cookie&&""!==document.cookie){const t=document.cookie.split(";");for(let n=0;n<t.length;n++){const r=t[n].trim();if(r.substring(0,10)===e+"=")return decodeURIComponent(r.substring(10))}}return""}("csrftoken")},controllerFromTestHtml:async function(e,t=null){Se();const n=$("body");$e.updateJquery(),n.safeEmpty().append(e),$e._isInit=!1,$e.cleanCache(),await $e.init_sdc();let r=$e.rootController.iterateAllChildren();if(!t)return r;const s=r[0].onRefresh,o=jest.spyOn(r[0],"onRefresh");return new Promise(e=>{o.mockImplementation(function(){o.mockRestore();const t=s.apply(r[0],arguments);return e(r),t})})},logout:()=>{Ce.remove("sessionid"),console.log("Logged out")},login:e=>{const t=globalThis.SDC_TEST_USER?.[e];return t?(Ce.set("sessionid",t),console.log(`Logged in as ${e}`),!0):(Ce.remove("sessionid"),console.warn(`Unknown test user: ${e}`),!1)}};export{ve as AbstractSDC,ue as SdcModel,ce as SdcQuerySet,T as allOff,$e as app,l as checkIfParamNumberBoolOrString,c as clearErrorsInForm,k as controllerFactory,L as on,te as registerModel,E as runControlFlowFunctions,u as setErrorsInForm,q as setEvent,Fe as socketReconnect,ke as test_utils,A as trigger};
2
+ let e;function t(){return new Promise(function(e){e()})}function n(e){return(e=(e=e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)).replace(/[0-9]+/g,e=>`-${e}`)).replace(/^[-]/g,"")}function r(e){return e.replace(/-./g,e=>`${e[1].toUpperCase()}`)}const s=(e,t)=>{let n=t,r=Object.getOwnPropertyNames(e.prototype).concat(Object.getOwnPropertySymbols(e.prototype));for(;""!==n.name;)Object.getOwnPropertyNames(n.prototype).concat(Object.getOwnPropertySymbols(n.prototype)).forEach(t=>{t.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/)||r.includes(t)||(r.push(t),Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(n.prototype,t)))}),n=Object.getPrototypeOf(n)};function o(e,t,n){return $.ajax({url:t,type:n||"POST",xhr:function(){var e=$.ajaxSettings.xhr();return e.upload&&e.upload.addEventListener("progress",i,!1),e},data:e,cache:!1,contentType:!1,processData:!1,beforeSend:function(e,t){(function(e){return/^(GET|HEAD|OPTIONS|TRACE)$/.test(e)})(t.type)||this.crossDomain||e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}})}function i(e){if(e.lengthComputable){var t=Math.round(e.loaded/e.total*100),n=$(".progress-container");100===t?n.hide():n.show(),t+="%",n.find(".progress-bar").css({width:t}).text(t)}}function l(e,t=null){return"string"!=typeof e?e:t&&void 0!==t[e]?"function"==typeof t[e]?t[e].bind(t):t[e]:e.match(/^(true|false)$/)?"true"===e:"undefined"!==e?"none"===e.toLowerCase()?null:e.match(/^-?\d+$/)?parseInt(e):e.match(/^-?\d+\.?\d+$/)?parseFloat(e):e.match(/^(['][^']*['])|(["][^"]*["])$/)?e.substr(1,e.length-2):e:void 0}function a(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}function c(e){e.find(".has-error").removeClass("has-error").find(".alert-danger").remove(),e.find(".non-field-errors").remove()}function u(e,t){t=$("<div>").append(t),e.find(".has-error").removeClass("has-error").find(".alert-danger").safeRemove(),e.find(".non-field-errors").safeRemove();let n=t.find("input[type=file]").parent();e.find("input[type=file]").parent().each(function(e){$(this).replaceWith(n[e])});let r=0===t.find(".non-field-errors").insertAfter(e.find(".hidden-form-fields")).length;return t.find(".has-error").each(function(){r=!1;let t=$(this),n=t.data("auto-id"),s=e.find(".form-group."+n);s.addClass("has-error"),s.find(".form-input-container").append(t.find(".alert-danger"))}),r}function d(e){let{type:t,name:n}=e;return n&&""!==n?"hidden"===t?(r=$(e).val()).toLowerCase().match(/^(true|false)$/)?"true"===r.toLowerCase():"undefined"!==r?"none"===r.toLowerCase()?null:r.match(/^-?\d+$/)?parseInt(r,10):r.match(/^-?\d+\.?\d+$/)?parseFloat(r):r.match(/^(['][^']*['])|(["][^"]*["])$/)?r.substring(1,r.length-1):r:void 0:"checkbox"===t?e.checked:"file"===t?e.files[0]:$(e).val():null;var r}const h=e=>String(e).padStart(2,"0");function f(e){if(null==e||""===e)return null;let t;if(e instanceof Date)t=e;else if("string"==typeof e&&/^\d{4}-\d{2}-\d{2}$/.test(e)){const[n,r,s]=e.split("-").map(Number);t=new Date(n,r-1,s)}else t=new Date(e);return isNaN(t.getTime())?null:t}function m(e){const t=f(e);return t?`${t.getFullYear()}-${h(t.getMonth()+1)}-${h(t.getDate())}`:""}function p(e,t){let{type:n,name:r}=e;if(r&&""!==r)if("datetime-local"===n)e.value=function(e){const t=f(e);return t?`${m(t)}T${h(t.getHours())}:${h(t.getMinutes())}`:""}(t);else if("date"===n)e.value=m(t);else if("checkbox"===n)e.checked=!!t;else if("file"===n){if(t instanceof File&&"undefined"!=typeof DataTransfer){let n=new DataTransfer;n.items.add(t),e.files=n}}else t instanceof ue?$(e).val(t.id):t instanceof ce?$(e).val(`[${t.getIds().join(",")}]`):(null===t&&(t=""),$(e).val(t));return null}function g(e,t=null){return Object.fromEntries(Object.entries(e).filter(([e,t])=>e!==U).map(([e,n])=>{if("string"==typeof n&&n.startsWith("SDC_JSON_MODEL=["))try{const{pk:t,fields:r}=JSON.parse(n.slice(16,-1));return[e,{...r,id:t}]}catch{}return[e,l(n,t)]}))}function y(e,t=null){return g(e.data(),t)}const v=["onbeforeunload","onunload"],w=Object.keys(window).filter(e=>/^on/.test(e)&&!v.includes(e)).map(e=>e.slice(2));function b(e,t,n){let r;switch(e){case"mouseleave":case"mouseout":case"mouseenter":return r=document.elementFromPoint(t.clientX,t.clientY),n!==r&&!n.contains(r);default:return!0}}function R(e){let t=e.type;Object.hasOwn(e,"namespace")&&e.namespace&&e.namespace.length&&(t+=`.${e.namespace}`);let n=$(e.target),r=null,s=!1,o=!1;for(e.stopImmediatePropagation=()=>o=!0,e.stopPropagation=()=>o=s=!0;n.length;){let i=n.attr(`sdc_${t}`);if(i&&b(t,e,n[0])){if(!r&&(r=W(n),!r))return;for(;r;){if(i.split(" ").forEach(o=>{if(s)return;let i=null;if("function"==typeof o)i=o;else if("function"==typeof r[o])i=r[o];else if("string"==typeof o&&o.startsWith("this.event_")){if(i=r.getEvents()[t],!i)return;if(i=i[o.slice(11)],!i)return}i&&i.call(r,n,e)}),o)return;r=r._parentController}}if(s)return;n=n.parent()}return{res:!0}}function N(e){const t=e.getEvents();for(let n in t)if(Object.hasOwn(t,n)){let r=t[n];for(let t in r)Object.hasOwn(r,t)&&e.find(t).each(function(){let e=$(this),r=e.attr(`sdc_${n}`)||null;r=r?r.split(" "):[];const s=`this.event_${t}`;-1===r.indexOf(s)&&(r.push(s),e.attr(`sdc_${n}`,r.join(" ")))})}}let C=[],O={};function S(e,t){if(e){let n=r(t._tagName);e._childController[n]||(e._childController[n]=[]),e._childController[n].push(t)}return t._parentController=e}function F(e,t,n,r){let o=[];r=function(e,t){e=(e=e.concat(O[t][1])).filter((e,t,n)=>n.indexOf(e)===t);let n=!0;for(;n;){n=!1;for(let t of e)for(let r of O[t][1])e.includes(r)||(e.push(r),n=!0)}return e}(r,n);for(let e of r)o.push(O[e][0]);let i=new(function(e,...t){let n={[e.name]:class{constructor(...n){let r={};t.forEach(e=>{let t;Object.assign(this,t=new e),t._tagName=e.prototype._tagName,t._isMixin=!0,r[e.name]=t}),Object.assign(this,new e),this._mixins=r}static get name(){return e.name}static className(){return this.name}get mixins(){return this._mixins}}}[e.name];return s(n,e),t.forEach(e=>{s(n,e)}),n}(O[n][0],...o));return i._tagName=n,S(e,i),i.$container=t,function(e,t){!function(e,t,n){if(!e)return!1;e.params=y(t,n._parentController)}(t,e,t)}(t,i),i}function k(e,t,n,s){if(C.includes(n)){let o=r(n);return window[o]||(window[o]=F(e,t,n,s)),window[o].$container=t,window[o]}return F(e,t,n,s)}function E(e,n){const r=function(e){return function(e){let t={args:{}};return e.contentUrl&&(t=B(e),e.contentUrl=t.url),Promise.all([V(e,t.args)]).then(function(e){let t=e[0];if(t)try{return $(t)}catch{return $("<div></div>").append(t)}return null})}(e).then(n=>!e.onLoad||e._onLoadDone?n:(e._onLoadDone=!0,(e.onLoad(n)||t()).then(()=>n)))}(e).then(function(t){return function(e,t){return z(e,t).then(function(t){if(t=t||!0,e.willShow){let n=e.willShow();if(n instanceof Promise)return n.then(function(){return t})}return t})}(e,t)}).then(()=>function(e,t){return Z(null,e,t)}(e,n)).catch(function(t){if("string"==typeof t||t instanceof $)return z(e,t);throw t});return e.load_async?Promise.resolve():r}function x(e){const t=function(e){let t=[];for(;e;)t.unshift(e),e=e._parentController;return t}(e.controller[0]),n=t.concat(e.controller.slice(1));for(let t of n)N(t),t.onRefresh(e.controller[0])}function I(e,t){let n=Boolean(e);return n?e.uuids.has(t._uuid)||(e.uuids.add(t._uuid),e.controller.push(t)):e={uuids:new Set([t._uuid]),controller:[t]},{isRunningProcess:n,refreshProcess:e}}let j={},P={};function L(e,t){return q(e),Object.hasOwn(P,e)?t[P[e]]?void j[e].push(t):console.log("No event handler: "+e,t):console.log("No event: "+e,t)}function q(e,t){t||(t=e),P[e]||(P[e]=t,j[e]=[])}function A(e){for(let t in j)if(Object.hasOwn(j,t))for(let n=j[t].length-1;n>=0;n--)e===j[t][n]&&j[t].splice(n,1)}function T(e){let n=Array.apply(null,arguments);if(e=n.shift(),!Object.hasOwn(j,e)||!Object.hasOwn(P,e))return t();let r=j[e],s=P[e],o=[];for(let e=0;e<r.length;e++){let t=r[e][s].apply(r[e],n);void 0!==t&&o.push(t)}return Promise.all(o)}let D={};const U="_controller_",M="_sdc_controller_";function J(e,t,n){if(!e)return[];let r=e.children(),s=[];return r.each(function(e,r){let o=$(r),i=o.prop("tagName").toLowerCase().split("_");$.inArray(i[0],t)>=0?s.push({tag:i[0],super:i.splice(1)||[],dom:o}):i[0].startsWith("this.")?o.addClass(`_bind_to_update_handler sdc_uuid_${n._uuid}`):s=s.concat(J(o,t,n))}),s}function V(e,t){const{contentUrl:n,_tagName:r,contentReload:s}=e;return n?D[r]?Promise.resolve(D[r]):(t.VERSION=$e.VERSION,t._method="content",$.get(n,t).then(function(e){return s||(D[r]=e),e}).catch(function(t){if(301===t.status){const n=t.responseJSON;return T("_RedirectOnView",n["url-link"]),s||(e.autoRedirect=n["url-link"]),"<p>Redirected</p>"}throw e.autoRedirect=null,"function"==typeof e.confirmPageLoaded&&T("navLoaded",{controller_name:()=>t.status}),`<sdc-error data-code="${t.status}">${t.responseText}</sdc-error>`})):Promise.resolve(!1)}function Q(e,t,n=null){return t=t||e.data(U),K($e.tagNames,e,t,n)}function B(e){let t=e.contentUrl;if(e&&0===e._urlParams.length){let n,r=/%\(([^)]+)\)\w/gm;for(e._urlParams=[];n=r.exec(t);)e._urlParams.push(n[1]),e.contentReload=!0}let{args:n,params:r}=function(e,t){const n=y(t,e),[r,s]=Object.entries(n).reduce(([t,n],[r,s])=>(e._urlParams.includes(r)?t[r]=s:n[r]=s,[t,n]),[{},{}]);return{params:r,args:s}}(e,e.$container);return e._urlParams.length&&(t=function(e,t,n){for(let r in e._urlParams)if(Object.hasOwn(e._urlParams,r)){let s=e._urlParams[r],o=RegExp("%\\("+s+"\\)\\w","gm");const i=n[s];i||console.warn(`${s} is not set for controller ${e._tagName}`),t=t.replace(o,i)}return t}(e,t,r)),e.parsedContentUrl=t,{url:t,args:n}}function W(e){return e.hasClass(M)?e.data(`${U}`):e.closest(`.${M}`).data(`${U}`)}function G(e,t,n,r,s){let o=e.data(U);return o?Q(e,o,s):(o=k(r,e,t,n),e.data(U,o),e.addClass(M),E(o,s))}function z(e,t,n=null){if(t&&t.length>0){e.$container.empty(),e.$container.attr(e._tagName,"");for(let t in e._mixins)e.$container.attr(e._mixins[t]._tagName,"");e.$container.append(t)}return Q(e.$container,e,n)}function K(e,t,n,r){return new Promise(s=>{let o=J(t,e,n),i=o.length;if(0===i)return s();for(let e=0;e<o.length;e++)G(o[e].dom,o[e].tag,o[e].super,n,r).then(()=>{if(i--,0===i)return s()})})}function H({$element:e,id:t=[],parent:n=null}){t.push(function(e){if(3===e[0].nodeType)return`TEXT__${e[0].nodeValue}`;const t=[e[0].tagName];return"INPUT"===e[0].nodeName&&[["name",""],["type","text"],["id",""]].forEach(([n,r])=>{const s=e.attr(n)??r;s&&t.push(s)}),t.join("__")}(e));const r={$element:e,id:t.join("::"),depth:t.length,idx:0,getRealParent:()=>n,getIdx:function(){return this.idx=Math.max(0,(this.getRealParent()?.getIdx()??-1)+e.index()+1),this.idx},op:null,parent:n};return r.getIdx.bind(r),[r].concat(e.contents().toArray().map(e=>H({$element:$(e),id:t.slice(),parent:r})).flat())}function X(e,t){const n=H({$element:t}),r=H({$element:e});n.map((e,t)=>e.idx=t),r.map((e,t)=>e.idx=t);const s=Math.max(...r.concat(n).map(e=>e.depth)),o=Y(n,r,s);let i=[];window.MAIN=t,window.OPS=o,o.forEach((e,t)=>{const{op:n,$element:r,idx:s}=e;if("keep_counterpart"===n.type){if(n.counterpart.getIdx()!==s){const t=e.getBefore();t?n.counterpart.$element.insertAfter(t.$element):e.getRealParent().$element.prepend(n.counterpart.$element)}!function(e,t){!function(e,t){if(!e||!t||!e._sdcListeners&&!t._sdcListeners)return;(e._sdcListeners??[]).forEach(([t,n])=>e.removeEventListener(t,n));const n=t._sdcListeners??[];n.forEach(([t,n])=>e.addEventListener(t,n)),e._sdcListeners=n}(e[0],t[0]);const n=e[0].attributes??[],r=t[0].attributes??[];[...n].forEach(n=>{t.is(`[${n.name}]`)||e.removeAttr(n.name)}),[...r].forEach(t=>{t.name.startsWith("data")||e.attr(t.name)===t.value||e.attr(t.name,t.value)}),e.removeData(),Object.entries(t.data()).forEach(([t,n])=>{e.data(t,n)})}(n.counterpart.$element,r),r.hasClass(M)&&(r.data(U).$container=n.counterpart.$element,r.data(U,null)),i.push(r)}else if("delete"===n.type)r.safeRemove();else if("insert"===n.type){const{after:t,target:n}=e.op;t?r.insertAfter(t.$element):n&&n.$element.prepend(r)}}),i.forEach(e=>e.safeRemove())}function Y(e,t,n){return t.filter(e=>e.depth===n&&!e.op).forEach(t=>{const n=e.find(e=>!e.op&&e.id===t.id);if(n){const e=(t,n)=>{t.op={type:"keep",idx:n.idx},n.op={type:"keep_counterpart",counterpart:t},t=t.parent,n=n.parent,!t||t.op||n?.op||e(t,n)};e(n,t)}}),n>1?Y(e,t,n-1):(e.forEach((t,n)=>{if(!t.op){const r=(e[n-1]?.op.idx??-1)+1;t.op={type:"delete",idx:r}}}),t.forEach((e,n)=>{if(e.getBefore=()=>function(e,n){const r=e.depth;for(;n>=1&&e.depth>=r;)if((e=t[n-=1]).depth===r)return"keep_counterpart"===e.op.type?e.op.counterpart:e;return null}(e,n),e.getRealParent=()=>{return(t=e).parent?"keep_counterpart"===t.parent.op.type?t.parent.op.counterpart:t.parent:null;var t},!e.op){const t=e.getRealParent(),n="insert"===t?.op.type?"insert_ignore":"insert";e.op={type:n,target:t,after:e.getBefore()}}}),[...e,...t].sort((e,t)=>(e.op?.idx??e.idx)-(t.op?.idx??t.idx)))}function Z(e,t,n=null){if(t||(t=W(e)),!t)return Promise.resolve();const{refreshProcess:r,isRunningProcess:s}=I(n,t);return e??=t.$container,K($e.tagNames,e,t,n).then(()=>function(e,t,n){return function(e,t,n){const r=[];return t.find(`._bind_to_update_handler.sdc_uuid_${e._uuid}`).each(function(){const t=$(this);let s;if(t.hasClass("_with_handler"))s=t.data("handler");else{let t=this.tagName.toLowerCase().replace(/^this./,"");e[t]&&(s=e[t])}if("function"==typeof s){const n=g(t.data(),e);s=s.bind(e)(n)}s&&r.push(Promise.resolve(s).then(r=>{let s=$("<div></div>");return s.append(r),""===t.html()&&t.append("<div></div>"),$e.reconcile(e,s,t.children(),n)}))}),Promise.all(r)}(e,t??e.$container,n)}(t,e,r).then(()=>{s||x(r)}))}const ee={};function te(e,t){ee[e]=t}function ne(e){return ee[e]}const re=25e3,se="_connecting_process";class oe extends Error{constructor(e){"string"==typeof e&&(e={msg:e,is_error:!0,header:"Error"}),super(e.msg),this.msg=e.msg,this.header=e.header,this.is_error=e.is_error,this.html=e.html}}class ie{constructor({name:e,url:t}){this.name=e,this.url=t,this.content=null}async load(e=!1){return!e&&this.content||(this.content=await new Promise((e,t)=>{$.get(this.url).then(e).catch(()=>{e("")})})),this.content}async text(){return this.load()}static isValid(e){return!(null===e||"object"!=typeof e||Array.isArray(e)||e instanceof File||"string"!=typeof e.url||"string"!=typeof e.name)}}function le(e){const t=parseInt(e??-1,10);return Number.isNaN(t)?-1:t}function ae(e){if(!e||"object"!=typeof e||e instanceof ue)return!1;const t=Object.keys(e);return!(0===t.length||!t.every(e=>"elem"===e||"data"===e)||"elem"in e&&null!==e.elem&&!(e.elem instanceof ue)||"data"in e&&null!==e.data&&"object"!=typeof e.data)}class ce{constructor(e,t={}){return this.valuesList=[],this.loaded=!1,this.modelName=e,this.modelQuery=t??{},this._onNoOpenRequests=[],this._isConnected=!1,this._isConnectingProcess=!1,this._autoReconnect=!0,this.socket=null,this.openRequest={},this.modelId=0,this.onUpdate=()=>{},this.onCreate=()=>{},this.onDelete=null,new Proxy(this,{get:(e,t)=>"symbol"==typeof t||isNaN(t)?e[t]:e.valuesList[t],set:(e,t,n)=>isNaN(t)?(e[t]=n,!0):(e.valuesList[t]=n,!0)})}[Symbol.iterator](){let e=-1;return{next:()=>(++e,e<this.valuesList.length?{value:this.valuesList[e],done:!1}:{value:null,done:!0})}}set on_create(e){this.onCreate=e}set on_update(e){this.onUpdate=e}set on_delete(e){this.onDelete=e}_removeIds(e){const t=this.valuesList.filter(t=>e.includes(t.id));return this.valuesList=this.valuesList.filter(t=>!e.includes(t.id)),t}setIds(e){const t=this._setIds(e),n={id__in:t.map(e=>e.id)};return this.setFilter(n),t}_setIds(e){if(null===e||""===e||Array.isArray(e)&&0===e.length)return this.valuesList=[],this.valuesList;if(e instanceof ce||e instanceof ue){const t=e instanceof ue?[e]:e.valuesList;return this.valuesList=t.map(e=>{const t=null!==e.id?this.byId(e.id):null;if(t)return t;const n=(e=>{const t=new e.constructor({});return t.setValues(e.serialize()),t})(e);return n._setQuerySet(this,!0),n}),this.valuesList}let t,n=Number.NaN;if(Number.isInteger(e))n=e;else if(e instanceof Array){const n=e.map(e=>parseInt(e));n.some(Number.isNaN)||(t=n)}else if("string"==typeof e){const r=e.split(",").map(e=>parseInt(e));r.some(Number.isNaN)?n=parseInt(e):t=r}if(Number.isNaN(n)){if(t){this.valuesList=this.valuesList.filter(e=>t.includes(e.id));const e=this.getIds();t.filter(t=>!e.includes(t)).forEach(e=>{this.valuesList.push(new(ne(this.modelName))({id:e}))})}}else this.valuesList=this.valuesList.filter(e=>n===e.id),0===this.valuesList.length&&(this.new().id=n);return this.valuesList}getIds(){return this.valuesList.map(e=>e.id)}get length(){return this.valuesList.length}byId(e){if(null!==e){const t=le(e);return this.valuesList.find(e=>e.id===t)??null}return null}setFilter(e){return this.modelQuery=e,this}addFilter(e){return this.modelQuery=Object.assign({},this.modelQuery,e),this}new(e={}){const t=new(ne(this.modelName))(e);return t._setQuerySet(this,!1),this.valuesList.push(t),t}load(e=null,{limit:t=null}={}){return this.valuesList=[],this.modelQuery=e??this.modelQuery,this._sendLoad(null,t)}update({modelQuery:e=null,item:t=null}){this.modelQuery=e??this.modelQuery;let n=t?{id:t.id}:this.modelQuery;return this._sendLoad(n)}delete({pk:e=null,id:t=null,elem:n=null}){if(e??=t,null===(e=n?n.id:e))throw new Error("pk or elem must be set");const r=a();return this.isConnected().then(()=>new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"delete",event_id:r,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e}})),this.openRequest[r]=[n=>{this._removeIds([le(e)]),t(n)},n]}))}_sendLoad(e=null,t=null){return this.isConnected().then(()=>{const n=a(),r={model_name:this.modelName,model_query:e??this.modelQuery};return null!==t&&(r.limit=t),new Promise((e,t)=>{this.socket.send(JSON.stringify({event:"model",event_type:"load",event_id:n,args:r})),this.openRequest[n]=[t=>{this.loaded=!0,e(t)},t]})})}_sendListView({modelQuery:e={},cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this.view({modelQuery:e,cbResolve:t,cbReject:n,templateContext:r,eventType:"list_view"})}view({viewName:e="html_list_template",modelQuery:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={},eventType:o="named_view"}){let i=$('<div class="container-fluid">');return this.isConnected().then(()=>{const l=a();this.socket.send(JSON.stringify({event:"model",event_type:o,event_id:l,args:{view_name:e,model_name:this.modelName,model_query:t,template_context:s}})),this.openRequest[l]=[e=>{i.append(e.html),$e.refresh(i),n&&n(e)},e=>{r&&r(e)}]}),i}_sendDetailView({pk:e=null,id:t=null,cbResolve:n=null,cbReject:r=null,templateContext:s={}}){e??=t,e=le(e);let o=$('<div class="container-fluid">');return this.isConnected().then(()=>{const t=a();this.socket.send(JSON.stringify({event:"model",event_type:"detail_view",event_id:t,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e,template_context:s}})),this.openRequest[t]=[e=>{o.append(e.html),$e.refresh(o),n&&n(e)},e=>{r&&r(e)}]}),o}getForm({modelObj:e,eventType:t,formName:n,$divForm:r,cbResolve:s,cbReject:o,formId:i}){const l=a(),c=e.id??-1;this.isConnected().then(()=>{this.socket.send(JSON.stringify({event:"model",event_type:t,event_id:l,args:{model_name:this.modelName,id:c,pk:c,form_name:n}}))});const u=null===c||-1===c?"create":"edit";this.openRequest[l]=[t=>{r.append(t.html);let o=r.closest("form").addClass(`sdc-model-${u}-form sdc-model-form ${i}`).data("model",e).data("model_pk",c).data("form_name",n).attr("SdcModelName",this.modelName).attr("SdcModelPK",c);e.addForm(o),o.length>0&&!o[0].hasAttribute("sdc_submit")&&o.attr("sdc_submit","submitModelFormDistributor"),$e.refresh(r).then(()=>null),s&&s(t)},e=>{o&&o(e)}]}async get(e=null,t=!1){if(t){const t=e?.id??this.modelQuery?.id;return e&&this.setFilter(e),this.byId(t)??this.new(e||this.modelQuery)}if(await this.load(e),1!==this.length)throw new Error(`model query returns ${this.length} but only 1 expected.`);return this.addFilter({id:this.valuesList[0].id}),this.valuesList[0]}detailView({pk:e,cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this._sendDetailView({id:e,cbResolve:t,cbReject:n,templateContext:r})}listView({modelQuery:e={},searchValues:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={}}){return this._sendListView({modelQuery:Object.assign({},this.modelQuery,e,{__search_values:t}),cbResolve:n,cbReject:r,templateContext:s})}save({pk:e=null,id:t=null,formName:n="edit_form",data:r=null}={}){e??=t;const s=le(e);return this.isConnected().then(()=>{let e;if(s>-1){const t=this.byId(s);if(!t)return Promise.reject(new oe(`Element not found with ID: ${s}`));e=[t]}else e=this.valuesList;let t=[];return e.forEach(e=>{const s=a();t.push(new Promise((t,o)=>{this._readFiles(e).then(i=>{const l=r?{...r}:e.serialize();l.id=e.id,this.socket.send(JSON.stringify({event:"model",event_type:"save",event_id:s,args:{form_name:n,model_name:this.modelName,model_query:this.modelQuery,data:l,id:l.id,pk:l.id,files:i}})),this.openRequest[s]=[e=>{let n="string"==typeof e.data.instance?JSON.parse(e.data.instance):e.data.instance;e.data.instance=this._parseServerRes(n),t(e)},o]})}))}),Promise.all(t)})}create(e=null){let{elem:t=null,data:n=null}=ae(e)?e:{data:e};n&&"object"==typeof n&&0===Object.keys(n).length&&(n=null);const r=a();return t||(t=this.new(n)),this.isConnected().then(()=>new Promise((e,s)=>{this._readFiles(t).then(o=>{this.socket.send(JSON.stringify({event:"model",event_type:"create",event_id:r,args:{model_name:this.modelName,model_query:this.modelQuery,data:n??t?.serialize()??{},files:o}})),this.openRequest[r]=[n=>{let r="string"==typeof n.data.instance?JSON.parse(n.data.instance):n.data.instance;t&&(t.id=r[0]?.id||r[0]?.pk),n.data.instance=this._parseServerRes(r)[0],e(n)},s]})}))}isConnected(){return new Promise((e,t)=>{if(this._isConnected)e();else if(this._isConnectingProcess&&this.openRequest[se]){const[n,r]=this.openRequest[se];this.openRequest[se]=[()=>{n(),e()},()=>{r(),t()}]}else this._isConnectingProcess=!0,this.openRequest[se]=[()=>{},()=>{}],this._connectToServer().then(()=>{e(this._checkConnection())})})}close(){this.socket&&(this._autoReconnect=!1,this.socket.onclose=()=>{},this.socket.close(),delete this.socket),this.valuesList.forEach(e=>{e._onClose()})}_readFiles(e){let t=[],n={};return e?(Object.keys(e.constructor.fields).forEach(r=>{const s=e[r];s instanceof File&&t.push(new Promise((e,t)=>{const o=a();this.openRequest[o]=[e,t],s.arrayBuffer().then(e=>{let t=new Uint8Array(e),i=Math.ceil(t.length/re);n[r]={id:o,file_name:s.name,field_name:r,content_length:s.size};for(let e=0;e<i;++e){const n=Array.from(t.slice(re*e,re*(e+1)));this.socket.send(JSON.stringify({event:"model",event_type:"upload",event_id:o,args:{chunk:n,idx:e,number_of_chunks:i,file_name:s.name,field_name:r,content_length:s.size,content_type:s.type,model_name:this.modelName,model_query:this.modelQuery}}))}}).catch(e=>{this._closeOpenRequest(o),t(e)})}))}),Promise.all(t).then(()=>n)):Promise.resolve(n)}async _onMessage(e){let t=JSON.parse(e.data);if(t.is_error)Object.hasOwn(this.openRequest,t.event_id)&&(this.openRequest[t.event_id][1](new oe(t)),this._closeOpenRequest(t.event_id)),(t.msg||t.header)&&T("pushErrorMsg",t.header||"",t.msg||""),"connect"===t.type&&(this.openRequest[se][1](new oe(t)),this._closeOpenRequest(se),this._autoReconnect=!1,this.socket.close());else{if((t.msg||t.header)&&T("pushMsg",t.header||"",t.msg||""),"connect"===t.type)this._isConnected=!0,this._isConnectingProcess=!1,this.openRequest[se][0](t),this._closeOpenRequest(se);else if(["load","list_view","named_view","detail_view"].includes(t.type)){const e=JSON.parse(t.args.data);t.args.data=await this._parseServerRes(e)}else if("on_update"===t.type||"on_create"===t.type){const e=JSON.parse(t.args.data);let n,r=await this._parseServerRes(e);n="on_create"===t.type?this.onCreate:this.onUpdate,n(r),t.args.data=r}else if("on_delete"===t.type){const e=JSON.parse(t.args.data).map(e=>le(e.id??e.pk)),n=this._removeIds(e);(this.onDelete??this.onUpdate)(n),t.args.data=n}let e=t.data?.instance;e&&(t.data.instance=JSON.parse(t.data.instance)),Object.hasOwn(this.openRequest,t.event_id)&&(this.openRequest[t.event_id][0](t),this._closeOpenRequest(t.event_id))}}noOpenRequests(){return new Promise(e=>{if(0===Object.keys(this.openRequest).length)return e();this._onNoOpenRequests.push(e)})}_closeOpenRequest(e){delete this.openRequest[e],0===Object.keys(this.openRequest).length&&(this._onNoOpenRequests.forEach(e=>e()),this._onNoOpenRequests=[])}_connectToServer(){return new Promise(e=>{const t=`${this.modelName}`+(this.modelId>0?`/${this.modelId}`:"");"https:"===window.location.protocol?this.socket=new WebSocket(`wss://${window.location.host}/sdc_ws/model/${t}`):this.socket=new WebSocket(`ws://${window.location.host}/sdc_ws/model/${t}`),this.socket.onmessage=this._onMessage.bind(this),this.socket.onclose=e=>{console.error(`SDC Model (${this.modelName}, ${this.modelId}) Socket closed unexpectedly`),this._isConnected=!1;for(const t of Object.values(this.openRequest))t[1](e);this.openRequest={},this._isConnectingProcess=!1,setTimeout(()=>{this._autoReconnect&&!this._isConnected&&this.isConnected().catch(()=>{})},1e3)},this.socket.onerror=e=>{if(console.error(`Model Socket encountered error: ${e} Closing socket`),this._isConnected)try{this.socket.close()}catch(e){}},this.socket.onopen=()=>{e()}})}_checkConnection(){const e=a();return new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"connect",event_id:e,args:{model_name:this.modelName,model_query:this.modelQuery}})),this.openRequest[e]=[t,n]})}_parseServerRes(e){const t=[];for(const n of e){const e=ne(this.modelName);if(!e)throw new Error(`${this.modelName} is no SdcModel. mybe the models ar not importad.`);const r=new e({id:n.id??n.pk,...n.fields}),s=this.byId(r.id);s?(s.setValues(r),t.push(s)):(this.valuesList.push(r),r._setQuerySet(this,!0),t.push(r))}return this.valuesList.sort((e,t)=>e._id-t._id),t}}class ue{static fields={};constructor(e){this._id=null,this._forms=[],this.loaded=!1,this.formId=a(),this.modelName=e}static querySet(e=null,t=null){const{modelName:n}=new this({});return t?t.querySet(n,e):new ce(n,e)}addForm(e){const t=this._onChange.bind(this);this._forms.push(e),e&&e.on("input.formWatcher change.formWatcher","input, select, textarea",t)}_onChange(e){const{name:t}=e.target;if(this.constructor.fields[t]){try{this[`set${t}`](d(e.target))}catch{return}this._updateForm(t,e.target)}}_updateForm(e,t=null){const n=this;this._forms.forEach(r=>{r.find(`[name="${e}"]`).each(function(){this!==t&&p(this,n[e])})})}setValues(e={}){throw new Error("setValues() must be implemented by subclass")}_setQuerySet(e,t){this._querySet=new WeakRef(e),this.loaded=t}get querySet(){return this._querySet.deref()}save({formName:e="edit_form",data:t=null}={}){return this._querySet.deref().save({pk:this.id,formName:e,data:t})}create(e=null){const t=ae(e)?e.data??null:e;return this._querySet.deref().create({elem:this,data:t})}delete(){return this._querySet.deref().delete({elem:this})}load(){return this._querySet.deref().update({item:this})}update(){return this.load()}get id(){return this._id}set id(e){this._id=e}set pk(e){this.id=e}get pk(){return this._id}close(){return this._querySet.deref().close()}_onClose(){Object.keys(this.constructor.fields).filter(e=>this[`_${e}`]instanceof ce).forEach(e=>this[`_${e}`].close())}detailView({cbResolve:e=null,cbReject:t=null,templateContext:n={}}){return this._querySet.deref().detailView({pk:this.id,cbResolve:e,cbReject:t,templateContext:n})}serialize(){return Object.entries(this.constructor.fields).reduce((e,[t,n])=>{const r=this[t];if(r instanceof ce)if(n.many_to_many||n.one_to_many)e[t]=r.getIds();else{const n=r.getIds();n.length>0?e[t]=n[0]:e[t]=null}else n.is_relation&&r instanceof ue?e[t]=r.id??null:r instanceof Date?e[t]="DateField"===n.type?m(r):r.toISOString():e[t]=r;return e},{})}toJson(){const e={};for(let t in this.constructor.fields){const n=this[t];n instanceof File?e[t]=n.name:e[t]=n instanceof ue?n.id:n instanceof ce?n.getIds():n}return e}syncFormToModel(e){return this.syncForm(e)}_resolveForms(e){return e&&e.hasClass(this.formId)?e:$(`.${this.formId}`)}syncModelToForm(e){e=this._resolveForms(e);const t=this,{fields:n}=this.constructor;e.each(function(){const e=le($(this).data("model_pk"));if(le(t.id)===e)for(let e of this.elements){let{name:r}=e;r&&""!==r&&n[r]&&p(e,t[r])}})}syncForm(e){e=this._resolveForms(e);const t=this,{fields:n}=this.constructor,r={};function s(e,s){if(n[e])try{t[e]=s}catch{}r[e]=s}return e.each(function(){const e=le($(this).data("model_pk"));if(t.id===e||null===t.id&&-1===e){for(let e of this.elements)s(e.name,d(e));return t}}),r}form({cbResolve:e=null,cbReject:t=null}={}){return null===this.id||-1===this.id?this._createForm({cbReject:t,cbResolve:e}):this._editForm({cbReject:t,cbResolve:e})}_createForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"create_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}_editForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"edit_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}namedForm({formName:e,cbResolve:t=null,cbReject:n=null}){let r=$('<div class="container-fluid">');return this._querySet.deref().getForm({modelObj:this,eventType:"named_form",formName:e,$divForm:r,cbResolve:t,cbReject:n,formId:this.formId}),r}validate(e,t){const n=function(e,t){const{type:n,required:r,max_length:s,is_relation:o,many_to_many:i,one_to_many:l,many_to_one:a,one_to_one:c,related_model:u}=t;if(r&&(null==e||""===e))return"This field is required";if(null==e||""===e)return null;if((i||l||a||c)&&(!(e instanceof ce)||e.modelName!==u))return"string"==typeof e&&(e=JSON.parse(e)),(i||a)&&Array.isArray(e)&&e.some(e=>!Number.isNaN(parseInt(e)))?null:"object"!=typeof e&&Number.isNaN(parseInt(e))?"Must be object or ID":null;switch(n){case"CharField":case"TextField":if("string"!=typeof e)return"Must be a string";if(s&&e.length>s)return`Max length is ${s}`;break;case"IntegerField":case"SmallIntegerField":case"BigIntegerField":case"PositiveIntegerField":case"PositiveSmallIntegerField":case"PositiveBigIntegerField":case"AutoField":case"SmallAutoField":case"BigAutoField":if(!isFinite(parseInt(e)))return"Must be an integer";break;case"FloatField":case"DecimalField":if(!isFinite(parseFloat(e)))return"Must be a number";break;case"BooleanField":if("boolean"!=typeof e)return"Must be a boolean";break;case"DateField":case"DateTimeField":if(isNaN(Date.parse(e)))return"Must be a valid date";break;case"EmailField":if("string"!=typeof e||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))return"Invalid email";break;case"URLField":try{new URL(e)}catch{return"Invalid URL"}break;case"UUIDField":if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(e))return"Invalid UUID";break;case"JSONField":if("string"==typeof e)try{JSON.parse(e)}catch{return"Must be valid JSON"}break;case"FileField":if(!(ie.isValid(e)||e instanceof File||e instanceof ie))return"Must be a valid file";if("undefined"!=typeof File&&e instanceof File){if(t.max_size&&e.size>t.max_size)return`File too large (max ${t.max_size} bytes)`;if(t.allowed_types&&!t.allowed_types.includes(e.type))return`Invalid file type (${e.type})`}}return null}(e,t);if(n)throw new Error(n)}parseValue(e,t){const{type:n,many_to_many:r,one_to_many:s,many_to_one:o,one_to_one:i}=t;if(null===e)return null;if((r||s||o||i)&&e&&"string"==typeof e)return JSON.parse(e);switch(n){case"CharField":case"TextField":case"SlugField":case"UUIDField":case"EmailField":return`${e}`;case"IntegerField":case"SmallIntegerField":case"BigIntegerField":case"PositiveIntegerField":case"PositiveSmallIntegerField":case"PositiveBigIntegerField":case"AutoField":case"SmallAutoField":case"BigAutoField":return parseInt(e,10);case"FloatField":case"DecimalField":return parseFloat(e);case"BooleanField":return!!e;case"DateField":case"DateTimeField":return f(e);case"URLField":return new URL(e);case"FileField":if(null==e)return null;if("string"==typeof e)return null;if(ie.isValid(e))return new ie(e);if(e instanceof ie)return new ie(e);if("undefined"!=typeof File&&e instanceof File)return e;break;case"JSONField":if("object"==typeof e)return e;if("string"==typeof e)return JSON.parse(e)}return e}}let de=!1,he=!1,fe=null,me={};function pe(){return window.SERVER_CALL_VIA_WEB_SOCKET?new Promise(e=>de?e():he?void setTimeout(()=>{pe().then(()=>{e()})},200):e(ge())):Promise.resolve(!0)}function _e(){window.SERVER_CALL_VIA_WEB_SOCKET&&function(){if(de){de=!1;try{fe.close()}catch(e){}}}()}function ge(){return he=!0,new Promise(e=>{fe="https:"===window.location.protocol?new WebSocket(`wss://${window.location.host}/sdc_ws/ws/`):new WebSocket(`ws://${window.location.host}/sdc_ws/ws/`),fe.onmessage=function(e){ye(JSON.parse(e.data))},fe.onclose=function(){de&&console.error("SDC Socket closed unexpectedly"),de=!1;for(const[e,t]of Object.entries(me))t[1]({}),delete me[e];setTimeout(()=>{ge()},1e3)},fe.onerror=function(e){if(console.error("Socket encountered error: ",e.message,"Closing socket"),de)try{fe.close()}catch(e){}},fe.onopen=function(){de=!0,he=!1,e()}})}function ye(e){if(e||(e={}),e.is_error)(e.msg||e.header)&&T("pushErrorMsg",e.header||"",e.msg||""),e.id&&me[e.id]&&(me[e.id][1](e.data||null),delete me[e.id]);else if((e.msg||e.header)&&T("pushMsg",e.header||"",e.msg||""),e.type&&"sdc_recall"===e.type){const{data:t}=e;t&&"object"==typeof t&&(t.msg||t.header)&&T("pushMsg",t.header||"",t.msg||""),e.id&&me[e.id]&&(me[e.id][0](e.data),delete me[e.id])}else if(e.type&&"sdc_event"===e.type){let{event:t}=e;t&&T(t,e.payload)}else e.type&&"sdc_redirect"===e.type&&T("onNavLink",e.link)}class ve{constructor(){this._uuid=a(),this.contentUrl="",this.contentReload=!1,this.parsedContentUrl=null,this.events=[],this.load_async=!1,this._allEvents=null,this._autoRedirect=null,this._params={},this._urlParams=[],this._models=[],this._cssUrls=[],this.afterShow=()=>{console.warn("afterShow is deprecated!!")},this._mixins={},this._tagName=Object.getPrototypeOf(this)._tagName??"",this._childController={},this._parentController=null,this._onLoadDone=!1,this.$container=null,this._isMixin=!1}get params(){return this._params}set params(e){this._params=e}_runLifecycle(e,t){$e.DEBUG&&!this._isMixin&&console.debug(e,this._tagName);let n=[];if(!this._isMixin){this._isMixin=!0;for(let r in this._mixins){let s=this._mixins[r];"function"==typeof s[e]&&n.push(s[e].apply(this,t))}return Promise.all(n).then(()=>{this._isMixin=!1})}}onInit(){$e.DEBUG&&!this._isMixin&&console.debug(Array.apply(null,arguments),this._tagName)}set autoRedirect(e){this._autoRedirect=e}get autoRedirect(){return this._autoRedirect}get parentController(){return this._parentController}get childController(){return this._childController}onLoad(){return this._runLifecycle("onLoad",arguments)}willShow(){return this._runLifecycle("willShow",arguments)}onRefresh(){return this._runLifecycle("onRefresh",arguments)}onRemove(){return this._runLifecycle("onRemove",arguments),!0}noOpenModelRequests(){return Promise.all(this._models.map(e=>e.noOpenRequests()))}remove(){for(const e of this._models)e.close();const{_childController:e}=this;for(let t in e)if(Object.hasOwn(e,t))for(let n of e[t])if(!n.remove())return!1;if(!this.onRemove||this.onRemove()){A(this);const e=r(this._tagName);if(this._parentController._childController[e]){let t=this._parentController._childController[e];for(let e=0;e<t.length;e++)t[e]===this&&t.splice(e,1)}return this.$container.remove(),!0}return!1}controller_name(){return this._tagName.replace(/-./g,e=>` ${e[1].toUpperCase()}`).replace(/^./g,e=>`${e.toUpperCase()}`)}addEvent(e,t,n){this.getEvents(),this._allEvents[e]=this._allEvents[e]||{},this._allEvents[e][t]=n}getEvents(){if(this._allEvents)return this._allEvents;let e=[];e=e.concat(this.events);for(let t in this._mixins){let n=this._mixins[t];Array.isArray(n.events)&&(e=e.concat(n.events))}return this._allEvents=_.merge({},...e)}post(e,t){return $e.post(this,e,t)}get(e,t){return $e.get(this,e,t)}submitForm(e,t,n){return $e.submitFormAndUpdateView(this,e,t,n)}serverCall(e,t){let n=this.contentUrl.match(/sdc_view\/([^/]+)/i);if(n&&!(n.length<2))return function(e,t,n,r,s){return s=function(e){return null==e?{}:"object"!=typeof e||Array.isArray(e)?{arg0:e}:e}(s),window.SERVER_CALL_VIA_WEB_SOCKET?function(e,t,n,r){let s=a();return pe().then(()=>{fe.send(JSON.stringify({event:"sdc_call",id:s,controller:t,app:e,function:n,args:r}))}),new Promise((e,t)=>{me[s]=[e,t]})}(e,t,r,s):function(e,t,n){return n={data:JSON.stringify(n),_sdc_func_name:t,_method:"sdc_server_call"},$.post({url:e,data:n,beforeSend:function(e,t){e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}}).then(e=>{const t=e._return_data;return ye(t),t}).catch(e=>{const t=e.responseJSON||{};throw t.is_error=!0,ye(t),e})}(n,r,s)}(n[1],this._tagName,this.parsedContentUrl??this.contentUrl,e,t);console.error("To use the serverCall function the contentUrl must contain sdc_view/<app>: "+this._tagName)}querySet(e,t={}){const n=new ce(e,t);return this._models.push(n),n}newModel(e,t={}){return console.warn("newModel is deprecated and will soon be removed. Please use this.querySet(modelName, modelQuery)"),this.querySet(e,t)}find(e){return this.$container.find(e)}refresh(){return $e.refresh(this.$container,this)}reload(){return $e.reloadController(this)}reconcile(e,t=null){return $e.reconcile(this,e,t)}submitModelFormDistributor(e,t){return"function"==typeof this._submitModelForm?this._submitModelForm(e,t):"function"==typeof this.submitModelForm?this.submitModelForm(e,t):this.defaultSubmitModelForm(e,t)}iterateAllChildren(){const{_childController:e}=this;let t=[];for(let n in e)if(Object.hasOwn(e,n))for(let r of e[n])t.push(r),t.push(...r.iterateAllChildren());return t}defaultSubmitModelForm(e,t){if(!this._isMixin){t.stopPropagation(),t.preventDefault();let{model:n,form_name:r}=e.data(),s=n.syncForm(e);return new Promise((t,o)=>{let i;i=null!==n.id&&n.id>=0?n.save({formName:r,data:s}):n.create({data:s}),i.then(n=>{c(e);const r=Array.isArray(n)?n[0]:n;this.submit_model_form_success&&this.submit_model_form_success(r);for(const e of this.iterateAllChildren())e.submit_model_form_success&&e.submit_model_form_success(r);t(n)}).catch(t=>{this.reconcile($(`<div class="container-fluid">${t.html}</div>`),e.find(".container-fluid").first()),this.submit_model_form_error&&this.submit_model_form_error(t);for(const e of this.iterateAllChildren())e.submit_model_form_error&&e.submit_model_form_error(t);o(t)})})}return Promise.resolve()}}const we={classname:"class"};window.sdcDom=function(e,t,...n){if(!e)return"";const r=function(e,t){let n,r=!1;if("string"==typeof e)n=$(document.createElement(e));else{const t=`this.${e.name}`;n=$(document.createElement(t)),n.data("handler",e),r=!0}return t&&Object.entries(t).forEach(([e,t])=>{if(e.startsWith("on")){const r=e.substring(2).toLowerCase();n[0].addEventListener(r,t),(n[0]._sdcListeners??=[]).push([r,t])}else we[e.toLowerCase()]&&(e=we[e.toLowerCase()]),n[0].setAttribute(e,t)}),r&&n.addClass("_bind_to_update_handler _with_handler"),n}(e,t);for(const e of n)r.append(e);return r};const be=e=>{e["url-link"]?T("onNavLink",e["url-link"]):window.location.href=e.url};let $e={CSRF_TOKEN:window.CSRF_TOKEN||"",LANGUAGE_CODE:window.LANGUAGE_CODE||"en",DEBUG:window.DEBUG||!1,VERSION:window.VERSION||"0.0",tagNames:[],Global:C,rootController:null,globalRootController:null,_isInit:!1,_origin_trigger:null,_globalControllerClasses:[],_createdGlobals:[],init_sdc:()=>{$e._isInit||($e._isInit=!0,$e._origin_trigger?_e():($e._origin_trigger=$.fn.trigger,$.fn.trigger=function(e){const t={}.hasOwnProperty.call(e,"type")?e.type:e;return w.includes(t)||(w.push(t),$(window).on(t,R)),$e._origin_trigger.call(this,e)},$e.updateJquery()),pe(),function(){const e=$(window);w.forEach(t=>{e.off(t).on(t,R)})}(),$e.rootController=$e.rootController||new ve,$e.globalRootController=$e.globalRootController||new ve),$e.tagNames=Object.keys(O);const t=C.filter(e=>!$e._createdGlobals.includes(e));$e._createdGlobals.push(...t);const n=$("<div></div>");t.forEach(e=>{const t=O[e][0];n.append(`<${t.prototype._tagName}></${t.prototype._tagName}>`)});const{refreshProcess:r}=I(null,$e.rootController);return K($e.tagNames,n,$e.globalRootController,r).then(()=>K($e.tagNames,(e||(e=$("body")),e),$e.rootController,r).then(e=>(x(r),e)))},updateJquery:()=>{$.fn.safeReplace=function(e){return $e.safeReplace($(this),e)},$.fn.safeEmpty=function(){return $e.safeEmpty($(this))},$.fn.safeRemove=function(){return $e.safeRemove($(this))}},controllerToTag:e=>n(e.name).replace(/-controller$/,""),registerGlobal:e=>{const t=$e.register(e);let n=e.prototype._tagName;return C.includes(n)||C.push(n),t},cleanCache:()=>{D={}},register:(e,t=!1)=>{let r=$e.controllerToTag(e);return!O[r]||t?(O[r]=[e,[]],e.prototype._tagName=r,{addMixin:(...e)=>{for(let t of e){let e;"string"==typeof t?e=n(t):t&&(e=$e.controllerToTag(t)),O[r][1].push(e)}}}):{addMixin:(...e)=>{}}},post:(e,t,n)=>(n||(n={}),n.CSRF_TOKEN=$e.CSRF_TOKEN,$e.ajax(e,t,n,$.post)),get:(e,t,n)=>$e.ajax(e,t,n,$.get),ajax:(e,t,n,r)=>{n||(n={}),n.VERSION=$e.VERSION,n._method=n._method||"api";const s=new Promise((o,i)=>r(t,n).then((t,n,r)=>{o(t,n,r),"redirect"===t.status?be(t):s.then(()=>{$e.refresh(e.$container)})}).catch((e,t,n)=>{301===e.status&&e.responseJSON?(e=e.responseJSON,be(e),o(e,t,n)):i(e,t,n)}));return s},submitFormAndUpdateView:(e,t,n,r)=>{let s=new FormData(t);const i=new Promise((l,a)=>{o(s,n||t.action,r||t.method).then((t,n,r)=>{l(t,n,r),"redirect"===t.status?be(t):i.then(()=>{$e.refresh(e.$container,e)})}).catch((e,t,n)=>{301===e.status?(e=e.responseJSON,be(e),l(e,t,n)):a(e,t,n)})});return i},submitForm:(e,t,n)=>{let r=new FormData(e);return new Promise((s,i)=>{o(r,t||e.action,n||e.method).then(s).catch(i)})},getController:e=>W(e),safeEmpty:e=>(e.children().each(function(e,t){let n=$(t);$e.safeRemove(n)}),e),safeReplace:(e,t)=>(t.insertBefore(e),$e.safeRemove(e)),safeRemove:e=>(e.each(function(){let e=$(this);e.data(`${U}`)&&e.data(`${U}`).remove()}),e.find(`.${M}`).each(function(){const e=$(this).data(`${U}`);e&&e.remove()}),e.remove()),reloadController:e=>function(e){if(e.contentUrl){let t=B(e);return e.contentUrl=t.url,V(e,t.args)}return new Promise(e=>{e($())})}(e).then(t=>{let n=$(t);return $e.reconcile(e,n)}),reconcile:(e,t,n=null,r=null)=>{if(!n){let n=e.$container.clone().empty();n.data(U,null),n.removeClass(M),n.append(t),t=n}n=n??e.$container;const{refreshProcess:s,isRunningProcess:o}=I(r,e);return Z(t,e,s).then(()=>{var r;return X(t,n),(r=e)._childController={},r.find(`.${M}`).each(function(){const e=$(this),t=W(e);t&&W(e.parent())===r&&S(r,t)}),o||x(s),e})},refresh:(e,t=null)=>Z(e,t)};function Re(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)"__proto__"!==r&&(e[r]=n[r])}return e}var Ne=function e(t,n){function r(e,r,s){if("undefined"!=typeof document){"number"==typeof(s=Re({},n,s)).expires&&(s.expires=new Date(Date.now()+864e5*s.expires)),s.expires&&(s.expires=s.expires.toUTCString()),e=encodeURIComponent(e).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var o="";for(var i in s)s[i]&&(o+="; "+i,!0!==s[i]&&(o+="="+s[i].split(";")[0]));return document.cookie=e+"="+t.write(r,e)+o}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var n=document.cookie?document.cookie.split("; "):[],r={},s=0;s<n.length;s++){var o=n[s].split("="),i=o.slice(1).join("=");try{var l=decodeURIComponent(o[0]);if(l in r||(r[l]=t.read(i,l)),e===l)break}catch(e){}}return e?r[e]:r}},remove:function(e,t){r(e,"",Re({},t,{expires:-1}))},withAttributes:function(t){return e(this.converter,Re({},this.attributes,t))},withConverter:function(t){return e(Re({},this.converter,t),this.attributes)}},{attributes:{value:Object.freeze(n)},converter:{value:Object.freeze(t)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"});let Ce,Oe=[];function Se(){if(!jest)throw new Error("JEST is not defined");0===Oe.length&&(Ce=$.ajax.bind($),Oe.push(jest.spyOn($,"ajax")),Oe[0].mockImplementation(function(e){return Ce(e).then(e=>e).catch(e=>e)}))}const Fe=_e,ke={get_controller:async function(e,t={},n=""){Se();const r=$("body");$e.updateJquery(),r.safeEmpty();const s=$(`<${e}>${n}</${e}>`);for(const[e,n]of Object.entries(t))s.data(e,n);const o=$("<div></div>").append(s);r.append(o),$e._isInit=!1,$e.cleanCache(),await $e.init_sdc();const i=$e.getController(s);return i.navControllerPath=[e],i},getCsrfToken:function(){return function(e){if(document.cookie&&""!==document.cookie){const t=document.cookie.split(";");for(let n=0;n<t.length;n++){const r=t[n].trim();if(r.substring(0,10)===e+"=")return decodeURIComponent(r.substring(10))}}return""}("csrftoken")},controllerFromTestHtml:async function(e,t=null){Se();const n=$("body");$e.updateJquery(),n.safeEmpty().append(e),$e._isInit=!1,$e.cleanCache(),await $e.init_sdc();let r=$e.rootController.iterateAllChildren();if(!t)return r;const s=r[0].onRefresh,o=jest.spyOn(r[0],"onRefresh");return new Promise(e=>{o.mockImplementation(function(){o.mockRestore();const t=s.apply(r[0],arguments);return e(r),t})})},logout:()=>{Ne.remove("sessionid"),console.log("Logged out")},login:e=>{const t=globalThis.SDC_TEST_USER?.[e];return t?(Ne.set("sessionid",t),console.log(`Logged in as ${e}`),!0):(Ne.remove("sessionid"),console.warn(`Unknown test user: ${e}`),!1)}};window&&(window.sdcApp=$e);export{ve as AbstractSDC,ue as SdcModel,ce as SdcQuerySet,A as allOff,$e as app,l as checkIfParamNumberBoolOrString,c as clearErrorsInForm,k as controllerFactory,L as on,te as registerModel,E as runControlFlowFunctions,u as setErrorsInForm,q as setEvent,Fe as socketReconnect,ke as test_utils,T as trigger};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdc_client",
3
- "version": "0.159.0",
3
+ "version": "0.160.1",
4
4
  "description": "Simple Dom Control",
5
5
  "main": "dist/ugly.index.js",
6
6
  "files": [
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "https://github.com/StarmanMartin/SimpleDomControlClient"
24
+ "url": "git+https://github.com/StarmanMartin/SimpleDomControlClient.git"
25
25
  },
26
26
  "keywords": [
27
27
  "Model-View-Controller",
package/src/index.js CHANGED
@@ -48,6 +48,10 @@ const test_utils = {
48
48
  },
49
49
  };
50
50
 
51
+ if(window) {
52
+ window.sdcApp = app;
53
+ }
54
+
51
55
  export {
52
56
  app,
53
57
  AbstractSDC,
@@ -329,12 +329,14 @@ export class SdcQuerySet {
329
329
  * Load model instances matching the current query into the queryset cache.
330
330
  *
331
331
  * @param {?object} modelQuery
332
+ * @param {object} [options]
333
+ * @param {?number} [options.limit] load at most this many instances (the server slices the query)
332
334
  * @returns {Promise<SdcQuerySet>}
333
335
  */
334
- load(modelQuery = null) {
336
+ load(modelQuery = null, { limit = null } = {}) {
335
337
  this.valuesList = [];
336
338
  this.modelQuery = modelQuery ?? this.modelQuery;
337
- return this._sendLoad();
339
+ return this._sendLoad(null, limit);
338
340
  }
339
341
 
340
342
  /**
@@ -392,19 +394,23 @@ export class SdcQuerySet {
392
394
  *
393
395
  * @returns {Promise<*>}
394
396
  */
395
- _sendLoad(loadQuery = null) {
397
+ _sendLoad(loadQuery = null, limit = null) {
396
398
  return this.isConnected().then(() => {
397
399
  const event_id = uuidv4();
400
+ const args = {
401
+ model_name: this.modelName,
402
+ model_query: loadQuery ?? this.modelQuery,
403
+ };
404
+ if (limit !== null) {
405
+ args.limit = limit;
406
+ }
398
407
  return new Promise((resolve, reject) => {
399
408
  this.socket.send(
400
409
  JSON.stringify({
401
410
  event: "model",
402
411
  event_type: "load",
403
412
  event_id,
404
- args: {
405
- model_name: this.modelName,
406
- model_query: loadQuery ?? this.modelQuery,
407
- },
413
+ args,
408
414
  }),
409
415
  );
410
416
 
@@ -575,7 +581,9 @@ export class SdcQuerySet {
575
581
  )
576
582
  .data("model", modelObj)
577
583
  .data("model_pk", pk)
578
- .data("form_name", formName);
584
+ .data("form_name", formName)
585
+ .attr('SdcModelName', this.modelName)
586
+ .attr('SdcModelPK', pk);
579
587
  modelObj.addForm($form);
580
588
  if ($form.length > 0 && !$form[0].hasAttribute("sdc_submit")) {
581
589
  $form.attr("sdc_submit", "submitModelFormDistributor");