@walkthru-earth/objex 0.1.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 (367) hide show
  1. package/LICENSE +396 -0
  2. package/README.md +114 -0
  3. package/dist/assets/favicon.svg +17 -0
  4. package/dist/components/CLAUDE.md +44 -0
  5. package/dist/components/browser/Breadcrumb.svelte +50 -0
  6. package/dist/components/browser/Breadcrumb.svelte.d.ts +7 -0
  7. package/dist/components/browser/CreateFolderDialog.svelte +98 -0
  8. package/dist/components/browser/CreateFolderDialog.svelte.d.ts +6 -0
  9. package/dist/components/browser/DeleteConfirmDialog.svelte +90 -0
  10. package/dist/components/browser/DeleteConfirmDialog.svelte.d.ts +8 -0
  11. package/dist/components/browser/DropZone.svelte +83 -0
  12. package/dist/components/browser/DropZone.svelte.d.ts +7 -0
  13. package/dist/components/browser/FileBrowser.svelte +229 -0
  14. package/dist/components/browser/FileBrowser.svelte.d.ts +3 -0
  15. package/dist/components/browser/FileRow.svelte +112 -0
  16. package/dist/components/browser/FileRow.svelte.d.ts +9 -0
  17. package/dist/components/browser/FileTreeSidebar.svelte +559 -0
  18. package/dist/components/browser/FileTreeSidebar.svelte.d.ts +8 -0
  19. package/dist/components/browser/RenameDialog.svelte +101 -0
  20. package/dist/components/browser/RenameDialog.svelte.d.ts +8 -0
  21. package/dist/components/browser/SearchBar.svelte +40 -0
  22. package/dist/components/browser/SearchBar.svelte.d.ts +6 -0
  23. package/dist/components/browser/UploadButton.svelte +65 -0
  24. package/dist/components/browser/UploadButton.svelte.d.ts +3 -0
  25. package/dist/components/editor/CodeMirrorEditor.svelte +404 -0
  26. package/dist/components/editor/CodeMirrorEditor.svelte.d.ts +12 -0
  27. package/dist/components/editor/MilkdownEditor.svelte +98 -0
  28. package/dist/components/editor/MilkdownEditor.svelte.d.ts +9 -0
  29. package/dist/components/editor/SqlEditor.svelte +173 -0
  30. package/dist/components/editor/SqlEditor.svelte.d.ts +7 -0
  31. package/dist/components/editor/SqlResultBlock.svelte +199 -0
  32. package/dist/components/editor/SqlResultBlock.svelte.d.ts +9 -0
  33. package/dist/components/layout/ConnectionDialog.svelte +439 -0
  34. package/dist/components/layout/ConnectionDialog.svelte.d.ts +9 -0
  35. package/dist/components/layout/LocaleToggle.svelte +32 -0
  36. package/dist/components/layout/LocaleToggle.svelte.d.ts +3 -0
  37. package/dist/components/layout/SafeLockToggle.svelte +37 -0
  38. package/dist/components/layout/SafeLockToggle.svelte.d.ts +18 -0
  39. package/dist/components/layout/Sidebar.svelte +314 -0
  40. package/dist/components/layout/Sidebar.svelte.d.ts +3 -0
  41. package/dist/components/layout/StatusBar.svelte +73 -0
  42. package/dist/components/layout/StatusBar.svelte.d.ts +3 -0
  43. package/dist/components/layout/TabBar.svelte +102 -0
  44. package/dist/components/layout/TabBar.svelte.d.ts +7 -0
  45. package/dist/components/layout/ThemeToggle.svelte +52 -0
  46. package/dist/components/layout/ThemeToggle.svelte.d.ts +3 -0
  47. package/dist/components/ui/badge/badge.svelte +49 -0
  48. package/dist/components/ui/badge/badge.svelte.d.ts +32 -0
  49. package/dist/components/ui/badge/index.d.ts +1 -0
  50. package/dist/components/ui/badge/index.js +1 -0
  51. package/dist/components/ui/button/button.svelte +82 -0
  52. package/dist/components/ui/button/button.svelte.d.ts +64 -0
  53. package/dist/components/ui/button/index.d.ts +2 -0
  54. package/dist/components/ui/button/index.js +4 -0
  55. package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte +40 -0
  56. package/dist/components/ui/context-menu/context-menu-checkbox-item.svelte.d.ts +9 -0
  57. package/dist/components/ui/context-menu/context-menu-content.svelte +28 -0
  58. package/dist/components/ui/context-menu/context-menu-content.svelte.d.ts +10 -0
  59. package/dist/components/ui/context-menu/context-menu-group-heading.svelte +21 -0
  60. package/dist/components/ui/context-menu/context-menu-group-heading.svelte.d.ts +7 -0
  61. package/dist/components/ui/context-menu/context-menu-group.svelte +7 -0
  62. package/dist/components/ui/context-menu/context-menu-group.svelte.d.ts +4 -0
  63. package/dist/components/ui/context-menu/context-menu-item.svelte +27 -0
  64. package/dist/components/ui/context-menu/context-menu-item.svelte.d.ts +8 -0
  65. package/dist/components/ui/context-menu/context-menu-label.svelte +24 -0
  66. package/dist/components/ui/context-menu/context-menu-label.svelte.d.ts +8 -0
  67. package/dist/components/ui/context-menu/context-menu-portal.svelte +7 -0
  68. package/dist/components/ui/context-menu/context-menu-portal.svelte.d.ts +3 -0
  69. package/dist/components/ui/context-menu/context-menu-radio-group.svelte +16 -0
  70. package/dist/components/ui/context-menu/context-menu-radio-group.svelte.d.ts +4 -0
  71. package/dist/components/ui/context-menu/context-menu-radio-item.svelte +33 -0
  72. package/dist/components/ui/context-menu/context-menu-radio-item.svelte.d.ts +4 -0
  73. package/dist/components/ui/context-menu/context-menu-separator.svelte +17 -0
  74. package/dist/components/ui/context-menu/context-menu-separator.svelte.d.ts +4 -0
  75. package/dist/components/ui/context-menu/context-menu-shortcut.svelte +20 -0
  76. package/dist/components/ui/context-menu/context-menu-shortcut.svelte.d.ts +5 -0
  77. package/dist/components/ui/context-menu/context-menu-sub-content.svelte +20 -0
  78. package/dist/components/ui/context-menu/context-menu-sub-content.svelte.d.ts +4 -0
  79. package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte +29 -0
  80. package/dist/components/ui/context-menu/context-menu-sub-trigger.svelte.d.ts +8 -0
  81. package/dist/components/ui/context-menu/context-menu-sub.svelte +7 -0
  82. package/dist/components/ui/context-menu/context-menu-sub.svelte.d.ts +3 -0
  83. package/dist/components/ui/context-menu/context-menu-trigger.svelte +7 -0
  84. package/dist/components/ui/context-menu/context-menu-trigger.svelte.d.ts +4 -0
  85. package/dist/components/ui/context-menu/context-menu.svelte +7 -0
  86. package/dist/components/ui/context-menu/context-menu.svelte.d.ts +3 -0
  87. package/dist/components/ui/context-menu/index.d.ts +17 -0
  88. package/dist/components/ui/context-menu/index.js +19 -0
  89. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
  90. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
  91. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +43 -0
  92. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
  93. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +29 -0
  94. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
  95. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
  96. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
  97. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
  98. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
  99. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
  100. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
  101. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +24 -0
  102. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
  103. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
  104. package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
  105. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
  106. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
  107. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +33 -0
  108. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
  109. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
  110. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
  111. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
  112. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
  113. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
  114. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
  115. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
  116. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
  117. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
  118. package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
  119. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
  120. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
  121. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
  122. package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
  123. package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
  124. package/dist/components/ui/dropdown-menu/index.js +18 -0
  125. package/dist/components/ui/input/index.d.ts +2 -0
  126. package/dist/components/ui/input/index.js +4 -0
  127. package/dist/components/ui/input/input.svelte +52 -0
  128. package/dist/components/ui/input/input.svelte.d.ts +13 -0
  129. package/dist/components/ui/resizable/index.d.ts +4 -0
  130. package/dist/components/ui/resizable/index.js +6 -0
  131. package/dist/components/ui/resizable/resizable-handle.svelte +30 -0
  132. package/dist/components/ui/resizable/resizable-handle.svelte.d.ts +8 -0
  133. package/dist/components/ui/resizable/resizable-pane-group.svelte +20 -0
  134. package/dist/components/ui/resizable/resizable-pane-group.svelte.d.ts +7 -0
  135. package/dist/components/ui/scroll-area/index.d.ts +3 -0
  136. package/dist/components/ui/scroll-area/index.js +5 -0
  137. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +31 -0
  138. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +4 -0
  139. package/dist/components/ui/scroll-area/scroll-area.svelte +47 -0
  140. package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +11 -0
  141. package/dist/components/ui/separator/index.d.ts +2 -0
  142. package/dist/components/ui/separator/index.js +4 -0
  143. package/dist/components/ui/separator/separator.svelte +21 -0
  144. package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
  145. package/dist/components/ui/sheet/index.d.ts +11 -0
  146. package/dist/components/ui/sheet/index.js +13 -0
  147. package/dist/components/ui/sheet/sheet-close.svelte +7 -0
  148. package/dist/components/ui/sheet/sheet-close.svelte.d.ts +4 -0
  149. package/dist/components/ui/sheet/sheet-content.svelte +62 -0
  150. package/dist/components/ui/sheet/sheet-content.svelte.d.ts +37 -0
  151. package/dist/components/ui/sheet/sheet-description.svelte +17 -0
  152. package/dist/components/ui/sheet/sheet-description.svelte.d.ts +4 -0
  153. package/dist/components/ui/sheet/sheet-footer.svelte +20 -0
  154. package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +5 -0
  155. package/dist/components/ui/sheet/sheet-header.svelte +20 -0
  156. package/dist/components/ui/sheet/sheet-header.svelte.d.ts +5 -0
  157. package/dist/components/ui/sheet/sheet-overlay.svelte +20 -0
  158. package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
  159. package/dist/components/ui/sheet/sheet-portal.svelte +7 -0
  160. package/dist/components/ui/sheet/sheet-portal.svelte.d.ts +3 -0
  161. package/dist/components/ui/sheet/sheet-title.svelte +13 -0
  162. package/dist/components/ui/sheet/sheet-title.svelte.d.ts +4 -0
  163. package/dist/components/ui/sheet/sheet-trigger.svelte +7 -0
  164. package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
  165. package/dist/components/ui/sheet/sheet.svelte +7 -0
  166. package/dist/components/ui/sheet/sheet.svelte.d.ts +3 -0
  167. package/dist/components/ui/switch/index.d.ts +2 -0
  168. package/dist/components/ui/switch/index.js +4 -0
  169. package/dist/components/ui/switch/switch.svelte +28 -0
  170. package/dist/components/ui/switch/switch.svelte.d.ts +8 -0
  171. package/dist/components/ui/tabs/index.d.ts +5 -0
  172. package/dist/components/ui/tabs/index.js +7 -0
  173. package/dist/components/ui/tabs/tabs-content.svelte +17 -0
  174. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
  175. package/dist/components/ui/tabs/tabs-list.svelte +16 -0
  176. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
  177. package/dist/components/ui/tabs/tabs-trigger.svelte +20 -0
  178. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  179. package/dist/components/ui/tabs/tabs.svelte +19 -0
  180. package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
  181. package/dist/components/ui/tooltip/index.d.ts +6 -0
  182. package/dist/components/ui/tooltip/index.js +8 -0
  183. package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
  184. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
  185. package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
  186. package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
  187. package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
  188. package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
  189. package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
  190. package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
  191. package/dist/components/ui/tooltip/tooltip.svelte +7 -0
  192. package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
  193. package/dist/components/viewers/ArchiveViewer.svelte +586 -0
  194. package/dist/components/viewers/ArchiveViewer.svelte.d.ts +7 -0
  195. package/dist/components/viewers/CLAUDE.md +60 -0
  196. package/dist/components/viewers/CodeViewer.svelte +553 -0
  197. package/dist/components/viewers/CodeViewer.svelte.d.ts +7 -0
  198. package/dist/components/viewers/CogViewer.svelte +1345 -0
  199. package/dist/components/viewers/CogViewer.svelte.d.ts +7 -0
  200. package/dist/components/viewers/CopcViewer.svelte +25 -0
  201. package/dist/components/viewers/CopcViewer.svelte.d.ts +7 -0
  202. package/dist/components/viewers/DatabaseViewer.svelte +169 -0
  203. package/dist/components/viewers/DatabaseViewer.svelte.d.ts +7 -0
  204. package/dist/components/viewers/FileInfo.svelte +174 -0
  205. package/dist/components/viewers/FileInfo.svelte.d.ts +10 -0
  206. package/dist/components/viewers/FlatGeobufViewer.svelte +755 -0
  207. package/dist/components/viewers/FlatGeobufViewer.svelte.d.ts +7 -0
  208. package/dist/components/viewers/GeoParquetMapViewer.svelte +278 -0
  209. package/dist/components/viewers/GeoParquetMapViewer.svelte.d.ts +17 -0
  210. package/dist/components/viewers/ImageViewer.svelte +233 -0
  211. package/dist/components/viewers/ImageViewer.svelte.d.ts +7 -0
  212. package/dist/components/viewers/LoadProgress.svelte +93 -0
  213. package/dist/components/viewers/LoadProgress.svelte.d.ts +15 -0
  214. package/dist/components/viewers/MapViewer.svelte +234 -0
  215. package/dist/components/viewers/MapViewer.svelte.d.ts +7 -0
  216. package/dist/components/viewers/MarkdownViewer.svelte +478 -0
  217. package/dist/components/viewers/MarkdownViewer.svelte.d.ts +7 -0
  218. package/dist/components/viewers/MediaViewer.svelte +121 -0
  219. package/dist/components/viewers/MediaViewer.svelte.d.ts +7 -0
  220. package/dist/components/viewers/ModelViewer.svelte +164 -0
  221. package/dist/components/viewers/ModelViewer.svelte.d.ts +7 -0
  222. package/dist/components/viewers/NotebookViewer.svelte +389 -0
  223. package/dist/components/viewers/NotebookViewer.svelte.d.ts +7 -0
  224. package/dist/components/viewers/PdfViewer.svelte +278 -0
  225. package/dist/components/viewers/PdfViewer.svelte.d.ts +7 -0
  226. package/dist/components/viewers/PmtilesViewer.svelte +191 -0
  227. package/dist/components/viewers/PmtilesViewer.svelte.d.ts +7 -0
  228. package/dist/components/viewers/QueryHistoryPanel.svelte +159 -0
  229. package/dist/components/viewers/QueryHistoryPanel.svelte.d.ts +8 -0
  230. package/dist/components/viewers/RawViewer.svelte +117 -0
  231. package/dist/components/viewers/RawViewer.svelte.d.ts +7 -0
  232. package/dist/components/viewers/StacMapViewer.svelte +20 -0
  233. package/dist/components/viewers/StacMapViewer.svelte.d.ts +7 -0
  234. package/dist/components/viewers/StyleEditorOverlay.svelte +27 -0
  235. package/dist/components/viewers/StyleEditorOverlay.svelte.d.ts +7 -0
  236. package/dist/components/viewers/TableGrid.svelte +355 -0
  237. package/dist/components/viewers/TableGrid.svelte.d.ts +12 -0
  238. package/dist/components/viewers/TableStatusBar.svelte +92 -0
  239. package/dist/components/viewers/TableStatusBar.svelte.d.ts +11 -0
  240. package/dist/components/viewers/TableToolbar.svelte +382 -0
  241. package/dist/components/viewers/TableToolbar.svelte.d.ts +25 -0
  242. package/dist/components/viewers/TableViewer.svelte +923 -0
  243. package/dist/components/viewers/TableViewer.svelte.d.ts +7 -0
  244. package/dist/components/viewers/ViewerRouter.svelte +70 -0
  245. package/dist/components/viewers/ViewerRouter.svelte.d.ts +7 -0
  246. package/dist/components/viewers/ZarrMapViewer.svelte +288 -0
  247. package/dist/components/viewers/ZarrMapViewer.svelte.d.ts +17 -0
  248. package/dist/components/viewers/ZarrViewer.svelte +256 -0
  249. package/dist/components/viewers/ZarrViewer.svelte.d.ts +7 -0
  250. package/dist/components/viewers/map/AttributeTable.svelte +52 -0
  251. package/dist/components/viewers/map/AttributeTable.svelte.d.ts +8 -0
  252. package/dist/components/viewers/map/MapContainer.svelte +158 -0
  253. package/dist/components/viewers/map/MapContainer.svelte.d.ts +12 -0
  254. package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte +389 -0
  255. package/dist/components/viewers/pmtiles/PmtilesArchiveView.svelte.d.ts +10 -0
  256. package/dist/components/viewers/pmtiles/PmtilesMapView.svelte +332 -0
  257. package/dist/components/viewers/pmtiles/PmtilesMapView.svelte.d.ts +11 -0
  258. package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte +373 -0
  259. package/dist/components/viewers/pmtiles/PmtilesTileInspector.svelte.d.ts +12 -0
  260. package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte +112 -0
  261. package/dist/components/viewers/pmtiles/SvgTileRenderer.svelte.d.ts +10 -0
  262. package/dist/file-icons/CLAUDE.md +21 -0
  263. package/dist/file-icons/FileTypeIcon.svelte +74 -0
  264. package/dist/file-icons/FileTypeIcon.svelte.d.ts +9 -0
  265. package/dist/file-icons/index.d.ts +56 -0
  266. package/dist/file-icons/index.js +1070 -0
  267. package/dist/i18n/CLAUDE.md +19 -0
  268. package/dist/i18n/ar.d.ts +1 -0
  269. package/dist/i18n/ar.js +404 -0
  270. package/dist/i18n/en.d.ts +1 -0
  271. package/dist/i18n/en.js +404 -0
  272. package/dist/i18n/index.svelte.d.ts +9 -0
  273. package/dist/i18n/index.svelte.js +27 -0
  274. package/dist/index.d.ts +20 -0
  275. package/dist/index.js +13 -0
  276. package/dist/query/CLAUDE.md +22 -0
  277. package/dist/query/engine.d.ts +56 -0
  278. package/dist/query/engine.js +6 -0
  279. package/dist/query/index.d.ts +4 -0
  280. package/dist/query/index.js +19 -0
  281. package/dist/query/wasm.d.ts +20 -0
  282. package/dist/query/wasm.js +890 -0
  283. package/dist/storage/CLAUDE.md +23 -0
  284. package/dist/storage/adapter.d.ts +21 -0
  285. package/dist/storage/adapter.js +1 -0
  286. package/dist/storage/browser-azure.d.ts +25 -0
  287. package/dist/storage/browser-azure.js +271 -0
  288. package/dist/storage/browser-cloud.d.ts +32 -0
  289. package/dist/storage/browser-cloud.js +293 -0
  290. package/dist/storage/index.d.ts +11 -0
  291. package/dist/storage/index.js +37 -0
  292. package/dist/storage/url-adapter.d.ts +19 -0
  293. package/dist/storage/url-adapter.js +51 -0
  294. package/dist/stores/CLAUDE.md +29 -0
  295. package/dist/stores/browser.svelte.d.ts +28 -0
  296. package/dist/stores/browser.svelte.js +160 -0
  297. package/dist/stores/connections.svelte.d.ts +56 -0
  298. package/dist/stores/connections.svelte.js +272 -0
  299. package/dist/stores/credentials.svelte.d.ts +56 -0
  300. package/dist/stores/credentials.svelte.js +79 -0
  301. package/dist/stores/files.svelte.d.ts +20 -0
  302. package/dist/stores/files.svelte.js +76 -0
  303. package/dist/stores/query-history.svelte.d.ts +16 -0
  304. package/dist/stores/query-history.svelte.js +57 -0
  305. package/dist/stores/safelock.svelte.d.ts +8 -0
  306. package/dist/stores/safelock.svelte.js +52 -0
  307. package/dist/stores/settings.svelte.d.ts +11 -0
  308. package/dist/stores/settings.svelte.js +101 -0
  309. package/dist/stores/tab-resources.svelte.d.ts +25 -0
  310. package/dist/stores/tab-resources.svelte.js +61 -0
  311. package/dist/stores/tabs.svelte.d.ts +17 -0
  312. package/dist/stores/tabs.svelte.js +110 -0
  313. package/dist/types/notebookjs.d.ts +14 -0
  314. package/dist/types.d.ts +47 -0
  315. package/dist/types.js +1 -0
  316. package/dist/utils/CLAUDE.md +54 -0
  317. package/dist/utils/analytics.d.ts +10 -0
  318. package/dist/utils/analytics.js +38 -0
  319. package/dist/utils/archive.d.ts +70 -0
  320. package/dist/utils/archive.js +333 -0
  321. package/dist/utils/column-types.d.ts +5 -0
  322. package/dist/utils/column-types.js +137 -0
  323. package/dist/utils/deck.d.ts +98 -0
  324. package/dist/utils/deck.js +208 -0
  325. package/dist/utils/evidence-context.d.ts +22 -0
  326. package/dist/utils/evidence-context.js +56 -0
  327. package/dist/utils/export.d.ts +2 -0
  328. package/dist/utils/export.js +51 -0
  329. package/dist/utils/format.d.ts +14 -0
  330. package/dist/utils/format.js +56 -0
  331. package/dist/utils/geoarrow.d.ts +32 -0
  332. package/dist/utils/geoarrow.js +672 -0
  333. package/dist/utils/hex.d.ts +10 -0
  334. package/dist/utils/hex.js +27 -0
  335. package/dist/utils/host-detection.d.ts +23 -0
  336. package/dist/utils/host-detection.js +289 -0
  337. package/dist/utils/map-selection.d.ts +12 -0
  338. package/dist/utils/map-selection.js +45 -0
  339. package/dist/utils/markdown-sql.d.ts +30 -0
  340. package/dist/utils/markdown-sql.js +73 -0
  341. package/dist/utils/markdown.d.ts +18 -0
  342. package/dist/utils/markdown.js +146 -0
  343. package/dist/utils/model3d.d.ts +13 -0
  344. package/dist/utils/model3d.js +62 -0
  345. package/dist/utils/parquet-metadata.d.ts +58 -0
  346. package/dist/utils/parquet-metadata.js +228 -0
  347. package/dist/utils/pdf.d.ts +8 -0
  348. package/dist/utils/pdf.js +28 -0
  349. package/dist/utils/pmtiles-tile.d.ts +38 -0
  350. package/dist/utils/pmtiles-tile.js +64 -0
  351. package/dist/utils/pmtiles.d.ts +46 -0
  352. package/dist/utils/pmtiles.js +135 -0
  353. package/dist/utils/shiki.d.ts +8 -0
  354. package/dist/utils/shiki.js +98 -0
  355. package/dist/utils/storage-url.d.ts +64 -0
  356. package/dist/utils/storage-url.js +374 -0
  357. package/dist/utils/url-state.d.ts +40 -0
  358. package/dist/utils/url-state.js +113 -0
  359. package/dist/utils/url.d.ts +27 -0
  360. package/dist/utils/url.js +115 -0
  361. package/dist/utils/wkb.d.ts +43 -0
  362. package/dist/utils/wkb.js +345 -0
  363. package/dist/utils/zarr.d.ts +39 -0
  364. package/dist/utils/zarr.js +204 -0
  365. package/dist/utils.d.ts +12 -0
  366. package/dist/utils.js +5 -0
  367. package/package.json +203 -0
