@kedem/okdb 1.0.0

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.
Files changed (260) hide show
  1. package/LICENSE +57 -0
  2. package/README.md +344 -0
  3. package/banner.jpg +0 -0
  4. package/bin/okdb.js +2 -0
  5. package/docs/OKDB-ARCHITECTURE.md +1036 -0
  6. package/docs/auth-and-sync.md +558 -0
  7. package/docs/auth-permissions.md +143 -0
  8. package/docs/change-log.md +169 -0
  9. package/docs/data-model.md +174 -0
  10. package/docs/embeddings.md +338 -0
  11. package/docs/files.md +131 -0
  12. package/docs/fts.md +139 -0
  13. package/docs/functions.md +514 -0
  14. package/docs/getting-started.md +233 -0
  15. package/docs/http-api.md +705 -0
  16. package/docs/index.md +115 -0
  17. package/docs/indexes.md +207 -0
  18. package/docs/logging.md +116 -0
  19. package/docs/manifest.json +38 -0
  20. package/docs/migration.md +154 -0
  21. package/docs/pipelines.md +598 -0
  22. package/docs/plugins.md +144 -0
  23. package/docs/querying.md +204 -0
  24. package/docs/queue.md +637 -0
  25. package/docs/sync.md +156 -0
  26. package/docs/transactions.md +140 -0
  27. package/docs/ttl.md +375 -0
  28. package/okdb.js +1 -0
  29. package/package.json +26 -0
  30. package/public/admin-app.js +1 -0
  31. package/public/android-chrome-192x192.png +0 -0
  32. package/public/android-chrome-512x512.png +0 -0
  33. package/public/apple-touch-icon.png +0 -0
  34. package/public/components/admin-route-host.ok.js +1 -0
  35. package/public/components/env-picker.ok.js +1 -0
  36. package/public/components/field-path-input.ok.js +1 -0
  37. package/public/components/field.html +6 -0
  38. package/public/components/geo-map.ok.js +1 -0
  39. package/public/components/ok-cron-input.ok.js +1 -0
  40. package/public/components/ok-dropzone.ok.js +1 -0
  41. package/public/components/ok-js-input.ok.js +1 -0
  42. package/public/components/ok-json-input.ok.js +1 -0
  43. package/public/components/ok-text-monaco-input.ok.js +1 -0
  44. package/public/components/theme-toggle.ok.js +1 -0
  45. package/public/favicon-16x16.png +0 -0
  46. package/public/favicon-32x32.png +0 -0
  47. package/public/favicon.ico +0 -0
  48. package/public/images/logo.png +0 -0
  49. package/public/images/logo.svg +333 -0
  50. package/public/index.html +6 -0
  51. package/public/layouts/_default.ok.html +1 -0
  52. package/public/layouts/okdb-cube.ok.html +1 -0
  53. package/public/login-app.js +1 -0
  54. package/public/login.html +1 -0
  55. package/public/modules/ok.js +1 -0
  56. package/public/sections/api/index.ok.html +1 -0
  57. package/public/sections/api/parts/api-endpoint.ok.js +1 -0
  58. package/public/sections/auth/index.ok.html +1 -0
  59. package/public/sections/auth/modals/create-token-modal.ok.js +1 -0
  60. package/public/sections/auth/modals/edit-token-modal.ok.js +1 -0
  61. package/public/sections/auth/modals/perm-info-popover.ok.js +1 -0
  62. package/public/sections/auth/parts/token-detail.ok.js +1 -0
  63. package/public/sections/auth/parts/token-list.ok.js +1 -0
  64. package/public/sections/db/index.ok.html +1 -0
  65. package/public/sections/db/modals/add-item-modal.ok.js +1 -0
  66. package/public/sections/db/modals/create-env-modal.ok.js +1 -0
  67. package/public/sections/db/modals/create-fts-modal.ok.js +1 -0
  68. package/public/sections/db/modals/create-index-modal.ok.js +1 -0
  69. package/public/sections/db/modals/create-pipeline-modal.ok.js +1 -0
  70. package/public/sections/db/modals/demo-env-modal.ok.js +1 -0
  71. package/public/sections/db/modals/remove-env-modal.ok.js +1 -0
  72. package/public/sections/db/modals/schema-edit-modal.ok.js +1 -0
  73. package/public/sections/db/parts/db-overview.ok.js +1 -0
  74. package/public/sections/db/parts/db-pipelines-panel.ok.js +1 -0
  75. package/public/sections/db/parts/edit-row.ok.js +1 -0
  76. package/public/sections/db/parts/tm-timeline.ok.js +1 -0
  77. package/public/sections/db/parts/type-changelog.ok.js +1 -0
  78. package/public/sections/db/parts/type-list.ok.js +1 -0
  79. package/public/sections/db/parts/type-pipelines-tab.ok.js +1 -0
  80. package/public/sections/db/parts/type-schema-tab.ok.js +1 -0
  81. package/public/sections/db/parts/type-viewer.ok.js +1 -0
  82. package/public/sections/db/parts/type-violations-tab.ok.js +1 -0
  83. package/public/sections/docs/index.ok.html +1 -0
  84. package/public/sections/embeddings/index.ok.html +1 -0
  85. package/public/sections/embeddings/modals/register-model-modal.ok.js +1 -0
  86. package/public/sections/embeddings/parts/embed-create-panel.ok.js +1 -0
  87. package/public/sections/embeddings/parts/embed-embedder-panel.ok.js +1 -0
  88. package/public/sections/embeddings/parts/embed-engine-declaration-editor.ok.js +1 -0
  89. package/public/sections/embeddings/parts/embed-engine-list.ok.js +1 -0
  90. package/public/sections/embeddings/parts/embed-indexer-panel.ok.js +1 -0
  91. package/public/sections/embeddings/parts/embed-lifecycle-bar.ok.js +1 -0
  92. package/public/sections/embeddings/parts/embed-model-catalog.ok.js +1 -0
  93. package/public/sections/embeddings/parts/embed-overview.ok.js +1 -0
  94. package/public/sections/embeddings/parts/embed-search-panel.ok.js +1 -0
  95. package/public/sections/embeddings/parts/embed-worker-panel.ok.js +1 -0
  96. package/public/sections/embeddings/parts/embeddings-engine-panel.ok.js +1 -0
  97. package/public/sections/embeddings/parts/engines-overview.ok.js +1 -0
  98. package/public/sections/embeddings/parts/pipeline-create-panel.ok.js +1 -0
  99. package/public/sections/engines/engine-panel-shared-style.js +1 -0
  100. package/public/sections/engines/engine-ui-utils.js +1 -0
  101. package/public/sections/engines/index.ok.html +1 -0
  102. package/public/sections/engines/modals/engine-modal.ok.js +1 -0
  103. package/public/sections/engines/parts/engine-declaration-editor.ok.js +1 -0
  104. package/public/sections/engines/parts/engine-lifecycle-actions.ok.js +1 -0
  105. package/public/sections/engines/parts/engine-panel-shell.ok.js +1 -0
  106. package/public/sections/engines/parts/engine-resource-card.ok.js +1 -0
  107. package/public/sections/engines/parts/engine-row-item.ok.js +1 -0
  108. package/public/sections/engines/parts/generic-engine-panel.ok.js +1 -0
  109. package/public/sections/files/index.ok.html +1 -0
  110. package/public/sections/files/parts/files-blob-status.ok.js +1 -0
  111. package/public/sections/files/parts/files-collection-list.ok.js +1 -0
  112. package/public/sections/files/parts/files-collection-panel.ok.js +1 -0
  113. package/public/sections/files/parts/files-file-list.ok.js +1 -0
  114. package/public/sections/files/parts/files-overview.ok.js +1 -0
  115. package/public/sections/files/parts/files-path-browser.ok.js +1 -0
  116. package/public/sections/files/parts/files-upload-panel.ok.js +1 -0
  117. package/public/sections/functions/index.ok.html +1 -0
  118. package/public/sections/functions/modals/function-modal.ok.js +1 -0
  119. package/public/sections/functions/parts/function-detail.ok.js +1 -0
  120. package/public/sections/functions/parts/function-logs.ok.js +1 -0
  121. package/public/sections/functions/parts/function-runner.ok.js +1 -0
  122. package/public/sections/functions/parts/functions-list.ok.js +1 -0
  123. package/public/sections/license/index.ok.html +1 -0
  124. package/public/sections/license/parts/license-panel.ok.js +1 -0
  125. package/public/sections/processors/index.ok.html +1 -0
  126. package/public/sections/queue/index.ok.html +1 -0
  127. package/public/sections/queue/modals/create-bucket-modal.ok.js +1 -0
  128. package/public/sections/queue/modals/edit-bucket-modal.ok.js +1 -0
  129. package/public/sections/queue/modals/edit-job-modal.ok.js +1 -0
  130. package/public/sections/queue/modals/enqueue-job-modal.ok.js +1 -0
  131. package/public/sections/queue/modals/job-type-modal.ok.js +1 -0
  132. package/public/sections/queue/parts/ok-job-form.ok.js +1 -0
  133. package/public/sections/queue/parts/queue-buckets.ok.js +1 -0
  134. package/public/sections/queue/parts/queue-job-types.ok.js +1 -0
  135. package/public/sections/queue/parts/queue-jobs.ok.js +1 -0
  136. package/public/sections/queue/parts/queue-types.ok.js +1 -0
  137. package/public/sections/queue/parts/queue-workers.ok.js +1 -0
  138. package/public/sections/sync/index.ok.html +5 -0
  139. package/public/sections/sync/parts/sync-node-detail.ok.js +1 -0
  140. package/public/sections/sync/parts/sync-retention.ok.js +1 -0
  141. package/public/sections/sync/parts/sync-topology.ok.js +1 -0
  142. package/public/sections/system/index.ok.html +1 -0
  143. package/public/sections/system/modals/data-ops-modal.ok.js +1 -0
  144. package/public/sections/system/parts/system-api-panel.ok.js +1 -0
  145. package/public/sections/system/parts/system-auth-panel.ok.js +1 -0
  146. package/public/sections/system/parts/system-log-history.ok.js +1 -0
  147. package/public/sections/system/parts/system-log.ok.js +1 -0
  148. package/public/sections/system/parts/system-status.ok.js +1 -0
  149. package/public/sections/system/parts/system-sync-panel.ok.js +1 -0
  150. package/public/sections/views/index.ok.html +1 -0
  151. package/public/sections/views/modals/create-view-modal.ok.js +1 -0
  152. package/public/sections/views/parts/view-detail.ok.js +1 -0
  153. package/public/sections/views/parts/views-list.ok.js +1 -0
  154. package/public/sections/views/parts/views-overview.ok.js +1 -0
  155. package/public/setup-app.js +1 -0
  156. package/public/setup.html +1 -0
  157. package/public/site.webmanifest +1 -0
  158. package/public/stores/auth-store.js +1 -0
  159. package/public/stores/events-store.js +1 -0
  160. package/public/stores/functions-store.js +1 -0
  161. package/public/stores/okdb-store.js +1 -0
  162. package/public/stores/theme-store.js +1 -0
  163. package/public/styles.css +1 -0
  164. package/public/test-cron-input.html +10 -0
  165. package/public/test-json-input.html +101 -0
  166. package/public/util/permissions.js +1 -0
  167. package/public/util/sift-schema.js +1 -0
  168. package/public/vendor/okjs/ok.esm.min.js +2 -0
  169. package/public/vendor/okjs/toolkit/behavior/async.ok.js +1 -0
  170. package/public/vendor/okjs/toolkit/components/ok-chart.ok.js +1 -0
  171. package/public/vendor/okjs/toolkit/components/ok-doc-viewer.ok.js +1 -0
  172. package/public/vendor/okjs/toolkit/components/ok-marked.ok.js +1 -0
  173. package/public/vendor/okjs/toolkit/components/ok-monaco.ok.js +1 -0
  174. package/public/vendor/okjs/toolkit/core/ok-layer-service.ok.js +1 -0
  175. package/public/vendor/okjs/toolkit/core/ok-layer.ok.js +1 -0
  176. package/public/vendor/okjs/toolkit/core/ok-overlay.ok.js +1 -0
  177. package/public/vendor/okjs/toolkit/core/ok-sandbox.ok.js +1 -0
  178. package/public/vendor/okjs/toolkit/core/transition.ok.js +1 -0
  179. package/public/vendor/okjs/toolkit/core/virtualized.ok.js +1 -0
  180. package/public/vendor/okjs/toolkit/devtools/ok-console-service.ok.js +1 -0
  181. package/public/vendor/okjs/toolkit/devtools/ok-console.ok.js +1 -0
  182. package/public/vendor/okjs/toolkit/devtools/ok-fps-monitor-service.ok.js +1 -0
  183. package/public/vendor/okjs/toolkit/devtools/ok-fps-monitor.ok.js +1 -0
  184. package/public/vendor/okjs/toolkit/devtools/ok-inspector-service.ok.js +1 -0
  185. package/public/vendor/okjs/toolkit/devtools/ok-inspector.ok.js +1 -0
  186. package/public/vendor/okjs/toolkit/devtools/ok-js-tree.ok.js +1 -0
  187. package/public/vendor/okjs/toolkit/devtools/ok-timeline-service.ok.js +1 -0
  188. package/public/vendor/okjs/toolkit/devtools/ok-timeline.ok.js +1 -0
  189. package/public/vendor/okjs/toolkit/docs/doc-viewer.ok.js +1 -0
  190. package/public/vendor/okjs/toolkit/editor/ok-live-component.ok.js +1 -0
  191. package/public/vendor/okjs/toolkit/editor/ok-live-example.ok.js +1 -0
  192. package/public/vendor/okjs/toolkit/editor/ok-live-shell.ok.js +1 -0
  193. package/public/vendor/okjs/toolkit/elements/ok-dropdown.ok.js +1 -0
  194. package/public/vendor/okjs/toolkit/elements/ok-icon.ok.js +1 -0
  195. package/public/vendor/okjs/toolkit/elements/ok-select.ok.js +1 -0
  196. package/public/vendor/okjs/toolkit/elements/ok-table.ok.js +1 -0
  197. package/public/vendor/okjs/toolkit/errors/ok-crash-boundary.ok.js +1 -0
  198. package/public/vendor/okjs/toolkit/errors/ok-crash-info.ok.js +1 -0
  199. package/public/vendor/okjs/toolkit/i18n/i18n-editor-examples.ok.js +1 -0
  200. package/public/vendor/okjs/toolkit/i18n/i18n-editor.ok.js +1 -0
  201. package/public/vendor/okjs/toolkit/i18n/i18n-key-editor-tips.ok.js +1 -0
  202. package/public/vendor/okjs/toolkit/i18n/i18n-key-editor.ok.js +1 -0
  203. package/public/vendor/okjs/toolkit/i18n/i18n-service.ok.js +1 -0
  204. package/public/vendor/okjs/toolkit/i18n/ok-i18n.js +1 -0
  205. package/public/vendor/okjs/toolkit/interaction/ok-contextmenu.ok.js +1 -0
  206. package/public/vendor/okjs/toolkit/interaction/ok-dismiss-service.ok.js +1 -0
  207. package/public/vendor/okjs/toolkit/interaction/ok-draggable.ok.js +1 -0
  208. package/public/vendor/okjs/toolkit/interaction/ok-flyover-panel.ok.js +1 -0
  209. package/public/vendor/okjs/toolkit/interaction/ok-flyover.ok.js +1 -0
  210. package/public/vendor/okjs/toolkit/interaction/ok-highlight-service.ok.js +1 -0
  211. package/public/vendor/okjs/toolkit/interaction/ok-highlight.ok.js +1 -0
  212. package/public/vendor/okjs/toolkit/interaction/ok-hotkeys-service.ok.js +1 -0
  213. package/public/vendor/okjs/toolkit/interaction/ok-picker-service.ok.js +1 -0
  214. package/public/vendor/okjs/toolkit/interaction/ok-popout-service.ok.js +1 -0
  215. package/public/vendor/okjs/toolkit/interaction/ok-popout.ok.js +1 -0
  216. package/public/vendor/okjs/toolkit/interaction/ok-portal-service.ok.js +1 -0
  217. package/public/vendor/okjs/toolkit/interaction/ok-submenu.ok.js +1 -0
  218. package/public/vendor/okjs/toolkit/layout/ok-resizer.ok.js +1 -0
  219. package/public/vendor/okjs/toolkit/manifest.js +1 -0
  220. package/public/vendor/okjs/toolkit/modals/ok-modal-service.ok.js +1 -0
  221. package/public/vendor/okjs/toolkit/modals/ok-modal.ok.js +1 -0
  222. package/public/vendor/okjs/toolkit/modals/ok-toast-service.ok.js +1 -0
  223. package/public/vendor/okjs/toolkit/modals/ok-window.ok.js +1 -0
  224. package/public/vendor/okjs/toolkit/navigation/hash-router.ok.js +1 -0
  225. package/public/vendor/okjs/toolkit/navigation/history-router.ok.js +1 -0
  226. package/public/vendor/okjs/toolkit/navigation/router.ok.js +1 -0
  227. package/public/vendor/okjs/toolkit/sync/reactive-sync-service.ok.js +1 -0
  228. package/public/vendor/okjs/toolkit/sync/reactive-sync.js +1 -0
  229. package/public/vendor/okjs/toolkit/theming/blocks/ok-design-button.css.js +1 -0
  230. package/public/vendor/okjs/toolkit/theming/blocks/ok-design-input.css.js +1 -0
  231. package/public/vendor/okjs/toolkit/theming/ok-design-style.js +1 -0
  232. package/public/vendor/okjs/toolkit/theming/ok-design-vars.js +1 -0
  233. package/public/vendor/okjs/toolkit/theming/ok-design.ok.js +1 -0
  234. package/public/vendor/okjs/toolkit/theming/ok-theme-editor/ok-theme-editor-input.ok.js +1 -0
  235. package/public/vendor/okjs/toolkit/theming/ok-theme-editor/ok-theme-editor-service.ok.js +1 -0
  236. package/public/vendor/okjs/toolkit/theming/ok-theme-editor/ok-theme-editor-style.js +1 -0
  237. package/public/vendor/okjs/toolkit/theming/ok-theme-editor/ok-theme-editor-utils.js +1 -0
  238. package/public/vendor/okjs/toolkit/theming/ok-theme-editor/ok-theme-editor-variable.ok.js +1 -0
  239. package/public/vendor/okjs/toolkit/theming/ok-theme-editor/ok-theme-editor-vm.js +1 -0
  240. package/public/vendor/okjs/toolkit/theming/ok-theme-editor/ok-theme-editor.ok.js +1 -0
  241. package/public/vendor/okjs/toolkit/theming/ok-theme.ok.js +1 -0
  242. package/public/view-models/type-query-vm.js +1 -0
  243. package/types/environment.d.ts +130 -0
  244. package/types/errors.d.ts +98 -0
  245. package/types/features/admin.d.ts +4 -0
  246. package/types/features/api.d.ts +18 -0
  247. package/types/features/auth.d.ts +31 -0
  248. package/types/features/embeddings.d.ts +39 -0
  249. package/types/features/engines.d.ts +23 -0
  250. package/types/features/files.d.ts +29 -0
  251. package/types/features/fts.d.ts +25 -0
  252. package/types/features/functions.d.ts +23 -0
  253. package/types/features/mcp.d.ts +17 -0
  254. package/types/features/pipelines.d.ts +19 -0
  255. package/types/features/queue.d.ts +189 -0
  256. package/types/features/sync.d.ts +34 -0
  257. package/types/features/time-machine.d.ts +32 -0
  258. package/types/features/views.d.ts +16 -0
  259. package/types/index.d.ts +153 -0
  260. package/types/options.d.ts +202 -0