@@ -0,0 +1,37 @@
1
+ import { connectionStore } from '../stores/connections.svelte.js';
2
+ import { BrowserAzureAdapter } from './browser-azure.js';
3
+ import { BrowserCloudAdapter } from './browser-cloud.js';
4
+ import { UrlAdapter } from './url-adapter.js';
5
+ const adapterCache = new Map();
6
+ // Singleton UrlAdapter — stateless, no connection needed
7
+ const urlAdapter = new UrlAdapter();
8
+ /**
9
+ * Returns the appropriate storage adapter for the given source.
10
+ * Caches adapter instances per connectionId.
11
+ */
12
+ export function getAdapter(source, connectionId) {
13
+ if (source === 'url') {
14
+ return urlAdapter;
15
+ }
16
+ if (!connectionId) {
17
+ throw new Error('A connectionId is required for remote storage adapters.');
18
+ }
19
+ let adapter = adapterCache.get(connectionId);
20
+ if (adapter)
21
+ return adapter;
22
+ const conn = connectionStore.getById(connectionId);
23
+ if (conn?.provider === 'azure') {
24
+ adapter = new BrowserAzureAdapter(connectionId);
25
+ }
26
+ else {
27
+ adapter = new BrowserCloudAdapter(connectionId);
28
+ }
29
+ adapterCache.set(connectionId, adapter);
30
+ return adapter;
31
+ }
32
+ /**
33
+ * Clear cached adapter for a connection (call on connection update/delete).
34
+ */
35
+ export function clearAdapterCache(connectionId) {
36
+ adapterCache.delete(connectionId);
37
+ }
@@ -0,0 +1,19 @@
1
+ import type { FileEntry, WriteResult } from '../types.js';
2
+ import type { StorageAdapter } from './adapter.js';
3
+ /**
4
+ * Minimal adapter for direct HTTPS URLs (source: 'url').
5
+ * Only supports read/head — no listing or writing.
6
+ * The `path` parameter is the full HTTPS URL.
7
+ */
8
+ export declare class UrlAdapter implements StorageAdapter {
9
+ readonly supportsWrite = false;
10
+ read(url: string, offset?: number, length?: number, signal?: AbortSignal): Promise<Uint8Array>;
11
+ head(url: string, signal?: AbortSignal): Promise<FileEntry>;
12
+ list(): Promise<FileEntry[]>;
13
+ put(): Promise<WriteResult>;
14
+ delete(): Promise<void>;
15
+ deletePrefix(): Promise<{
16
+ deleted: number;
17
+ }>;
18
+ copy(): Promise<WriteResult>;
19
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Minimal adapter for direct HTTPS URLs (source: 'url').
3
+ * Only supports read/head — no listing or writing.
4
+ * The `path` parameter is the full HTTPS URL.
5
+ */
6
+ export class UrlAdapter {
7
+ supportsWrite = false;
8
+ async read(url, offset, length, signal) {
9
+ const headers = {};
10
+ if (offset !== undefined && length !== undefined) {
11
+ headers.Range = `bytes=${offset}-${offset + length - 1}`;
12
+ }
13
+ else if (offset !== undefined) {
14
+ headers.Range = `bytes=${offset}-`;
15
+ }
16
+ const res = await fetch(url, { headers, signal });
17
+ if (!res.ok)
18
+ throw new Error(`HTTP ${res.status}: ${res.statusText}`);
19
+ return new Uint8Array(await res.arrayBuffer());
20
+ }
21
+ async head(url, signal) {
22
+ const res = await fetch(url, { method: 'HEAD', signal });
23
+ if (!res.ok)
24
+ throw new Error(`HTTP ${res.status}: ${res.statusText}`);
25
+ const name = url.split('/').pop()?.split('?')[0] || 'file';
26
+ const ext = name.includes('.') ? name.split('.').pop().toLowerCase() : '';
27
+ return {
28
+ name,
29
+ path: url,
30
+ is_dir: false,
31
+ size: Number(res.headers.get('content-length') || 0),
32
+ modified: new Date(res.headers.get('last-modified') || 0).getTime(),
33
+ extension: ext
34
+ };
35
+ }
36
+ async list() {
37
+ return [];
38
+ }
39
+ async put() {
40
+ throw new Error('Write not supported for direct URL sources');
41
+ }
42
+ async delete() {
43
+ throw new Error('Delete not supported for direct URL sources');
44
+ }
45
+ async deletePrefix() {
46
+ throw new Error('Delete not supported for direct URL sources');
47
+ }
48
+ async copy() {
49
+ throw new Error('Copy not supported for direct URL sources');
50
+ }
51
+ }
@@ -0,0 +1,29 @@
1
+ # stores/
2
+
3
+ Svelte 5 rune-based stores. All use `$state` / `$state.raw` / `$derived`.
4
+
5
+ ```mermaid
6
+ graph LR
7
+ CONN[connections.svelte.ts] --> CRED[credentials.svelte.ts]
8
+ TABS[tabs.svelte.ts] --> TR[tab-resources.svelte.ts]
9
+ FILES[files.svelte.ts] --> CONN
10
+ BR[browser.svelte.ts] --> FILES
11
+ SET[settings.svelte.ts]
12
+ QH[query-history.svelte.ts]
13
+ SL[safelock.svelte.ts]
14
+ ```
15
+
16
+ | File | Export | Used by |
17
+ |------|--------|--------|
18
+ | `connections.svelte.ts` | `connectionStore` | url.ts, browser-azure, browser-cloud, storage/index, ConnectionDialog, Sidebar, TableToolbar, +page.svelte |
19
+ | `credentials.svelte.ts` | `credentialStore` | url.ts, browser-azure, browser-cloud, Sidebar, query/wasm |
20
+ | `tabs.svelte.ts` | `tabStore` | StatusBar, TabBar, Sidebar, FileRow, FileTreeSidebar, +page.svelte |
21
+ | `tab-resources.svelte.ts` | `tabResources` | CogViewer, TableViewer, FlatGeobufViewer, ArchiveViewer, ModelViewer, GeoParquetMapViewer, DatabaseViewer, MediaViewer, PdfViewer, RawViewer, MarkdownViewer, ZarrMapViewer, NotebookViewer, MapViewer, CodeViewer, ImageViewer, PmtilesViewer |
22
+ | `files.svelte.ts` | `fileStore` | StatusBar |
23
+ | `browser.svelte.ts` | `browser` | StatusBar, Sidebar, FileBrowser, DropZone, UploadButton, FileRow, DeleteConfirmDialog, FileTreeSidebar, RenameDialog, CreateFolderDialog, +page.svelte |
24
+ | `settings.svelte.ts` | `settings` | LocaleToggle, ThemeToggle, scroll-area, TableViewer, FlatGeobufViewer, GeoParquetMapViewer, MapContainer, CodeMirrorEditor, +layout.svelte |
25
+ | `query-history.svelte.ts` | `queryHistory` | TableViewer, QueryHistoryPanel, SqlEditor |
26
+ | `safelock.svelte.ts` | `safeLock` | SafeLockToggle, FileBrowser, DropZone, FileRow |
27
+
28
+ All stores are module-level singletons (SPA, no SSR).
29
+ Use `$state.raw` for arrays >100 items. Credentials never touch localStorage.
@@ -0,0 +1,28 @@
1
+ import type { Connection, FileEntry } from '../types.js';
2
+ export declare const browser: {
3
+ readonly activeConnection: Connection | null;
4
+ readonly currentPrefix: string;
5
+ readonly entries: FileEntry[];
6
+ readonly loading: boolean;
7
+ readonly error: string | null;
8
+ readonly uploading: boolean;
9
+ readonly uploadProgress: {
10
+ current: number;
11
+ total: number;
12
+ };
13
+ readonly canWrite: boolean;
14
+ browse: (connection: Connection, prefix?: string) => Promise<void>;
15
+ navigateTo: (prefix: string) => Promise<void>;
16
+ navigateUp: () => Promise<void>;
17
+ clear: () => void;
18
+ refresh: () => Promise<void>;
19
+ uploadFile: (fileName: string, data: Uint8Array, contentType?: string) => Promise<void>;
20
+ uploadFiles: (files: Array<{
21
+ name: string;
22
+ data: Uint8Array;
23
+ type?: string;
24
+ }>) => Promise<void>;
25
+ deleteEntry: (entry: FileEntry) => Promise<void>;
26
+ renameEntry: (entry: FileEntry, newName: string) => Promise<void>;
27
+ createFolder: (name: string) => Promise<void>;
28
+ };
@@ -0,0 +1,160 @@
1
+ import { getAdapter } from '../storage/index.js';
2
+ import { credentialStore } from './credentials.svelte.js';
3
+ import { safeLock } from './safelock.svelte.js';
4
+ function createBrowserStore() {
5
+ let activeConnection = $state(null);
6
+ let currentPrefix = $state('');
7
+ let entries = $state([]);
8
+ let loading = $state(false);
9
+ let error = $state(null);
10
+ let uploading = $state(false);
11
+ let uploadProgress = $state({ current: 0, total: 0 });
12
+ async function browse(connection, prefix) {
13
+ activeConnection = connection;
14
+ const startPrefix = prefix ?? connection.rootPrefix ?? '';
15
+ currentPrefix = startPrefix;
16
+ loading = true;
17
+ error = null;
18
+ entries = [];
19
+ try {
20
+ const adapter = getAdapter('remote', connection.id);
21
+ const result = await adapter.list(startPrefix);
22
+ entries = result;
23
+ }
24
+ catch (e) {
25
+ error = e instanceof Error ? e.message : String(e);
26
+ }
27
+ finally {
28
+ loading = false;
29
+ }
30
+ }
31
+ async function navigateTo(prefix) {
32
+ if (!activeConnection)
33
+ return;
34
+ await browse(activeConnection, prefix);
35
+ }
36
+ async function navigateUp() {
37
+ if (!activeConnection || !currentPrefix)
38
+ return;
39
+ const parts = currentPrefix.replace(/\/+$/, '').split('/');
40
+ parts.pop();
41
+ const parent = parts.length > 0 ? `${parts.join('/')}/` : '';
42
+ await browse(activeConnection, parent);
43
+ }
44
+ function clear() {
45
+ activeConnection = null;
46
+ currentPrefix = '';
47
+ entries = [];
48
+ loading = false;
49
+ error = null;
50
+ }
51
+ async function refresh() {
52
+ if (!activeConnection)
53
+ return;
54
+ await browse(activeConnection, currentPrefix);
55
+ }
56
+ function assertWritable() {
57
+ if (safeLock.locked)
58
+ throw new Error('Safe lock is enabled. Unlock to perform write operations.');
59
+ if (!activeConnection)
60
+ throw new Error('No active connection.');
61
+ }
62
+ async function uploadFile(fileName, data, contentType) {
63
+ assertWritable();
64
+ const adapter = getAdapter('remote', activeConnection.id);
65
+ const key = currentPrefix + fileName;
66
+ await adapter.put(key, data, contentType);
67
+ }
68
+ async function uploadFiles(files) {
69
+ assertWritable();
70
+ uploading = true;
71
+ uploadProgress = { current: 0, total: files.length };
72
+ try {
73
+ for (const file of files) {
74
+ await uploadFile(file.name, file.data, file.type);
75
+ uploadProgress = { current: uploadProgress.current + 1, total: files.length };
76
+ }
77
+ await refresh();
78
+ }
79
+ finally {
80
+ uploading = false;
81
+ uploadProgress = { current: 0, total: 0 };
82
+ }
83
+ }
84
+ async function deleteEntry(entry) {
85
+ assertWritable();
86
+ const adapter = getAdapter('remote', activeConnection.id);
87
+ if (entry.is_dir) {
88
+ await adapter.deletePrefix(entry.path);
89
+ }
90
+ else {
91
+ await adapter.delete(entry.path);
92
+ }
93
+ await refresh();
94
+ }
95
+ async function renameEntry(entry, newName) {
96
+ assertWritable();
97
+ if (newName === entry.name)
98
+ throw new Error('New name is the same as the current name.');
99
+ const adapter = getAdapter('remote', activeConnection.id);
100
+ // Build the new key by replacing the last segment
101
+ const parentPrefix = entry.path.replace(/[^/]*\/?$/, '');
102
+ const newKey = entry.is_dir ? `${parentPrefix + newName}/` : parentPrefix + newName;
103
+ await adapter.copy(entry.path, newKey);
104
+ if (entry.is_dir) {
105
+ await adapter.deletePrefix(entry.path);
106
+ }
107
+ else {
108
+ await adapter.delete(entry.path);
109
+ }
110
+ await refresh();
111
+ }
112
+ async function createFolder(name) {
113
+ assertWritable();
114
+ const adapter = getAdapter('remote', activeConnection.id);
115
+ const key = `${currentPrefix + name}/`;
116
+ await adapter.put(key, new Uint8Array(0));
117
+ await refresh();
118
+ }
119
+ return {
120
+ get activeConnection() {
121
+ return activeConnection;
122
+ },
123
+ get currentPrefix() {
124
+ return currentPrefix;
125
+ },
126
+ get entries() {
127
+ return entries;
128
+ },
129
+ get loading() {
130
+ return loading;
131
+ },
132
+ get error() {
133
+ return error;
134
+ },
135
+ get uploading() {
136
+ return uploading;
137
+ },
138
+ get uploadProgress() {
139
+ return uploadProgress;
140
+ },
141
+ get canWrite() {
142
+ if (!activeConnection)
143
+ return false;
144
+ if (activeConnection.anonymous)
145
+ return false;
146
+ return credentialStore.has(activeConnection.id);
147
+ },
148
+ browse,
149
+ navigateTo,
150
+ navigateUp,
151
+ clear,
152
+ refresh,
153
+ uploadFile,
154
+ uploadFiles,
155
+ deleteEntry,
156
+ renameEntry,
157
+ createFolder
158
+ };
159
+ }
160
+ export const browser = createBrowserStore();
@@ -0,0 +1,56 @@
1
+ import type { Connection, ConnectionConfig } from '../types.js';
2
+ import type { DetectedHost } from '../utils/host-detection.js';
3
+ export declare const connectionStore: {
4
+ readonly items: Connection[];
5
+ readonly loaded: boolean;
6
+ /**
7
+ * Load connections from localStorage.
8
+ * Safe to call multiple times — subsequent calls are no-ops.
9
+ */
10
+ load(): Promise<void>;
11
+ /**
12
+ * Force-reload connections.
13
+ */
14
+ reload(): Promise<void>;
15
+ /**
16
+ * Save a new connection to localStorage.
17
+ */
18
+ save(config: ConnectionConfig): Promise<string | null>;
19
+ /**
20
+ * Update an existing connection.
21
+ */
22
+ update(id: string, config: ConnectionConfig): Promise<boolean>;
23
+ /**
24
+ * Remove a connection by ID.
25
+ */
26
+ remove(id: string): Promise<boolean>;
27
+ /**
28
+ * Test whether a connection is reachable via a lightweight list.
29
+ */
30
+ test(id: string): Promise<boolean>;
31
+ /**
32
+ * Test a connection using provided config values (works for both new
33
+ * and existing connections without saving first).
34
+ */
35
+ testWithConfig(config: ConnectionConfig, existingId?: string): Promise<boolean>;
36
+ /** True when a dialog open has been requested and not yet consumed. */
37
+ readonly dialogRequested: boolean;
38
+ /** Request opening the new-connection dialog from anywhere. */
39
+ requestDialog(): void;
40
+ /** Mark the dialog request as consumed. */
41
+ clearDialogRequest(): void;
42
+ /**
43
+ * Synchronous lookup by ID (from the already-loaded list).
44
+ */
45
+ getById(id: string): Connection | undefined;
46
+ /**
47
+ * Find an existing connection that matches bucket + endpoint.
48
+ */
49
+ findByBucketEndpoint(bucket: string, endpoint: string): Connection | undefined;
50
+ /**
51
+ * Create a connection from a DetectedHost, deduplicating by bucket+endpoint.
52
+ * Returns the connection ID (existing or newly created).
53
+ */
54
+ saveHostConnection(detected: DetectedHost): Promise<string>;
55
+ };
56
+ export { connectionStore as connections };
@@ -0,0 +1,272 @@
1
+ import { credentialStore, storeToNative } from './credentials.svelte.js';
2
+ const CONNECTIONS_KEY = 'obstore-explore-connections';
3
+ // ---------------------------------------------------------------------------
4
+ // localStorage helpers
5
+ // ---------------------------------------------------------------------------
6
+ function loadFromLocalStorage() {
7
+ if (typeof window === 'undefined')
8
+ return [];
9
+ try {
10
+ const raw = localStorage.getItem(CONNECTIONS_KEY);
11
+ if (raw) {
12
+ return JSON.parse(raw);
13
+ }
14
+ }
15
+ catch {
16
+ // ignore parse errors
17
+ }
18
+ return [];
19
+ }
20
+ function persistToLocalStorage(connections) {
21
+ if (typeof window === 'undefined')
22
+ return;
23
+ try {
24
+ localStorage.setItem(CONNECTIONS_KEY, JSON.stringify(connections));
25
+ }
26
+ catch {
27
+ // ignore storage errors
28
+ }
29
+ }
30
+ // ---------------------------------------------------------------------------
31
+ // Store
32
+ // ---------------------------------------------------------------------------
33
+ function createConnectionsStore() {
34
+ let connections = $state([]);
35
+ let loaded = $state(false);
36
+ let dialogRequest = $state(0);
37
+ return {
38
+ get items() {
39
+ return connections;
40
+ },
41
+ get loaded() {
42
+ return loaded;
43
+ },
44
+ /**
45
+ * Load connections from localStorage.
46
+ * Safe to call multiple times — subsequent calls are no-ops.
47
+ */
48
+ async load() {
49
+ if (loaded)
50
+ return;
51
+ connections = loadFromLocalStorage();
52
+ loaded = true;
53
+ },
54
+ /**
55
+ * Force-reload connections.
56
+ */
57
+ async reload() {
58
+ loaded = false;
59
+ await this.load();
60
+ },
61
+ /**
62
+ * Save a new connection to localStorage.
63
+ */
64
+ async save(config) {
65
+ const id = crypto.randomUUID();
66
+ const conn = {
67
+ id,
68
+ name: config.name,
69
+ provider: config.provider,
70
+ endpoint: config.endpoint,
71
+ bucket: config.bucket,
72
+ region: config.region,
73
+ anonymous: config.anonymous,
74
+ authMethod: config.authMethod,
75
+ rootPrefix: config.rootPrefix
76
+ };
77
+ connections = [...connections, conn];
78
+ persistToLocalStorage(connections);
79
+ // Store credentials in memory (never persisted to localStorage).
80
+ if (!config.anonymous) {
81
+ if (config.sas_token) {
82
+ const creds = { type: 'sas-token', sasToken: config.sas_token };
83
+ credentialStore.set(id, creds);
84
+ storeToNative(id, creds).catch(() => { });
85
+ }
86
+ else if (config.access_key && config.secret_key) {
87
+ const creds = {
88
+ type: 'sigv4',
89
+ accessKey: config.access_key,
90
+ secretKey: config.secret_key
91
+ };
92
+ credentialStore.set(id, creds);
93
+ storeToNative(id, creds).catch(() => { });
94
+ }
95
+ }
96
+ return id;
97
+ },
98
+ /**
99
+ * Update an existing connection.
100
+ */
101
+ async update(id, config) {
102
+ const idx = connections.findIndex((c) => c.id === id);
103
+ if (idx === -1)
104
+ return false;
105
+ connections[idx] = {
106
+ ...connections[idx],
107
+ name: config.name,
108
+ provider: config.provider,
109
+ endpoint: config.endpoint,
110
+ bucket: config.bucket,
111
+ region: config.region,
112
+ anonymous: config.anonymous,
113
+ authMethod: config.authMethod,
114
+ rootPrefix: config.rootPrefix
115
+ };
116
+ connections = [...connections];
117
+ persistToLocalStorage(connections);
118
+ // Invalidate cached adapter for this connection
119
+ import('../storage/index.js').then(({ clearAdapterCache }) => clearAdapterCache(id));
120
+ // Update in-memory credentials.
121
+ if (!config.anonymous) {
122
+ if (config.sas_token) {
123
+ const creds = { type: 'sas-token', sasToken: config.sas_token };
124
+ credentialStore.set(id, creds);
125
+ storeToNative(id, creds).catch(() => { });
126
+ }
127
+ else if (config.access_key && config.secret_key) {
128
+ const creds = {
129
+ type: 'sigv4',
130
+ accessKey: config.access_key,
131
+ secretKey: config.secret_key
132
+ };
133
+ credentialStore.set(id, creds);
134
+ storeToNative(id, creds).catch(() => { });
135
+ }
136
+ else {
137
+ credentialStore.remove(id);
138
+ }
139
+ }
140
+ else {
141
+ credentialStore.remove(id);
142
+ }
143
+ return true;
144
+ },
145
+ /**
146
+ * Remove a connection by ID.
147
+ */
148
+ async remove(id) {
149
+ const before = connections.length;
150
+ connections = connections.filter((c) => c.id !== id);
151
+ persistToLocalStorage(connections);
152
+ credentialStore.remove(id);
153
+ // Invalidate cached adapter for this connection
154
+ import('../storage/index.js').then(({ clearAdapterCache }) => clearAdapterCache(id));
155
+ return connections.length < before;
156
+ },
157
+ /**
158
+ * Test whether a connection is reachable via a lightweight list.
159
+ */
160
+ async test(id) {
161
+ const { getAdapter } = await import(/* @vite-ignore */ '$lib/storage/index.js');
162
+ const adapter = getAdapter('remote', id);
163
+ await adapter.list('');
164
+ return true;
165
+ },
166
+ /**
167
+ * Test a connection using provided config values (works for both new
168
+ * and existing connections without saving first).
169
+ */
170
+ async testWithConfig(config, existingId) {
171
+ const tempId = existingId ?? `temp-test-${Date.now()}`;
172
+ const tempConn = {
173
+ id: tempId,
174
+ name: config.name,
175
+ provider: config.provider,
176
+ endpoint: config.endpoint,
177
+ bucket: config.bucket,
178
+ region: config.region,
179
+ anonymous: config.anonymous,
180
+ authMethod: config.authMethod,
181
+ rootPrefix: config.rootPrefix
182
+ };
183
+ // Temporarily register connection + credentials so the adapter can find them
184
+ const hadConn = connections.some((c) => c.id === tempId);
185
+ const prevCreds = credentialStore.get(tempId);
186
+ if (!hadConn) {
187
+ connections = [...connections, tempConn];
188
+ // Don't persist — this is a temp test connection
189
+ }
190
+ if (!config.anonymous) {
191
+ if (config.sas_token) {
192
+ credentialStore.set(tempId, { type: 'sas-token', sasToken: config.sas_token });
193
+ }
194
+ else if (config.access_key && config.secret_key) {
195
+ credentialStore.set(tempId, {
196
+ type: 'sigv4',
197
+ accessKey: config.access_key,
198
+ secretKey: config.secret_key
199
+ });
200
+ }
201
+ }
202
+ try {
203
+ const { getAdapter } = await import(/* @vite-ignore */ '$lib/storage/index.js');
204
+ const adapter = getAdapter('remote', tempId);
205
+ await adapter.list(config.rootPrefix || '');
206
+ return true;
207
+ }
208
+ finally {
209
+ // Cleanup: remove temp connection if we added it
210
+ if (!hadConn) {
211
+ connections = connections.filter((c) => c.id !== tempId);
212
+ // Don't persist — was never in localStorage
213
+ }
214
+ // Restore previous credentials or remove temp ones
215
+ if (prevCreds) {
216
+ credentialStore.set(tempId, prevCreds);
217
+ }
218
+ else if (!hadConn) {
219
+ credentialStore.remove(tempId);
220
+ }
221
+ // Also clear any cached adapter for the temp connection
222
+ import('../storage/index.js').then(({ clearAdapterCache }) => clearAdapterCache(tempId));
223
+ }
224
+ },
225
+ /** True when a dialog open has been requested and not yet consumed. */
226
+ get dialogRequested() {
227
+ return dialogRequest > 0;
228
+ },
229
+ /** Request opening the new-connection dialog from anywhere. */
230
+ requestDialog() {
231
+ dialogRequest++;
232
+ },
233
+ /** Mark the dialog request as consumed. */
234
+ clearDialogRequest() {
235
+ dialogRequest = 0;
236
+ },
237
+ /**
238
+ * Synchronous lookup by ID (from the already-loaded list).
239
+ */
240
+ getById(id) {
241
+ return connections.find((c) => c.id === id);
242
+ },
243
+ /**
244
+ * Find an existing connection that matches bucket + endpoint.
245
+ */
246
+ findByBucketEndpoint(bucket, endpoint) {
247
+ return connections.find((c) => c.bucket === bucket && c.endpoint === endpoint);
248
+ },
249
+ /**
250
+ * Create a connection from a DetectedHost, deduplicating by bucket+endpoint.
251
+ * Returns the connection ID (existing or newly created).
252
+ */
253
+ async saveHostConnection(detected) {
254
+ const existing = this.findByBucketEndpoint(detected.bucket, detected.endpoint);
255
+ if (existing)
256
+ return existing.id;
257
+ const name = detected.bucket === '$web' ? `Azure Static Web` : detected.bucket;
258
+ const id = await this.save({
259
+ name,
260
+ provider: detected.provider === 'unknown' ? 's3' : detected.provider,
261
+ endpoint: detected.endpoint,
262
+ bucket: detected.bucket,
263
+ region: detected.region,
264
+ anonymous: true,
265
+ rootPrefix: detected.rootPrefix || undefined
266
+ });
267
+ return id;
268
+ }
269
+ };
270
+ }
271
+ export const connectionStore = createConnectionsStore();
272
+ export { connectionStore as connections };