@@ -0,0 +1 @@
1
+ const _0x4a43e5=_0x10b9;function _0x10b9(_0x1672db,_0x2e5d23){_0x1672db=_0x1672db-0x158;const _0x38cf6a=_0x38cf();let _0x10b9e0=_0x38cf6a[_0x1672db];return _0x10b9e0;}(function(_0x54531a,_0x34cfdc){const _0x5e457b=_0x10b9,_0x4ecd2d=_0x54531a();while(!![]){try{const _0x2a0304=-parseInt(_0x5e457b(0x213))/0x1+-parseInt(_0x5e457b(0x1d2))/0x2+parseInt(_0x5e457b(0x159))/0x3*(parseInt(_0x5e457b(0x1c3))/0x4)+-parseInt(_0x5e457b(0x1bd))/0x5*(parseInt(_0x5e457b(0x1d7))/0x6)+parseInt(_0x5e457b(0x18d))/0x7*(-parseInt(_0x5e457b(0x21e))/0x8)+-parseInt(_0x5e457b(0x216))/0x9*(-parseInt(_0x5e457b(0x191))/0xa)+parseInt(_0x5e457b(0x1bf))/0xb;if(_0x2a0304===_0x34cfdc)break;else _0x4ecd2d['push'](_0x4ecd2d['shift']());}catch(_0x585c35){_0x4ecd2d['push'](_0x4ecd2d['shift']());}}}(_0x38cf,0x4f0ca));export default{'tag':_0x4a43e5(0x1a9),'unwrap':!0x0,'context':_0x15953a=>({'w':0x384,'h':0x1f4,'layout':{'cx':0x0,'cy':0x0,'r':0x0,'pos':{}},'_ro':null,'_tick':null,'now':Date['now'](),'selectedNodeId':null,'selectedLinkKey':null,'hoveredLinkKey':null,'hoveredNodeId':null,'lastUpdatedAt':null,'autoRefresh':!0x0,'autoRefreshIntervalMs':0x1388,'_autoRefreshTimer':null,'loadingTopology':!0x1,'editingLink':null,'linkEditDir':_0x4a43e5(0x205),'linkEditEnvs':null,'linkEditEnabled':!0x0,'savingLink':!0x1,'panX':0x0,'panY':0x0,'zoom':0x1,'_drag':null,'_customPos':{},'_svgEl':null,'_groupEl':null,'_applyTransform'(){const _0x3466c7=_0x4a43e5;this[_0x3466c7(0x208)]||(this[_0x3466c7(0x208)]=this['_svgEl']?.[_0x3466c7(0x166)](_0x3466c7(0x1e7))),this[_0x3466c7(0x208)]&&this['_groupEl'][_0x3466c7(0x1b0)](_0x3466c7(0x1b9),_0x3466c7(0x20d)+this[_0x3466c7(0x1ab)]+','+this[_0x3466c7(0x20e)]+_0x3466c7(0x1e6)+this['zoom']+')');},'_px2vb'(){const _0x1f03f3=_0x4a43e5;if(!this[_0x1f03f3(0x221)])return{'sx':0x1,'sy':0x1};const _0x51937f=this[_0x1f03f3(0x221)][_0x1f03f3(0x1af)]();return{'sx':this['w']/(_0x51937f[_0x1f03f3(0x19f)]||0x1),'sy':this['h']/(_0x51937f[_0x1f03f3(0x211)]||0x1)};},'_onWheel'(_0x3f07af){const _0x512fd5=_0x4a43e5;if(!this[_0x512fd5(0x221)])return;const _0x3d9868=this['_svgEl']['getBoundingClientRect'](),{sx:_0x58671a,sy:_0xb7019d}=this[_0x512fd5(0x1fa)](),_0x179dda=(_0x3f07af[_0x512fd5(0x1d9)]-_0x3d9868[_0x512fd5(0x1c2)])*_0x58671a,_0x1c2b03=(_0x3f07af['clientY']-_0x3d9868[_0x512fd5(0x1ff)])*_0xb7019d,_0x3db30d=_0x3f07af[_0x512fd5(0x169)]<0x0?1.12:0x1/1.12,_0x300e7c=Math[_0x512fd5(0x180)](0.1,Math[_0x512fd5(0x176)](0x8,this['zoom']*_0x3db30d)),_0x4ca67f=_0x300e7c/this[_0x512fd5(0x158)];this[_0x512fd5(0x1ab)]=_0x179dda+(this[_0x512fd5(0x1ab)]-_0x179dda)*_0x4ca67f,this[_0x512fd5(0x20e)]=_0x1c2b03+(this[_0x512fd5(0x20e)]-_0x1c2b03)*_0x4ca67f,this['zoom']=_0x300e7c,this[_0x512fd5(0x15c)]();},'_onSvgMousedown'(_0x1faa02){const _0x1fec68=_0x4a43e5;if(0x0!==_0x1faa02[_0x1fec68(0x1ae)])return;_0x1faa02[_0x1fec68(0x1c9)]();let _0x55c6ea=null,_0x3730d0=_0x1faa02[_0x1fec68(0x1f4)];for(;_0x3730d0&&_0x3730d0!==this[_0x1fec68(0x221)];){if(_0x3730d0['id']&&_0x3730d0['id'][_0x1fec68(0x16a)]('nd-')){_0x55c6ea=_0x3730d0['id'][_0x1fec68(0x223)](0x3);break;}_0x3730d0=_0x3730d0[_0x1fec68(0x21d)];}if(_0x55c6ea){const _0x375192=this[_0x1fec68(0x221)][_0x1fec68(0x1af)](),{sx:_0x4437de,sy:_0x52866a}=this[_0x1fec68(0x1fa)](),_0x7466df=(_0x1faa02[_0x1fec68(0x1d9)]-_0x375192[_0x1fec68(0x1c2)])*_0x4437de,_0x5103ba=(_0x1faa02[_0x1fec68(0x17b)]-_0x375192[_0x1fec68(0x1ff)])*_0x52866a,_0x1c8bef=(_0x7466df-this[_0x1fec68(0x1ab)])/this[_0x1fec68(0x158)],_0x5d5f1e=(_0x5103ba-this[_0x1fec68(0x20e)])/this[_0x1fec68(0x158)],_0x2d88e6=this[_0x1fec68(0x183)](_0x55c6ea)||{'x':_0x1c8bef,'y':_0x5d5f1e};this[_0x1fec68(0x225)]={'type':_0x1fec68(0x217),'id':_0x55c6ea,'ox':_0x1c8bef-_0x2d88e6['x'],'oy':_0x5d5f1e-_0x2d88e6['y']};}else this['_drag']={'type':'pan','sx':_0x1faa02[_0x1fec68(0x1d9)],'sy':_0x1faa02['clientY'],'px':this[_0x1fec68(0x1ab)],'py':this[_0x1fec68(0x20e)]};this[_0x1fec68(0x221)]&&(this[_0x1fec68(0x221)][_0x1fec68(0x190)][_0x1fec68(0x17d)]='grabbing');},'_onMousemove'(_0x3ce3e9){const _0x2fd6b9=_0x4a43e5;if(!this[_0x2fd6b9(0x225)])return;const {sx:_0x3095b7,sy:_0x345f5c}=this[_0x2fd6b9(0x1fa)]();if(_0x2fd6b9(0x18b)===this[_0x2fd6b9(0x225)]['type'])this[_0x2fd6b9(0x1ab)]=this[_0x2fd6b9(0x225)]['px']+(_0x3ce3e9[_0x2fd6b9(0x1d9)]-this[_0x2fd6b9(0x225)]['sx'])*_0x3095b7,this[_0x2fd6b9(0x20e)]=this['_drag']['py']+(_0x3ce3e9[_0x2fd6b9(0x17b)]-this[_0x2fd6b9(0x225)]['sy'])*_0x345f5c,this[_0x2fd6b9(0x15c)]();else{const _0x364c45=this[_0x2fd6b9(0x221)][_0x2fd6b9(0x1af)](),_0x23001d=(_0x3ce3e9[_0x2fd6b9(0x1d9)]-_0x364c45[_0x2fd6b9(0x1c2)])*_0x3095b7,_0x3f62e6=(_0x3ce3e9[_0x2fd6b9(0x17b)]-_0x364c45['top'])*_0x345f5c,_0xb2db71=(_0x23001d-this['panX'])/this[_0x2fd6b9(0x158)],_0x4884f7=(_0x3f62e6-this[_0x2fd6b9(0x20e)])/this['zoom'];this[_0x2fd6b9(0x161)]={...this[_0x2fd6b9(0x161)],[this['_drag']['id']]:{'x':_0xb2db71-this[_0x2fd6b9(0x225)]['ox'],'y':_0x4884f7-this[_0x2fd6b9(0x225)]['oy']}},this[_0x2fd6b9(0x21a)]();}},'_onMouseup'(){const _0x29b065=_0x4a43e5;this[_0x29b065(0x225)]=null,this[_0x29b065(0x221)]&&(this[_0x29b065(0x221)][_0x29b065(0x190)][_0x29b065(0x17d)]='grab');},get 'externalSelectedNodeId'(){return _0x15953a['$attr']['selected_node_id']??null;},get 'selfId'(){return _0x15953a['$attr']['self_id'];},get 'topology'(){const _0x316d94=_0x4a43e5;return _0x15953a[_0x316d94(0x1f1)][_0x316d94(0x1db)]||{};},get 'availableEnvs'(){const _0x5baa7d=_0x4a43e5;return _0x15953a[_0x5baa7d(0x1f1)][_0x5baa7d(0x210)]||[];},get 'envButtons'(){const _0x4e725f=_0x4a43e5,_0x3fc3e6=this['linkEditEnvs'];return(_0x15953a[_0x4e725f(0x1f1)]['available_envs']||[])[_0x4e725f(0x1bc)](_0x2e1c8e=>({'name':_0x2e1c8e,'style':null===_0x3fc3e6||Array['isArray'](_0x3fc3e6)&&_0x3fc3e6[_0x4e725f(0x174)](_0x2e1c8e)?_0x4e725f(0x1f6):''}));},get 'dirButtons'(){const _0x5b5331=_0x4a43e5,_0x3a13ee=this[_0x5b5331(0x188)];if(!_0x3a13ee)return[];const _0x4f6e21=_0x3a13ee['lo']['slice'](0x0,0x6),_0x2fa57b=_0x3a13ee['hi']['slice'](0x0,0x6),_0x443ef7=this[_0x5b5331(0x195)];return[{'canon':_0x5b5331(0x205),'label':_0x4f6e21+_0x5b5331(0x21b)+_0x2fa57b},{'canon':'lo_to_hi','label':_0x4f6e21+_0x5b5331(0x18c)+_0x2fa57b},{'canon':'hi_to_lo','label':_0x2fa57b+'\x20→\x20'+_0x4f6e21}][_0x5b5331(0x1bc)](_0x106aa6=>({..._0x106aa6,'style':_0x106aa6[_0x5b5331(0x17c)]===_0x443ef7?'border-color:var(--accent);color:var(--accent)':''}));},get 'nodes'(){const _0xa0f622=_0x4a43e5;return Object[_0xa0f622(0x1d5)](this[_0xa0f622(0x1db)]||{})['filter'](_0x2fdf9b=>_0x2fdf9b&&null!=_0x2fdf9b['id'])[_0xa0f622(0x1d4)]((_0x4344bd,_0x193827)=>String(_0x4344bd['id'])[_0xa0f622(0x1cc)](String(_0x193827['id'])));},get 'nodeList'(){const _0x31685c=_0x4a43e5;return this[_0x31685c(0x200)][_0x31685c(0x1bc)](_0x434533=>{const _0x103552=this['_customPos'][_0x434533['id']]||this['layout']['pos']?.[_0x434533['id']]||{'x':this['w']/0x2,'y':this['h']/0x2};return{..._0x434533,'px':_0x103552['x'],'py':_0x103552['y']};});},get 'links'(){const _0xc7991e=_0x4a43e5,_0x242dfe=this['topology']||{},_0x4b41ef=_0x242dfe[this['selfId']]||Object[_0xc7991e(0x1d5)](_0x242dfe)[_0xc7991e(0x1f7)](_0x1b98d3=>null!=_0x1b98d3?.[_0xc7991e(0x18f)]),_0x1a608f=_0x4b41ef?.[_0xc7991e(0x18f)]||{},_0x163ca7=new Map(),_0x2d55a2=(_0x22f7fe,_0x5939a6)=>({'status':_0x22f7fe[_0xc7991e(0x165)]||_0xc7991e(0x1ad),'backlog':Math[_0xc7991e(0x180)](0x0,Number(_0x5939a6??0x0)-Number(_0x22f7fe[_0xc7991e(0x1b2)]??0x0)),'last_seen':_0x22f7fe['last_seen']??null,'last_error':_0x22f7fe[_0xc7991e(0x192)]??null});for(const _0x3ff9f in _0x242dfe){const _0xe05bb5=_0x242dfe[_0x3ff9f];if(_0xe05bb5?.[_0xc7991e(0x1ac)])for(const _0x1eee5f in _0xe05bb5[_0xc7991e(0x1ac)]){const _0x4d8148=_0x3ff9f<_0x1eee5f?_0x3ff9f:_0x1eee5f,_0x1d0466=_0x3ff9f<_0x1eee5f?_0x1eee5f:_0x3ff9f,_0x3a3780=_0x4d8148+':'+_0x1d0466;_0x163ca7['has'](_0x3a3780)||_0x163ca7['set'](_0x3a3780,{'lo':_0x4d8148,'hi':_0x1d0466,'lo_pull':null,'hi_pull':null});const _0x44d6aa=_0x163ca7[_0xc7991e(0x182)](_0x3a3780),_0x1ff56e=_0xe05bb5[_0xc7991e(0x1ac)][_0x1eee5f];_0x3ff9f===_0x4d8148?_0x44d6aa[_0xc7991e(0x1dd)]=_0x2d55a2(_0x1ff56e,_0x242dfe[_0x1eee5f]?.[_0xc7991e(0x1b2)]):_0x44d6aa['hi_pull']=_0x2d55a2(_0x1ff56e,_0x242dfe[_0x1eee5f]?.[_0xc7991e(0x1b2)]);}}for(const _0x174840 in _0x1a608f)if(_0x1a608f[_0x174840]&&!_0x163ca7[_0xc7991e(0x1c6)](_0x174840)){const _0x31cf82=_0x1a608f[_0x174840];_0x163ca7['set'](_0x174840,{'lo':_0x31cf82['node_lo'],'hi':_0x31cf82['node_hi'],'lo_pull':null,'hi_pull':null});}return[..._0x163ca7['entries']()][_0xc7991e(0x1bc)](([_0x2d8ca9,_0x1f2383])=>({'key':_0x2d8ca9,'lo':_0x1f2383['lo'],'hi':_0x1f2383['hi'],'link':_0x1a608f[_0x2d8ca9]||null,'lo_pull':_0x1f2383[_0xc7991e(0x1dd)],'hi_pull':_0x1f2383[_0xc7991e(0x1b1)]}));},'_linkConfig'(_0x6e99b){const _0x1222c2=_0x4a43e5,_0x1cff3f=(this[_0x1222c2(0x1db)]||{})[this[_0x1222c2(0x21f)]];return _0x1cff3f?.[_0x1222c2(0x18f)]?.[_0x6e99b]||null;},'_linkHealth'(_0x3e470c){const _0x7117a2=_0x4a43e5;if(_0x3e470c[_0x7117a2(0x207)]&&!_0x3e470c[_0x7117a2(0x207)]['enabled'])return _0x7117a2(0x178);const _0xdcac51=_0x3e470c[_0x7117a2(0x207)]?.[_0x7117a2(0x1fb)]??_0x7117a2(0x205),_0x3c5d6c=[];'both'!==_0xdcac51&&_0x7117a2(0x21c)!==_0xdcac51||_0x3c5d6c[_0x7117a2(0x16d)](_0x3e470c[_0x7117a2(0x1b1)]),'both'!==_0xdcac51&&'hi_to_lo'!==_0xdcac51||_0x3c5d6c[_0x7117a2(0x16d)](_0x3e470c[_0x7117a2(0x1dd)]);const _0x37a174=[_0x7117a2(0x19b),_0x7117a2(0x16f),_0x7117a2(0x202),'behind',_0x7117a2(0x218),'stale','ok'];let _0x4d02a5='stale';for(const _0x275045 of _0x3c5d6c){const _0x2baa9b=this[_0x7117a2(0x171)](_0x275045);_0x37a174[_0x7117a2(0x15f)](_0x2baa9b)<_0x37a174[_0x7117a2(0x15f)](_0x4d02a5)&&(_0x4d02a5=_0x2baa9b);}return _0x4d02a5;},'_pullHealth'(_0x28c6d7){const _0x1f711e=_0x4a43e5;if(!_0x28c6d7)return _0x1f711e(0x184);if(_0x1f711e(0x218)===_0x28c6d7['status'])return _0x1f711e(0x218);if(_0x28c6d7[_0x1f711e(0x1b5)]){const _0x2b439c=this['now']-Number(_0x28c6d7[_0x1f711e(0x1b5)]);return _0x28c6d7[_0x1f711e(0x1e9)]>0x32?_0x1f711e(0x16f):_0x28c6d7['backlog']>0x5?_0x1f711e(0x202):_0x28c6d7[_0x1f711e(0x1e9)]>0x0?'behind':_0x2b439c>0x7530?_0x1f711e(0x184):'ok';}return _0x28c6d7['last_error']?_0x1f711e(0x19b):'stale';},'_healthMarker':_0x221180=>'error'===_0x221180?'err':'reconciling'===_0x221180?_0x4a43e5(0x1f2):_0x4a43e5(0x16f)===_0x221180?_0x4a43e5(0x16f):'lag-med'===_0x221180||_0x4a43e5(0x15b)===_0x221180||_0x4a43e5(0x184)===_0x221180?'lag-med':'ok','_linkDirLabel'(_0x29a60f){const _0x535503=_0x4a43e5;if(!_0x29a60f['link'])return _0x29a60f['lo']['slice'](0x0,0x6)+'\x20⇄\x20'+_0x29a60f['hi']['slice'](0x0,0x6)+_0x535503(0x1f8);if(!_0x29a60f[_0x535503(0x207)][_0x535503(0x1d0)])return _0x535503(0x178);const _0xca40d0=_0x29a60f['lo']['slice'](0x0,0x6),_0x115997=_0x29a60f['hi'][_0x535503(0x223)](0x0,0x6);switch(_0x29a60f['link'][_0x535503(0x1fb)]){case _0x535503(0x205):return _0xca40d0+'\x20⇄\x20'+_0x115997;case _0x535503(0x21c):return _0xca40d0+_0x535503(0x18c)+_0x115997;case'hi_to_lo':return _0x115997+_0x535503(0x18c)+_0xca40d0;default:return _0x29a60f[_0x535503(0x207)][_0x535503(0x1fb)];}},get 'selection'(){const _0x291457=_0x4a43e5;if(this[_0x291457(0x20a)]){const _0x27cd4b=this[_0x291457(0x18f)][_0x291457(0x1f7)](_0x3d9439=>_0x3d9439[_0x291457(0x163)]===this['selectedLinkKey'])||null;if(_0x27cd4b)return{'type':_0x291457(0x207),'data':_0x27cd4b};}if(this[_0x291457(0x181)]){const _0x50c874=this[_0x291457(0x1db)][this['selectedNodeId']]||null;return _0x50c874?{'type':_0x291457(0x217),'id':this[_0x291457(0x181)],'data':_0x50c874}:null;}return null;},get 'freshnessLabel'(){const _0x7df670=_0x4a43e5;if(!this[_0x7df670(0x1ee)])return'never';const _0x135b2a=this[_0x7df670(0x222)]-this['lastUpdatedAt'];return _0x135b2a<0x5dc?_0x7df670(0x222):_0x135b2a<0x1388?_0x7df670(0x164):_0x135b2a<0x3a98?'recent':Math[_0x7df670(0x1d8)](_0x135b2a/0x3e8)+'s\x20ago';},get 'freshnessClass'(){const _0x1ee452=_0x4a43e5;if(!this[_0x1ee452(0x1ee)])return _0x1ee452(0x1ea);const _0x42f6db=this['now']-this[_0x1ee452(0x1ee)];return _0x42f6db<0x1388?_0x1ee452(0x1e0):_0x42f6db<0x3a98?'fresh-ok':_0x1ee452(0x1ea);},'_recomputeLayout'(){const _0x55e54f=_0x4a43e5,_0x2bdc44=this[_0x55e54f(0x200)],_0x1709c5=this['w']/0x2,_0x2fa0b3=this['h']/0x2,_0x5bf22f=Math['max'](0x50,Math[_0x55e54f(0x176)](_0x1709c5,_0x2fa0b3)-this['nodeRadius']()-0x3c),_0x5d4661={},_0x53c50b=_0x2bdc44[_0x55e54f(0x1da)]||0x1;_0x2bdc44[_0x55e54f(0x1e3)]((_0x263156,_0x3e417d)=>{const _0x104fa7=_0x55e54f;if(0x1===_0x53c50b)return void(_0x5d4661[_0x263156['id']]={'x':_0x1709c5,'y':_0x2fa0b3});const _0x3bfb2d=0x2===_0x53c50b?0x0===_0x3e417d?Math['PI']:0x0:_0x3e417d/_0x53c50b*Math['PI']*0x2-Math['PI']/0x2;_0x5d4661[_0x263156['id']]={'x':_0x1709c5+_0x5bf22f*Math[_0x104fa7(0x1d3)](_0x3bfb2d),'y':_0x2fa0b3+_0x5bf22f*Math[_0x104fa7(0x19a)](_0x3bfb2d)};}),this[_0x55e54f(0x1a6)]={'cx':_0x1709c5,'cy':_0x2fa0b3,'r':_0x5bf22f,'pos':_0x5d4661};},'_measure'(){const _0x4d60a1=_0x4a43e5,_0x259a37=(this[_0x4d60a1(0x221)]||_0x15953a['$el'])['getBoundingClientRect']();this['w']=Math[_0x4d60a1(0x180)](0x12c,_0x259a37[_0x4d60a1(0x19f)]||0x384),this['h']=Math['max'](0xc8,_0x259a37[_0x4d60a1(0x211)]||0x1f4),this['_recomputeLayout']();},'_effectivePos'(_0xf3dda){const _0x4662a2=_0x4a43e5;return this[_0x4662a2(0x161)][_0xf3dda]||this[_0x4662a2(0x1a6)]['pos']?.[_0xf3dda]||null;},'fitView'(){const _0x45ade7=_0x4a43e5;this['_measure']();const _0x11d823=this[_0x45ade7(0x200)];if(!_0x11d823[_0x45ade7(0x1da)])return;let _0x2287c2=0x1/0x0,_0x22cf34=0x1/0x0,_0x4dd328=-0x1/0x0,_0x2df4fd=-0x1/0x0;for(const _0x1f8884 of _0x11d823){const _0x39fe28=this['_effectivePos'](_0x1f8884['id']);_0x39fe28&&(_0x2287c2=Math[_0x45ade7(0x176)](_0x2287c2,_0x39fe28['x']),_0x22cf34=Math[_0x45ade7(0x176)](_0x22cf34,_0x39fe28['y']),_0x4dd328=Math[_0x45ade7(0x180)](_0x4dd328,_0x39fe28['x']),_0x2df4fd=Math[_0x45ade7(0x180)](_0x2df4fd,_0x39fe28['y']));}if(!isFinite(_0x2287c2))return;const _0x46c7d2=this[_0x45ade7(0x1c0)]()+0x3c;_0x2287c2-=_0x46c7d2,_0x22cf34-=_0x46c7d2,_0x4dd328+=_0x46c7d2,_0x2df4fd+=_0x46c7d2;const _0x29319b=_0x4dd328-_0x2287c2,_0x219148=_0x2df4fd-_0x22cf34,_0x5ba9d5=0.88*Math[_0x45ade7(0x176)](this['w']/_0x29319b,this['h']/_0x219148,0x3);this['zoom']=_0x5ba9d5,this[_0x45ade7(0x1ab)]=this['w']/0x2-(_0x2287c2+_0x29319b/0x2)*_0x5ba9d5,this['panY']=this['h']/0x2-(_0x22cf34+_0x219148/0x2)*_0x5ba9d5,this['_applyTransform']();},'resetLayout'(){const _0x3a7769=_0x4a43e5;this[_0x3a7769(0x161)]={};try{localStorage[_0x3a7769(0x1cb)]('okdb-topo-pos');}catch{}this[_0x3a7769(0x1b6)]();},'_savePositions'(){const _0x34c63b=_0x4a43e5;try{localStorage[_0x34c63b(0x1e1)](_0x34c63b(0x194),JSON[_0x34c63b(0x1e4)](this[_0x34c63b(0x161)]));}catch{}},'_loadPositions'(){const _0x2278bd=_0x4a43e5;try{const _0x52b477=localStorage['getItem'](_0x2278bd(0x194));_0x52b477&&(this[_0x2278bd(0x161)]=JSON['parse'](_0x52b477));}catch{}},'nodeRadius':()=>0x16,'linkPath'(_0x47857e){const _0x67a02c=_0x4a43e5,_0x372437=this[_0x67a02c(0x183)](_0x47857e['lo']),_0x533857=this[_0x67a02c(0x183)](_0x47857e['hi']);if(!_0x372437||!_0x533857)return'';const _0x1c8438=_0x533857['x']-_0x372437['x'],_0xc9f869=_0x533857['y']-_0x372437['y'],_0x2d092f=Math['sqrt'](_0x1c8438*_0x1c8438+_0xc9f869*_0xc9f869)||0x1,_0x1e8bc3=this[_0x67a02c(0x1c0)]();return'M\x20'+(_0x372437['x']+_0x1c8438/_0x2d092f*_0x1e8bc3)+'\x20'+(_0x372437['y']+_0xc9f869/_0x2d092f*_0x1e8bc3)+_0x67a02c(0x1f3)+(_0x533857['x']-_0x1c8438/_0x2d092f*_0x1e8bc3)+'\x20'+(_0x533857['y']-_0xc9f869/_0x2d092f*_0x1e8bc3);},'reconciling':!0x1,'reconcilingTarget':null,async 'refreshTopology'(){const _0x4b8daa=_0x4a43e5;if(!this[_0x4b8daa(0x20f)]){this[_0x4b8daa(0x20f)]=!0x0;try{const _0x375ca4=await fetch('/api/sync/topology'),_0x219362=await _0x375ca4['json'](),_0x293686=_0x219362[_0x4b8daa(0x17a)]??_0x219362;_0x15953a[_0x4b8daa(0x1f1)][_0x4b8daa(0x1db)]=_0x293686[_0x4b8daa(0x1db)]??_0x293686,_0x15953a[_0x4b8daa(0x1f1)][_0x4b8daa(0x210)]=_0x293686['availableEnvs']??[],this[_0x4b8daa(0x1ee)]=Date[_0x4b8daa(0x222)]();}catch(_0x156331){console['error']('refresh\x20failed',_0x156331);}finally{this[_0x4b8daa(0x20f)]=!0x1;}}},async 'reconcileAll'(){const _0x550684=_0x4a43e5;if(!this[_0x550684(0x218)]){this['reconciling']=!0x0,this[_0x550684(0x1ef)]=_0x550684(0x185);try{await fetch(_0x550684(0x1b8),{'method':_0x550684(0x1ec)}),await this[_0x550684(0x17f)]();}finally{this[_0x550684(0x218)]=!0x1,this['reconcilingTarget']=null;}}},async 'reconcileNode'(_0x201d35){const _0x5ee106=_0x4a43e5;if(!this[_0x5ee106(0x218)]){this[_0x5ee106(0x218)]=!0x0,this['reconcilingTarget']=_0x201d35;try{_0x201d35===this[_0x5ee106(0x21f)]?await fetch(_0x5ee106(0x206),{'method':'POST'}):await fetch(this[_0x5ee106(0x1db)][_0x201d35]?.[_0x5ee106(0x196)]+_0x5ee106(0x206),{'method':_0x5ee106(0x1ec)}),await this[_0x5ee106(0x17f)]();}finally{this[_0x5ee106(0x218)]=!0x1,this['reconcilingTarget']=null;}}},async 'reconcileLink'(_0x4e47de){const _0x1c4d96=_0x4a43e5;if(this[_0x1c4d96(0x218)])return;this['reconciling']=!0x0,this[_0x1c4d96(0x1ef)]=_0x4e47de[_0x1c4d96(0x163)];const _0x131567=_0x4e47de['lo']===this[_0x1c4d96(0x21f)]?_0x4e47de['hi']:_0x4e47de['lo'];try{await fetch('/api/sync/reconcile-peer',{'method':_0x1c4d96(0x1ec),'headers':{'Content-Type':_0x1c4d96(0x179)},'body':JSON[_0x1c4d96(0x1e4)]({'peer_id':_0x131567})}),await this[_0x1c4d96(0x17f)]();}finally{this['reconciling']=!0x1,this[_0x1c4d96(0x1ef)]=null;}},'openLinkEditor'(_0xa85a56){const _0x473af9=_0x4a43e5;this[_0x473af9(0x188)]=_0xa85a56,this[_0x473af9(0x195)]=_0xa85a56[_0x473af9(0x207)]?.[_0x473af9(0x1fb)]??_0x473af9(0x205),this[_0x473af9(0x1a4)]=_0xa85a56[_0x473af9(0x207)]?.[_0x473af9(0x1a5)]??null,this['linkEditEnabled']=!0x1!==_0xa85a56['link']?.['enabled'];},'closeLinkEditor'(){const _0x298aa9=_0x4a43e5;this[_0x298aa9(0x188)]=null;},'toggleLinkEnv'(_0x3309d){const _0x21748c=_0x4a43e5;if(null===this[_0x21748c(0x1a4)])this[_0x21748c(0x1a4)]=this['availableEnvs']['filter'](_0x4897f9=>_0x4897f9!==_0x3309d);else{const _0x3b9a10=new Set(this[_0x21748c(0x1a4)]);_0x3b9a10[_0x21748c(0x1c6)](_0x3309d)?_0x3b9a10['delete'](_0x3309d):_0x3b9a10[_0x21748c(0x19d)](_0x3309d);const _0x49584d=[..._0x3b9a10];this['linkEditEnvs']=_0x49584d['length']===this['availableEnvs'][_0x21748c(0x1da)]?null:_0x49584d;}},async 'saveLink'(){const _0x4bba0c=_0x4a43e5;if(!this[_0x4bba0c(0x188)]||this[_0x4bba0c(0x1a7)])return;this[_0x4bba0c(0x1a7)]=!0x0;const _0xec4a8d=this['editingLink'];try{const _0x50a35d=await fetch(_0x4bba0c(0x1c7)+_0xec4a8d['lo']+'/'+_0xec4a8d['hi'],{'method':_0x4bba0c(0x201),'headers':{'Content-Type':_0x4bba0c(0x179)},'body':JSON['stringify']({'direction':this[_0x4bba0c(0x195)],'envs':this[_0x4bba0c(0x1a4)],'enabled':this[_0x4bba0c(0x1a0)]})});if(!_0x50a35d['ok']){const _0x2af442=await _0x50a35d[_0x4bba0c(0x1f0)]();throw new Error(_0x2af442?.['error']?.[_0x4bba0c(0x18a)]||_0x4bba0c(0x19c));}this['closeLinkEditor'](),await this[_0x4bba0c(0x17f)]();}catch(_0x61fcbb){alert(_0x61fcbb[_0x4bba0c(0x18a)]);}finally{this[_0x4bba0c(0x1a7)]=!0x1;}},async 'deleteLink'(){const _0x3df017=_0x4a43e5;if(!this['editingLink']||this[_0x3df017(0x1a7)])return;if(!confirm(_0x3df017(0x16e)))return;this['savingLink']=!0x0;const _0x3bf2c8=this[_0x3df017(0x188)];try{await fetch('/api/sync/links/'+_0x3bf2c8['lo']+'/'+_0x3bf2c8['hi'],{'method':_0x3df017(0x199)}),this[_0x3df017(0x1eb)](),await this[_0x3df017(0x17f)]();}catch(_0x307b3e){alert(_0x307b3e[_0x3df017(0x18a)]);}finally{this[_0x3df017(0x1a7)]=!0x1;}},'deselect'(){const _0x8c205e=_0x4a43e5;this[_0x8c205e(0x181)]=null,this[_0x8c205e(0x20a)]=null,this[_0x8c205e(0x1b4)]=null,this['hoveredNodeId']=null,this['editingLink']=null,_0x15953a[_0x8c205e(0x1b3)]?.(_0x8c205e(0x172),null),_0x15953a[_0x8c205e(0x1b3)]?.('selectLink',null);},'pickNode'(_0x26c5e9){const _0x3bd40f=_0x4a43e5;this[_0x3bd40f(0x181)]=_0x26c5e9,this['selectedLinkKey']=null,this['editingLink']=null,_0x15953a[_0x3bd40f(0x1b3)]?.(_0x3bd40f(0x172),_0x26c5e9),_0x15953a['$dispatch']?.(_0x3bd40f(0x1f5),null);},'pickLink'(_0x3f144b){const _0x348adf=_0x4a43e5,_0x5337f6=this[_0x348adf(0x18f)][_0x348adf(0x1f7)](_0x294895=>_0x294895[_0x348adf(0x163)]===_0x3f144b)||null;if(_0x5337f6&&(!this[_0x348adf(0x181)]||_0x5337f6['lo']===this[_0x348adf(0x181)]||_0x5337f6['hi']===this[_0x348adf(0x181)])){if(this[_0x348adf(0x20a)]===_0x3f144b)return this[_0x348adf(0x20a)]=null,this[_0x348adf(0x188)]=null,void _0x15953a[_0x348adf(0x1b3)]?.(_0x348adf(0x1f5),null);this[_0x348adf(0x20a)]=_0x3f144b,this[_0x348adf(0x181)]||(this['selectedNodeId']=_0x5337f6['lo'],_0x15953a['$dispatch']?.(_0x348adf(0x172),this[_0x348adf(0x181)])),_0x15953a['$dispatch']?.(_0x348adf(0x1f5),_0x3f144b);}},async 'copy'(_0x2ba80f){const _0x58ee9c=_0x4a43e5;try{await navigator[_0x58ee9c(0x1dc)][_0x58ee9c(0x20b)](String(_0x2ba80f??''));}catch(_0xfb9f26){}},'_sPointerEventsFor'(_0x2baefa){const _0x5969a4=_0x4a43e5;return this[_0x5969a4(0x181)]&&_0x2baefa['lo']!==this[_0x5969a4(0x181)]&&_0x2baefa['hi']!==this[_0x5969a4(0x181)]?_0x5969a4(0x177):_0x5969a4(0x1fc);},'_sEnabledBadge':_0x3529dd=>_0x3529dd?'color:var(--ok)':_0x4a43e5(0x203),'_sEnabledBtn':_0x331a1c=>_0x331a1c?_0x4a43e5(0x1fd):_0x4a43e5(0x1a2),'nodeHealth'(_0x4da8e6){const _0x44829f=_0x4a43e5,_0x1aac57=this['links'][_0x44829f(0x1fe)](_0x5c90e3=>_0x5c90e3['lo']===_0x4da8e6||_0x5c90e3['hi']===_0x4da8e6);if(!_0x1aac57[_0x44829f(0x1da)])return'ok';const _0x5f19ff=_0x1aac57[_0x44829f(0x1bc)](_0x48a9c7=>this[_0x44829f(0x17e)](_0x48a9c7));return _0x5f19ff[_0x44829f(0x174)](_0x44829f(0x19b))?'error':_0x5f19ff[_0x44829f(0x174)](_0x44829f(0x16f))?_0x44829f(0x16b):_0x5f19ff[_0x44829f(0x174)]('lag-med')?'lagging':_0x5f19ff[_0x44829f(0x174)]('behind')?_0x44829f(0x15b):_0x5f19ff[_0x44829f(0x1cd)](_0x8bb64a=>_0x44829f(0x184)===_0x8bb64a||_0x44829f(0x178)===_0x8bb64a)?_0x44829f(0x184):'ok';},'isLinkInteractable'(_0x3e514f){const _0x221676=_0x4a43e5;return!this[_0x221676(0x181)]||_0x3e514f['lo']===this[_0x221676(0x181)]||_0x3e514f['hi']===this['selectedNodeId'];},'isActiveLink'(_0xd11bd1){const _0x1adccd=_0x4a43e5;return this[_0x1adccd(0x20a)]===_0xd11bd1[_0x1adccd(0x163)]||this[_0x1adccd(0x1b4)]===_0xd11bd1[_0x1adccd(0x163)]&&this['isLinkInteractable'](_0xd11bd1);},'nodeClass'(_0x4381dc){const _0x3b341a=_0x4a43e5;let _0x21e935='nd';const _0x4cf01f=this[_0x3b341a(0x181)],_0x1cdfea=this[_0x3b341a(0x1a1)];if(_0x4cf01f&&_0x4cf01f!==_0x4381dc['id']&&(_0x21e935+=_0x3b341a(0x219)),_0x4cf01f===_0x4381dc['id']&&(_0x21e935+=_0x3b341a(0x1b7)),this[_0x3b341a(0x20a)]){const _0x1408ff=this['links'][_0x3b341a(0x1f7)](_0x31d456=>_0x31d456[_0x3b341a(0x163)]===this[_0x3b341a(0x20a)]);!_0x1408ff||_0x1408ff['lo']!==_0x4381dc['id']&&_0x1408ff['hi']!==_0x4381dc['id']||_0x4cf01f===_0x4381dc['id']||(_0x21e935+=_0x3b341a(0x1df));}_0x4cf01f||_0x1cdfea!==_0x4381dc['id']||(_0x21e935+=_0x3b341a(0x20c));const _0x555744=this[_0x3b341a(0x175)](_0x4381dc['id']);return'error'===_0x555744?_0x21e935+=_0x3b341a(0x209):_0x3b341a(0x16b)===_0x555744?_0x21e935+=_0x3b341a(0x1cf):_0x3b341a(0x16c)===_0x555744?_0x21e935+=_0x3b341a(0x1aa):_0x3b341a(0x15b)===_0x555744?_0x21e935+=_0x3b341a(0x1a8):_0x3b341a(0x184)===_0x555744&&(_0x21e935+=_0x3b341a(0x189)),_0x21e935;},'linkClass'(_0x3b72a6){const _0xa2aa8d=_0x4a43e5;let _0x1e4120='ln';const _0x31ee1b=this[_0xa2aa8d(0x20a)]===_0x3b72a6[_0xa2aa8d(0x163)],_0x2b6135=this[_0xa2aa8d(0x1b4)]===_0x3b72a6['key']&&this[_0xa2aa8d(0x1ce)](_0x3b72a6);switch(this[_0xa2aa8d(0x1ce)](_0x3b72a6)||_0x31ee1b||(_0x1e4120+=_0xa2aa8d(0x15d)),_0x31ee1b?_0x1e4120+='\x20ln-selected':_0x2b6135&&(_0x1e4120+='\x20ln-hover'),this['_linkHealth'](_0x3b72a6)){case'disabled':_0x1e4120+=_0xa2aa8d(0x220);break;case'error':_0x1e4120+='\x20ln-err';break;case _0xa2aa8d(0x218):_0x1e4120+='\x20ln-rec';break;case'lag-high':_0x1e4120+=_0xa2aa8d(0x1a3);break;case _0xa2aa8d(0x202):_0x1e4120+=_0xa2aa8d(0x15a);break;case _0xa2aa8d(0x15b):_0x1e4120+=_0xa2aa8d(0x1c5);break;case _0xa2aa8d(0x184):_0x1e4120+=_0xa2aa8d(0x18e);break;default:_0x1e4120+=_0xa2aa8d(0x1bb);}return _0x1e4120;},'linkMarker'(_0x1cbdd6){const _0x3147d4=_0x4a43e5,_0x167e00=_0x1cbdd6[_0x3147d4(0x207)]?.['direction']??'both';return _0x3147d4(0x205)!==_0x167e00&&_0x3147d4(0x21c)!==_0x167e00?'':_0x1cbdd6['link']&&!_0x1cbdd6[_0x3147d4(0x207)][_0x3147d4(0x1d0)]?_0x3147d4(0x1c8):'url(#arrow-'+this[_0x3147d4(0x1de)](this[_0x3147d4(0x171)](_0x1cbdd6['hi_pull']))+')';},'linkStartMarker'(_0x5e0fe8){const _0x23983b=_0x4a43e5,_0x5dec82=_0x5e0fe8['link']?.[_0x23983b(0x1fb)]??_0x23983b(0x205);return _0x23983b(0x205)!==_0x5dec82&&_0x23983b(0x197)!==_0x5dec82?'':_0x5e0fe8[_0x23983b(0x207)]&&!_0x5e0fe8[_0x23983b(0x207)][_0x23983b(0x1d0)]?_0x23983b(0x1c4):'url(#arrow-rev-'+this[_0x23983b(0x1de)](this[_0x23983b(0x171)](_0x5e0fe8[_0x23983b(0x1dd)]))+')';}}),'mount'(_0x3e986c){const _0x29308c=_0x4a43e5;this[_0x29308c(0x221)]=_0x3e986c[_0x29308c(0x204)][_0x29308c(0x166)]('svg'),this[_0x29308c(0x208)]=this[_0x29308c(0x221)]?.[_0x29308c(0x166)](_0x29308c(0x1e7)),this[_0x29308c(0x221)]&&(this[_0x29308c(0x221)][_0x29308c(0x190)][_0x29308c(0x17d)]=_0x29308c(0x187)),this[_0x29308c(0x1e2)](),this[_0x29308c(0x1d6)](),this['_ro']=new ResizeObserver(()=>this[_0x29308c(0x1b6)]()),this[_0x29308c(0x168)]['observe'](_0x3e986c[_0x29308c(0x204)]),this[_0x29308c(0x1ca)]=setInterval(()=>{const _0x151586=_0x29308c;this[_0x151586(0x222)]=Date[_0x151586(0x222)]();},0x3e8),this[_0x29308c(0x17f)]()[_0x29308c(0x186)](()=>this[_0x29308c(0x1b6)]()),this[_0x29308c(0x167)]=_0x11198c=>{const _0x1f7f00=_0x29308c;_0x11198c[_0x1f7f00(0x1c9)](),this[_0x1f7f00(0x198)](_0x11198c);},this[_0x29308c(0x221)]&&this[_0x29308c(0x221)][_0x29308c(0x215)](_0x29308c(0x1e8),this[_0x29308c(0x167)],{'passive':!0x1}),this[_0x29308c(0x1be)]=_0x4ce6f0=>this['_onSvgMousedown'](_0x4ce6f0),this['_svgEl']&&this[_0x29308c(0x221)][_0x29308c(0x215)](_0x29308c(0x1ba),this[_0x29308c(0x1be)]),this[_0x29308c(0x160)]=_0x5c63a4=>this[_0x29308c(0x162)](_0x5c63a4),this['_mouseupCb']=()=>this[_0x29308c(0x170)](),window[_0x29308c(0x215)]('mousemove',this['_mousemoveCb']),window[_0x29308c(0x215)](_0x29308c(0x19e),this[_0x29308c(0x214)]),this[_0x29308c(0x1d1)]=()=>{const _0x493dcf=_0x29308c;document['hidden']||this[_0x493dcf(0x17f)]();},document[_0x29308c(0x215)](_0x29308c(0x1c1),this[_0x29308c(0x1d1)]),this[_0x29308c(0x173)]&&(this['_autoRefreshTimer']=setInterval(()=>this[_0x29308c(0x17f)](),this['autoRefreshIntervalMs'])),this[_0x29308c(0x181)]=this[_0x29308c(0x193)],_0x3e986c[_0x29308c(0x1e5)](()=>_0x3e986c['$attr'][_0x29308c(0x15e)],_0x32994d=>{const _0x597afd=_0x29308c;this[_0x597afd(0x181)]=_0x32994d??null,_0x32994d||(this[_0x597afd(0x20a)]=null);});},'unmount'(){const _0x35fab9=_0x4a43e5;this[_0x35fab9(0x168)]?.[_0x35fab9(0x1f9)](),clearInterval(this[_0x35fab9(0x1ca)]),clearInterval(this[_0x35fab9(0x212)]),this[_0x35fab9(0x221)]&&(this[_0x35fab9(0x221)][_0x35fab9(0x1ed)](_0x35fab9(0x1e8),this[_0x35fab9(0x167)]),this[_0x35fab9(0x221)][_0x35fab9(0x1ed)]('mousedown',this[_0x35fab9(0x1be)])),window[_0x35fab9(0x1ed)]('mousemove',this[_0x35fab9(0x160)]),window[_0x35fab9(0x1ed)]('mouseup',this[_0x35fab9(0x214)]),document[_0x35fab9(0x1ed)](_0x35fab9(0x1c1),this[_0x35fab9(0x1d1)]);},'template':_0x4a43e5(0x224)};function _0x38cf(){const _0xa9b2ff=['clientY','canon','cursor','_linkHealth','refreshTopology','max','selectedNodeId','get','_effectivePos','stale','all','then','grab','editingLink','\x20nd-stale','message','pan','\x20→\x20','413749XVCXkF','\x20ln-stale','links','style','202610BwJWPL','last_error','externalSelectedNodeId','okdb-topo-pos','linkEditDir','address','hi_to_lo','_onWheel','DELETE','sin','error','Save\x20failed','add','mouseup','width','linkEditEnabled','hoveredNodeId','border-color:var(--dis);color:var(--dis)','\x20ln-lag-high','linkEditEnvs','envs','layout','savingLink','\x20nd-behind','sync-topology','\x20nd-lag','panX','peers','idle','button','getBoundingClientRect','setAttribute','hi_pull','clock','$dispatch','hoveredLinkKey','last_seen','fitView','\x20nd-sel','/api/sync/reconcile-all','transform','mousedown','\x20ln-ok','map','5CDsYtV','_mousedownCb','9115887rawOJG','nodeRadius','visibilitychange','left','134672EqdNxI','url(#arrow-rev-disabled)','\x20ln-behind-light','has','/api/sync/links/','url(#arrow-disabled)','preventDefault','_tick','removeItem','localeCompare','every','isLinkInteractable','\x20nd-critical','enabled','_visibilityHandler','1273834ImusrS','cos','sort','values','_loadPositions','1999338HVQihs','floor','clientX','length','topology','clipboard','lo_pull','_healthMarker','\x20nd-sel2','fresh-now','setItem','_measure','forEach','stringify','$watch',')\x20scale(','.topo-g','wheel','backlog','fresh-stale','closeLinkEditor','POST','removeEventListener','lastUpdatedAt','reconcilingTarget','json','$attr','rec','\x20L\x20','target','selectLink','border-color:var(--accent);color:var(--accent);background:var(--bg)','find','\x20(mesh)','disconnect','_px2vb','direction','pointer-events:stroke;cursor:pointer','border-color:var(--ok);color:var(--ok)','filter','top','nodes','PUT','lag-med','color:var(--dis);opacity:0.7','$el','both','/api/sync/reconcile','link','_groupEl','\x20nd-err','selectedLinkKey','writeText','\x20nd-hover','translate(','panY','loadingTopology','available_envs','height','_autoRefreshTimer','211804DUUYFq','_mouseupCb','addEventListener','99HrUjnn','node','reconciling','\x20nd-dim','_savePositions','\x20⇄\x20','lo_to_hi','parentElement','16rhNUrH','selfId','\x20ln-disabled','_svgEl','now','slice','<div\x20style=\x22--bg:var(--okdb-app-bg-deep);\x20--panel:var(--okdb-app-surface);\x20--panel2:var(--okdb-app-bg-deep);\x20--border:var(--okdb-app-border);\x20--border2:var(--okdb-app-surface-2);\x0a\x20\x20--text:var(--okdb-app-fg);\x20--muted:var(--okdb-app-fg-muted);\x20--accent:var(--okdb-accent);\x20--ok:var(--okdb-success);\x20--rec:var(--okdb-accent);\x0a\x20\x20--warn:var(--okdb-warning);\x20--bad:var(--okdb-danger);\x20--err:var(--okdb-danger);\x20--dis:var(--okdb-app-fg-subtle);\x0a\x20\x20border:1px\x20solid\x20var(--border);\x20border-radius:12px;\x20background:var(--bg);\x20color:var(--text);\x0a\x20\x20display:flex;\x20flex-direction:column;\x20flex:1;\x20position:relative;\x20overflow:hidden;\x0a\x20\x20font-family:\x20ui-monospace,\x20monospace;\x22><div\x20style=\x22padding:12px\x2014px;display:flex;justify-content:space-between;border-bottom:1px\x20solid\x20var(--border2);background:var(--panel);align-items:center;\x22><div\x20style=\x22display:flex;align-items:center;gap:10px;\x22><div\x20style=\x22font-weight:700;letter-spacing:0.8px;color:var(--accent);\x22>NETWORK_TOPOLOGY</div><button\x20@click=\x22reconcileAll()\x22\x20:disabled=\x22reconciling\x22\x20style=\x22font-size:11px;padding:4px\x2010px;border-radius:8px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--accent);cursor:pointer;\x22><span\x20style=\x22display:flex;align-items:center;gap:6px;\x22><span\x20:style=\x22reconcilingTarget===\x27all\x27?\x27display:inline-block\x27:\x27display:none\x27\x22\x20class=\x22spinner\x22/>\x20{{reconcilingTarget===\x27all\x27?\x27RECONCILING\x27:\x27RECONCILE\x20ALL\x27}}</span></button>\x20<button\x20@click=\x22refreshTopology()\x22\x20:disabled=\x22loadingTopology\x22\x20style=\x22font-size:11px;padding:4px\x2010px;border-radius:8px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--muted);cursor:pointer;\x22>REFRESH</button>\x20<button\x20@click=\x22fitView()\x22\x20style=\x22font-size:11px;padding:4px\x2010px;border-radius:8px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--muted);cursor:pointer;\x22\x20title=\x22Fit\x20all\x20nodes\x20into\x20view\x22>FIT</button>\x20<button\x20@click=\x22resetLayout()\x22\x20style=\x22font-size:11px;padding:4px\x2010px;border-radius:8px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--muted);cursor:pointer;\x22\x20title=\x22Reset\x20node\x20positions\x22>RESET</button>\x20<span\x20:style=\x22{opacity:loadingTopology?1:0}\x22\x20class=\x22spinner\x22/></div><div\x20style=\x22display:flex;align-items:center;gap:12px;font-size:11px;\x22><span\x20:class=\x22freshnessClass\x22>updated:\x20{{freshnessLabel}}</span>\x20<span\x20style=\x22opacity:0.75;\x22>{{nodes.length}}\x20NODES\x20//\x20{{links.length}}\x20LINKS</span></div></div><div\x20style=\x22flex:1;position:relative;\x22><svg\x20:viewBox=\x22\x270\x200\x20\x27+w+\x27\x20\x27+h\x22\x20style=\x22width:100%;height:100%;\x22><rect\x20:width=\x22w\x22\x20:height=\x22h\x22\x20fill=\x22transparent\x22\x20style=\x22pointer-events:all\x22\x20@click=\x22deselect()\x22/><defs><marker\x20id=\x22arrow-ok\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--ok)\x22/></marker><marker\x20id=\x22arrow-rec\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--rec)\x22/></marker><marker\x20id=\x22arrow-err\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--err)\x22/></marker><marker\x20id=\x22arrow-lag-med\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--warn)\x22/></marker><marker\x20id=\x22arrow-lag-high\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--bad)\x22/></marker><marker\x20id=\x22arrow-disabled\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--dis)\x22/></marker><marker\x20id=\x22arrow-rev-ok\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto-start-reverse\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--ok)\x22/></marker><marker\x20id=\x22arrow-rev-rec\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto-start-reverse\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--rec)\x22/></marker><marker\x20id=\x22arrow-rev-err\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto-start-reverse\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--err)\x22/></marker><marker\x20id=\x22arrow-rev-lag-med\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto-start-reverse\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--warn)\x22/></marker><marker\x20id=\x22arrow-rev-lag-high\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto-start-reverse\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--bad)\x22/></marker><marker\x20id=\x22arrow-rev-disabled\x22\x20viewBox=\x220\x200\x2010\x2010\x22\x20refX=\x2210\x22\x20refY=\x225\x22\x20markerWidth=\x226\x22\x20markerHeight=\x226\x22\x20orient=\x22auto-start-reverse\x22><path\x20d=\x22M\x200\x200\x20L\x2010\x205\x20L\x200\x2010\x20z\x22\x20fill=\x22var(--dis)\x22/></marker></defs><style>.ln\x20{\x20fill:none;\x20stroke-width:1.9;\x20opacity:0.70;\x20transition:opacity\x200.14s,stroke-width\x200.14s,filter\x200.14s;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-ok\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{\x20stroke:var(--ok);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-behind-light\x20{\x20stroke:var(--okdb-info);\x20opacity:0.8;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-rec\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{\x20stroke:var(--rec);\x20stroke-dasharray:4\x203;\x20animation:dash\x201.1s\x20linear\x20infinite;\x20filter:drop-shadow(0\x200\x204px\x20rgba(77,163,255,0.5));\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-lag-med\x20\x20\x20\x20\x20\x20{\x20stroke:var(--warn);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-lag-high\x20\x20\x20\x20\x20{\x20stroke:var(--bad);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-err\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{\x20stroke:var(--err);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-stale\x20\x20\x20\x20\x20\x20\x20\x20{\x20stroke:var(--okdb-app-fg-subtle);\x20opacity:0.5;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-disabled\x20\x20\x20\x20\x20{\x20stroke:var(--dis);\x20stroke-dasharray:6\x204;\x20opacity:0.45;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-dim\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{\x20opacity:0.08;\x20filter:none\x20!important;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-hover\x20\x20\x20\x20\x20\x20\x20\x20{\x20stroke-width:3.0;\x20opacity:1;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.ln-selected\x20\x20\x20\x20\x20{\x20stroke:var(--accent)\x20!important;\x20stroke-width:5.2\x20!important;\x20opacity:1\x20!important;\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20filter:drop-shadow(0\x200\x204px\x20rgba(77,163,255,0.9))\x20drop-shadow(0\x200\x2010px\x20rgba(77,163,255,0.35));\x20}\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd\x20circle\x20{\x20fill:var(--bg);\x20stroke:var(--border);\x20stroke-width:2;\x20transition:stroke\x200.14s,stroke-width\x200.14s,filter\x200.14s,opacity\x200.14s;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd\x20text\x20\x20\x20{\x20fill:var(--muted);\x20font-size:11px;\x20pointer-events:none;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-hover\x20\x20circle\x20{\x20stroke:rgba(77,163,255,0.8);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-sel\x20\x20\x20\x20circle\x20{\x20stroke:var(--accent);\x20stroke-width:3.4;\x20filter:drop-shadow(0\x200\x204px\x20rgba(77,163,255,0.75))\x20drop-shadow(0\x200\x2010px\x20rgba(77,163,255,0.25));\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-sel2\x20\x20\x20circle\x20{\x20stroke:rgba(77,163,255,0.75);\x20stroke-width:3.0;\x20filter:drop-shadow(0\x200\x206px\x20rgba(77,163,255,0.25));\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-dim\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{\x20opacity:0.22;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-err\x20\x20\x20\x20circle\x20\x20{\x20stroke:var(--err);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-stale\x20\x20circle\x20\x20{\x20stroke:var(--okdb-app-fg-subtle);\x20stroke-width:2;\x20opacity:0.7;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-behind\x20circle\x20\x20{\x20stroke:var(--okdb-info);\x20stroke-width:2.5;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-lag\x20\x20\x20\x20circle\x20\x20{\x20stroke:var(--warn);\x20stroke-width:3;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.nd-critical\x20circle\x20{\x20stroke:var(--bad);\x20stroke-width:3.5;\x20filter:drop-shadow(0\x200\x206px\x20rgba(255,77,77,0.5));\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.fresh-now\x20\x20\x20{\x20color:var(--ok);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.fresh-ok\x20\x20\x20\x20{\x20color:var(--okdb-info);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.fresh-stale\x20{\x20color:var(--warn);\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20.spinner\x20{\x20display:inline-block;\x20width:12px;\x20height:12px;\x20border:2px\x20solid\x20rgba(77,163,255,0.2);\x20border-top:2px\x20solid\x20var(--accent);\x20border-radius:50%;\x20animation:spin\x200.8s\x20linear\x20infinite;\x20flex-shrink:0;\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20@keyframes\x20dash\x20{\x20to\x20{\x20stroke-dashoffset:-14;\x20}\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20@keyframes\x20spin\x20\x20{\x20to\x20{\x20transform:rotate(360deg);\x20}\x20}</style><g\x20class=\x22topo-g\x22><for\x20:=\x22links\x22\x20let:l><if\x20:=\x22!isActiveLink(l)\x22><g><path\x20:d=\x22linkPath(l)\x22\x20stroke=\x22transparent\x22\x20stroke-width=\x2214\x22\x20fill=\x22none\x22\x20:style=\x22_sPointerEventsFor(l)\x22\x20@mouseenter=\x22isLinkInteractable(l)?(hoveredLinkKey=l.key):null\x22\x20@mouseleave=\x22hoveredLinkKey=null\x22\x20@click=\x22pickLink(l.key)\x22/><path\x20:d=\x22linkPath(l)\x22\x20:class=\x22linkClass(l)\x22\x20:marker-end=\x22linkMarker(l)\x22\x20:marker-start=\x22linkStartMarker(l)\x22><title>{{l.lo.slice(0,8)}}\x20↔\x20{{l.hi.slice(0,8)}}\x20direction:\x20{{l.link\x20?\x20l.link.direction\x20:\x20\x27mesh\x27}}\x20enabled:\x20{{l.link\x20?\x20l.link.enabled\x20:\x20true}}\x20envs:\x20{{l.link\x20&&\x20l.link.envs\x20?\x20l.link.envs.join(\x27,\x20\x27)\x20:\x20\x27all\x27}}</title></path></g></if></for><for\x20:=\x22nodeList\x22\x20let:n><g\x20:id=\x22\x27nd-\x27+n.id\x22\x20:transform=\x22\x27translate(\x27+n.px+\x27,\x27+n.py+\x27)\x27\x22\x20:class=\x22nodeClass(n)\x22\x20@mouseenter=\x22hoveredNodeId=n.id\x22\x20@mouseleave=\x22hoveredNodeId=null\x22\x20@click=\x22pickNode(n.id)\x22><circle\x20:r=\x22nodeRadius()\x22/><text\x20text-anchor=\x22middle\x22\x20dy=\x224\x22>{{n.id.slice(0,6)}}</text><title>{{n.id}}\x20clock:\x20{{n.clock\x20??\x20\x27--\x27}}\x20addr:\x20{{n.address\x20??\x20\x27—\x27}}</title></g></for><for\x20:=\x22links\x22\x20let:l><if\x20:=\x22isActiveLink(l)\x22><g><path\x20:d=\x22linkPath(l)\x22\x20stroke=\x22transparent\x22\x20stroke-width=\x2216\x22\x20fill=\x22none\x22\x20:style=\x22_sPointerEventsFor(l)\x22\x20@mouseenter=\x22isLinkInteractable(l)?(hoveredLinkKey=l.key):null\x22\x20@mouseleave=\x22hoveredLinkKey=null\x22\x20@click=\x22pickLink(l.key)\x22/><path\x20:d=\x22linkPath(l)\x22\x20:class=\x22linkClass(l)\x22\x20:marker-end=\x22linkMarker(l)\x22\x20:marker-start=\x22linkStartMarker(l)\x22/></g></if></for></g></svg><if\x20:=\x22selection\x20||\x20editingLink\x22><div\x20style=\x22position:absolute;top:18px;right:18px;width:320px;background:var(--panel);border:1px\x20solid\x20var(--border);border-radius:12px;padding:16px;box-shadow:0\x2016px\x2034px\x20rgba(0,0,0,0.45);border-left:4px\x20solid\x20var(--accent);\x22><div\x20style=\x22display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;\x22><span\x20style=\x22font-size:10px;background:var(--bg);padding:3px\x207px;border-radius:6px;color:var(--accent);letter-spacing:0.6px;\x22>{{editingLink\x20?\x20\x27LINK_CONFIG\x27\x20:\x20selection.type.toUpperCase()}}\x20</span><span\x20@click=\x22editingLink\x20?\x20closeLinkEditor()\x20:\x20deselect()\x22\x20style=\x22cursor:pointer;opacity:0.7;font-size:16px;line-height:12px;\x22>×</span></div><if\x20:=\x22!editingLink\x20&&\x20selection\x20&&\x20selection.type\x20===\x20\x27node\x27\x22><div\x20style=\x22font-size:13px;\x22><div\x20style=\x22display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px;\x22><div\x20style=\x22color:var(--text);font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\x22>{{selection.id}}</div><button\x20@click=\x22copy(selection.id)\x22\x20style=\x22border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--muted);font-size:11px;padding:4px\x208px;border-radius:8px;cursor:pointer;\x22>copy</button></div><div\x20style=\x22display:grid;grid-template-columns:92px\x201fr;row-gap:8px;column-gap:10px;\x22><div\x20style=\x22opacity:0.65;\x22>Clock</div><div>{{selection.data.clock??\x27--\x27}}</div><div\x20style=\x22opacity:0.65;\x22>Addr</div><div\x20style=\x22font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\x22>{{selection.data.address||\x27N/A\x27}}</div><div\x20style=\x22opacity:0.65;\x22>Status</div><div\x20:style=\x22selection.data.error?\x27color:var(--err)\x27:\x27color:var(--ok)\x27\x22>{{selection.data.error?(\x27ERR:\x20\x27+selection.data.error):\x27OK\x27}}</div></div><div\x20style=\x22margin-top:12px;border-top:1px\x20solid\x20var(--border2);padding-top:10px;\x22><div\x20style=\x22font-size:11px;opacity:0.7;margin-bottom:6px;\x22>Tags</div><div\x20style=\x22display:flex;flex-wrap:wrap;gap:6px;\x22><if\x20:=\x22!(selection.data.tags\x20||\x20[]).length\x22><span\x20style=\x22font-size:11px;opacity:0.45;\x22>No\x20tags</span></if><for\x20:=\x22selection.data.tags\x20||\x20[]\x22\x20let:tag><span\x20style=\x22font-size:10px;padding:2px\x208px;border-radius:999px;border:1px\x20solid\x20var(--okdb-accent-soft-border);color:var(--okdb-accent);background:var(--okdb-accent-soft-bg);\x22>{{tag}}</span></for></div></div><div\x20style=\x22margin-top:12px;border-top:1px\x20solid\x20var(--border2);padding-top:10px;\x22><div\x20style=\x22font-size:11px;opacity:0.7;margin-bottom:6px;\x22>Available\x20envs</div><div\x20style=\x22font-size:11px;color:var(--muted);line-height:1.5;word-break:break-word;\x22>{{(selection.data.availableEnvs\x20||\x20[]).join(\x27,\x20\x27)\x20||\x20\x27—\x27}}</div></div><div\x20style=\x22margin-top:12px;border-top:1px\x20solid\x20var(--border2);padding-top:10px;\x22><div\x20style=\x22font-size:11px;opacity:0.7;margin-bottom:6px;\x22>Outbound\x20peers</div><div\x20style=\x22display:flex;flex-wrap:wrap;gap:6px;\x22><for\x20:=\x22Object.keys(selection.data.peers||{})\x22\x20let:pid><span\x20style=\x22font-size:11px;padding:3px\x207px;border:1px\x20solid\x20var(--border);background:var(--panel2);border-radius:999px;color:var(--muted);\x22>{{pid.slice(0,8)}}</span></for></div></div><div\x20style=\x22margin-top:14px;\x22><button\x20@click=\x22reconcileNode(selection.id)\x22\x20:disabled=\x22reconciling\x22\x20style=\x22width:100%;box-sizing:border-box;padding:6px\x2010px;border-radius:8px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--accent);cursor:pointer;font-size:12px;\x22><span\x20style=\x22display:flex;align-items:center;justify-content:center;gap:6px;\x22><span\x20:style=\x22reconcilingTarget===selection.id?\x27display:inline-block\x27:\x27display:none\x27\x22\x20class=\x22spinner\x22/>\x20{{reconcilingTarget===selection.id?\x27RECONCILING\x27:\x27RECONCILE\x20NODE\x27}}</span></button></div></div></if><if\x20:=\x22!editingLink\x20&&\x20selection\x20&&\x20selection.type\x20===\x20\x27link\x27\x22><div\x20style=\x22font-size:13px;\x22><div\x20style=\x22margin-bottom:12px;\x22><div\x20style=\x22display:flex;align-items:center;gap:8px;margin-bottom:6px;\x22><span\x20style=\x22font-family:monospace;font-size:12px;font-weight:700;\x22>{{selection.data.lo.slice(0,8)}}</span>\x20<span\x20style=\x22font-size:16px;color:var(--accent);\x22>{{selection.data.link\x20?\x20(selection.data.link.direction\x20===\x20\x27lo_to_hi\x27\x20?\x20\x27→\x27\x20:\x20selection.data.link.direction\x20===\x20\x27hi_to_lo\x27\x20?\x20\x27←\x27\x20:\x20\x27⇄\x27)\x20:\x20\x27⇄\x27}}\x20</span><span\x20style=\x22font-family:monospace;font-size:12px;font-weight:700;\x22>{{selection.data.hi.slice(0,8)}}</span><if\x20:=\x22selection.data.link\x22><span\x20style=\x22font-size:11px;margin-left:4px;\x22\x20:style=\x22_sEnabledBadge(selection.data.link.enabled)\x22>{{selection.data.link.enabled\x20?\x20\x27●\x20on\x27\x20:\x20\x27○\x20off\x27}}</span></if></div><if\x20:=\x22selection.data.link\x20&&\x20selection.data.link.envs\x22><div\x20style=\x22font-size:11px;opacity:0.45;\x22>envs:\x20{{selection.data.link.envs.join(\x27,\x20\x27)}}</div></if><if\x20:=\x22!selection.data.link\x22><div\x20style=\x22font-size:11px;opacity:0.45;\x22>no\x20link\x20config\x20—\x20mesh\x20(legacy)</div></if></div><div\x20style=\x22border:1px\x20solid\x20var(--border2);border-radius:8px;overflow:hidden;margin-bottom:12px;font-size:11px;\x22><if\x20:=\x22!selection.data.link\x20||\x20selection.data.link.direction\x20===\x20\x27both\x27\x20||\x20selection.data.link.direction\x20===\x20\x27lo_to_hi\x27\x22><div\x20style=\x22padding:9px\x2011px;border-bottom:1px\x20solid\x20var(--bg);\x22><div\x20style=\x22display:flex;align-items:center;gap:6px;margin-bottom:6px;\x22><span\x20style=\x22font-family:monospace;opacity:0.7;\x22>{{selection.data.lo.slice(0,6)}}</span>\x20<span\x20style=\x22color:var(--accent);\x22>→</span>\x20<span\x20style=\x22font-family:monospace;opacity:0.7;\x22>{{selection.data.hi.slice(0,6)}}</span>\x20<span\x20style=\x22opacity:0.4;\x22>(hi\x20receives\x20from\x20lo)</span></div><div\x20style=\x22display:grid;grid-template-columns:70px\x201fr;row-gap:4px;gap:6px;opacity:0.85;\x22><span\x20style=\x22opacity:0.5;\x22>status</span>\x20<span>{{selection.data.hi_pull\x20?\x20selection.data.hi_pull.status\x20:\x20\x27—\x27}}</span>\x20<span\x20style=\x22opacity:0.5;\x22>backlog</span>\x20<span>{{selection.data.hi_pull\x20?\x20selection.data.hi_pull.backlog\x20:\x20\x27—\x27}}</span>\x20<span\x20style=\x22opacity:0.5;\x22>last\x20seen</span>\x20<span>{{selection.data.hi_pull\x20&&\x20selection.data.hi_pull.last_seen\x20?\x20(Math.round((now\x20-\x20selection.data.hi_pull.last_seen)/1000)\x20+\x20\x27s\x20ago\x27)\x20:\x20\x27—\x27}}</span><if\x20:=\x22selection.data.hi_pull\x20&&\x20selection.data.hi_pull.last_error\x22><span\x20style=\x22opacity:0.5;\x22>error</span>\x20<span\x20style=\x22color:var(--err);\x22>{{selection.data.hi_pull.last_error}}</span></if></div></div></if><if\x20:=\x22!selection.data.link\x20||\x20selection.data.link.direction\x20===\x20\x27both\x27\x20||\x20selection.data.link.direction\x20===\x20\x27hi_to_lo\x27\x22><div\x20style=\x22padding:9px\x2011px;\x22><div\x20style=\x22display:flex;align-items:center;gap:6px;margin-bottom:6px;\x22><span\x20style=\x22font-family:monospace;opacity:0.7;\x22>{{selection.data.hi.slice(0,6)}}</span>\x20<span\x20style=\x22color:var(--accent);\x22>→</span>\x20<span\x20style=\x22font-family:monospace;opacity:0.7;\x22>{{selection.data.lo.slice(0,6)}}</span>\x20<span\x20style=\x22opacity:0.4;\x22>(lo\x20receives\x20from\x20hi)</span></div><div\x20style=\x22display:grid;grid-template-columns:70px\x201fr;row-gap:4px;gap:6px;opacity:0.85;\x22><span\x20style=\x22opacity:0.5;\x22>status</span>\x20<span>{{selection.data.lo_pull\x20?\x20selection.data.lo_pull.status\x20:\x20\x27—\x27}}</span>\x20<span\x20style=\x22opacity:0.5;\x22>backlog</span>\x20<span>{{selection.data.lo_pull\x20?\x20selection.data.lo_pull.backlog\x20:\x20\x27—\x27}}</span>\x20<span\x20style=\x22opacity:0.5;\x22>last\x20seen</span>\x20<span>{{selection.data.lo_pull\x20&&\x20selection.data.lo_pull.last_seen\x20?\x20(Math.round((now\x20-\x20selection.data.lo_pull.last_seen)/1000)\x20+\x20\x27s\x20ago\x27)\x20:\x20\x27—\x27}}</span><if\x20:=\x22selection.data.lo_pull\x20&&\x20selection.data.lo_pull.last_error\x22><span\x20style=\x22opacity:0.5;\x22>error</span>\x20<span\x20style=\x22color:var(--err);\x22>{{selection.data.lo_pull.last_error}}</span></if></div></div></if></div><div\x20style=\x22display:flex;flex-direction:column;gap:7px;\x22><button\x20@click=\x22reconcileLink(selection.data)\x22\x20:disabled=\x22reconciling\x22\x20style=\x22width:100%;box-sizing:border-box;padding:7px;border-radius:8px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--accent);cursor:pointer;font-size:12px;\x22><span\x20style=\x22display:flex;align-items:center;justify-content:center;gap:6px;\x22><span\x20:style=\x22reconcilingTarget===selection.data.key?\x27display:inline-block\x27:\x27display:none\x27\x22\x20class=\x22spinner\x22/>\x20{{reconcilingTarget===selection.data.key\x20?\x20\x27Reconciling…\x27\x20:\x20\x27Reconcile\x27}}</span></button>\x20<button\x20@click=\x22openLinkEditor(selection.data)\x22\x20style=\x22width:100%;box-sizing:border-box;padding:7px;border-radius:8px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--muted);cursor:pointer;font-size:12px;\x22>✎\x20Configure\x20Link</button></div></div></if><if\x20:=\x22editingLink\x22><div\x20style=\x22font-size:13px;\x22><div\x20style=\x22margin-bottom:14px;\x22><div\x20style=\x22font-family:monospace;font-size:11px;opacity:0.5;margin-bottom:2px;\x22>link\x20id</div><div\x20style=\x22font-family:monospace;font-size:11px;\x22>{{editingLink.key}}</div></div><div\x20style=\x22margin-bottom:14px;\x22><div\x20style=\x22font-size:11px;opacity:0.5;margin-bottom:7px;\x22>Direction</div><div\x20style=\x22display:flex;flex-direction:column;gap:5px;\x22><for\x20:=\x22dirButtons\x22\x20let:btn><button\x20@click=\x22linkEditDir\x20=\x20btn.canon\x22\x20:style=\x22btn.style\x22\x20style=\x22width:100%;box-sizing:border-box;padding:7px\x2010px;border-radius:7px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--muted);cursor:pointer;font-size:12px;font-family:monospace;text-align:left;\x22>{{btn.label}}</button></for></div></div><if\x20:=\x22availableEnvs.length\x22><div\x20style=\x22margin-bottom:14px;\x22><div\x20style=\x22font-size:11px;opacity:0.5;margin-bottom:7px;\x22>Data\x20envs\x20—\x20{{linkEditEnvs\x20===\x20null\x20?\x20\x27all\x27\x20:\x20linkEditEnvs.length\x20+\x20\x27\x20selected\x27}}</div><div\x20style=\x22display:flex;flex-wrap:wrap;gap:5px;\x22><for\x20:=\x22envButtons\x22\x20let:btn><button\x20@click=\x22toggleLinkEnv(btn.name)\x22\x20:style=\x22btn.style\x22\x20style=\x22padding:4px\x2010px;border-radius:6px;border:1px\x20solid\x20var(--border);background:var(--panel2);color:var(--muted);cursor:pointer;font-size:11px;\x22>{{btn.name}}</button></for></div></div></if><div\x20style=\x22margin-bottom:16px;display:flex;align-items:center;gap:10px;\x22><span\x20style=\x22font-size:11px;opacity:0.5;\x22>Enabled</span>\x20<button\x20@click=\x22linkEditEnabled=!linkEditEnabled\x22\x20:style=\x22_sEnabledBtn(linkEditEnabled)\x22\x20style=\x22padding:4px\x2012px;border-radius:6px;border:1px\x20solid;background:var(--panel2);cursor:pointer;font-size:11px;\x22>{{linkEditEnabled\x20?\x20\x27●\x20ON\x27\x20:\x20\x27○\x20OFF\x27}}</button></div><div\x20style=\x22display:flex;gap:8px;\x22><button\x20@click=\x22saveLink()\x22\x20:disabled=\x22savingLink\x22\x20style=\x22flex:1;padding:8px;border-radius:8px;border:1px\x20solid\x20var(--accent);background:rgba(77,163,255,0.1);color:var(--accent);cursor:pointer;font-size:12px;\x22><span\x20style=\x22display:flex;align-items:center;justify-content:center;gap:5px;\x22><span\x20:style=\x22savingLink?\x27display:inline-block\x27:\x27display:none\x27\x22\x20class=\x22spinner\x22/>\x20Save</span></button>\x20<button\x20@click=\x22deleteLink()\x22\x20:disabled=\x22savingLink\x22\x20style=\x22padding:8px\x2014px;border-radius:8px;border:1px\x20solid\x20#3d1a1a;background:rgba(255,59,48,0.08);color:var(--err);cursor:pointer;font-size:12px;\x22>Remove</button></div></div></if></div></if></div><div\x20style=\x22padding:9px\x2014px;background:var(--bg);border-top:1px\x20solid\x20var(--border2);display:flex;gap:16px;font-size:11px;align-items:center;flex-wrap:wrap;opacity:0.9;\x22><span><span\x20style=\x22color:var(--ok);\x22>●</span>\x20synced</span>\x20<span><span\x20style=\x22color:var(--okdb-info);\x22>●</span>\x20behind</span>\x20<span><span\x20style=\x22color:var(--rec);\x22>●</span>\x20reconciling</span>\x20<span><span\x20style=\x22color:var(--warn);\x22>●</span>\x20lag</span>\x20<span><span\x20style=\x22color:var(--err);\x22>●</span>\x20error</span>\x20<span><span\x20style=\x22color:var(--dis);\x22>●</span>\x20disabled</span>\x20<span\x20style=\x22opacity:0.4;\x22>⇄\x20both\x20→\x20send\x20←\x20receive\x20--\x20disabled\x20(click\x20to\x20inspect)</span></div></div>','_drag','zoom','51lAEYxG','\x20ln-lag-med','behind','_applyTransform','\x20ln-dim','selected_node_id','indexOf','_mousemoveCb','_customPos','_onMousemove','key','few\x20seconds\x20ago','status','querySelector','_wheelCb','_ro','deltaY','startsWith','critical','lagging','push','Remove\x20this\x20data\x20link?\x20Nodes\x20stay\x20connected\x20but\x20data\x20will\x20stop\x20syncing.','lag-high','_onMouseup','_pullHealth','select','autoRefresh','includes','nodeHealth','min','pointer-events:none','disabled','application/json','data'];_0x38cf=function(){return _0xa9b2ff;};return _0x38cf();}
@@ -0,0 +1 @@
1
+ <script type="module">import createEnvModal from"../db/modals/create-env-modal.ok.js";import demoEnvModal from"../db/modals/demo-env-modal.ok.js";import removeEnvModal from"../db/modals/remove-env-modal.ok.js";import dataOpsModal from"./modals/data-ops-modal.ok.js";import systemLog from"./parts/system-log.ok.js";import systemLogHistory from"./parts/system-log-history.ok.js";import systemSyncPanel from"./parts/system-sync-panel.ok.js";import systemAuthPanel from"./parts/system-auth-panel.ok.js";import systemApiPanel from"./parts/system-api-panel.ok.js";import licensePanel from"../license/parts/license-panel.ok.js";import docViewer from"@toolkit/components/ok-doc-viewer.ok.js";export default{tag:"system-index",unwrap:!0,dependencies:[systemLog,systemLogHistory,systemSyncPanel,systemAuthPanel,systemApiPanel,licensePanel,docViewer,createEnvModal,demoEnvModal,removeEnvModal,dataOpsModal],context:e=>({_systemWildcard(){const t=e.$vars.$router?.match("/system/*");return t?.params?.["*"]??""},get subView(){return this._parseSubView(this._systemWildcard())},_parseSubView(e){const t=e??"";return t&&"overview"!==t?"logs"===t?"logs":"events"===t?"events":"sync"===t?"sync":"api"===t?"api":"auth"===t?"auth":"license"===t?"license":t.startsWith("docs")?"docs":"overview":"overview"},goToSystemSub(t){const o=e.$vars.$router;if(!o)return;const s=e.$ok.stores.okdb.selectedEnv,n=s?`?env=${encodeURIComponent(s)}`:"";o.push(`/system/${t}${n}`)},docsManifest:[],docsAnchor:"",get docsCurrentFile(){return this._parseDocsFile(this._systemWildcard())},_parseDocsFile(e){const t=e??"",o=t.startsWith("docs/")?t.slice(5):"";return o?o.replace(/\.md$/,"")+".md":"index.md"},docsIsActive(e){return this.docsCurrentFile===e},docsNavigateTo(e){const t=e.replace(/\.md$/,"");this.docsAnchor="",this.goToSystemSub("docs/"+t)},docsOnAnchorChange(e){this.docsAnchor=e},async loadDocsManifest(){if(!this.docsManifest.length)try{const e=await fetch("/docs/manifest.json");e.ok&&(this.docsManifest=await e.json())}catch{}},info:null,runtime:null,syncInfo:null,envs:[],loading:!1,error:null,autoRefresh:!0,_timer:null,metrics:null,async load(){this.loading=!0,this.error=null;try{const e=await fetch(`${__ENV__.API}/info`),t=await e.json();if(!e.ok)throw new Error(t?.error?.message||"Failed to load info");this.info=t.data??t}catch(e){this.error=e?.message||String(e)}finally{this.loading=!1}try{const t=await fetch(`${__ENV__.API}/envs`);if(t.ok){const o=await t.json();this.envs=o.data??[],e.$ok.stores.okdb.envs=this.envs}}catch{}try{const e=await fetch(`${__ENV__.API}/system/runtime`);if(e.ok){const t=await e.json();this.runtime=t.data??t}}catch{}try{const e=await fetch(`${__ENV__.API}/system/metrics`);if(e.ok){const t=await e.json();this.metrics=t.data??null}}catch{}try{const e=await fetch(`${__ENV__.API}/sync/info`);this.syncInfo=e.ok?(await e.json()).data??null:null}catch{this.syncInfo=null}},get approxSize(){const e=(this.envs||[]).reduce((e,t)=>e+(t.size||0),0);if(!e)return"--";const t=["B","KB","MB","GB","TB"];let o=e,s=0;for(;o>=1024&&s<t.length-1;)o/=1024,s++;return o.toFixed(2)+" "+t[s]},get typeList(){const e=[];for(const t of this.envs||[])for(const o of t.types||[])o.name.startsWith("~")||e.push({name:o.name,env:t.name,count:o.count??0});return e.sort((e,t)=>e.name.localeCompare(t.name)||e.env.localeCompare(t.env))},get systemTypeList(){const e=[];for(const t of this.envs||[])for(const o of t.types||[])o.name.startsWith("~")&&e.push({name:o.name,env:t.name,count:o.count??0});return e.sort((e,t)=>e.name.localeCompare(t.name)||e.env.localeCompare(t.env))},get totalTypeCount(){return this.typeList.length},get plugins(){return(this.info?.plugins||[]).filter(Boolean)},get config(){return this.info?.config??null},get durabilityLabel(){const e=this.config?.durability;return{strict:{label:"Strict",color:"var(--okdb-success)",hint:"Full fsync on every commit."},balanced:{label:"Balanced",color:"var(--okdb-accent)",hint:"Async fsync worker — crash-safe, fast."},fast:{label:"Fast",color:"var(--okdb-warning)",hint:"No per-commit fsync. May lose last tx on crash."},custom:{label:"Custom",color:"var(--okdb-purple)",hint:"Manual LMDB flags. No preset applied."}}[e]??{label:e??"--",color:"var(--okdb-app-fg-muted)",hint:""}},get configWarnings(){return this.config?.warnings??[]},formatBytes(e){if(null==e)return"--";const t=["B","KB","MB","GB","TB"];let o=e,s=0;for(;o>=1024&&s<t.length-1;)o/=1024,s++;return o.toFixed(0===s?0:2)+" "+t[s]},formatUptime(e){if(null==e)return"--";const t=Math.floor(e),o=Math.floor(t/86400),s=Math.floor(t%86400/3600),n=Math.floor(t%3600/60),a=t%60;return o>0?`${o}d ${s}h ${n}m`:s>0?`${s}h ${n}m ${a}s`:n>0?`${n}m ${a}s`:`${a}s`},formatLoad:e=>e&&e.length?e.map(e=>e.toFixed(2)).join(" / "):"--",pct:(e,t)=>e&&t?Math.round(e/t*100):0,get clock(){return this.syncInfo?.clock??this.info?.clock??"--"},get nodeId(){return this.syncInfo?.node?.id??this.info?.id??"--"},get nodeAddress(){return this.syncInfo?.node?.address??null},formatNum:e=>null==e?"--":Number(e).toLocaleString(),copyId(){navigator.clipboard?.writeText(this.nodeId).catch(()=>{})},changelogOpen:!1,changelogBusy:!1,changelogError:null,changes:[],changelogLimit:50,async loadChangelog(){this.changelogBusy=!0,this.changelogError=null;try{const e=new URLSearchParams({limit:this.changelogLimit}),t=await fetch(`${__ENV__.API}/system/changelog?${e}`),o=await t.json();if(!t.ok)throw new Error(o?.error?.message||"Failed");this.changes=o.data??[]}catch(e){this.changelogError=e?.message||String(e)}finally{this.changelogBusy=!1}},get changelogHasOlder(){return this.changes.length===this.changelogLimit},loadMoreChangelog(){this.changelogLimit=Math.min(this.changelogLimit+100,1e3),this.loadChangelog()},toggleChangelog(){this.changelogOpen=!this.changelogOpen,this.changelogOpen&&!this.changes.length&&this.loadChangelog()},actionColor:e=>({put:"var(--okdb-success)",remove:"var(--okdb-danger)",type_register:"var(--okdb-accent)",type_drop:"var(--okdb-danger)",index_register:"var(--okdb-purple)",index_drop:"var(--okdb-warning)"}[e]||"var(--okdb-app-fg-muted)"),actionLabel:e=>(e||"").replace(/_/g," ").toUpperCase(),shortKey:e=>e?e.length<=20?e:e.slice(0,10)+"…"+e.slice(-6):"—",relTime(e){if(!e)return"—";const t=Date.now()-e;return t<5e3?"just now":t<6e4?`${Math.round(t/1e3)}s ago`:t<36e5?`${Math.round(t/6e4)}m ago`:t<864e5?`${Math.round(t/36e5)}h ago`:new Date(e).toLocaleDateString()},showSystemEnvs:!1,get totalEnvSize(){return(this.envs||[]).reduce((e,t)=>e+(t.size||0),0)},get userEnvs(){return(this.envs||[]).filter(e=>!e.name.startsWith("~"))},get systemEnvs(){return(this.envs||[]).filter(e=>e.name.startsWith("~"))},get visibleEnvs(){return this.showSystemEnvs?this.envs:this.userEnvs},get orphanedEnvs(){return(this.envs||[]).filter(e=>e.orphaned)},goToEnv(t){e.$ok.stores.okdb.selectEnv(t),e.$vars.$router?.push?.("/db?env="+encodeURIComponent(t))},async openCreateEnv(){await e.$ok.shared.modal.open({owner:e,title:"Create Environment",content:'<create-env-modal :modal="modal" :on-done="onDone" />',context:t=>({modal:t,onDone:async()=>{await e.$ok.stores.okdb.reloadEnvs(),await this.load()}})})},async openDemoModal(){await e.$ok.shared.modal.open({owner:e,title:'<span style="background:linear-gradient(135deg,var(--okdb-accent),var(--okdb-purple) 50%,var(--okdb-success));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-weight:700;font-size:15px;">✦ Demo Environment</span>',canDrag:!0,content:'<demo-env-modal :modal="modal" :on-done="onDone" />',context:t=>({modal:t,onDone:async t=>{e.$ok.stores.okdb.selectEnv(t),await e.$ok.stores.okdb.reloadEnvs(),await this.load(),e.$ok.shared?.toast?.success?.(`✦ Demo environment "${t}" is ready!`)}})})},_compactingEnvs:{},async compactEnv(t){if(!this._compactingEnvs[t]){this._compactingEnvs={...this._compactingEnvs,[t]:!0};try{const o=await fetch(`${__ENV__.API}/env/${encodeURIComponent(t)}/compact`,{method:"POST"}),s=await o.json();if(!o.ok)throw new Error(s?.error?.message||"Compact failed");const n=s.data??{},a=n.saved>0?`✓ Compacted "${t}": ${this.formatBytes(n.sizeBefore)} → ${this.formatBytes(n.sizeAfter)} (saved ${this.formatBytes(n.saved)}, ${n.savedPct}%)`:`✓ Compacted "${t}" — no space reclaimed (${this.formatBytes(n.sizeAfter)})`;e.$ok.shared?.toast?.success?.(a),await this.load()}catch(t){e.$ok.shared?.toast?.error?.("Compact failed: "+(t?.message||t))}finally{const e={...this._compactingEnvs};delete e[t],this._compactingEnvs=e}}},async openRemoveEnv(t){await e.$ok.shared.modal.open({owner:e,title:"Remove Environment",content:'<remove-env-modal :modal="modal" :env-name="envName" :on-done="onDone" />',context:o=>({modal:o,envName:t,onDone:async(t,o)=>{await e.$ok.stores.okdb.reloadEnvs(),e.$ok.stores.okdb.selectedEnv===t&&e.$ok.stores.okdb.selectEnv(e.$ok.stores.okdb._pickBestEnv()),await this.load(),o?.filesLocked?.length?e.$ok.shared?.toast?.warn?.(`"${t}" removed — some files could not be deleted (locked)`):e.$ok.shared?.toast?.success?.(`Environment "${t}" removed and files deleted`)}})})},async dismissOrphan(t){try{const o=await fetch(`${__ENV__.API}/env/${encodeURIComponent(t)}`,{method:"DELETE"}),s=await o.json().catch(()=>({}));if(!o.ok)throw new Error(s?.error?.message||o.statusText);const n=s.data??s;await e.$ok.stores.okdb.reloadEnvs(),await this.load(),n?.filesLocked?.length?e.$ok.shared?.toast?.warn?.(`Orphan "${t}" dismissed — some files could not be deleted (locked)`):e.$ok.shared?.toast?.info?.(`Orphan "${t}" dismissed`)}catch(t){e.$ok.shared?.toast?.error?.("Dismiss failed: "+(t?.message||t))}},async openDataOps(t){await e.$ok.shared.modal.open({owner:e,title:"⬦ Data Operations",canDrag:!0,content:'<data-ops-modal :modal="modal" :envs="envs" :on-done="onDone" :initial-tab="initialTab" />',context:o=>({modal:o,envs:this.envs,initialTab:t||"export",onDone:async()=>{await this.load(),e.$ok.shared?.toast?.success?.("Operation complete")}})})},logView:"live"}),async mount(e){await this.load(),this._timer=setInterval(()=>{this.autoRefresh&&"overview"===this.subView&&this.load()},1e4);const t=()=>{fetch(`${__ENV__.API}/envs`).then(e=>e.json()).then(t=>{this.envs=t.data??[],e.$ok.stores.okdb.envs=this.envs}).catch(()=>{})},o=e.$ok.stores.events?.on?.("env:opened",t),s=e.$ok.stores.events?.on?.("env:removed",t);this._unsubEnv=()=>{o?.(),s?.()},await this.loadDocsManifest()},unmount(){clearInterval(this._timer),this._unsubEnv?.()}}</script><template><component import="../../layouts/_default.ok.html"><template name="header"></template><template name="sidebar"><if :="subView === 'docs'"><nav class="sys-subnav" style="margin-bottom:6px"><button class="sys-subnav__item" @click="goToSystemSub('overview')" style="opacity:.6;font-size:11px">← System</button></nav><nav class="docs-nav" aria-label="Documentation"><each :of="docsManifest" let:item="item"><if :="item.file"><button class="docs-nav__item docs-nav__item--standalone" :class="{'docs-nav__item--active': docsIsActive(item.file)}" @click="docsNavigateTo(item.file)">{{ item.label }}</button></if><if :="item.children"><div class="docs-nav__group"><span class="docs-nav__group-label">{{ item.label }}</span><each :of="item.children" let:child="child"><button class="docs-nav__item" :class="{'docs-nav__item--active': docsIsActive(child.file)}" @click="docsNavigateTo(child.file)">{{ child.label }}</button></each></div></if></each></nav></if><if :="subView !== 'docs'"><nav class="sys-subnav" aria-label="System navigation"><button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='overview'}" @click="goToSystemSub('overview')"><span class="sys-subnav__icon">⚙</span> Overview</button> <button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='logs'}" @click="goToSystemSub('logs')"><span class="sys-subnav__icon">📋</span> Logs</button> <button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='events'}" @click="goToSystemSub('events')"><span class="sys-subnav__icon">⚡</span> Events</button><div class="sys-subnav__divider"></div><button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='sync'}" @click="goToSystemSub('sync')"><span class="sys-subnav__icon">⇄</span> Sync</button> <button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='auth'}" @click="goToSystemSub('auth')"><span class="sys-subnav__icon">🔐</span> Auth</button> <button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='license'}" @click="goToSystemSub('license')"><span class="sys-subnav__icon">🔑</span> License</button><div class="sys-subnav__divider"></div><button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='api'}" @click="goToSystemSub('api')"><span class="sys-subnav__icon">⌁</span> API</button> <button class="sys-subnav__item" :class="{'sys-subnav__item--active': subView==='docs'}" @click="goToSystemSub('docs')"><span class="sys-subnav__icon">≡</span> Docs</button></nav></if></template><template name="default"><if :="subView === 'logs'"><div style="display:flex;flex-direction:column;gap:12px;height:100%;min-height:0"><div style="display:flex;align-items:center;gap:8px;flex-shrink:0"><div style="font-weight:600;font-size:15px;opacity:.8">Logs</div><div style="display:flex;gap:2px;padding:2px;background:var(--okdb-app-surface);border-radius:8px;border:1px solid var(--okdb-app-border)"><button @click="logView='live'" :style="logView==='live' ?'background:var(--okdb-app-surface-2);color:var(--okdb-accent);border-color:color-mix(in srgb, var(--okdb-accent) 27%, transparent);':'background:transparent;border-color:transparent;opacity:.7;'" style="padding:4px 14px;border-radius:6px;font-size:12px">Live</button> <button @click="logView='history'" :style="logView==='history' ?'background:var(--okdb-app-surface-2);color:var(--okdb-accent);border-color:color-mix(in srgb, var(--okdb-accent) 27%, transparent);':'background:transparent;border-color:transparent;opacity:.7;'" style="padding:4px 14px;border-radius:6px;font-size:12px">History</button></div></div><if :="logView === 'live'"><system-log :initial-source="'log'" style="flex:1;min-height:300px"/></if><if :="logView === 'history'"><system-log-history style="flex:1;min-height:300px"/></if></div></if><if :="subView === 'events'"><div style="display:flex;flex-direction:column;gap:12px;height:100%;min-height:0"><div style="font-weight:600;font-size:15px;opacity:.8;flex-shrink:0">Events</div><system-log :initial-source="'event'" style="flex:1;min-height:300px"/></div></if><if :="subView === 'sync'"><system-sync-panel style="height:100%;min-height:0"/></if><if :="subView === 'auth'"><system-auth-panel style="height:100%;min-height:0"/></if><if :="subView === 'api'"><system-api-panel style="height:100%;min-height:0"/></if><if :="subView === 'docs'"><div class="docs-wrap"><ok-doc-viewer :blocks="[]" root="/docs/" prefix="#/system/docs/" :file="docsCurrentFile" :anchor="docsAnchor" :manifest="docsManifest" sidebar-title="On this page" @anchor-change="docsOnAnchorChange($event.detail)"/></div></if><if :="subView === 'overview'"><div style="display:flex;flex-direction:column;gap:20px;max-width:900px"><div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap"><div style="font-weight:600;font-size:16px">Overview</div><button @click="load()" :disabled="loading" style="opacity:.8;font-size:12px">↻ Refresh</button> <label style="display:flex;align-items:center;gap:6px;font-size:12px;opacity:.7;cursor:pointer"><input type="checkbox" :checked="autoRefresh" @change="autoRefresh = $el.checked"/> Auto-refresh 10s</label><if :="loading"><span style="font-size:12px;opacity:.55">Loading…</span></if></div><if :="error"><div style="color:var(--okdb-danger);font-size:13px;padding:10px;border:1px solid var(--okdb-danger);border-radius:8px">{{error}}</div></if><div style="display:grid;grid-template-columns:1fr 1fr;gap:16px"><div class="card"><div class="card-title">Node Identity</div><div class="kv-grid"><div class="kv-key">Node ID</div><div class="kv-val" style="display:flex;align-items:center;gap:6px"><span style="font-family:monospace;font-size:12px;word-break:break-all">{{nodeId}}</span> <button @click="copyId()" style="font-size:10px;padding:2px 6px;opacity:.7">copy</button></div><if :="nodeAddress"><div class="kv-key">Address</div><div class="kv-val" style="font-family:monospace;font-size:12px">{{nodeAddress}}</div></if><div class="kv-key">Clock</div><div class="kv-val" style="font-family:monospace">{{formatNum(clock)}}</div><div class="kv-key">DB State</div><div class="kv-val" style="color:var(--okdb-success)">open</div><div class="kv-key">OKDB</div><div class="kv-val" style="font-family:monospace">v{{info?.versions?.okdb ?? info?.version ?? '--'}}</div><div class="kv-key">lmdb-js</div><div class="kv-val" style="font-family:monospace">v{{info?.versions?.lmdb ?? '--'}}</div><div class="kv-key">LMDB</div><div class="kv-val" style="font-family:monospace;font-size:11px;opacity:.7">{{info?.versions?.lmdbNative ?? '--'}}</div></div></div><div class="card"><div class="card-title">Storage (all environments)</div><div class="kv-grid"><div class="kv-key">Total Size</div><div class="kv-val" style="font-size:20px;font-weight:600;color:var(--okdb-accent)">{{approxSize}}</div><div class="kv-key">Environments</div><div class="kv-val">{{(envs || []).length}}</div><div class="kv-key">User Types</div><div class="kv-val">{{totalTypeCount}}</div><div class="kv-key">Page Size</div><div class="kv-val">{{formatNum(info?.pageSize)}} B</div><div class="kv-key">Map Size</div><div class="kv-val">{{info?.config?.lmdbOptions?.mapSize ? (info.config.lmdbOptions.mapSize/1024/1024/1024).toFixed(2)+' GB' : '--'}} <span style="opacity:.4;font-size:11px">(per env)</span></div></div></div></div><if :="envs && envs.length > 0"><div class="card"><div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap"><div style="font-weight:600;font-size:14px;flex:1">Environments ({{userEnvs.length}}<if :="systemEnvs.length > 0"><span style="opacity:.4;font-size:12px;font-weight:400">+ {{systemEnvs.length}} system</span></if>)</div><span style="font-size:12px;opacity:.5">{{formatBytes(totalEnvSize)}}</span><if :="systemEnvs.length > 0"><button @click="showSystemEnvs = !showSystemEnvs" style="font-size:11px;padding:3px 8px;opacity:.6">{{showSystemEnvs ? '▴ hide system' : '⚙ show system'}}</button></if><button @click="openCreateEnv()" style="font-size:11px;padding:4px 10px;opacity:.8">+ Create</button> <button @click="openDemoModal()" style="font-size:11px;padding:4px 12px;background:linear-gradient(135deg,color-mix(in srgb,var(--okdb-accent) 7%,transparent),color-mix(in srgb,var(--okdb-purple) 7%,transparent));border:1px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);color:var(--okdb-accent);border-radius:6px;font-weight:600" title="Generate a demo environment">✦ Demo</button></div><table class="sys-table"><thead><tr><th>Name</th><th style="text-align:right">Size</th><th style="text-align:right">Clock</th><th style="text-align:right">Types</th><th style="text-align:center">Sync</th><th></th></tr></thead><tbody><tr as="repeat" :of="visibleEnvs" let:item="e" class="sys-table-row"><td style="font-family:monospace;font-size:12px"><a @click.prevent="goToEnv(e.name)" href="#" style="color:var(--okdb-accent);text-decoration:none" :title="'Explore '+e.name">{{e.name}}</a><if :="e.parentEnv"><span style="font-size:10px;opacity:.4;font-family:monospace;margin-left:4px">↳ {{e.parentEnv}}</span></if></td><td style="text-align:right;font-size:12px;font-family:monospace;opacity:.8">{{formatBytes(e.size)}}</td><td style="text-align:right;font-family:monospace;font-size:12px;opacity:.7">{{e.sync ? formatNum(e.clock) : '—'}}</td><td style="text-align:right;font-size:12px;opacity:.7">{{e.types ? e.types.length : 0}}</td><td style="text-align:center"><span :style="e.sync?'color:var(--okdb-success);font-size:11px;':'opacity:.4;font-size:11px;'">{{e.sync?'✓':'✗'}}</span></td><td style="text-align:right;white-space:nowrap"><button @click="compactEnv(e.name)" :disabled="_compactingEnvs[e.name]" :style="_compactingEnvs[e.name]?'font-size:10px;padding:2px 8px;opacity:.35;cursor:not-allowed;':'font-size:10px;padding:2px 8px;opacity:.55;'">{{_compactingEnvs[e.name]?'⏳ compacting…':'⬡ compact'}}</button><if :="e.name !== '~system'"><button @click="openRemoveEnv(e.name)" style="font-size:10px;padding:2px 8px;opacity:.45;color:var(--okdb-danger);border-color:color-mix(in srgb,var(--okdb-danger) 20%,transparent);margin-left:4px">🗑 remove</button></if></td></tr></tbody></table><if :="orphanedEnvs.length > 0"><div style="margin-top:16px;border-top:1px solid var(--okdb-app-border);padding-top:14px"><div style="font-size:12px;font-weight:600;opacity:.6;margin-bottom:8px;display:flex;align-items:center;gap:6px"><span style="color:var(--okdb-orange)">⚠</span> Orphaned sub-environments ({{orphanedEnvs.length}}) <span style="font-size:11px;font-weight:400;opacity:.55;margin-left:2px">— parent was removed; data on disk is intact</span></div><table class="sys-table"><tbody><tr as="repeat" :of="orphanedEnvs" let:item="e" class="sys-table-row"><td style="font-family:monospace;font-size:12px;opacity:.5;text-decoration:line-through">{{e.name}}</td><td style="font-size:11px;opacity:.4;font-style:italic">orphaned from <span style="font-family:monospace">{{e.orphanedFrom ?? '—'}}</span></td><td style="text-align:right;white-space:nowrap"><button @click="dismissOrphan(e.name)" style="font-size:10px;padding:2px 8px;opacity:.5;color:var(--okdb-danger);border-color:color-mix(in srgb,var(--okdb-danger) 20%,transparent)">✕ dismiss</button></td></tr></tbody></table></div></if></div></if><div class="card" style="border:1px solid color-mix(in srgb,var(--okdb-accent) 9%,transparent);background:linear-gradient(135deg,var(--okdb-app-bg-deep),var(--okdb-app-surface))"><div style="display:flex;align-items:center;gap:14px;flex-wrap:wrap"><div style="flex:1;min-width:200px"><div style="font-weight:600;font-size:14px;margin-bottom:4px;display:flex;align-items:center;gap:8px"><span style="color:var(--okdb-accent);opacity:.7">⬦</span> Data Operations</div><div style="font-size:12px;opacity:.45;line-height:1.5">Export &amp; import logical NDJSON snapshots · hot filesystem backup</div></div><div style="display:flex;gap:8px;flex-shrink:0;flex-wrap:wrap;align-items:center"><button @click="openDataOps('export')" style="display:flex;align-items:center;gap:6px;padding:7px 15px;border-radius:8px;font-size:12px;font-weight:600;background:linear-gradient(135deg,var(--okdb-app-bg-deep),var(--okdb-app-bg-deep));border:1px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);color:var(--okdb-accent);cursor:pointer;white-space:nowrap">⬇ Export</button> <button @click="openDataOps('import')" style="display:flex;align-items:center;gap:6px;padding:7px 15px;border-radius:8px;font-size:12px;font-weight:600;background:linear-gradient(135deg,var(--okdb-app-bg-deep),var(--okdb-app-bg-deep));border:1px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);color:var(--okdb-accent);cursor:pointer;white-space:nowrap">⬆ Import</button><div style="width:1px;height:24px;background:var(--okdb-app-border);margin:0 2px;flex-shrink:0"></div><button @click="openDataOps('backup')" style="display:flex;align-items:center;gap:6px;padding:7px 15px;border-radius:8px;font-size:12px;font-weight:600;background:linear-gradient(135deg,var(--okdb-app-bg-deep),var(--okdb-app-bg-deep));border:1px solid color-mix(in srgb,var(--okdb-purple) 27%,transparent);color:var(--okdb-purple);cursor:pointer;white-space:nowrap">🗄 Backup</button></div></div></div><div style="display:grid;grid-template-columns:1fr 1fr;gap:16px"><div class="card"><div class="card-title">Configuration</div><div class="kv-grid"><div class="kv-key">Durability</div><div class="kv-val" style="display:flex;align-items:center;gap:6px"><span :style="'font-size:11px;font-weight:600;padding:2px 8px;border-radius:999px;border:1px solid;color:'+durabilityLabel.color+';border-color:'+durabilityLabel.color+'44;background:'+durabilityLabel.color+'11;'">{{durabilityLabel.label}}</span> <span style="opacity:.5;font-size:11px;flex:1">{{durabilityLabel.hint}}</span></div><div class="kv-key">Compression</div><div class="kv-val"><span :style="config?.lmdbOptions?.compression?'color:var(--okdb-success)':'opacity:.5'">{{config?.lmdbOptions?.compression?'LZ4 enabled':'disabled'}}</span></div><div class="kv-key">Encryption</div><div class="kv-val"><span :style="config?.lmdbOptions?.encryptionKey?'color:var(--okdb-success)':'opacity:.5'">{{config?.lmdbOptions?.encryptionKey?'Chacha8 enabled':'none'}}</span></div><div class="kv-key">Map Size</div><div class="kv-val">{{formatBytes(config?.lmdbOptions?.mapSize)}}</div><div class="kv-key">Max DBs</div><div class="kv-val">{{formatNum(config?.lmdbOptions?.maxDbs)}}</div></div><if :="configWarnings.length > 0"><div style="margin-top:10px;display:flex;flex-direction:column;gap:4px"><for :="configWarnings" let:w><div style="font-size:11px;color:var(--okdb-warning);background:color-mix(in srgb,var(--okdb-warning) 7%,transparent);border:1px solid color-mix(in srgb,var(--okdb-warning) 20%,transparent);border-radius:6px;padding:5px 8px;line-height:1.4">⚠ {{w}}</div></for></div></if></div><div class="card"><div class="card-title">Process</div><if :="!runtime"><div style="opacity:.4;font-size:12px">Loading…</div></if><if :="runtime"><div class="kv-grid"><div class="kv-key">PID</div><div class="kv-val" style="font-family:monospace">{{runtime.process?.pid}}</div><div class="kv-key">Uptime</div><div class="kv-val">{{formatUptime(runtime.process?.uptime)}}</div><div class="kv-key">Node.js</div><div class="kv-val" style="font-family:monospace">v{{runtime.process?.node}}</div><div class="kv-key" style="align-self:center">CPU</div><div class="kv-val" style="display:flex;align-items:center;gap:6px"><div style="flex:1;height:6px;background:var(--okdb-app-border);border-radius:3px;overflow:hidden"><div :style="'height:100%;border-radius:3px;transition:width .4s;background:'+(runtime.process?.cpu?.pct>80?'var(--okdb-danger)':runtime.process?.cpu?.pct>40?'var(--okdb-warning)':'var(--okdb-success)')+';width:'+(runtime.process?.cpu?.pct??0)+'%;'"></div></div><span style="font-size:11px;opacity:.6;min-width:30px">{{runtime.process?.cpu?.pct??0}}%</span></div><div class="kv-key">RSS</div><div class="kv-val">{{formatBytes(runtime.process?.memory?.rss)}}</div><div class="kv-key">Heap Used</div><div class="kv-val">{{formatBytes(runtime.process?.memory?.heapUsed)}} <span style="opacity:.45;font-size:11px">/ {{formatBytes(runtime.process?.memory?.heapTotal)}}</span></div><div class="kv-key" style="align-self:center">Heap %</div><div class="kv-val" style="display:flex;align-items:center;gap:6px"><div style="flex:1;height:6px;background:var(--okdb-app-border);border-radius:3px;overflow:hidden"><div :style="'height:100%;background:var(--okdb-accent);border-radius:3px;width:'+pct(runtime.process?.memory?.heapUsed,runtime.process?.memory?.heapTotal)+'%;'"></div></div><span style="font-size:11px;opacity:.6;min-width:30px">{{pct(runtime.process?.memory?.heapUsed,runtime.process?.memory?.heapTotal)}}%</span></div><div class="kv-key">External</div><div class="kv-val">{{formatBytes(runtime.process?.memory?.external)}}</div></div></if></div></div><div class="card"><div class="card-title">Machine</div><if :="!runtime"><div style="opacity:.4;font-size:12px">Loading…</div></if><if :="runtime"><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px"><div><div style="font-size:11px;opacity:.5;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px">Memory</div><div style="font-size:22px;font-weight:600;color:var(--okdb-accent)">{{formatBytes(runtime.os?.freeMemory)}}</div><div style="font-size:11px;opacity:.5;margin-top:2px">free of {{formatBytes(runtime.os?.totalMemory)}}</div><div style="margin-top:8px;height:6px;background:var(--okdb-app-border);border-radius:3px;overflow:hidden"><div :style="'height:100%;background:var(--okdb-accent);border-radius:3px;width:'+pct(runtime.os?.totalMemory-runtime.os?.freeMemory,runtime.os?.totalMemory)+'%;'"></div></div><div style="font-size:11px;opacity:.45;margin-top:3px">{{pct(runtime.os?.totalMemory-runtime.os?.freeMemory,runtime.os?.totalMemory)}}% used</div></div><div><div style="font-size:11px;opacity:.5;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px">CPU</div><div style="font-size:14px;font-weight:600">{{runtime.os?.cpuCount}} core{{runtime.os?.cpuCount!==1?'s':''}}</div><div style="font-size:11px;opacity:.5;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis" :title="runtime.os?.cpuModel">{{runtime.os?.cpuModel}}</div><div style="margin-top:8px;font-size:11px;opacity:.6">Load avg (1m/5m/15m)</div><div style="font-size:13px;font-family:monospace;margin-top:2px">{{formatLoad(runtime.os?.loadAvg)}}</div></div><div><div style="font-size:11px;opacity:.5;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px">Platform</div><div style="font-size:14px;font-weight:600;text-transform:capitalize">{{runtime.os?.platform}}</div><div style="font-size:11px;opacity:.5;margin-top:3px">{{runtime.os?.arch}}</div><div style="font-size:11px;opacity:.35;margin-top:6px;word-break:break-all">{{runtime.os?.release}}</div><div style="font-size:11px;opacity:.4;margin-top:3px;font-family:monospace">{{runtime.os?.hostname}}</div></div></div></if></div><if :="metrics"><div class="card"><div class="card-title">API Metrics</div><div style="display:grid;grid-template-columns:1fr 1fr;gap:16px"><div><div style="font-size:11px;opacity:.5;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px">Lifetime</div><div class="kv-grid"><div class="kv-key">Requests</div><div class="kv-val" style="color:var(--okdb-accent);font-weight:600">{{formatNum(metrics.lifetime?.requests)}}</div><div class="kv-key">Reads</div><div class="kv-val">{{formatNum(metrics.lifetime?.reads)}}</div><div class="kv-key">Writes</div><div class="kv-val">{{formatNum(metrics.lifetime?.writes)}}</div><div class="kv-key">Errors</div><div class="kv-val" :style="metrics.lifetime?.errors>0?'color:var(--okdb-danger);':'opacity:.5;'">{{formatNum(metrics.lifetime?.errors)}}</div><div class="kv-key">Avg Read</div><div class="kv-val" style="font-family:monospace">{{metrics.lifetime?.avgReadMs!=null?metrics.lifetime.avgReadMs+'ms':'—'}}</div><div class="kv-key">Avg Write</div><div class="kv-val" style="font-family:monospace">{{metrics.lifetime?.avgWriteMs!=null?metrics.lifetime.avgWriteMs+'ms':'—'}}</div></div></div><div><div style="font-size:11px;opacity:.5;text-transform:uppercase;letter-spacing:.05em;margin-bottom:8px">Last 60 seconds</div><div class="kv-grid"><div class="kv-key">Req/s</div><div class="kv-val" style="color:var(--okdb-success);font-weight:600">{{metrics.window?.reqPerSec}}</div><div class="kv-key">Read/s</div><div class="kv-val">{{metrics.window?.readPerSec}}</div><div class="kv-key">Write/s</div><div class="kv-val">{{metrics.window?.writePerSec}}</div><div class="kv-key">Requests</div><div class="kv-val">{{formatNum(metrics.window?.requests)}}</div><div class="kv-key">Avg Read</div><div class="kv-val" style="font-family:monospace">{{metrics.window?.avgReadMs!=null?metrics.window.avgReadMs+'ms':'—'}}</div><div class="kv-key">Avg Write</div><div class="kv-val" style="font-family:monospace">{{metrics.window?.avgWriteMs!=null?metrics.window.avgWriteMs+'ms':'—'}}</div></div></div></div></div></if><if :="plugins.length > 0"><div class="card"><div class="card-title">Plugins ({{plugins.length}})</div><div style="display:flex;flex-wrap:wrap;gap:8px"><for :="plugins" let:p><span style="padding:4px 12px;border-radius:999px;font-size:12px;border:1px solid color-mix(in srgb,var(--okdb-accent) 33%,transparent);color:var(--okdb-accent);background:color-mix(in srgb,var(--okdb-accent) 7%,transparent)">{{p}}</span></for></div></div></if><if :="typeList.length > 0"><div class="card"><div class="card-title">Types ({{typeList.length}} across all environments)</div><table class="sys-table"><thead><tr><th>Type</th><th>Environment</th><th style="text-align:right">Records</th></tr></thead><tbody><tr as="repeat" :of="typeList" let:item="entry"><td style="font-family:monospace;font-size:12px">{{entry.name}}</td><td style="font-family:monospace;font-size:11px;opacity:.55">{{entry.env}}</td><td style="text-align:right;color:var(--okdb-accent)">{{formatNum(entry.count)}}</td></tr></tbody></table></div></if><if :="systemTypeList.length > 0"><div class="card"><details><summary style="cursor:pointer;font-weight:600;font-size:13px;list-style:none;display:flex;align-items:center;gap:8px"><span>▶</span><span>Internal / System Types ({{systemTypeList.length}})</span></summary><table class="sys-table" style="margin-top:10px"><thead><tr><th>Type</th><th>Environment</th><th style="text-align:right">Records</th></tr></thead><tbody><tr as="repeat" :of="systemTypeList" let:item="entry"><td style="font-family:monospace;font-size:12px;opacity:.7">{{entry.name}}</td><td style="font-family:monospace;font-size:11px;opacity:.45">{{entry.env}}</td><td style="text-align:right;color:var(--okdb-accent);opacity:.7">{{formatNum(entry.count)}}</td></tr></tbody></table></details></div></if><div class="card"><div style="display:flex;align-items:center;gap:10px;cursor:pointer" @click="toggleChangelog()"><div style="font-weight:600;font-size:14px;flex:1">System Change Log</div><span style="font-size:12px;opacity:.5">all environments</span> <span style="opacity:.5;font-size:12px">{{changelogOpen ? '▲' : '▼'}}</span></div><if :="changelogOpen"><div style="margin-top:12px;display:flex;flex-direction:column;gap:8px"><if :="changelogError"><div style="color:var(--okdb-danger);font-size:12px">{{changelogError}}</div></if><div style="display:flex;gap:6px;align-items:center"><button @click="loadChangelog()" :disabled="changelogBusy" style="font-size:12px;opacity:.8">↻ Refresh</button> <span style="font-size:12px;opacity:.5;margin-left:auto">showing {{changes.length}} entries</span></div><div style="overflow:auto;max-height:400px"><table style="width:100%;border-collapse:collapse;font-size:12px"><thead style="position:sticky;top:0;background:var(--okdb-app-surface);z-index:1"><tr><th class="cl-th" style="width:80px">Env</th><th class="cl-th" style="width:110px">Action</th><th class="cl-th" style="width:80px">Type</th><th class="cl-th">Key</th><th class="cl-th" style="width:90px;text-align:right">When</th></tr></thead><tbody><tr as="repeat" :of="changes" let:item="ch" class="cl-row"><td class="cl-td" style="font-family:monospace;font-size:10px;opacity:.5;white-space:nowrap;max-width:80px;overflow:hidden;text-overflow:ellipsis" :title="ch._env">{{ch._env||'default'}}</td><td class="cl-td"><span :style="'font-size:10px;padding:2px 5px;border-radius:3px;border:1px solid;color:'+actionColor(ch.action)+';border-color:'+actionColor(ch.action)+'44;'">{{actionLabel(ch.action)}}</span></td><td class="cl-td" style="font-family:monospace;font-size:11px;opacity:.75;max-width:80px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" :title="ch.type">{{ch.type||'—'}}</td><td class="cl-td" style="font-family:monospace;font-size:11px;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" :title="ch.key">{{shortKey(ch.key)}}</td><td class="cl-td" style="text-align:right;opacity:.55;white-space:nowrap;font-size:11px">{{relTime(ch.timestamp)}}</td></tr></tbody></table></div><if :="changelogHasOlder"><button @click="loadMoreChangelog()" :disabled="changelogBusy" style="font-size:12px;align-self:flex-end">Load more ▼ ({{changelogLimit+100}})</button></if></div></if></div></div></if><if :="subView === 'license'"><license-panel/></if></template></component></template><style>.sys-subnav{display:flex;flex-direction:column;gap:2px}.sys-subnav__item{display:flex;align-items:center;gap:6px;width:100%;text-align:left;padding:6px 10px;border-radius:7px;background:0 0;border-color:transparent;color:var(--okdb-app-fg-muted);font-size:12px;cursor:pointer;transition:color .13s,background .13s,border-color .13s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.sys-subnav__item:hover{background:var(--okdb-app-surface-2);border-color:var(--okdb-app-border);color:var(--okdb-app-fg)}.sys-subnav__item--active{background:var(--okdb-app-bg-deep)!important;border-color:color-mix(in srgb,var(--okdb-accent) 27%,transparent)!important;color:var(--okdb-accent)!important}.sys-subnav__icon{font-size:12px;opacity:.7;flex-shrink:0}.sys-subnav__item--active .sys-subnav__icon{opacity:1}.sys-subnav__divider{height:1px;background:var(--okdb-app-surface);margin:3px 2px}.docs-nav{display:flex;flex-direction:column;gap:1px;margin:0 -10px;padding:2px 0}.docs-nav__item{display:block;width:100%;text-align:left;padding:5px 14px;border-radius:0;border:none;border-left:2px solid transparent;background:0 0;color:var(--okdb-app-fg-muted);font-size:12.5px;cursor:pointer;transition:color .13s,background .13s,border-color .13s;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.55;letter-spacing:.01em}.docs-nav__item--standalone{font-weight:500;color:var(--okdb-app-fg);margin-top:2px}.docs-nav__item:hover{background:var(--okdb-app-surface-2);color:var(--okdb-app-fg);border-left-color:var(--okdb-app-border-strong)}.docs-nav__item--active{background:var(--okdb-accent-soft-bg)!important;color:var(--okdb-accent)!important;border-left-color:var(--okdb-accent)!important;font-weight:500}.docs-nav__group{margin-top:6px;padding-top:4px;border-top:1px solid var(--okdb-app-surface)}.docs-nav__group-label{display:block;font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--okdb-app-fg-faint);padding:4px 14px 5px;pointer-events:none;user-select:none}.docs-wrap{margin:-20px -24px -6px;min-height:calc(100% + 26px)}.docs-wrap ok-doc-viewer{--ok_color-accent:var(--okdb-accent);--ok_color-fg:var(--okdb-app-fg);--ok_color-muted-fg:var(--okdb-app-fg-muted);--ok_color-muted-border:var(--okdb-app-border);--font-mono:'Cascadia Code','Fira Code','Consolas',monospace;display:block;min-height:100%}.docs-wrap ok-doc-viewer .md table{border-collapse:collapse;width:100%;margin:1.2rem 0;font-size:13px}.docs-wrap ok-doc-viewer .md td,.docs-wrap ok-doc-viewer .md th{border:1px solid var(--okdb-app-border);padding:7px 12px;text-align:left}.docs-wrap ok-doc-viewer .md th{background:var(--okdb-app-surface-2);color:#8fc8e8;font-weight:600;font-size:12px;letter-spacing:.03em}.docs-wrap ok-doc-viewer .md tr:hover td{background:var(--okdb-app-surface)}.docs-wrap ok-doc-viewer .md a{color:var(--okdb-accent);text-decoration:none;border-bottom:1px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);transition:border-color .15s,color .15s}.docs-wrap ok-doc-viewer .md a:hover{color:#7fd8ff;border-bottom-color:#7fd8ff88}.docs-wrap ok-doc-viewer .md code:not(pre code){background:var(--okdb-app-bg-deep);border:1px solid var(--okdb-app-border);color:var(--okdb-accent);padding:1px 6px;border-radius:4px;font-size:.9em}.docs-wrap ok-doc-viewer .md blockquote{border-left:3px solid color-mix(in srgb,var(--okdb-accent) 27%,transparent);margin:1rem 0;padding:6px 14px;background:var(--okdb-app-surface);border-radius:0 6px 6px 0;color:var(--okdb-app-fg-muted);font-style:italic}.card{background:var(--okdb-app-surface);border-radius:12px;padding:16px;box-shadow:0 0 5px #ffffff1a}.card-title{font-weight:600;margin-bottom:12px;font-size:14px}.kv-grid{display:grid;grid-template-columns:110px 1fr;gap:6px 12px;font-size:13px}.kv-key{opacity:.6}.kv-val{word-break:break-all}.sys-table{width:100%;border-collapse:collapse;font-size:13px}.sys-table th{text-align:left;padding:6px 8px;border-bottom:1px solid var(--okdb-app-border);opacity:.6;font-weight:500;font-size:11px;text-transform:uppercase;letter-spacing:.04em}.sys-table td{padding:5px 8px;border-bottom:1px solid var(--okdb-app-border)}.sys-table tr:last-child td{border-bottom:none}.sys-table tr:hover td{background:#ffffff08}.cl-th{padding:5px 8px;text-align:left;font-weight:500;font-size:10px;text-transform:uppercase;letter-spacing:.04em;opacity:.5;border-bottom:1px solid var(--okdb-app-border)}.cl-td{padding:5px 8px;border-bottom:1px solid var(--okdb-app-border)}.cl-row:hover .cl-td{background:#ffffff06}</style>
@@ -0,0 +1 @@
1
+ const _0x19ed73=_0x532a;function _0x4d71(){const _0xd1d8e5=['changes','slice','backupDlError','canBackup','importDropExisting','true','file','target','exportBusy','status','parse','exportError','exportSelEnvs','input','body','1959841JsVBwu','trim','5398390sxnPrB','catch','importFile','data-ops-modal','exportDone','onDone','API','importError','backupCompact','json','importIncludeChanges','change','exportCanRun','backupDlBusy','exportSingleEnvTypes','importSelTypes','exportInit','match','36ekeImC','text','10WtsBNv','386001SdMMIr','9004lNjODX','removeChild','backupEnvNames','createObjectURL','files','importFileTypes','types','includeChanges','download','importDragOver','exportIncludeChanges','env','name','export','envs','now','map','toFixed','blob','userEnvs','onchange','backupSelEnvs','384ZCbnkn','startsWith','88jeMNgD','split','keys','backupError','exportIsSingleEnv','schema','all','backupBusy','close','.ndjson','.ndjson,.jsonl,.json,.txt','./okdb-backup-','filter','headers','get','accept','modal','records','application/json','importDone','stringify','data','13760lUCbQG','11IRYMie','click','appendChild','length','POST','content-disposition','message','join','type','okdb-backup-','application/x-ndjson','/system/import?','HTTP\x20','envName','exportSelectedTypeNames','backupResult','getDate','backupDlDone','set','_setImportFile','size','getMonth','importEnvOverride','error','\x0a<div\x20style=\x22min-width:520px;\x20max-width:640px;\x20display:flex;\x20flex-direction:column;\x20gap:0;\x22>\x0a\x0a\x20\x20<!--\x20Tab\x20bar\x20-->\x0a\x20\x20<div\x20style=\x22display:flex;\x20gap:2px;\x20padding:3px;\x20background:var(--okdb-app-bg-deep);\x20border-radius:9px;\x20margin-bottom:22px;\x20border:1px\x20solid\x20var(--okdb-app-border);\x22>\x0a\x20\x20\x20\x20<button\x20@click=\x22tab=\x27export\x27\x22\x0a\x20\x20\x20\x20\x20\x20:style=\x22tab===\x27export\x27\x20?\x20\x27flex:1;background:var(--okdb-app-surface-2);color:var(--okdb-accent);border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);font-weight:600;\x27\x20:\x20\x27flex:1;background:transparent;border-color:transparent;opacity:.5;\x27\x22\x0a\x20\x20\x20\x20\x20\x20style=\x22padding:7px\x200;border-radius:7px;font-size:13px;transition:all\x20.15s;cursor:pointer;\x22>\x0a\x20\x20\x20\x20\x20\x20⬇\x20Export\x0a\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20<button\x20@click=\x22tab=\x27import\x27\x22\x0a\x20\x20\x20\x20\x20\x20:style=\x22tab===\x27import\x27\x20?\x20\x27flex:1;background:var(--okdb-app-surface-2);color:var(--okdb-accent);border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2027%,\x20transparent);font-weight:600;\x27\x20:\x20\x27flex:1;background:transparent;border-color:transparent;opacity:.5;\x27\x22\x0a\x20\x20\x20\x20\x20\x20style=\x22padding:7px\x200;border-radius:7px;font-size:13px;transition:all\x20.15s;cursor:pointer;\x22>\x0a\x20\x20\x20\x20\x20\x20⬆\x20Import\x0a\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20<button\x20@click=\x22tab=\x27backup\x27\x22\x0a\x20\x20\x20\x20\x20\x20:style=\x22tab===\x27backup\x27\x20?\x20\x27flex:1;background:var(--okdb-app-surface-2);color:var(--okdb-purple);border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2027%,\x20transparent);font-weight:600;\x27\x20:\x20\x27flex:1;background:transparent;border-color:transparent;opacity:.5;\x27\x22\x0a\x20\x20\x20\x20\x20\x20style=\x22padding:7px\x200;border-radius:7px;font-size:13px;transition:all\x20.15s;cursor:pointer;\x22>\x0a\x20\x20\x20\x20\x20\x20🗄\x20Backup\x0a\x20\x20\x20\x20</button>\x0a\x20\x20</div>\x0a\x0a\x20\x20<!--\x20═══\x20EXPORT\x20═══════════════════════════════════════════════════════════\x20-->\x0a\x20\x20<if\x20:=\x22tab\x20===\x20\x27export\x27\x22>\x0a\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:18px;\x22>\x0a\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:12px;opacity:.5;line-height:1.5;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20Streaming\x20NDJSON\x20export\x20—\x20portable\x20across\x20OKDB\x20versions,\x20importable\x20into\x20any\x20instance.\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Environments\x20-->\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:8px;margin-bottom:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22\x20style=\x22flex:1;margin:0;\x22>Environments</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22exportToggleAllEnvs(true)\x22\x20\x20class=\x22dops-micro\x22>all</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22exportToggleAllEnvs(false)\x22\x20class=\x22dops-micro\x22>none</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-wrap:wrap;gap:6px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<for\x20:=\x22userEnvs\x22\x20let:e>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22exportSelEnvs[e.name]\x20?\x20\x27background:var(--okdb-app-surface-2);border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2033%,\x20transparent);color:#e2eaf4;\x27\x20:\x20\x27background:var(--okdb-app-surface);border-color:var(--okdb-app-border);opacity:.55;\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22display:flex;align-items:center;gap:5px;padding:5px\x2011px;border-radius:999px;font-size:12px;cursor:pointer;border:1px\x20solid;transition:all\x20.12s;user-select:none;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22!!exportSelEnvs[e.name]\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@change=\x22exportSelEnvs\x20=\x20{...exportSelEnvs,\x20[e.name]:\x20$el.checked}\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22display:none;\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20:style=\x22exportSelEnvs[e.name]\x20?\x20\x27color:var(--okdb-accent);font-size:10px;\x27\x20:\x20\x27display:none;\x27\x22>✓</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{{e.name}}\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.4;font-size:10px;\x22>{{e.types\x20?\x20e.types.filter(t=>!t.name.startsWith(\x27~\x27)).length\x20:\x200}}\x20types</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</for>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Types\x20(only\x20for\x20single\x20env)\x20-->\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22exportIsSingleEnv\x20&&\x20exportSingleEnvTypes.length\x20>\x200\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:8px;margin-bottom:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22\x20style=\x22flex:1;margin:0;\x22>Types</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22\x20style=\x22font-size:11px;gap:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22exportAllTypes\x22\x20@change=\x22exportAllTypes\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.6;\x22>All\x20types</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!exportAllTypes\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:0;background:var(--okdb-app-bg-deep);border:1px\x20solid\x20var(--okdb-app-border);border-radius:8px;overflow:hidden;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;padding:5px\x2010px;border-bottom:1px\x20solid\x20var(--okdb-app-border);gap:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22exportToggleAllTypes(true)\x22\x20\x20class=\x22dops-micro\x22>all</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22exportToggleAllTypes(false)\x22\x20class=\x22dops-micro\x22>none</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;max-height:140px;overflow-y:auto;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<for\x20:=\x22exportSingleEnvTypes\x22\x20let:t>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20style=\x22display:flex;align-items:center;gap:8px;padding:6px\x2010px;cursor:pointer;transition:background\x20.1s;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22exportSelTypes[t]\x20?\x20\x27background:#1a2a1a;\x27\x20:\x20\x27\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@mouseenter=\x22$el.style.background=exportSelTypes[t]?\x27#1a2a1a\x27:\x27var(--okdb-app-surface)\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@mouseleave=\x22$el.style.background=exportSelTypes[t]?\x27#1a2a1a\x27:\x27\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22!!exportSelTypes[t]\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@change=\x22exportSelTypes\x20=\x20{...exportSelTypes,\x20[t]:\x20$el.checked}\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-family:monospace;font-size:12px;\x22>{{t}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</for>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22!exportIsSingleEnv\x20&&\x20exportSelectedEnvNames.length\x20>\x201\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:11px;opacity:.4;font-style:italic;\x22>All\x20types\x20will\x20be\x20exported\x20from\x20each\x20selected\x20environment.</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Options\x20-->\x0a\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22exportIncludeChanges\x22\x20@change=\x22exportIncludeChanges\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span>Include\x20changelog\x20<span\x20style=\x22opacity:.4;font-size:11px;\x22>(sync\x20history)</span></span>\x0a\x20\x20\x20\x20\x20\x20</label>\x0a\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22exportError\x22><div\x20class=\x22dops-error\x22>{{exportError}}</div></if>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Success\x20-->\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22exportDone\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-success\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:8px;margin-bottom:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>✓</span><span\x20style=\x22font-weight:600;\x22>Downloaded</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.4;font-size:11px;margin-left:auto;\x22>{{formatBytes(exportDone.bytes)}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:grid;grid-template-columns:repeat(3,1fr);gap:6px;font-size:12px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22exportDone.envCount\x20>\x201\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-stat\x22><div\x20class=\x22dops-stat-n\x22>{{exportDone.envCount}}</div><div>envs</div></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-stat\x22><div\x20class=\x22dops-stat-n\x22>{{exportDone.types}}</div><div>types</div></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-stat\x22><div\x20class=\x22dops-stat-n\x22>{{exportDone.records}}</div><div>records</div></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-stat\x22><div\x20class=\x22dops-stat-n\x22>{{exportDone.changes}}</div><div>changes</div></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:10px;opacity:.35;margin-top:6px;font-family:monospace;word-break:break-all;\x22>{{exportDone.filename}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:8px;justify-content:flex-end;margin-top:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22close()\x22\x20class=\x22dops-btn-ghost\x22>Cancel</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22runExport()\x22\x20:disabled=\x22!exportCanRun\x22\x20class=\x22dops-btn-primary\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22exportBusy\x22><span\x20class=\x22dops-spinner\x22></span>\x20Exporting…</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!exportBusy\x22>⬇\x20Download\x20NDJSON</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</if>\x0a\x0a\x20\x20<!--\x20═══\x20IMPORT\x20═══════════════════════════════════════════════════════════\x20-->\x0a\x20\x20<if\x20:=\x22tab\x20===\x20\x27import\x27\x22>\x0a\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:18px;\x22>\x0a\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:12px;opacity:.5;line-height:1.5;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20Upload\x20a\x20OKDB\x20NDJSON\x20export.\x20Types,\x20indexes,\x20and\x20records\x20are\x20restored\x20automatically.\x0a\x20\x20\x20\x20\x20\x20\x20\x20Multi-env\x20files\x20restore\x20each\x20environment\x20separately.\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Drop\x20zone\x20-->\x0a\x20\x20\x20\x20\x20\x20<div\x20@click=\x22pickFile()\x22\x20@drop=\x22onDrop($event)\x22\x20@dragover=\x22onDragOver($event)\x22\x20@dragleave=\x22onDragLeave()\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22importDragOver\x20?\x20\x27border-color:var(--okdb-accent);background:color-mix(in\x20srgb,\x20var(--okdb-accent)\x205%,\x20transparent);\x27\x20:\x20importFile\x20?\x20\x27border-color:color-mix(in\x20srgb,\x20var(--okdb-success)\x2033%,\x20transparent);background:#0a1a10;\x27\x20:\x20\x27border-color:var(--okdb-app-border);background:var(--okdb-app-bg-deep);\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20style=\x22border:2px\x20dashed;border-radius:10px;padding:24px\x2016px;text-align:center;cursor:pointer;transition:all\x20.15s;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!importFile\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:22px;opacity:.4;margin-bottom:8px;\x22>📂</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:13px;opacity:.7;\x22>Drop\x20.ndjson\x20file\x20here\x20or\x20<span\x20style=\x22color:var(--okdb-accent);\x22>click\x20to\x20browse</span></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:11px;opacity:.3;margin-top:4px;\x22>.ndjson\x20·\x20.jsonl\x20·\x20.json</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22importFile\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:20px;margin-bottom:6px;\x22>📄</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:13px;font-weight:600;color:var(--okdb-success);font-family:monospace;word-break:break-all;\x22>{{importFile.name}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:11px;opacity:.45;margin-top:3px;\x22>{{formatBytes(importFile.size)}}\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22importFileTypes.length\x22>\x20·\x20{{importFileTypes.length}}\x20type{{importFileTypes.length!==1?\x27s\x27:\x27\x27}}\x20detected</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20·\x20click\x20to\x20change</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Types\x20filter\x20(from\x20file)\x20-->\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22importFileTypes.length\x20>\x200\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:8px;margin-bottom:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22\x20style=\x22flex:1;margin:0;\x22>Types\x20to\x20import</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22\x20style=\x22font-size:11px;gap:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22importAllTypes\x22\x20@change=\x22importAllTypes\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.6;\x22>All</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!importAllTypes\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:0;background:var(--okdb-app-bg-deep);border:1px\x20solid\x20var(--okdb-app-border);border-radius:8px;overflow:hidden;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;padding:5px\x2010px;border-bottom:1px\x20solid\x20var(--okdb-app-border);gap:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22importToggleAllTypes(true)\x22\x20\x20class=\x22dops-micro\x22>all</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22importToggleAllTypes(false)\x22\x20class=\x22dops-micro\x22>none</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;max-height:130px;overflow-y:auto;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<for\x20:=\x22importFileTypes\x22\x20let:t>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20style=\x22display:flex;align-items:center;gap:8px;padding:6px\x2010px;cursor:pointer;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22importSelTypes[t]\x20?\x20\x27background:#1a2a1a;\x27\x20:\x20\x27\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22!!importSelTypes[t]\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@change=\x22importSelTypes\x20=\x20{...importSelTypes,\x20[t]:\x20$el.checked}\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-family:monospace;font-size:12px;\x22>{{t}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</for>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Target\x20env\x20override\x20-->\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22>Target\x20environment\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.35;font-size:11px;font-weight:400;\x22>(leave\x20empty\x20to\x20use\x20the\x20file\x27s\x20source\x20env)</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<select\x20:value=\x22importEnvOverride\x22\x20@change=\x22importEnvOverride\x20=\x20$el.value\x22\x20class=\x22dops-select\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20value=\x22\x22>—\x20from\x20file\x20header\x20—</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<for\x20:=\x22userEnvs\x22\x20let:e>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<option\x20:value=\x22e.name\x22>{{e.name}}</option>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</for>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</select>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Options\x20-->\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:7px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22importDropExisting\x22\x20@change=\x22importDropExisting\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>Drop\x20&amp;\x20recreate\x20existing\x20types\x20<span\x20style=\x22opacity:.4;font-size:11px;\x22>(replaces\x20current\x20data)</span></span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22importIncludeChanges\x22\x20@change=\x22importIncludeChanges\x20=\x20$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>Restore\x20changelog\x20rows</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Advanced\x20-->\x0a\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22importShowAdvanced=!importShowAdvanced\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22font-size:11px;opacity:.4;background:transparent;border:none;padding:0;cursor:pointer;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{{importShowAdvanced?\x27▴\x20hide\x27:\x27▾\x27}}\x20advanced\x0a\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22importShowAdvanced\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22\x20style=\x22margin-top:10px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22>Batch\x20size\x20<span\x20style=\x22opacity:.35;font-size:11px;\x22>(records\x20per\x20write-txn)</span></label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22number\x22\x20min=\x2210\x22\x20max=\x2210000\x22\x20step=\x2210\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:value=\x22importBatchSize\x22\x20@input=\x22importBatchSize=Number($el.value)||500\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22dops-input\x22\x20style=\x22max-width:120px;\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22importError\x22><div\x20class=\x22dops-error\x22>{{importError}}</div></if>\x0a\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22importDone\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-success\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:8px;margin-bottom:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>✓</span><span\x20style=\x22font-weight:600;\x22>Import\x20complete</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:grid;grid-template-columns:repeat(3,1fr);gap:6px;font-size:12px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-stat\x22><div\x20class=\x22dops-stat-n\x22>{{importDone.types}}</div><div>types</div></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-stat\x22><div\x20class=\x22dops-stat-n\x22>{{importDone.records}}</div><div>records</div></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-stat\x22><div\x20class=\x22dops-stat-n\x22>{{importDone.changes}}</div><div>changes</div></div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:8px;justify-content:flex-end;margin-top:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22close()\x22\x20class=\x22dops-btn-ghost\x22>Cancel</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22runImport()\x22\x20:disabled=\x22!canImport\x22\x20class=\x22dops-btn-primary\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22importBusy\x22><span\x20class=\x22dops-spinner\x22></span>\x20Importing…</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!importBusy\x22>⬆\x20Import\x20File</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</if>\x0a\x0a\x20\x20<!--\x20═══\x20BACKUP\x20════════════════════════════════════════════════════════════\x20-->\x0a\x20\x20<if\x20:=\x22tab\x20===\x20\x27backup\x27\x22>\x0a\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:0;\x22>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Mode\x20tabs\x20-->\x0a\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:0;margin-bottom:18px;border-bottom:1px\x20solid\x20var(--okdb-app-border);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22backupMode=\x27server\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22backupMode===\x27server\x27\x20?\x20\x27color:var(--okdb-purple);border-bottom:2px\x20solid\x20var(--okdb-purple);opacity:1;\x27\x20:\x20\x27border-bottom:2px\x20solid\x20transparent;opacity:.45;\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22padding:6px\x2016px;background:transparent;border:none;border-radius:0;font-size:13px;cursor:pointer;transition:all\x20.15s;margin-bottom:-1px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20🗄\x20Server\x20backup\x0a\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22backupMode=\x27download\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22backupMode===\x27download\x27\x20?\x20\x27color:var(--okdb-purple);border-bottom:2px\x20solid\x20var(--okdb-purple);opacity:1;\x27\x20:\x20\x27border-bottom:2px\x20solid\x20transparent;opacity:.45;\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22padding:6px\x2016px;background:transparent;border:none;border-radius:0;font-size:13px;cursor:pointer;transition:all\x20.15s;margin-bottom:-1px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20⬇\x20Download\x20to\x20PC\x0a\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Server\x20backup\x20mode\x20-->\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupMode\x20===\x20\x27server\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:16px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:12px;opacity:.5;line-height:1.5;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Hot\x20LMDB\x20page-copy\x20backup\x20—\x20atomic,\x20exact\x20snapshot,\x20no\x20serialisation.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Writes\x20to\x20a\x20directory\x20<em>on\x20the\x20server</em>.\x20The\x20output\x20can\x20be\x20used\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20directly\x20as\x20a\x20OKDB\x20data\x20path.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Dest\x20dir\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22>Destination\x20directory\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.35;font-size:11px;font-weight:400;\x22>(server-side\x20path)</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22text\x22\x20:value=\x22backupDestDir\x22\x20@input=\x22backupDestDir=$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22dops-input\x22\x20style=\x22font-family:monospace;\x22\x20spellcheck=\x22false\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Env\x20selection\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22\x20style=\x22margin-bottom:8px;\x22>Environments</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:12px;margin-bottom:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22radio\x22\x20name=\x22bkEnvMode\x22\x20value=\x22all\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22backupEnvMode===\x27all\x27\x22\x20@change=\x22backupEnvMode=\x27all\x27\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>All</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22radio\x22\x20name=\x22bkEnvMode\x22\x20value=\x22selected\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22backupEnvMode===\x27selected\x27\x22\x20@change=\x22backupEnvMode=\x27selected\x27\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>Select…</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupEnvMode===\x27selected\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-wrap:wrap;gap:6px;padding:10px;background:var(--okdb-app-bg-deep);border-radius:8px;border:1px\x20solid\x20var(--okdb-app-border);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<for\x20:=\x22userEnvs\x22\x20let:e>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22backupSelEnvs[e.name]\x20?\x20\x27background:var(--okdb-app-surface);border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2027%,\x20transparent);color:#e2d8f4;\x27\x20:\x20\x27background:var(--okdb-app-surface);border-color:var(--okdb-app-border);opacity:.55;\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22display:flex;align-items:center;gap:5px;padding:5px\x2011px;border-radius:999px;font-size:12px;cursor:pointer;border:1px\x20solid;transition:all\x20.12s;user-select:none;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22!!backupSelEnvs[e.name]\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@change=\x22backupSelEnvs={...backupSelEnvs,[e.name]:$el.checked}\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22display:none;\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20:style=\x22backupSelEnvs[e.name]?\x27color:var(--okdb-purple);font-size:10px;\x27:\x27display:none;\x27\x22>✓</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{{e.name}}\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</for>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x20:checked=\x22backupCompact\x22\x20@change=\x22backupCompact=$el.checked\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>Compact\x20while\x20copying\x20<span\x20style=\x22opacity:.4;font-size:11px;\x22>(smaller\x20files,\x20slightly\x20slower)</span></span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupError\x22><div\x20class=\x22dops-error\x22>{{backupError}}</div></if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupResult\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-success\x22\x20style=\x22border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2020%,\x20transparent);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:8px;margin-bottom:10px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>✓</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-weight:600;color:var(--okdb-app-fg);\x22>Server\x20backup\x20complete</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.4;font-size:11px;margin-left:auto;\x22>{{backupResult.durationMs}}ms</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<for\x20:=\x22backupResult.envs||[]\x22\x20let:e>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22background:#1a1228;border-radius:6px;padding:7px\x2010px;font-size:12px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:8px;align-items:center;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-family:monospace;font-weight:600;color:var(--okdb-purple);\x22>{{e.name}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.35;font-size:11px;\x22>{{formatBytes(e.sizeBefore)}}\x20→\x20{{formatBytes(e.sizeAfter)}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-family:monospace;font-size:10px;opacity:.4;margin-top:3px;word-break:break-all;\x22>{{e.dest}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</for>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:8px;justify-content:flex-end;margin-top:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22close()\x22\x20class=\x22dops-btn-ghost\x22>Cancel</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22runBackup()\x22\x20:disabled=\x22!canBackup\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22padding:8px\x2020px;border-radius:8px;font-size:13px;font-weight:600;background:linear-gradient(135deg,#1e1530,#150f22);border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-purple)\x2033%,\x20transparent);color:var(--okdb-purple);cursor:pointer;display:flex;align-items:center;gap:6px;transition:all\x20.15s;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupBusy\x22><span\x20class=\x22dops-spinner\x22\x20style=\x22border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2027%,\x20transparent);border-top-color:var(--okdb-purple);\x22></span>\x20Backing\x20up…</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!backupBusy\x22>🗄\x20Run\x20Server\x20Backup</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Download\x20backup\x20mode\x20-->\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupMode\x20===\x20\x27download\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:16px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:12px;opacity:.5;line-height:1.5;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Export\x20all\x20environments\x20as\x20a\x20single\x20portable\x20NDJSON\x20file\x20and\x20download\x20it\x20to\x20your\x20computer.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20This\x20file\x20can\x20be\x20imported\x20back\x20into\x20any\x20OKDB\x20instance.\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Env\x20selection\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-field\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-label\x22\x20style=\x22margin-bottom:8px;\x22>Environments\x20to\x20include</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:12px;margin-bottom:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22radio\x22\x20name=\x22dlEnvMode\x22\x20value=\x22all\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22backupEnvMode===\x27all\x27\x22\x20@change=\x22backupEnvMode=\x27all\x27\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>All\x20environments</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x20class=\x22dops-check\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22radio\x22\x20name=\x22dlEnvMode\x22\x20value=\x22selected\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22backupEnvMode===\x27selected\x27\x22\x20@change=\x22backupEnvMode=\x27selected\x27\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>Select…</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupEnvMode===\x27selected\x27\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-wrap:wrap;gap:6px;padding:10px;background:var(--okdb-app-bg-deep);border-radius:8px;border:1px\x20solid\x20var(--okdb-app-border);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<for\x20:=\x22userEnvs\x22\x20let:e>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<label\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:style=\x22backupSelEnvs[e.name]\x20?\x20\x27background:var(--okdb-app-surface);border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2027%,\x20transparent);\x27\x20:\x20\x27background:var(--okdb-app-surface);border-color:var(--okdb-app-border);opacity:.55;\x27\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22display:flex;align-items:center;gap:5px;padding:5px\x2011px;border-radius:999px;font-size:12px;cursor:pointer;border:1px\x20solid;transition:all\x20.12s;user-select:none;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x20type=\x22checkbox\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:checked=\x22!!backupSelEnvs[e.name]\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@change=\x22backupSelEnvs={...backupSelEnvs,[e.name]:$el.checked}\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22display:none;\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20:style=\x22backupSelEnvs[e.name]?\x27color:var(--okdb-purple);font-size:10px;\x27:\x27display:none;\x27\x22>✓</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{{e.name}}\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</label>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</for>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupDlError\x22><div\x20class=\x22dops-error\x22>{{backupDlError}}</div></if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupDlDone\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22dops-success\x22\x20style=\x22border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2020%,\x20transparent);\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:8px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span>✓</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-weight:600;color:var(--okdb-app-fg);\x22>Downloaded</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.4;font-size:11px;\x22>{{formatBytes(backupDlDone.bytes)}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-family:monospace;font-size:10px;opacity:.35;margin-top:5px;word-break:break-all;\x22>{{backupDlDone.filename}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:8px;justify-content:flex-end;margin-top:4px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22close()\x22\x20class=\x22dops-btn-ghost\x22>Cancel</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22runDownloadBackup()\x22\x20:disabled=\x22!canBackupDl\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22padding:8px\x2020px;border-radius:8px;font-size:13px;font-weight:600;background:linear-gradient(135deg,#1e1530,#150f22);border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-purple)\x2033%,\x20transparent);color:var(--okdb-purple);cursor:pointer;display:flex;align-items:center;gap:6px;transition:all\x20.15s;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22backupDlBusy\x22><span\x20class=\x22dops-spinner\x22\x20style=\x22border-color:color-mix(in\x20srgb,\x20var(--okdb-purple)\x2027%,\x20transparent);border-top-color:var(--okdb-purple);\x22></span>\x20Downloading…</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!backupDlBusy\x22>⬇\x20Download\x20Backup</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</if>\x0a\x0a</div>\x0a\x0a<style>\x0a\x20\x20.dops-field\x20{\x20display:flex;\x20flex-direction:column;\x20gap:5px;\x20}\x0a\x20\x20.dops-label\x20{\x20font-size:12px;\x20opacity:.6;\x20font-weight:500;\x20}\x0a\x20\x20.dops-input\x20{\x0a\x20\x20\x20\x20background:var(--okdb-app-bg-deep);\x20border:1px\x20solid\x20var(--okdb-app-border);\x20border-radius:6px;\x0a\x20\x20\x20\x20color:inherit;\x20padding:7px\x2010px;\x20font-size:13px;\x20width:100%;\x0a\x20\x20\x20\x20box-sizing:border-box;\x20transition:border-color\x20.15s;\x0a\x20\x20}\x0a\x20\x20.dops-input:focus\x20{\x20outline:none;\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2033%,\x20transparent);\x20}\x0a\x20\x20.dops-select\x20{\x0a\x20\x20\x20\x20background:var(--okdb-app-bg-deep);\x20border:1px\x20solid\x20var(--okdb-app-border);\x20border-radius:6px;\x0a\x20\x20\x20\x20color:inherit;\x20padding:7px\x2010px;\x20font-size:13px;\x20width:100%;\x20box-sizing:border-box;\x20cursor:pointer;\x0a\x20\x20}\x0a\x20\x20.dops-select:focus\x20{\x20outline:none;\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2033%,\x20transparent);\x20}\x0a\x20\x20.dops-check\x20{\x20display:flex;\x20align-items:center;\x20gap:8px;\x20font-size:13px;\x20cursor:pointer;\x20user-select:none;\x20}\x0a\x20\x20.dops-micro\x20{\x0a\x20\x20\x20\x20padding:2px\x208px;\x20border-radius:4px;\x20font-size:10px;\x20background:transparent;\x0a\x20\x20\x20\x20border:1px\x20solid\x20var(--okdb-app-border);\x20opacity:.5;\x20cursor:pointer;\x20transition:opacity\x20.1s;\x0a\x20\x20}\x0a\x20\x20.dops-micro:hover\x20{\x20opacity:.85;\x20}\x0a\x20\x20.dops-error\x20{\x0a\x20\x20\x20\x20background:#2a1010;\x20border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-danger)\x2027%,\x20transparent);\x20border-radius:8px;\x0a\x20\x20\x20\x20padding:10px\x2012px;\x20font-size:12px;\x20color:var(--okdb-danger);\x20line-height:1.5;\x0a\x20\x20}\x0a\x20\x20.dops-success\x20{\x0a\x20\x20\x20\x20background:#0d1a14;\x20border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-success)\x2020%,\x20transparent);\x20border-radius:8px;\x0a\x20\x20\x20\x20padding:12px\x2014px;\x20font-size:13px;\x20color:#d1fae5;\x0a\x20\x20}\x0a\x20\x20.dops-stat\x20{\x0a\x20\x20\x20\x20background:#071410;\x20border-radius:6px;\x20padding:8px;\x20text-align:center;\x20font-size:11px;\x20opacity:.8;\x0a\x20\x20}\x0a\x20\x20.dops-stat-n\x20{\x20font-size:18px;\x20font-weight:700;\x20color:var(--okdb-success);\x20}\x0a\x20\x20.dops-btn-primary\x20{\x0a\x20\x20\x20\x20padding:8px\x2020px;\x20border-radius:8px;\x20font-size:13px;\x20font-weight:600;\x0a\x20\x20\x20\x20background:linear-gradient(135deg,#1e4060,#1a3050);\x0a\x20\x20\x20\x20border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-accent)\x2033%,\x20transparent);\x20color:var(--okdb-accent);\x0a\x20\x20\x20\x20cursor:pointer;\x20display:flex;\x20align-items:center;\x20gap:6px;\x20transition:all\x20.15s;\x0a\x20\x20}\x0a\x20\x20.dops-btn-primary:hover:not(:disabled)\x20{\x20border-color:color-mix(in\x20srgb,\x20var(--okdb-accent)\x2053%,\x20transparent);\x20}\x0a\x20\x20.dops-btn-primary:disabled\x20{\x20opacity:.35;\x20cursor:not-allowed;\x20}\x0a\x20\x20.dops-btn-ghost\x20{\x0a\x20\x20\x20\x20padding:8px\x2016px;\x20border-radius:8px;\x20font-size:13px;\x0a\x20\x20\x20\x20background:transparent;\x20border:1px\x20solid\x20var(--okdb-app-border);\x20opacity:.55;\x20cursor:pointer;\x0a\x20\x20}\x0a\x20\x20.dops-btn-ghost:hover\x20{\x20opacity:.85;\x20}\x0a\x20\x20.dops-spinner\x20{\x0a\x20\x20\x20\x20display:inline-block;\x20width:12px;\x20height:12px;\x0a\x20\x20\x20\x20border:2px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-accent)\x2020%,\x20transparent);\x20border-top-color:var(--okdb-accent);\x0a\x20\x20\x20\x20border-radius:50%;\x20animation:dops-spin\x20.6s\x20linear\x20infinite;\x0a\x20\x20}\x0a\x20\x20@keyframes\x20dops-spin\x20{\x20to\x20{\x20transform:rotate(360deg);\x20}\x20}\x0a</style>\x0a','exportSelectedEnvNames','importBatchSize','dataTransfer','/system/export?','$attr','okdb-export-','87moGFRY','520456pMYOJy','initialTab','find','5159yVjQyu','importAllTypes','exportSelTypes','createElement','header','href','/system/backup','preventDefault','revokeObjectURL','importBusy'];_0x4d71=function(){return _0xd1d8e5;};return _0x4d71();}function _0x532a(_0x15ef28,_0x9ce57){_0x15ef28=_0x15ef28-0x1a0;const _0x4d7155=_0x4d71();let _0x532a3e=_0x4d7155[_0x15ef28];return _0x532a3e;}(function(_0x6d673f,_0x9d73bb){const _0x1a32a5=_0x532a,_0x17ea56=_0x6d673f();while(!![]){try{const _0x30a39f=parseInt(_0x1a32a5(0x1e4))/0x1+-parseInt(_0x1a32a5(0x1c3))/0x2*(-parseInt(_0x1a32a5(0x1e3))/0x3)+-parseInt(_0x1a32a5(0x218))/0x4*(parseInt(_0x1a32a5(0x216))/0x5)+-parseInt(_0x1a32a5(0x1ab))/0x6*(parseInt(_0x1a32a5(0x1e7))/0x7)+-parseInt(_0x1a32a5(0x1ad))/0x8*(parseInt(_0x1a32a5(0x217))/0x9)+-parseInt(_0x1a32a5(0x202))/0xa*(-parseInt(_0x1a32a5(0x1c4))/0xb)+parseInt(_0x1a32a5(0x214))/0xc*(-parseInt(_0x1a32a5(0x200))/0xd);if(_0x30a39f===_0x9d73bb)break;else _0x17ea56['push'](_0x17ea56['shift']());}catch(_0x27e957){_0x17ea56['push'](_0x17ea56['shift']());}}}(_0x4d71,0x455bf));export default{'tag':_0x19ed73(0x205),'attr':{'modal':{},'envs':{'default':()=>[]},'onDone':{},'initialTab':{'default':_0x19ed73(0x1a2)}},'context'(_0xbb70a2){const _0x369b77=_0x19ed73;function _0x42bc79(){const _0x10d080=_0x532a,_0x280432=new Date(),_0x2cbdb3=_0x2618ea=>String(_0x2618ea)['padStart'](0x2,'0');return _0x280432['getFullYear']()+'-'+_0x2cbdb3(_0x280432[_0x10d080(0x1d9)]()+0x1)+'-'+_0x2cbdb3(_0x280432[_0x10d080(0x1d4)]());}return{'tab':_0xbb70a2[_0x369b77(0x1e1)][_0x369b77(0x1e5)]||_0x369b77(0x1a2),'formatBytes':function(_0x2083b9){const _0x18c8fb=_0x369b77;if(null==_0x2083b9)return'--';const _0x109770=['B','KB','MB','GB','TB'];let _0x5ccb59=_0x2083b9,_0x1740b8=0x0;for(;_0x5ccb59>=0x400&&_0x1740b8<_0x109770['length']-0x1;)_0x5ccb59/=0x400,_0x1740b8++;return _0x5ccb59[_0x18c8fb(0x1a6)](0x0===_0x1740b8?0x0:0x2)+'\x20'+_0x109770[_0x1740b8];},get 'userEnvs'(){const _0xcbf0d4=_0x369b77;return(_0xbb70a2[_0xcbf0d4(0x1e1)][_0xcbf0d4(0x1a3)]||[])[_0xcbf0d4(0x1b9)](_0xca04a6=>!_0xca04a6[_0xcbf0d4(0x1a1)][_0xcbf0d4(0x1ac)]('~'));},'typesForEnv'(_0x378881){const _0x26642d=_0x369b77,_0x5cbfe8=(_0xbb70a2[_0x26642d(0x1e1)][_0x26642d(0x1a3)]||[])[_0x26642d(0x1e6)](_0x1fb261=>_0x1fb261['name']===_0x378881);return(_0x5cbfe8?.[_0x26642d(0x21e)]||[])[_0x26642d(0x1b9)](_0x25704e=>!_0x25704e[_0x26642d(0x1a1)][_0x26642d(0x1ac)]('~'))[_0x26642d(0x1a5)](_0x431b21=>_0x431b21[_0x26642d(0x1a1)]);},'exportSelEnvs':{},'exportIncludeChanges':!0x1,'exportBusy':!0x1,'exportError':null,'exportDone':null,'exportSelTypes':{},'exportAllTypes':!0x0,get 'exportSelectedEnvNames'(){const _0x132796=_0x369b77;return Object[_0x132796(0x1af)](this[_0x132796(0x1fd)])[_0x132796(0x1b9)](_0x140a95=>this[_0x132796(0x1fd)][_0x140a95]);},get 'exportIsSingleEnv'(){const _0x2b1d8=_0x369b77;return 0x1===this[_0x2b1d8(0x1dd)][_0x2b1d8(0x1c7)];},get 'exportSingleEnvTypes'(){const _0x2e3735=_0x369b77;return this[_0x2e3735(0x1b1)]?this['typesForEnv'](this[_0x2e3735(0x1dd)][0x0]):[];},get 'exportSelectedTypeNames'(){const _0x1cd5e8=_0x369b77;return!this['exportIsSingleEnv']||this['exportAllTypes']?null:Object[_0x1cd5e8(0x1af)](this[_0x1cd5e8(0x1e9)])[_0x1cd5e8(0x1b9)](_0x24bb92=>this[_0x1cd5e8(0x1e9)][_0x24bb92]);},get 'exportCanRun'(){const _0x41fddf=_0x369b77;return this['exportSelectedEnvNames'][_0x41fddf(0x1c7)]>0x0&&!this[_0x41fddf(0x1f9)];},'exportToggleAllEnvs'(_0x3c9fb1){const _0x175cfb=_0x369b77,_0x34f9d6={};for(const _0x3a6ce1 of this[_0x175cfb(0x1a8)])_0x34f9d6[_0x3a6ce1['name']]=_0x3c9fb1;this['exportSelEnvs']=_0x34f9d6;},'exportToggleAllTypes'(_0x2326aa){const _0x2e4b93=_0x369b77,_0x194ebe={};for(const _0x54cf0d of this[_0x2e4b93(0x210)])_0x194ebe[_0x54cf0d]=_0x2326aa;this[_0x2e4b93(0x1e9)]=_0x194ebe;},'exportInit'(){const _0x2400bc=_0x369b77;0x0===Object['keys'](this[_0x2400bc(0x1fd)])[_0x2400bc(0x1c7)]&&this[_0x2400bc(0x1a8)]['length']&&(this[_0x2400bc(0x1fd)]={[this[_0x2400bc(0x1a8)][0x0][_0x2400bc(0x1a1)]]:!0x0});},async 'runExport'(){const _0x43819b=_0x369b77;if(this[_0x43819b(0x20e)]){this[_0x43819b(0x1f9)]=!0x0,this[_0x43819b(0x1fc)]=null,this[_0x43819b(0x206)]=null;try{const _0x11d8e2=this[_0x43819b(0x1dd)],_0x2d6df1=_0x11d8e2['length']>0x1,_0x32caaf=new URLSearchParams();_0x2d6df1?_0x32caaf[_0x43819b(0x1d6)](_0x43819b(0x1a3),_0x11d8e2[_0x43819b(0x1cb)](',')):_0x32caaf[_0x43819b(0x1d6)](_0x43819b(0x1a0),_0x11d8e2[0x0]),this[_0x43819b(0x222)]&&_0x32caaf[_0x43819b(0x1d6)](_0x43819b(0x21f),_0x43819b(0x1f6));const _0x1663be=this[_0x43819b(0x1d2)];_0x1663be&&_0x1663be['length']&&_0x32caaf[_0x43819b(0x1d6)]('types',_0x1663be[_0x43819b(0x1cb)](','));const _0x51036e=await fetch(__ENV__[_0x43819b(0x208)]+_0x43819b(0x1e0)+_0x32caaf);if(!_0x51036e['ok']){const _0x582b35=await _0x51036e[_0x43819b(0x20b)]()[_0x43819b(0x203)](()=>({}));throw new Error(_0x582b35?.['error']?.[_0x43819b(0x1ca)]||_0x43819b(0x1d0)+_0x51036e[_0x43819b(0x1fa)]);}const _0x537c5d=await _0x51036e[_0x43819b(0x1a7)](),_0xade1f0=URL[_0x43819b(0x21b)](_0x537c5d),_0x3f832d=document['createElement']('a'),_0x14394f=_0x51036e[_0x43819b(0x1ba)][_0x43819b(0x1bb)]('content-disposition')||'',_0x13e415=_0x14394f[_0x43819b(0x213)](/filename="?([^"]+)"?/)?.[0x1]||_0x43819b(0x1e2)+_0x11d8e2[_0x43819b(0x1cb)]('+')+'-'+Date[_0x43819b(0x1a4)]()+'.ndjson';_0x3f832d[_0x43819b(0x1ec)]=_0xade1f0,_0x3f832d[_0x43819b(0x220)]=_0x13e415,document[_0x43819b(0x1ff)][_0x43819b(0x1c6)](_0x3f832d),_0x3f832d[_0x43819b(0x1c5)](),document[_0x43819b(0x1ff)]['removeChild'](_0x3f832d),URL['revokeObjectURL'](_0xade1f0);const _0x170bcd=(await _0x537c5d['text']())[_0x43819b(0x1ae)]('\x0a')[_0x43819b(0x1b9)](_0x5c921c=>_0x5c921c[_0x43819b(0x201)]())['map'](_0x5a27be=>{const _0x309969=_0x43819b;try{return JSON[_0x309969(0x1fb)](_0x5a27be);}catch{return null;}})['filter'](Boolean);this[_0x43819b(0x206)]={'filename':_0x13e415,'bytes':_0x537c5d['size'],'envCount':_0x2d6df1?_0x11d8e2[_0x43819b(0x1c7)]:0x1,'types':_0x170bcd[_0x43819b(0x1b9)](_0xda0814=>_0x43819b(0x1b2)===_0xda0814['r'])[_0x43819b(0x1c7)],'records':_0x170bcd['filter'](_0xfad137=>_0x43819b(0x1c2)===_0xfad137['r'])['length'],'changes':_0x170bcd[_0x43819b(0x1b9)](_0x2ea0e9=>_0x43819b(0x20d)===_0x2ea0e9['r'])[_0x43819b(0x1c7)]};}catch(_0x281994){this[_0x43819b(0x1fc)]=_0x281994?.['message']||String(_0x281994);}finally{this[_0x43819b(0x1f9)]=!0x1;}}},'importFile':null,'importEnvOverride':'','importSelTypes':{},'importAllTypes':!0x0,'importDropExisting':!0x1,'importIncludeChanges':!0x1,'importBatchSize':0x1f4,'importShowAdvanced':!0x1,'importBusy':!0x1,'importError':null,'importDone':null,'importDragOver':!0x1,'importFileTypes':[],get 'importSelectedTypeNames'(){const _0x1b0631=_0x369b77;return this[_0x1b0631(0x1e8)]?null:Object[_0x1b0631(0x1af)](this[_0x1b0631(0x211)])['filter'](_0x301f94=>this[_0x1b0631(0x211)][_0x301f94]);},get 'canImport'(){const _0x3f35ab=_0x369b77;return!!this[_0x3f35ab(0x204)]&&!this[_0x3f35ab(0x1f0)];},'onDrop'(_0x5f5092){const _0x4a1aeb=_0x369b77;_0x5f5092[_0x4a1aeb(0x1ee)](),this[_0x4a1aeb(0x221)]=!0x1;const _0x6140e=_0x5f5092[_0x4a1aeb(0x1df)]?.[_0x4a1aeb(0x21c)]?.[0x0];_0x6140e&&this[_0x4a1aeb(0x1d7)](_0x6140e);},'onDragOver'(_0x17bffa){const _0x5ef57d=_0x369b77;_0x17bffa[_0x5ef57d(0x1ee)](),this['importDragOver']=!0x0;},'onDragLeave'(){const _0x13c75a=_0x369b77;this[_0x13c75a(0x221)]=!0x1;},'pickFile'(){const _0x7dd8d2=_0x369b77,_0x392523=document[_0x7dd8d2(0x1ea)](_0x7dd8d2(0x1fe));_0x392523['type']=_0x7dd8d2(0x1f7),_0x392523[_0x7dd8d2(0x1bc)]=_0x7dd8d2(0x1b7),_0x392523[_0x7dd8d2(0x1a9)]=_0x57d8f1=>{const _0x2f6889=_0x7dd8d2,_0x4caa16=_0x57d8f1[_0x2f6889(0x1f8)][_0x2f6889(0x21c)]?.[0x0];_0x4caa16&&this[_0x2f6889(0x1d7)](_0x4caa16);},_0x392523[_0x7dd8d2(0x1c5)]();},async '_setImportFile'(_0x256980){const _0x5b72d7=_0x369b77;this[_0x5b72d7(0x204)]=_0x256980,this[_0x5b72d7(0x209)]=null,this[_0x5b72d7(0x1c0)]=null,this['importFileTypes']=[];try{const _0x4f9866=(await _0x256980[_0x5b72d7(0x1f2)](0x0,0x8000)[_0x5b72d7(0x215)]())['split']('\x0a')[_0x5b72d7(0x1b9)](_0x353e4a=>_0x353e4a[_0x5b72d7(0x201)]()),_0x2ba207=_0x4f9866[_0x5b72d7(0x1a5)](_0x141278=>{const _0x399edc=_0x5b72d7;try{return JSON[_0x399edc(0x1fb)](_0x141278);}catch{return null;}})[_0x5b72d7(0x1b9)](_0x3bd378=>_0x5b72d7(0x1b2)===_0x3bd378?.['r']);this[_0x5b72d7(0x21d)]=[...new Set(_0x2ba207[_0x5b72d7(0x1a5)](_0x2e1ac3=>_0x2e1ac3[_0x5b72d7(0x1cc)]))];const _0x247961=_0x4f9866[_0x5b72d7(0x1a5)](_0x1518e2=>{const _0x3accf4=_0x5b72d7;try{return JSON[_0x3accf4(0x1fb)](_0x1518e2);}catch{return null;}})[_0x5b72d7(0x1e6)](_0x568d55=>_0x5b72d7(0x1eb)===_0x568d55?.['r']);_0x247961?.[_0x5b72d7(0x1d1)]&&this[_0x5b72d7(0x1da)];}catch{}},'importToggleAllTypes'(_0x492b68){const _0x55584=_0x369b77,_0x4baa6f={};for(const _0x31c085 of this[_0x55584(0x21d)])_0x4baa6f[_0x31c085]=_0x492b68;this[_0x55584(0x211)]=_0x4baa6f;},async 'runImport'(){const _0x5058e7=_0x369b77;if(this['importFile']){this[_0x5058e7(0x1f0)]=!0x0,this[_0x5058e7(0x209)]=null,this[_0x5058e7(0x1c0)]=null;try{const _0x5cae56=new URLSearchParams({'dropExisting':String(this[_0x5058e7(0x1f5)]),'includeChanges':String(this[_0x5058e7(0x20c)]),'batchSize':String(this[_0x5058e7(0x1de)]||0x1f4)});this[_0x5058e7(0x1da)]&&_0x5cae56[_0x5058e7(0x1d6)](_0x5058e7(0x1a0),this[_0x5058e7(0x1da)]);const _0x1da042=this['importSelectedTypeNames'];_0x1da042&&_0x1da042[_0x5058e7(0x1c7)]&&_0x5cae56[_0x5058e7(0x1d6)]('types',_0x1da042[_0x5058e7(0x1cb)](','));const _0x382a3d=await fetch(__ENV__[_0x5058e7(0x208)]+_0x5058e7(0x1cf)+_0x5cae56,{'method':_0x5058e7(0x1c8),'headers':{'content-type':_0x5058e7(0x1ce)},'body':this[_0x5058e7(0x204)]}),_0x259eaf=await _0x382a3d[_0x5058e7(0x20b)]()['catch'](()=>({}));if(!_0x382a3d['ok'])throw new Error(_0x259eaf?.[_0x5058e7(0x1db)]?.[_0x5058e7(0x1ca)]||_0x5058e7(0x1d0)+_0x382a3d[_0x5058e7(0x1fa)]);const _0x4caafd=_0x259eaf[_0x5058e7(0x1c2)]??_0x259eaf;this[_0x5058e7(0x1c0)]={'types':_0x4caafd['types']??0x0,'records':_0x4caafd[_0x5058e7(0x1be)]??0x0,'changes':_0x4caafd[_0x5058e7(0x1f1)]??0x0},_0xbb70a2[_0x5058e7(0x1e1)][_0x5058e7(0x207)]?.();}catch(_0x2e1949){this[_0x5058e7(0x209)]=_0x2e1949?.[_0x5058e7(0x1ca)]||String(_0x2e1949);}finally{this[_0x5058e7(0x1f0)]=!0x1;}}},'backupMode':'server','backupDestDir':_0x369b77(0x1b8)+_0x42bc79(),'backupSelEnvs':{},'backupEnvMode':_0x369b77(0x1b3),'backupCompact':!0x0,'backupBusy':!0x1,'backupError':null,'backupResult':null,'backupDlBusy':!0x1,'backupDlError':null,'backupDlDone':null,get 'backupEnvNames'(){const _0x8e139e=_0x369b77;return _0x8e139e(0x1b3)===this['backupEnvMode']?null:Object[_0x8e139e(0x1af)](this[_0x8e139e(0x1aa)])['filter'](_0x5e49f7=>this[_0x8e139e(0x1aa)][_0x5e49f7]);},get 'canBackup'(){const _0x4a5cb6=_0x369b77;return this['backupDestDir']['trim']()[_0x4a5cb6(0x1c7)]>0x0&&!this[_0x4a5cb6(0x1b4)];},get 'canBackupDl'(){const _0x1b00e4=_0x369b77;return!this[_0x1b00e4(0x20f)];},async 'runBackup'(){const _0xed5fa6=_0x369b77;if(this[_0xed5fa6(0x1f4)]){this[_0xed5fa6(0x1b4)]=!0x0,this['backupError']=null,this[_0xed5fa6(0x1d3)]=null;try{const _0x2fd754=await fetch(__ENV__[_0xed5fa6(0x208)]+_0xed5fa6(0x1ed),{'method':_0xed5fa6(0x1c8),'headers':{'content-type':_0xed5fa6(0x1bf)},'body':JSON[_0xed5fa6(0x1c1)]({'destDir':this['backupDestDir'][_0xed5fa6(0x201)](),'envNames':this['backupEnvNames'],'compact':this[_0xed5fa6(0x20a)]})}),_0xe237a9=await _0x2fd754[_0xed5fa6(0x20b)]()[_0xed5fa6(0x203)](()=>({}));if(!_0x2fd754['ok'])throw new Error(_0xe237a9?.[_0xed5fa6(0x1db)]?.[_0xed5fa6(0x1ca)]||_0xed5fa6(0x1d0)+_0x2fd754[_0xed5fa6(0x1fa)]);this[_0xed5fa6(0x1d3)]=_0xe237a9['data']??_0xe237a9;}catch(_0x133826){this[_0xed5fa6(0x1b0)]=_0x133826?.[_0xed5fa6(0x1ca)]||String(_0x133826);}finally{this[_0xed5fa6(0x1b4)]=!0x1;}}},async 'runDownloadBackup'(){const _0x5e16be=_0x369b77;this['backupDlBusy']=!0x0,this[_0x5e16be(0x1f3)]=null,this['backupDlDone']=null;try{const _0x4abe91=this[_0x5e16be(0x21a)],_0x3cc4fd=new URLSearchParams();_0x4abe91?.[_0x5e16be(0x1c7)]?_0x3cc4fd[_0x5e16be(0x1d6)](_0x5e16be(0x1a3),_0x4abe91[_0x5e16be(0x1cb)](',')):_0x3cc4fd[_0x5e16be(0x1d6)](_0x5e16be(0x1a3),this[_0x5e16be(0x1a8)]['map'](_0x5d3663=>_0x5d3663[_0x5e16be(0x1a1)])[_0x5e16be(0x1cb)](','));const _0x8be961=await fetch(__ENV__[_0x5e16be(0x208)]+_0x5e16be(0x1e0)+_0x3cc4fd);if(!_0x8be961['ok']){const _0x54b3f0=await _0x8be961['json']()[_0x5e16be(0x203)](()=>({}));throw new Error(_0x54b3f0?.[_0x5e16be(0x1db)]||'HTTP\x20'+_0x8be961['status']);}const _0x42f2ee=await _0x8be961[_0x5e16be(0x1a7)](),_0x4a105d=URL['createObjectURL'](_0x42f2ee),_0x269246=document[_0x5e16be(0x1ea)]('a'),_0x3b1304=_0x8be961[_0x5e16be(0x1ba)]['get'](_0x5e16be(0x1c9))||'',_0x327949=_0x3b1304[_0x5e16be(0x213)](/filename="?([^"]+)"?/)?.[0x1]||_0x5e16be(0x1cd)+_0x42bc79()+_0x5e16be(0x1b6);_0x269246[_0x5e16be(0x1ec)]=_0x4a105d,_0x269246[_0x5e16be(0x220)]=_0x327949,document[_0x5e16be(0x1ff)]['appendChild'](_0x269246),_0x269246[_0x5e16be(0x1c5)](),document[_0x5e16be(0x1ff)][_0x5e16be(0x219)](_0x269246),URL[_0x5e16be(0x1ef)](_0x4a105d),this[_0x5e16be(0x1d5)]={'filename':_0x327949,'bytes':_0x42f2ee[_0x5e16be(0x1d8)]};}catch(_0x4b71f9){this[_0x5e16be(0x1f3)]=_0x4b71f9?.['message']||String(_0x4b71f9);}finally{this[_0x5e16be(0x20f)]=!0x1;}},'close'(){const _0x44f333=_0x369b77;_0xbb70a2[_0x44f333(0x1e1)][_0x44f333(0x1bd)][_0x44f333(0x1b5)]();},'mount'(){const _0x45df81=_0x369b77;this[_0x45df81(0x212)]();}};},'template':_0x19ed73(0x1dc)};
@@ -0,0 +1 @@
1
+ const _0x37641d=_0x43f6;(function(_0x471700,_0x11f7fe){const _0x101834=_0x43f6,_0x590126=_0x471700();while(!![]){try{const _0x451c0c=-parseInt(_0x101834(0x144))/0x1+parseInt(_0x101834(0x148))/0x2*(parseInt(_0x101834(0x14a))/0x3)+-parseInt(_0x101834(0x161))/0x4*(parseInt(_0x101834(0x143))/0x5)+parseInt(_0x101834(0x160))/0x6*(-parseInt(_0x101834(0x14d))/0x7)+-parseInt(_0x101834(0x162))/0x8*(-parseInt(_0x101834(0x15b))/0x9)+-parseInt(_0x101834(0x165))/0xa+parseInt(_0x101834(0x136))/0xb*(parseInt(_0x101834(0x158))/0xc);if(_0x451c0c===_0x11f7fe)break;else _0x590126['push'](_0x590126['shift']());}catch(_0x7112de){_0x590126['push'](_0x590126['shift']());}}}(_0x206a,0xc77a5));import _0x3026df from'../../api/parts/api-endpoint.ok.js';import _0x4536a0 from'@toolkit/elements/ok-icon.ok.js';export default{'tag':_0x37641d(0x13d),'unwrap':!0x0,'dependencies':[_0x3026df,_0x4536a0],'context':()=>({'routes':[],'loading':!0x1,'error':null,'selected':null,'search':'','tagOrder':[_0x37641d(0x150),'types',_0x37641d(0x13f),_0x37641d(0x15d),_0x37641d(0x154),_0x37641d(0x135),'queue',_0x37641d(0x140),_0x37641d(0x163),_0x37641d(0x133),'envs',_0x37641d(0x159)],async 'load'(){const _0x151b04=_0x37641d;this[_0x151b04(0x131)]=!0x0,this[_0x151b04(0x145)]=null;try{const _0x8d6fdf=await fetch(__ENV__[_0x151b04(0x13a)]+_0x151b04(0x13b)),_0x28787b=await _0x8d6fdf['json']();if(!_0x8d6fdf['ok'])throw new Error(_0x28787b?.[_0x151b04(0x145)]?.[_0x151b04(0x147)]||_0x151b04(0x146));this[_0x151b04(0x13e)]=_0x28787b[_0x151b04(0x13f)]??[];}catch(_0x57a35a){this[_0x151b04(0x145)]=_0x57a35a?.[_0x151b04(0x147)]||String(_0x57a35a);}finally{this[_0x151b04(0x131)]=!0x1;}},get 'filtered'(){const _0x5d2ea9=_0x37641d,_0x297b2a=this[_0x5d2ea9(0x13c)]['trim']()[_0x5d2ea9(0x142)]();return _0x297b2a?this[_0x5d2ea9(0x13e)]['filter'](_0x3d5add=>_0x3d5add['path'][_0x5d2ea9(0x142)]()[_0x5d2ea9(0x164)](_0x297b2a)||_0x3d5add[_0x5d2ea9(0x132)][_0x5d2ea9(0x142)]()[_0x5d2ea9(0x164)](_0x297b2a)||(_0x3d5add[_0x5d2ea9(0x14f)]?.['summary']||'')['toLowerCase']()[_0x5d2ea9(0x164)](_0x297b2a)||(_0x3d5add[_0x5d2ea9(0x14f)]?.[_0x5d2ea9(0x15f)]||[])[_0x5d2ea9(0x156)](_0x1a8ccb=>_0x1a8ccb[_0x5d2ea9(0x164)](_0x297b2a))):this['routes'];},get 'groups'(){const _0x3f76ec=_0x37641d,_0x2682f0=new Map();for(const _0x4a5708 of this['filtered']){const _0x127a30=_0x4a5708[_0x3f76ec(0x14f)]?.['tags']?.[0x0]??_0x3f76ec(0x137);_0x2682f0[_0x3f76ec(0x141)](_0x127a30)||_0x2682f0['set'](_0x127a30,[]),_0x2682f0['get'](_0x127a30)['push'](_0x4a5708);}return[..._0x2682f0[_0x3f76ec(0x134)]()][_0x3f76ec(0x15e)](([_0x286758],[_0xfeaf65])=>{const _0x34dc8b=_0x3f76ec,_0x107e31=this[_0x34dc8b(0x14b)][_0x34dc8b(0x14e)](_0x286758),_0x236853=this[_0x34dc8b(0x14b)][_0x34dc8b(0x14e)](_0xfeaf65);return-0x1===_0x107e31&&-0x1===_0x236853?_0x286758[_0x34dc8b(0x15c)](_0xfeaf65):-0x1===_0x107e31?0x1:-0x1===_0x236853?-0x1:_0x107e31-_0x236853;})['map'](([_0x921496,_0x354fea])=>({'tag':_0x921496,'routes':_0x354fea}));},'methodColor':_0x2e248f=>({'GET':_0x37641d(0x14c),'POST':_0x37641d(0x153),'PUT':_0x37641d(0x130),'PATCH':_0x37641d(0x149),'DELETE':_0x37641d(0x15a)}[_0x2e248f]||_0x37641d(0x152)),'select'(_0x41fbc0){const _0x47ed9f=_0x37641d;this[_0x47ed9f(0x157)]=null,setTimeout(()=>{const _0x12f556=_0x47ed9f;this[_0x12f556(0x157)]=_0x41fbc0;},0x0);},'back'(){const _0x1a6898=_0x37641d;this[_0x1a6898(0x157)]=null;},'shortPath':_0x412542=>_0x412542[_0x37641d(0x151)](/^\/api/,'')[_0x37641d(0x151)](/\[[^\]]*\]/g,''),'optionalHint'(_0x1781e3){const _0x556730=_0x37641d,_0x20cbb3=_0x1781e3[_0x556730(0x138)](/\[([^\]]*)\]/);return _0x20cbb3?_0x20cbb3[0x1][_0x556730(0x151)](/=\w+/g,''):null;}}),'init'(){const _0x51e666=_0x37641d;this[_0x51e666(0x139)]();},'template':'\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;height:100%;min-height:0;\x22>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20──\x20Detail\x20view\x20──\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22selected\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;height:100%;min-height:0;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Back\x20bar\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:12px;margin-bottom:16px;flex-shrink:0;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@click=\x22back()\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22display:flex;align-items:center;gap:5px;font-size:12px;padding:5px\x2012px;color:var(--okdb-accent-muted);border-color:var(--okdb-app-border);border-radius:6px;background:transparent;cursor:pointer;transition:background\x20.12s;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22api-back-btn\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20←\x20Routes\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:12px;font-family:monospace;opacity:.6;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20:style=\x22\x27color:\x27+methodColor(selected.method)+\x27;font-weight:700;\x27\x22>{{\x20selected.method\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20{{\x20selected.path\x20}}\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<api-endpoint\x20:endpoint=\x22selected\x22\x20style=\x22flex:1;min-height:0;overflow:auto;\x22\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20──\x20List\x20view\x20──\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!selected\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;gap:14px;height:100%;min-height:0;\x22>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Search\x20bar\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;align-items:center;gap:10px;flex-shrink:0;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<input\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20type=\x22text\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20placeholder=\x22Filter\x20routes…\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20!value=\x22search\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@input=\x22search\x20=\x20$el.value\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22flex:1;background:var(--okdb-app-bg-deep);border:1px\x20solid\x20var(--okdb-app-border);border-radius:7px;padding:7px\x2012px;color:var(--okdb-app-fg);font-size:12px;outline:none;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22loading\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<ok-icon\x20name=\x22loader\x22\x20class=\x22spin\x22\x20style=\x22width:18px;height:18px;opacity:.5;flex-shrink:0;\x22></ok-icon>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22routes.length\x20>\x200\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;opacity:.35;white-space:nowrap;flex-shrink:0;\x22>{{\x20filtered.length\x20}}\x20/\x20{{\x20routes.length\x20}}\x20routes</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Error\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22error\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22color:var(--okdb-danger);font-size:12px;padding:8px;border:1px\x20solid\x20color-mix(in\x20srgb,\x20var(--okdb-danger)\x2020%,\x20transparent);border-radius:6px;flex-shrink:0;\x22>{{\x20error\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Route\x20groups\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:18px;padding-bottom:12px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22groups\x22\x20let:item=\x22g\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:10px;text-transform:uppercase;letter-spacing:.07em;opacity:.38;margin-bottom:6px;padding:0\x204px;\x22>{{\x20g.tag\x20}}</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:grid;grid-template-columns:repeat(auto-fill,\x20minmax(260px,\x201fr));gap:2px;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22g.routes\x22\x20let:item=\x22r\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@click=\x22select(r)\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:title=\x22r.meta?.summary\x20||\x20r.path\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22api-route-card\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20:style=\x22\x27font-size:10px;font-weight:700;width:42px;flex-shrink:0;text-align:center;color:\x27+methodColor(r.method)+\x27;\x27\x22>{{\x20r.method\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;flex-direction:column;min-width:0;flex:1;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-family:monospace;font-size:11px;color:var(--okdb-accent-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22optionalHint(r.path)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22opacity:.3;\x22>{{\x20optionalHint(r.path)\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>{{\x20shortPath(r.path)\x20}}\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22r.meta?.summary\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20style=\x22font-size:11px;color:var(--okdb-app-fg-faint);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:1px;\x22>{{\x20r.meta.summary\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!loading\x20&&\x20routes.length\x20===\x200\x20&&\x20!error\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22font-size:12px;opacity:.4;padding:8px;\x22>No\x20routes\x20loaded.</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20','style':_0x37641d(0x155)};function _0x43f6(_0x1fd57b,_0xb1eedc){_0x1fd57b=_0x1fd57b-0x130;const _0x206a3e=_0x206a();let _0x43f69f=_0x206a3e[_0x1fd57b];return _0x43f69f;}function _0x206a(){const _0x2ff0c8=['fts','32796599MQnMiz','other','match','load','API','/docs','search','system-api-panel','routes','data','pipelines','has','toLowerCase','85vzzvLh','1008052dLhOIY','error','Failed\x20to\x20load\x20routes','message','4dfXqgm','var(--okdb-indigo)','678420nFRIYY','tagOrder','var(--okdb-accent)','6748GwmLVe','indexOf','meta','system','replace','var(--okdb-app-fg-muted)','var(--okdb-success)','indexes','.api-back-btn:hover{background:var(--okdb-app-surface-2)!important;border-color:var(--okdb-app-border-strong)!important}.api-route-card{display:flex;align-items:center;gap:8px;padding:7px\x2010px;background:0\x200;border:1px\x20solid\x20transparent;border-radius:6px;cursor:pointer;text-align:left;min-width:0;transition:background\x20.1s,border-color\x20.1s}.api-route-card:hover{background:var(--okdb-app-bg-deep);border-color:var(--okdb-app-border)}','some','selected','12mpteoT','docs','var(--okdb-danger)','8667qLdALA','localeCompare','changelog','sort','tags','1734EBSNCj','229768ZzFvXo','2168UhmNiC','sync','includes','6145390gqBVVk','var(--okdb-warning)','loading','method','embeddings','entries'];_0x206a=function(){return _0x2ff0c8;};return _0x206a();}
@@ -0,0 +1 @@
1
+ const _0x401dd8=_0x3031;(function(_0x54b462,_0x478c04){const _0x2741fd=_0x3031,_0xc9d6e4=_0x54b462();while(!![]){try{const _0x406a99=parseInt(_0x2741fd(0x1ac))/0x1+-parseInt(_0x2741fd(0x1af))/0x2+parseInt(_0x2741fd(0x1b2))/0x3+parseInt(_0x2741fd(0x1ad))/0x4*(parseInt(_0x2741fd(0x1a7))/0x5)+-parseInt(_0x2741fd(0x1b7))/0x6+parseInt(_0x2741fd(0x19f))/0x7*(parseInt(_0x2741fd(0x1a9))/0x8)+-parseInt(_0x2741fd(0x1bb))/0x9;if(_0x406a99===_0x478c04)break;else _0xc9d6e4['push'](_0xc9d6e4['shift']());}catch(_0xb7647d){_0xc9d6e4['push'](_0xc9d6e4['shift']());}}}(_0x3cb1,0xf130e));import _0x131df3 from'../../auth/parts/token-list.ok.js';import _0x1f4b89 from'../../auth/parts/token-detail.ok.js';function _0x3031(_0x3a63c7,_0x179bd5){_0x3a63c7=_0x3a63c7-0x19f;const _0x3cb1be=_0x3cb1();let _0x30310d=_0x3cb1be[_0x3a63c7];return _0x30310d;}function _0x3cb1(){const _0x376e74=['$innerContext','system-auth-panel','message','10963506JEdgYa','Delete\x20failed','toast','selectedToken','3920787wHitjj','load','Unnamed','$ok','open','<edit-token-modal\x20:modal=\x22modal\x22\x20:token=\x22token\x22\x20:on-done=\x22onDone\x22\x20/>','shared','success','selectedTokenId','7416143uyBKfH','tokenListEl','/auth/tokens/','API','modal','Failed\x20to\x20delete\x20token','Token\x20deleted','DELETE','15jDBIho','label','8NItjHE','.auth-panel-btn:hover{background:var(--okdb-app-surface-2)!important;border-color:var(--okdb-app-border-strong)!important;color:var(--okdb-accent-muted)!important}','$scope','232445YSFNsY','1307468JIpvsj','selectToken','1091482uDjkQc','Edit\x20Token:\x20','\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22display:flex;gap:0;height:100%;min-height:0;\x22>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Left:\x20token\x20list\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22width:240px;flex-shrink:0;border-right:1px\x20solid\x20var(--okdb-app-surface-2);display:flex;flex-direction:column;gap:8px;padding-right:12px;min-height:0;overflow:hidden;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@click=\x22openCreateModal()\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22flex-shrink:0;padding:6px\x2010px;border:1px\x20solid\x20var(--okdb-app-border);border-radius:6px;background:transparent;color:var(--okdb-accent-muted);font-size:12px;font-weight:500;cursor:pointer;text-align:left;width:100%;transition:background\x20.12s,border-color\x20.12s,color\x20.12s;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20class=\x22auth-panel-btn\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20+\x20New\x20Token\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<token-list\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:ref=\x22tokenListEl\x20=\x20$el\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:selected-id=\x22selectedTokenId\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@selected=\x22selectToken($event.detail)\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20style=\x22flex:1;min-height:0;\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<!--\x20Right:\x20token\x20detail\x20-->\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<div\x20style=\x22flex:1;min-width:0;padding-left:18px;overflow:auto;\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<token-detail\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20:token=\x22selectedToken\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@edit=\x22openEditModal($event.detail)\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20@delete=\x22deleteToken($event.detail)\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20/>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20','4572174rpARTj','Create\x20Token'];_0x3cb1=function(){return _0x376e74;};return _0x3cb1();}import _0x47f16e from'../../auth/modals/create-token-modal.ok.js';import _0x5bf686 from'../../auth/modals/edit-token-modal.ok.js';export default{'tag':_0x401dd8(0x1b5),'unwrap':!0x0,'dependencies':[_0x131df3,_0x1f4b89,_0x47f16e,_0x5bf686],'context':_0x2ce747=>({'selectedToken':null,'tokenListEl':null,'selectedTokenId':null,'selectToken'(_0x297aa4){const _0x5cd1fb=_0x401dd8;this[_0x5cd1fb(0x1ba)]=_0x297aa4??null,this[_0x5cd1fb(0x1c3)]=_0x297aa4?.['id']??null;},async 'openCreateModal'(){const _0x4592b7=_0x401dd8;await _0x2ce747[_0x4592b7(0x1be)][_0x4592b7(0x1c1)][_0x4592b7(0x1a3)][_0x4592b7(0x1bf)]({'owner':_0x2ce747,'title':_0x4592b7(0x1b3),'content':'<create-token-modal\x20:modal=\x22modal\x22\x20:on-done=\x22onDone\x22\x20/>','context':_0x23b9e2=>({'modal':_0x23b9e2,'onDone':async _0x6ae010=>{const _0x4e9911=_0x4592b7;if(_0x6ae010?.['id']){const _0x377323=this[_0x4e9911(0x1a0)]?.['$scope']?.[_0x4e9911(0x1b4)];_0x377323&&(_0x377323['_selectedId']=_0x6ae010['id']),this[_0x4e9911(0x1ae)](_0x6ae010);}await this[_0x4e9911(0x1a0)]?.['$scope']?.[_0x4e9911(0x1b4)]?.[_0x4e9911(0x1bc)]?.();}})});},async 'openEditModal'(_0x38b9ef){const _0x36a36e=_0x401dd8;await _0x2ce747[_0x36a36e(0x1be)]['shared'][_0x36a36e(0x1a3)]['open']({'owner':_0x2ce747,'title':_0x36a36e(0x1b0)+(_0x38b9ef[_0x36a36e(0x1a8)]||_0x36a36e(0x1bd)),'content':_0x36a36e(0x1c0),'context':_0x2ab127=>({'modal':_0x2ab127,'token':_0x38b9ef,'onDone':async()=>{const _0x1226b9=_0x36a36e;await this['tokenListEl']?.['$scope']?.['$innerContext']?.[_0x1226b9(0x1bc)]?.();}})});},async 'deleteToken'(_0x3c8183){const _0x3bfc3d=_0x401dd8;try{const _0x2aada6=await fetch(__ENV__[_0x3bfc3d(0x1a2)]+_0x3bfc3d(0x1a1)+encodeURIComponent(_0x3c8183),{'method':_0x3bfc3d(0x1a6)});if(!_0x2aada6['ok']){const _0x1ab30f=await _0x2aada6['json']();throw new Error(_0x1ab30f?.['error']?.['message']||_0x3bfc3d(0x1a4));}_0x2ce747[_0x3bfc3d(0x1be)][_0x3bfc3d(0x1c1)]?.[_0x3bfc3d(0x1b9)]?.[_0x3bfc3d(0x1c2)]?.(_0x3bfc3d(0x1a5)),this[_0x3bfc3d(0x1ae)](null),await this['tokenListEl']?.[_0x3bfc3d(0x1ab)]?.['$innerContext']?.[_0x3bfc3d(0x1bc)]?.();}catch(_0xd73646){_0x2ce747[_0x3bfc3d(0x1be)][_0x3bfc3d(0x1c1)]?.[_0x3bfc3d(0x1b9)]?.['error']?.(_0xd73646?.[_0x3bfc3d(0x1b6)]||_0x3bfc3d(0x1b8));}}}),'template':_0x401dd8(0x1b1),'style':_0x401dd8(0x1aa)};
@@ -0,0 +1 @@
1
+ const _0x2b4317=_0x4374;function _0x2a9d(){const _0x4c4518=['\x20selected','hasMore','131929zFtaom','/system/logs?','totalCount','append','212847kRLbZF','levels','all','level','length','24h','loading','48TBVOjQ','data','2006810mhJVOk','message','entries','4634778ceAXhq','toTimeString','toUpperCase','clear','1269mhkdjk','cursor','34806SPiMTi','add','load','Failed\x20to\x20load\x20logs','var(--okdb-danger)','padStart','push','stringify','getMilliseconds','sort','next_cursor','system-log-history','feature','API','error','seenNodes','All\x20time','\x0a<div\x20class=\x22history\x22>\x0a\x0a\x20\x20<!--\x20Toolbar\x20row\x201:\x20filters\x20-->\x0a\x20\x20<div\x20class=\x22history__toolbar\x22>\x0a\x20\x20\x20\x20<span\x20class=\x22history__title\x22>History</span>\x0a\x0a\x20\x20\x20\x20<!--\x20Time\x20range\x20-->\x0a\x20\x20\x20\x20<div\x20class=\x22history__group\x22>\x0a\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__label\x22>Time</span>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22history__pills\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setTimeRange(\x271h\x27)\x22\x20:class=\x22timeRange===\x271h\x27\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>1h</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setTimeRange(\x276h\x27)\x22\x20:class=\x22timeRange===\x276h\x27\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>6h</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setTimeRange(\x2724h\x27)\x22\x20:class=\x22timeRange===\x2724h\x27\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>24h</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setTimeRange(\x277d\x27)\x22\x20:class=\x22timeRange===\x277d\x27\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>7d</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setTimeRange(\x27all\x27)\x22\x20:class=\x22timeRange===\x27all\x27\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>All</button>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20<div\x20class=\x22history__spacer\x22></div>\x0a\x0a\x20\x20\x20\x20<!--\x20Refresh\x20and\x20count\x20-->\x0a\x20\x20\x20\x20<button\x20@click=\x22resetAndLoad()\x22\x20:disabled=\x22loading\x22\x20class=\x22pill\x22\x20style=\x22white-space:nowrap;\x22>↻\x20Refresh</button>\x0a\x20\x20\x20\x20<span\x20class=\x22history__count\x22>{{\x20totalCount\x20}}</span>\x0a\x20\x20</div>\x0a\x0a\x20\x20<!--\x20Toolbar\x20row\x202:\x20level\x20filter\x20-->\x0a\x20\x20<div\x20class=\x22history__toolbar\x20history__toolbar--sub\x22>\x0a\x20\x20\x20\x20<span\x20class=\x22history__label\x22>Level</span>\x0a\x20\x20\x20\x20<div\x20class=\x22history__pills\x22>\x0a\x20\x20\x20\x20\x20\x20<button\x20@click=\x22clearLevels()\x22\x20:class=\x22levels.length\x20===\x200\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>All</button>\x0a\x20\x20\x20\x20\x20\x20<button\x20@click=\x22toggleLevel(\x27info\x27)\x22\x20:class=\x22levels.includes(\x27info\x27)\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22\x20style=\x22color:var(--okdb-accent)\x22>info</button>\x0a\x20\x20\x20\x20\x20\x20<button\x20@click=\x22toggleLevel(\x27warn\x27)\x22\x20:class=\x22levels.includes(\x27warn\x27)\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22\x20style=\x22color:var(--okdb-warning)\x22>warn</button>\x0a\x20\x20\x20\x20\x20\x20<button\x20@click=\x22toggleLevel(\x27error\x27)\x22\x20:class=\x22levels.includes(\x27error\x27)\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22\x20style=\x22color:var(--okdb-danger)\x22>error</button>\x0a\x20\x20\x20\x20\x20\x20<button\x20@click=\x22toggleLevel(\x27debug\x27)\x22\x20:class=\x22levels.includes(\x27debug\x27)\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22\x20style=\x22color:var(--okdb-app-fg-muted)\x22>debug</button>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</div>\x0a\x0a\x20\x20<!--\x20Toolbar\x20row\x203:\x20feature\x20dropdown\x20-->\x0a\x20\x20<if\x20:=\x22seenFeatures.length\x20>\x200\x22>\x0a\x20\x20\x20\x20<div\x20class=\x22history__toolbar\x20history__toolbar--sub\x22>\x0a\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__label\x22>Feature</span>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22history__pills\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setFeature(null)\x22\x20:class=\x22feature\x20===\x20null\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>All</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22seenFeatures\x22\x20let:item=\x22s\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setFeature(s)\x22\x20:class=\x22feature\x20===\x20s\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>{{\x20s\x20}}</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</if>\x0a\x0a\x20\x20<!--\x20Toolbar\x20row\x204:\x20node\x20dropdown\x20-->\x0a\x20\x20<if\x20:=\x22seenNodes.length\x20>\x200\x22>\x0a\x20\x20\x20\x20<div\x20class=\x22history__toolbar\x20history__toolbar--sub\x22>\x0a\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__label\x22>Node</span>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22history__pills\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setNode(null)\x22\x20:class=\x22node\x20===\x20null\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>All</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<each\x20:of=\x22seenNodes\x22\x20let:item=\x22n\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<button\x20@click=\x22setNode(n)\x22\x20:class=\x22node\x20===\x20n\x20?\x20\x27pill\x20pill--on\x27\x20:\x20\x27pill\x27\x22>{{\x20n\x20}}</button>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</each>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</if>\x0a\x0a\x20\x20<!--\x20Error\x20state\x20-->\x0a\x20\x20<if\x20:=\x22error\x22>\x0a\x20\x20\x20\x20<div\x20class=\x22history__error\x22>{{\x20error\x20}}</div>\x0a\x20\x20</if>\x0a\x0a\x20\x20<!--\x20Log\x20entries\x20list\x20-->\x0a\x20\x20<div\x20class=\x22history__list\x22>\x0a\x20\x20\x20\x20<if\x20:=\x22entries.length\x20===\x200\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22history__empty\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22loading\x22>Loading…</if>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22!loading\x20&&\x20!error\x22>No\x20log\x20entries</if>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20</if>\x0a\x0a\x20\x20\x20\x20<each\x20:of=\x22entries\x22\x20let:item=\x22entry\x22>\x0a\x20\x20\x20\x20\x20\x20<div\x20class=\x22history__row\x22\x20@click=\x22toggleExpanded(entry.key)\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__ts\x22>{{\x20fmtTime(entry.ts)\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__level\x22\x20:style=\x22\x27color:\x27\x20+\x20levelColor(entry.level)\x22>{{\x20entry.level\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__feature\x22\x20v-if=\x22entry.feature\x22>{{\x20entry.feature\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__msg\x22>{{\x20entry.msg\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__node\x22\x20v-if=\x22entry.node\x22>{{\x20entry.node\x20}}</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<if\x20:=\x22entry.context\x20!=\x20null\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<span\x20class=\x22history__has-context\x22>⊕</span>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20\x20\x20</div>\x0a\x0a\x20\x20\x20\x20\x20\x20<!--\x20Expanded\x20context\x20-->\x0a\x20\x20\x20\x20\x20\x20<if\x20:=\x22expandedKeys.has(entry.key)\x20&&\x20entry.context\x20!=\x20null\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20<div\x20class=\x22history__context\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20<pre>{{\x20fmtContext(entry.context)\x20}}</pre>\x0a\x20\x20\x20\x20\x20\x20\x20\x20</div>\x0a\x20\x20\x20\x20\x20\x20</if>\x0a\x20\x20\x20\x20</each>\x0a\x20\x20</div>\x0a\x0a\x20\x20<!--\x20Load\x20more\x20button\x20-->\x0a\x20\x20<if\x20:=\x22hasMore\x22>\x0a\x20\x20\x20\x20<div\x20class=\x22history__footer\x22>\x0a\x20\x20\x20\x20\x20\x20<button\x20@click=\x22load()\x22\x20:disabled=\x22loading\x22\x20class=\x22history__load-more\x22>\x0a\x20\x20\x20\x20\x20\x20\x20\x20{{\x20loading\x20?\x20\x27Loading…\x27\x20:\x20\x27Load\x20More\x27\x20}}\x0a\x20\x20\x20\x20\x20\x20</button>\x0a\x20\x20\x20\x20</div>\x0a\x20\x20</If>\x0a\x0a</div>\x0a','expandedKeys','112CUujLq','splice','var(--okdb-app-fg-muted)','918950VuYARj','node','timeRange','from','All','resetAndLoad','23330weChFc','join','map','#ccc','seenFeatures','now','var(--okdb-warning)'];_0x2a9d=function(){return _0x4c4518;};return _0x2a9d();}(function(_0xb3f6a8,_0x25ed6b){const _0x2a095a=_0x4374,_0xe8e804=_0xb3f6a8();while(!![]){try{const _0x3b808a=parseInt(_0x2a095a(0x221))/0x1+parseInt(_0x2a095a(0x20b))/0x2+-parseInt(_0x2a095a(0x1f9))/0x3*(-parseInt(_0x2a095a(0x200))/0x4)+-parseInt(_0x2a095a(0x202))/0x5+-parseInt(_0x2a095a(0x205))/0x6+parseInt(_0x2a095a(0x1f5))/0x7*(-parseInt(_0x2a095a(0x21e))/0x8)+parseInt(_0x2a095a(0x209))/0x9*(parseInt(_0x2a095a(0x227))/0xa);if(_0x3b808a===_0x25ed6b)break;else _0xe8e804['push'](_0xe8e804['shift']());}catch(_0x4fbe96){_0xe8e804['push'](_0xe8e804['shift']());}}}(_0x2a9d,0xa5c63));function _0x4374(_0x14319e,_0x59d806){_0x14319e=_0x14319e-0x1ed;const _0x2a9d61=_0x2a9d();let _0x43742c=_0x2a9d61[_0x14319e];return _0x43742c;}const e={'info':'var(--okdb-accent)','warn':_0x2b4317(0x1f2),'error':_0x2b4317(0x20f),'debug':_0x2b4317(0x220)},t={'1h':0x36ee80,'6h':0x1499700,'24h':0x5265c00,'7d':0x240c8400,'all':null};export default{'tag':_0x2b4317(0x216),'context':()=>({'level':null,'levels':[],'feature':null,'node':null,'timeRange':_0x2b4317(0x1fe),'entries':[],'seenFeatures':[],'seenNodes':[],'totalCount':0x0,'cursor':null,'hasMore':!0x1,'loading':!0x1,'error':null,'expandedKeys':new Set(),get 'levelsPill'(){const _0x422dbf=_0x2b4317;return 0x0===this['levels'][_0x422dbf(0x1fd)]?_0x422dbf(0x225):this[_0x422dbf(0x1fa)][_0x422dbf(0x1fd)]+_0x422dbf(0x1f3);},get 'timeRangeLabel'(){const _0x40b4cc=_0x2b4317;return _0x40b4cc(0x1fb)===this[_0x40b4cc(0x223)]?_0x40b4cc(0x21b):this[_0x40b4cc(0x223)][_0x40b4cc(0x207)]();},'clearLevels'(){const _0x2777f8=_0x2b4317;this[_0x2777f8(0x1fa)][_0x2777f8(0x21f)](0x0,this[_0x2777f8(0x1fa)][_0x2777f8(0x1fd)]),this[_0x2777f8(0x226)]();},'toggleLevel'(_0x2105a6){const _0x41ed99=_0x2b4317,_0x48eab5=this[_0x41ed99(0x1fa)]['indexOf'](_0x2105a6);_0x48eab5>=0x0?this[_0x41ed99(0x1fa)][_0x41ed99(0x21f)](_0x48eab5,0x1):this['levels'][_0x41ed99(0x211)](_0x2105a6),this[_0x41ed99(0x226)]();},'setTimeRange'(_0x2cfb6c){this['timeRange']=_0x2cfb6c,this['resetAndLoad']();},'setFeature'(_0x218d6c){const _0x11f0f0=_0x2b4317;this['feature']=this[_0x11f0f0(0x217)]===_0x218d6c?null:_0x218d6c,this['resetAndLoad']();},'setNode'(_0x2e25a5){const _0xd538cf=_0x2b4317;this[_0xd538cf(0x222)]=this[_0xd538cf(0x222)]===_0x2e25a5?null:_0x2e25a5,this['resetAndLoad']();},'toggleExpanded'(_0x384de2){const _0x5d91ea=_0x2b4317;this[_0x5d91ea(0x21d)]['has'](_0x384de2)?this[_0x5d91ea(0x21d)]['delete'](_0x384de2):this[_0x5d91ea(0x21d)][_0x5d91ea(0x20c)](_0x384de2);},async 'load'(){const _0x39a816=_0x2b4317;this[_0x39a816(0x1ff)]=!0x0,this[_0x39a816(0x219)]=null;try{const _0x2aab83=Date[_0x39a816(0x1f1)](),_0x1fde21=_0x39a816(0x1fb)===this[_0x39a816(0x223)]?0x0:_0x2aab83-t[this[_0x39a816(0x223)]],_0x290c30=new URLSearchParams();_0x290c30[_0x39a816(0x1f8)](_0x39a816(0x224),String(_0x1fde21)),_0x290c30[_0x39a816(0x1f8)]('to',String(_0x2aab83)),this[_0x39a816(0x1fa)][_0x39a816(0x1fd)]>0x0&&_0x290c30['append'](_0x39a816(0x1fc),this[_0x39a816(0x1fa)][_0x39a816(0x1ed)](',')),this[_0x39a816(0x217)]&&_0x290c30['append'](_0x39a816(0x217),this[_0x39a816(0x217)]),this[_0x39a816(0x222)]&&_0x290c30[_0x39a816(0x1f8)](_0x39a816(0x222),this[_0x39a816(0x222)]),this['cursor']&&_0x290c30[_0x39a816(0x1f8)](_0x39a816(0x20a),String(this[_0x39a816(0x20a)]));const _0x28601b=await fetch(__ENV__[_0x39a816(0x218)]+_0x39a816(0x1f6)+_0x290c30),_0x38a446=await _0x28601b['json']();if(!_0x28601b['ok'])throw new Error(_0x38a446?.[_0x39a816(0x219)]?.['message']||_0x39a816(0x20e));const _0x4152e9=_0x38a446[_0x39a816(0x201)]||_0x38a446['result']||{},_0x1a1189=_0x4152e9['entries']||[];this[_0x39a816(0x20a)]?this[_0x39a816(0x204)][_0x39a816(0x211)](..._0x1a1189):this[_0x39a816(0x204)]=_0x1a1189,this['cursor']=_0x4152e9[_0x39a816(0x215)]??null,this[_0x39a816(0x1f4)]=null!==_0x4152e9[_0x39a816(0x215)];const _0x12447a=new Set(this[_0x39a816(0x204)][_0x39a816(0x1ee)](_0x11c6ca=>_0x11c6ca[_0x39a816(0x217)])['filter'](Boolean)),_0x2d3ff9=new Set(this[_0x39a816(0x204)][_0x39a816(0x1ee)](_0x17d4d0=>_0x17d4d0['node'])['filter'](Boolean));this[_0x39a816(0x1f0)]=Array[_0x39a816(0x224)](_0x12447a)[_0x39a816(0x214)](),this[_0x39a816(0x21a)]=Array[_0x39a816(0x224)](_0x2d3ff9)['sort'](),this[_0x39a816(0x1f7)]=this[_0x39a816(0x204)][_0x39a816(0x1fd)];}catch(_0xfe462e){this[_0x39a816(0x219)]=_0xfe462e?.[_0x39a816(0x203)]||String(_0xfe462e),this[_0x39a816(0x204)]=[];}this[_0x39a816(0x1ff)]=!0x1;},'resetAndLoad'(){const _0x5695ba=_0x2b4317;this['cursor']=null,this[_0x5695ba(0x204)]=[],this[_0x5695ba(0x1f0)]=[],this['seenNodes']=[],this[_0x5695ba(0x21d)][_0x5695ba(0x208)](),this[_0x5695ba(0x20d)]();},'fmtTime'(_0x2edb56){const _0x1db12c=_0x2b4317;if(!_0x2edb56)return'';const _0x1bcd23=new Date(_0x2edb56);return _0x1bcd23[_0x1db12c(0x206)]()['slice'](0x0,0x8)+'.'+String(_0x1bcd23[_0x1db12c(0x213)]())[_0x1db12c(0x210)](0x3,'0');},'fmtContext'(_0x2c880b){const _0x3e1720=_0x2b4317;if(null==_0x2c880b)return'';if('string'==typeof _0x2c880b)return _0x2c880b;try{return JSON[_0x3e1720(0x212)](_0x2c880b);}catch{return String(_0x2c880b);}},'levelColor':_0x5b2232=>e[_0x5b2232]??_0x2b4317(0x1ef)}),'mount'(){const _0x1a33a2=_0x2b4317;this[_0x1a33a2(0x20d)]();},'template':_0x2b4317(0x21c),'style':'.history{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--okdb-app-bg-deep);border-radius:12px;overflow:hidden;border:1px\x20solid\x20var(--okdb-app-border)}.history__toolbar{display:flex;align-items:center;gap:6px;padding:7px\x2010px;background:var(--okdb-app-surface);border-bottom:1px\x20solid\x20var(--okdb-app-border);flex-shrink:0;flex-wrap:wrap}.history__toolbar--sub{padding:5px\x2010px;background:var(--okdb-app-bg-deep);border-bottom:1px\x20solid\x20var(--okdb-app-surface)}.history__title{font-weight:600;font-size:13px;white-space:nowrap;margin-right:2px}.history__label{font-size:10px;opacity:.45;text-transform:uppercase;letter-spacing:.06em;white-space:nowrap;flex-shrink:0}.history__group{display:flex;align-items:center;gap:6px}.history__pills{display:flex;gap:3px;flex-wrap:wrap}.history__spacer{flex:1}.history__count,.pill{font-size:11px;white-space:nowrap}.history__count{opacity:.4;margin-right:4px}.pill{border:1px\x20solid\x20var(--okdb-app-border);background:0\x200;padding:2px\x209px;border-radius:999px;cursor:pointer;color:#666;transition:border-color\x20.12s,color\x20.12s,background\x20.12s}.pill:hover{border-color:var(--okdb-app-fg-muted);color:var(--okdb-app-fg-muted)}.pill:disabled{opacity:.5;cursor:not-allowed}.pill--on{border-color:var(--okdb-accent);background:var(--okdb-app-surface-2);color:var(--okdb-accent)}.history__error{color:var(--okdb-danger);font-size:12px;padding:8px\x2010px;background:var(--okdb-danger-deep-bg);border-bottom:1px\x20solid\x20var(--okdb-app-border)}.history__list{flex:1;overflow-y:auto;font-family:monospace;font-size:12px;padding:2px\x200;min-height:0}.history__row{display:flex;gap:8px;padding:2px\x2010px;border-bottom:1px\x20solid\x20var(--okdb-app-bg-deep);align-items:baseline;min-height:20px;cursor:pointer;transition:background\x20.12s}.history__row:hover{background:var(--okdb-app-surface)}.history__ts{color:var(--okdb-app-fg-muted);flex-shrink:0;font-size:11px;user-select:none;width:86px}.history__level{width:40px;flex-shrink:0;font-weight:700;font-size:10px;text-transform:uppercase;letter-spacing:.04em}.history__feature{flex-shrink:0;font-size:11px;color:var(--okdb-app-fg-muted)}.history__context\x20pre,.history__msg{white-space:pre-wrap;word-break:break-word}.history__msg{flex:1;color:var(--okdb-app-fg);min-width:0}.history__node{flex-shrink:0;font-size:11px;color:var(--okdb-app-fg-muted)}.history__has-context{flex-shrink:0;color:var(--okdb-accent);cursor:pointer;user-select:none}.history__context{background:var(--okdb-app-bg-deep);padding:6px\x2010px\x206px\x2096px;border-bottom:1px\x20solid\x20var(--okdb-app-surface);font-size:11px}.history__context\x20pre{margin:0;color:var(--okdb-app-fg-muted)}.history__empty{padding:24px\x2014px;opacity:.4;font-style:italic;font-size:12px;text-align:center}.history__footer{padding:8px\x2010px;background:var(--okdb-app-surface);border-top:1px\x20solid\x20var(--okdb-app-border);flex-shrink:0;text-align:center}.history__load-more{padding:4px\x2014px;border-radius:6px;font-size:12px;background:var(--okdb-app-surface-2);border:1px\x20solid\x20var(--okdb-app-border);color:var(--okdb-accent);cursor:pointer;transition:background\x20.12s,border-color\x20.12s}.history__load-more:hover{background:var(--okdb-app-surface-2);border-color:var(--okdb-app-fg-muted)}.history__load-more:disabled{opacity:.5;cursor:not-allowed}'};