@marimo-team/frontend 0.23.16-dev4 → 0.23.16-dev40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{CellStatus-BalYv0pK.js → CellStatus-C6Cj3oJc.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-DI7mV-Gw.js → ConnectedDataExplorerComponent-CMaZapRd.js} +1 -1
- package/dist/assets/{ErrorBoundary-C7_5jjWi.js → ErrorBoundary-DzTD8LVq.js} +1 -1
- package/dist/assets/{ImperativeModal-BIavOiUv.js → ImperativeModal-fY-ZfT0b.js} +1 -1
- package/dist/assets/{JsonOutput-CkCD-FgM.js → JsonOutput-CyzvjIjx.js} +12 -12
- package/dist/assets/{LazyAnyLanguageCodeMirror-sVm_hz8A.js → LazyAnyLanguageCodeMirror-B2JvSXP-.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-DO2k2fA5.js → MarimoErrorOutput-CIuzXFFo.js} +4 -4
- package/dist/assets/{RSPContexts-CgC81f0I.js → RSPContexts-WiCgGm__.js} +1 -1
- package/dist/assets/RenderHTML-Cd-PP5ZR.js +1 -0
- package/dist/assets/{RunButton-BKRupqr7.js → RunButton-CnYWedW4.js} +1 -1
- package/dist/assets/{add-cell-with-ai-CEZtaZCK.js → add-cell-with-ai-ByOBQT99.js} +8 -8
- package/dist/assets/add-connection-dialog-C97ylgk0.js +170 -0
- package/dist/assets/{agent-panel-CHB6t7Zy.js → agent-panel-Dxo9WUKV.js} +5 -5
- package/dist/assets/ai-model-dropdown-Bvqy98cI.js +5 -0
- package/dist/assets/{alert-dialog-BXegNC0I.js → alert-dialog-Bb8Lz8ko.js} +1 -1
- package/dist/assets/{any-language-editor-DCpZRrpx.js → any-language-editor--tRHs8C_.js} +1 -1
- package/dist/assets/{app-config-button-NrM9ywXA.js → app-config-button-v1lG63C2.js} +1 -1
- package/dist/assets/{button-eIihcbUw.js → button-DDGiD1NW.js} +1 -1
- package/dist/assets/{cache-panel-wllSTlbM.js → cache-panel-DcQUeUpg.js} +1 -1
- package/dist/assets/{capabilities-B09j1Eor.js → capabilities-DoEg0XwL.js} +1 -1
- package/dist/assets/{cell-editor-B5JVq7_q.js → cell-editor-BKrHbyX_.js} +16 -16
- package/dist/assets/cell-link-w5IbCQV4.js +1 -0
- package/dist/assets/cells-DzyDERZy.js +235 -0
- package/dist/assets/{chat-display-BG08ltQ3.js → chat-display-Ccgk4vbE.js} +1 -1
- package/dist/assets/{chat-panel-P2CzCtXJ.js → chat-panel--53TIc3t.js} +4 -4
- package/dist/assets/{chat-ui-fAJZAoTD.js → chat-ui-B5rBxgsw.js} +4 -4
- package/dist/assets/{column-preview-Dne1dIt0.js → column-preview-Cb8R9kfl.js} +1 -1
- package/dist/assets/{command-CAJLPEBq.js → command-Dqxie4gq.js} +1 -1
- package/dist/assets/{command-palette-iOCqUIs1.js → command-palette-B1S9PjZi.js} +1 -1
- package/dist/assets/{common-CD6Mj8n6.js → common-CJ3baa6D.js} +1 -1
- package/dist/assets/components-DpUIWGaj.js +1 -0
- package/dist/assets/config-B-Q7J_6d.js +1 -0
- package/dist/assets/{config-COUOIPEq.js → config-BJVx3eBW.js} +1 -1
- package/dist/assets/{copy-BtTOqPTS.js → copy-Bxb1_Gtw.js} +1 -1
- package/dist/assets/{copy-icon-C2pG0ZNK.js → copy-icon-neDQUo4Q.js} +1 -1
- package/dist/assets/{createReducer-C7kZ8zEe.js → createReducer-DGx5Af-C.js} +1 -1
- package/dist/assets/{datasource-ySAiC9gr.js → datasource-D_VcQMEn.js} +2 -2
- package/dist/assets/{dates-D-kIKDYA.js → dates-C2LWzsCZ.js} +1 -1
- package/dist/assets/{dependency-graph-panel-BF23EwcD.js → dependency-graph-panel-DY5lvPDx.js} +3 -3
- package/dist/assets/{dialog-D1DEsRZ2.js → dialog-BCVepWLJ.js} +1 -1
- package/dist/assets/{dist-ByVeMWkr.js → dist-BLN8PNJV.js} +1 -1
- package/dist/assets/dist-CiVShZKM.js +2 -0
- package/dist/assets/{documentation-panel-e9Fi9R7e.js → documentation-panel-CGhwxsXK.js} +1 -1
- package/dist/assets/download-DpS57jyt.js +9 -0
- package/dist/assets/{dropdown-menu-BFZLnWeO.js → dropdown-menu-dHmZR8bI.js} +1 -1
- package/dist/assets/{edit-page-7X3HYey7.js → edit-page-DA765yQV.js} +6 -6
- package/dist/assets/{error-banner-B6eIlxzg.js → error-banner-BSxEOIn2.js} +1 -1
- package/dist/assets/error-entries-CTYMwfsh.js +8 -0
- package/dist/assets/{error-panel-DdsUL6b7.js → error-panel-DGAkG5kW.js} +1 -1
- package/dist/assets/{es-1D83cgiu.js → es-gYgfF8y5.js} +1 -1
- package/dist/assets/{esm-BL7jQmzn.js → esm-B30N1GS0.js} +1 -1
- package/dist/assets/{field-BeZbVzXA.js → field-BsxD35VE.js} +1 -1
- package/dist/assets/{file-explorer-panel-Ntq1-VbF.js → file-explorer-panel-BKUo-MDh.js} +3 -3
- package/dist/assets/{file-icons-Cb54mIL8.js → file-icons-DfWENcb8.js} +1 -1
- package/dist/assets/{file-name-input-BWFcK1ey.js → file-name-input-CNVZtm5K.js} +1 -1
- package/dist/assets/floating-outline-LitP0wCD.js +1 -0
- package/dist/assets/focus-CNKbm-Xz.js +1 -0
- package/dist/assets/{form-B6BkSCJb.js → form-nHzLTU1m.js} +2 -2
- package/dist/assets/{formats-ClEFGPy-.js → formats-DzmLpc9A.js} +1 -1
- package/dist/assets/{formatting-B_41gSF5.js → formatting-CDf6w1Kt.js} +1 -1
- package/dist/assets/{fullscreen-dUjPYOmm.js → fullscreen-CTDqNQr6.js} +1 -1
- package/dist/assets/{gallery-page-CWQQAYpa.js → gallery-page-CJ3ms1Hn.js} +1 -1
- package/dist/assets/{glide-data-editor-lMARFWHS.js → glide-data-editor-j2igs9Y_.js} +1 -1
- package/dist/assets/home-page-DM9Z_IJ7.js +4 -0
- package/dist/assets/{html-to-image-CwmX28T9.js → html-to-image-JaxFFZcr.js} +2 -2
- package/dist/assets/index-C7_REKh1.js +38 -0
- package/dist/assets/index-D6Dp_PFj.css +2 -0
- package/dist/assets/{input-CqrUjynb.js → input-JxFwu-3G.js} +1 -1
- package/dist/assets/kiosk-mode-BumOFEtY.js +1 -0
- package/dist/assets/{label-BElwWzf0.js → label-CqjrpwRC.js} +1 -1
- package/dist/assets/{layout-CUlZijwG.js → layout-B29hqiiK.js} +5 -5
- package/dist/assets/{links-CToBjIIj.js → links-CZr5bjvo.js} +1 -1
- package/dist/assets/logs-panel-CQRPYS8j.js +1 -0
- package/dist/assets/{markdown-renderer-QvXG0CRk.js → markdown-renderer-sEayY9-m.js} +2 -2
- package/dist/assets/{menu-items-DbSLBfXR.js → menu-items-CCi6aOPm.js} +1 -1
- package/dist/assets/{mermaid-Bh0flEIb.js → mermaid-CYN0wOyG.js} +1 -1
- package/dist/assets/{name-cell-input-C6cukQ9k.js → name-cell-input-B-aj1KH3.js} +1 -1
- package/dist/assets/node-sql-parser-Si4oZ2P-.js +68 -0
- package/dist/assets/{numbers-CeeaFKqu.js → numbers-rmawRqQP.js} +1 -1
- package/dist/assets/{outline-panel-BPlg9_CE.js → outline-panel-BOryk60D.js} +1 -1
- package/dist/assets/{packages-panel-BzQF60rG.js → packages-panel-DoYDLty3.js} +1 -1
- package/dist/assets/pair-with-agent-modal-BCRSACei.js +4 -0
- package/dist/assets/panels-Bb4fIHgH.js +4 -0
- package/dist/assets/{popover-DrHQ3KEt.js → popover-Bcz1Zikb.js} +1 -1
- package/dist/assets/process-output-d-LEMtGI.js +1 -0
- package/dist/assets/{radio-group-CLBjGkt5.js → radio-group-DfioQthW.js} +1 -1
- package/dist/assets/{readonly-code-display-D63oRtBP.js → readonly-code-display-C9fu8tvK.js} +1 -1
- package/dist/assets/{readonly-python-code-CW_G5e4E.js → readonly-python-code-DHxOnQGj.js} +1 -1
- package/dist/assets/{renderShortcut-BZLr8D7H.js → renderShortcut-Bl8_FVn8.js} +1 -1
- package/dist/assets/{reveal-component-BLMTmd8T.js → reveal-component-5jf0W625.js} +60 -60
- package/dist/assets/{run-page-B6pgDYEJ.js → run-page-BMKx9ld_.js} +1 -1
- package/dist/assets/{runs-D51Xwrsk.js → runs-DBTXqJHS.js} +1 -1
- package/dist/assets/scratchpad-panel-C8z8vzBX.js +1 -0
- package/dist/assets/{scroll-to-bottom-button-Cgr10kaJ.js → scroll-to-bottom-button-C8yfT4wq.js} +1 -1
- package/dist/assets/{secrets-panel-Cc5KDBk6.js → secrets-panel-6J6wcuVR.js} +1 -1
- package/dist/assets/{select-B5TFNjmU.js → select-BP75_5jJ.js} +1 -1
- package/dist/assets/{session-CEFnN9Cq.js → session-BmukRjSi.js} +1 -1
- package/dist/assets/{session-panel-Y0Oon0sD.js → session-panel-BVVk-02h.js} +1 -1
- package/dist/assets/{share-CYpcX4N4.js → share-852X_cqy.js} +1 -1
- package/dist/assets/{skeleton-D3QPxqWC.js → skeleton-Bubr9pIj.js} +1 -1
- package/dist/assets/slides-DkEgzTJB.css +1 -0
- package/dist/assets/{snippets-panel-CXpGflMO.js → snippets-panel-U2-iok-c.js} +1 -1
- package/dist/assets/{spec-CzqcmYQk.js → spec-C7opZZRp.js} +1 -1
- package/dist/assets/{state-BvdK8eiw.js → state-D10U2MwA.js} +1 -1
- package/dist/assets/{state-WBgc7MiA.js → state-DDag0B_B.js} +1 -1
- package/dist/assets/state-DtziTd1T.js +3 -0
- package/dist/assets/{state-DBzEQtWz.js → state-DxQhUsG9.js} +1 -1
- package/dist/assets/{strings-Djnbwmfl.js → strings--BknHX9C.js} +1 -1
- package/dist/assets/{swiper-component-DInvCxhI.js → swiper-component-g8EXE911.js} +1 -1
- package/dist/assets/switch-OVajJBPR.js +1 -0
- package/dist/assets/{terminal-D3IQBBYo.js → terminal-217O8hlZ.js} +1 -1
- package/dist/assets/{textarea-CpFfEUet.js → textarea-Bmzmbbpo.js} +1 -1
- package/dist/assets/{tooltip-CFX4fYHU.js → tooltip-4bZlU7jl.js} +1 -1
- package/dist/assets/{tooltip-HLb6RxVp.js → tooltip-B7U4xkIN.js} +1 -1
- package/dist/assets/{tracing-CKn3gWHw.js → tracing-B5XFvMmV.js} +1 -1
- package/dist/assets/{tracing-panel-BU-o_LCd.js → tracing-panel-DnR2bYDe.js} +2 -2
- package/dist/assets/{tree-actions-CsC2XmGo.js → tree-actions-Dx9CDaxV.js} +1 -1
- package/dist/assets/{useBoolean-D89u30n-.js → useBoolean-CFj86iac.js} +1 -1
- package/dist/assets/useCellActionButton-DypR3yDt.js +1 -0
- package/dist/assets/{useDeleteCell-EPH4kcG7.js → useDeleteCell-vMXAr3rY.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-CZnK7N2L.js → useDependencyPanelTab-CwdwKf7A.js} +1 -1
- package/dist/assets/useEventListener-C0195JsF.js +1 -0
- package/dist/assets/{useHotkey-DIuRH8Wu.js → useHotkey-DLZvrRZT.js} +1 -1
- package/dist/assets/{useIframeCapabilities-Ccb4fvKc.js → useIframeCapabilities-j6fR_dBA.js} +1 -1
- package/dist/assets/{useInstallPackage-BRbUAUFn.js → useInstallPackage-WiYBwhUO.js} +1 -1
- package/dist/assets/{useInterval-CC0vKpWm.js → useInterval-CWBTUy5W.js} +1 -1
- package/dist/assets/useNotebookActions-jWIcmpv0.js +12 -0
- package/dist/assets/{useRunCells-CSSF_mJ0.js → useRunCells-C2dvU2jA.js} +1 -1
- package/dist/assets/{useSplitCell-9Qz93yPZ.js → useSplitCell-C1tubdNi.js} +1 -1
- package/dist/assets/{useTheme-KXqAyDPC.js → useTheme-Bxv9B31g.js} +1 -1
- package/dist/assets/{utils-Z80SV4_d.js → utils-BWBBpCkT.js} +1 -1
- package/dist/assets/{vega-component-Cie3ag_T.js → vega-component-Db8KjZJG.js} +1 -1
- package/dist/assets/{write-secret-modal-DEEn7sZV.js → write-secret-modal-3-v-dHVj.js} +1 -1
- package/dist/index.html +68 -68
- package/package.json +3 -4
- package/src/__mocks__/requests.ts +45 -4
- package/src/components/data-table/__tests__/__snapshots__/chart-spec-model.test.ts.snap +174 -21
- package/src/components/data-table/__tests__/chart-spec-model.test.ts +102 -1
- package/src/components/data-table/column-summary/chart-spec-model.tsx +163 -103
- package/src/components/data-table/column-summary/legacy-chart-spec.ts +15 -7
- package/src/components/data-table/column-summary/utils.ts +26 -7
- package/src/components/data-table/types.ts +1 -1
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +99 -18
- package/src/components/editor/actions/__tests__/pdf-export.test.ts +0 -4
- package/src/components/editor/actions/pair-with-agent-commands.ts +21 -10
- package/src/components/editor/actions/pair-with-agent-modal.tsx +2 -2
- package/src/components/editor/actions/pdf-export.ts +1 -4
- package/src/components/editor/actions/useNotebookActions.tsx +7 -13
- package/src/components/editor/cell/code/__tests__/cell-editor-activity-lifecycle.test.ts +250 -0
- package/src/components/editor/cell/code/cell-editor.tsx +13 -7
- package/src/components/editor/chrome/panels/__tests__/logs-panel.test.tsx +25 -0
- package/src/components/editor/chrome/panels/logs-panel.tsx +12 -2
- package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap +50 -0
- package/src/components/editor/connections/storage/__tests__/as-code.test.ts +87 -8
- package/src/components/editor/connections/storage/as-code.ts +40 -21
- package/src/components/editor/connections/storage/schemas.ts +83 -42
- package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +1 -1
- package/src/components/slides/__tests__/cell-output-block.test.tsx +40 -0
- package/src/components/slides/__tests__/slide-cell-view.test.tsx +33 -0
- package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +198 -0
- package/src/components/slides/reveal-component.tsx +25 -19
- package/src/components/slides/slide-cell-view.tsx +1 -1
- package/src/components/slides/slide-scroll-hint.tsx +161 -0
- package/src/components/slides/slides.css +4 -2
- package/src/components/static-html/share-modal.tsx +1 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/core/cells/__tests__/cells.test.ts +12 -2
- package/src/core/cells/__tests__/logs.test.ts +5 -5
- package/src/core/cells/cells.ts +17 -4
- package/src/core/cells/document-changes.ts +1 -0
- package/src/core/cells/logs.ts +14 -4
- package/src/core/codemirror/copilot/__tests__/language-server.test.ts +396 -100
- package/src/core/codemirror/copilot/__tests__/transport.test.ts +128 -540
- package/src/core/codemirror/copilot/language-server.ts +182 -70
- package/src/core/codemirror/copilot/transport.ts +15 -207
- package/src/core/codemirror/copilot/types.ts +9 -2
- package/src/core/codemirror/find-replace/__tests__/navigate.test.ts +42 -30
- package/src/core/codemirror/find-replace/navigate.ts +2 -0
- package/src/core/codemirror/go-to-definition/__tests__/commands.test.ts +24 -3
- package/src/core/codemirror/go-to-definition/commands.ts +3 -0
- package/src/core/codemirror/keymaps/__tests__/keymaps.test.ts +31 -2
- package/src/core/codemirror/keymaps/keymaps.ts +12 -0
- package/src/core/codemirror/language/__tests__/sql.test.ts +443 -61
- package/src/core/codemirror/language/languages/python.ts +23 -11
- package/src/core/codemirror/language/languages/sql/completion-store.ts +5 -1
- package/src/core/codemirror/language/languages/sql/sql.ts +210 -3
- package/src/core/codemirror/lsp/__tests__/federated-lsp.test.ts +161 -0
- package/src/core/codemirror/lsp/__tests__/log-messages.test.ts +53 -0
- package/src/core/codemirror/lsp/__tests__/normalize-markdown-math.test.ts +25 -0
- package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +598 -156
- package/src/core/codemirror/lsp/__tests__/transports.test.ts +112 -0
- package/src/core/codemirror/lsp/federated-lsp.ts +76 -23
- package/src/core/codemirror/lsp/log-messages.ts +37 -0
- package/src/core/codemirror/lsp/normalize-markdown-math.ts +8 -4
- package/src/core/codemirror/lsp/notebook-lsp.ts +220 -56
- package/src/core/codemirror/lsp/transports.ts +8 -1
- package/src/core/codemirror/lsp/types.ts +68 -8
- package/src/core/codemirror/lsp/utils.ts +14 -0
- package/src/core/codemirror/utils.ts +28 -0
- package/src/core/hotkeys/hotkeys.ts +0 -2
- package/src/core/islands/__tests__/bridge.test.ts +107 -0
- package/src/core/islands/bridge.ts +16 -0
- package/src/core/lsp/__tests__/transport.test.ts +509 -337
- package/src/core/lsp/transport.ts +304 -132
- package/src/core/mode.ts +10 -0
- package/src/core/network/__tests__/api.test.ts +42 -0
- package/src/core/network/__tests__/connection.test.ts +45 -0
- package/src/core/network/__tests__/requests-lazy.test.ts +32 -1
- package/src/core/network/__tests__/requests-network.test.ts +21 -0
- package/src/core/network/api.ts +27 -0
- package/src/core/network/connection.ts +15 -0
- package/src/core/network/requests-lazy.ts +1 -0
- package/src/core/network/requests-network.ts +14 -8
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.tsx +1 -0
- package/src/core/network/types.ts +22 -6
- package/src/core/rtc/state.ts +9 -0
- package/src/core/static/download-html.ts +5 -14
- package/src/core/wasm/bridge.ts +4 -2
- package/src/core/wasm/worker/types.ts +5 -2
- package/src/css/app/codemirror.css +16 -2
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/__tests__/FormPlugin.test.tsx +162 -0
- package/src/stories/log-viewer.stories.tsx +12 -6
- package/src/utils/__tests__/download.test.tsx +24 -1
- package/src/utils/download.ts +11 -6
- package/dist/assets/RenderHTML-BCvU9dYz.js +0 -1
- package/dist/assets/add-connection-dialog-B-jCRNTN.js +0 -170
- package/dist/assets/ai-model-dropdown-DXgLphFa.js +0 -5
- package/dist/assets/cell-link-DqBkyAFe.js +0 -1
- package/dist/assets/cells-Cf7bHHq3.js +0 -229
- package/dist/assets/components-BH6gDVv6.js +0 -1
- package/dist/assets/config-BbOTTCYY.js +0 -1
- package/dist/assets/dist-BCMBu0rO.js +0 -2
- package/dist/assets/download-BomYt3nl.js +0 -9
- package/dist/assets/error-entries-Birw-8VX.js +0 -8
- package/dist/assets/floating-outline-wz-WSRgP.js +0 -1
- package/dist/assets/focus-DiEyfiAG.js +0 -1
- package/dist/assets/home-page-DJ4jJsZj.js +0 -4
- package/dist/assets/index-A71LAt6h.css +0 -2
- package/dist/assets/index-CMZzy-dF.js +0 -38
- package/dist/assets/kiosk-mode-ABm3oYgq.js +0 -1
- package/dist/assets/logs-panel-iFV4ZJ9b.js +0 -1
- package/dist/assets/node-sql-parser-BWgUjcfV.js +0 -68
- package/dist/assets/pair-with-agent-modal-CKOYwOYw.js +0 -4
- package/dist/assets/panels-Dj45fW-v.js +0 -4
- package/dist/assets/process-output-BEhIGfkO.js +0 -1
- package/dist/assets/scratchpad-panel-B0mEqBNk.js +0 -1
- package/dist/assets/slides-MCbMDtlY.css +0 -1
- package/dist/assets/state-BZQc7xxL.js +0 -3
- package/dist/assets/switch-CvweaCXq.js +0 -1
- package/dist/assets/useCellActionButton-CRfIEVB5.js +0 -1
- package/dist/assets/useEventListener-B_w3A283.js +0 -1
- package/dist/assets/useNotebookActions-DTXAoukG.js +0 -12
|
@@ -39,7 +39,7 @@ import type { UserConfig } from "@/core/config/config-schema";
|
|
|
39
39
|
import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
40
40
|
import { connectionAtom } from "@/core/network/connection";
|
|
41
41
|
import { useRequestClient } from "@/core/network/requests";
|
|
42
|
-
import { isRtcEnabled } from "@/core/rtc/state";
|
|
42
|
+
import { canUseRtc, isRtcEnabled } from "@/core/rtc/state";
|
|
43
43
|
import { useSaveNotebook } from "@/core/saving/save-component";
|
|
44
44
|
import { isAppConnecting } from "@/core/websocket/connection-utils";
|
|
45
45
|
import type { Theme } from "@/theme/useTheme";
|
|
@@ -342,7 +342,7 @@ const CellEditorInternal = ({
|
|
|
342
342
|
saveOrNameNotebook,
|
|
343
343
|
]);
|
|
344
344
|
|
|
345
|
-
const rtcEnabled = isRtcEnabled();
|
|
345
|
+
const rtcEnabled = isRtcEnabled() && canUseRtc(cellId);
|
|
346
346
|
const handleInitializeEditor = useEvent(() => {
|
|
347
347
|
// If rtc is enabled, use collaborative editing
|
|
348
348
|
if (rtcEnabled) {
|
|
@@ -451,6 +451,7 @@ const CellEditorInternal = ({
|
|
|
451
451
|
setIsEditorMounted(true);
|
|
452
452
|
return;
|
|
453
453
|
}
|
|
454
|
+
setIsEditorMounted(false);
|
|
454
455
|
if (serializedEditorState !== null) {
|
|
455
456
|
handleDeserializeEditor();
|
|
456
457
|
setIsEditorMounted(true);
|
|
@@ -479,11 +480,12 @@ const CellEditorInternal = ({
|
|
|
479
480
|
handleReconfigureEditor();
|
|
480
481
|
}, [handleReconfigureEditor, extensions, editorViewRef]);
|
|
481
482
|
|
|
482
|
-
// Destroy the editor when the component is unmounted
|
|
483
|
+
// Destroy the editor when the component is unmounted. Read the ref in cleanup
|
|
484
|
+
// (not setup) so Activity hide/show cycles don't leave a stale destroyed view.
|
|
483
485
|
useEffect(() => {
|
|
484
|
-
const ev = editorViewRef.current;
|
|
485
486
|
return () => {
|
|
486
|
-
|
|
487
|
+
editorViewRef.current?.destroy();
|
|
488
|
+
editorViewRef.current = null;
|
|
487
489
|
};
|
|
488
490
|
}, [editorViewRef]);
|
|
489
491
|
|
|
@@ -635,14 +637,18 @@ CellCodeMirrorEditor.displayName = "CellCodeMirrorEditor";
|
|
|
635
637
|
// Wait until the websocket connection is open before rendering the editor
|
|
636
638
|
// This is used for real-time collaboration since the backend needs the connection started
|
|
637
639
|
// before connecting the rtc websockets
|
|
638
|
-
function WithWaitUntilConnected<T extends
|
|
640
|
+
function WithWaitUntilConnected<T extends Pick<CellEditorProps, "id">>(
|
|
639
641
|
Component: React.ComponentType<T>,
|
|
640
642
|
) {
|
|
641
643
|
const WaitUntilConnectedComponent = (props: T) => {
|
|
642
644
|
const connection = useAtomValue(connectionAtom);
|
|
643
645
|
const [rtcDoc, setRtcDoc] = useAtom(connectedDocAtom);
|
|
644
646
|
|
|
645
|
-
if (
|
|
647
|
+
if (
|
|
648
|
+
isRtcEnabled() &&
|
|
649
|
+
canUseRtc(props.id) &&
|
|
650
|
+
(isAppConnecting(connection.state) || rtcDoc === undefined)
|
|
651
|
+
) {
|
|
646
652
|
return (
|
|
647
653
|
<div className="flex h-full w-full items-baseline p-4">
|
|
648
654
|
<DelayMount milliseconds={1000} fallback={null}>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { render, screen } from "@testing-library/react";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import type { CellLog } from "@/core/cells/logs";
|
|
6
|
+
import { LogViewer } from "../logs-panel";
|
|
7
|
+
|
|
8
|
+
describe("LogViewer", () => {
|
|
9
|
+
it("labels logs that came from a language server instead of a cell", () => {
|
|
10
|
+
const logs: CellLog[] = [
|
|
11
|
+
{
|
|
12
|
+
timestamp: 0,
|
|
13
|
+
level: "stderr",
|
|
14
|
+
message: "pylsp failed to start",
|
|
15
|
+
source: { type: "lsp", name: "pylsp" },
|
|
16
|
+
},
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
render(<LogViewer logs={logs} />);
|
|
20
|
+
|
|
21
|
+
expect(screen.getByText("(lsp:pylsp)")).toBeInTheDocument();
|
|
22
|
+
expect(screen.getByText("pylsp failed to start")).toBeInTheDocument();
|
|
23
|
+
expect(screen.getByText("STDERR")).toBeInTheDocument();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -4,7 +4,11 @@ import { FileTextIcon } from "lucide-react";
|
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { ClearButton } from "@/components/buttons/clear-button";
|
|
6
6
|
import { useCellActions, useCellLogs } from "@/core/cells/cells";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
type CellLog,
|
|
9
|
+
formatLogTimestamp,
|
|
10
|
+
logSourceLabel,
|
|
11
|
+
} from "@/core/cells/logs";
|
|
8
12
|
import { cn } from "@/utils/cn";
|
|
9
13
|
import { CellLink } from "../../links/cell-link";
|
|
10
14
|
import { PanelEmptyState } from "./empty-state";
|
|
@@ -84,7 +88,13 @@ function formatLog(log: CellLog) {
|
|
|
84
88
|
</span>
|
|
85
89
|
<span className={cn("shrink-0", color)}>{level}</span>
|
|
86
90
|
<span className="shrink-0 text-(--gray-10)">
|
|
87
|
-
(
|
|
91
|
+
(
|
|
92
|
+
{log.source.type === "cell" ? (
|
|
93
|
+
<CellLink cellId={log.source.cellId} />
|
|
94
|
+
) : (
|
|
95
|
+
logSourceLabel(log.source)
|
|
96
|
+
)}
|
|
97
|
+
)
|
|
88
98
|
</span>
|
|
89
99
|
{log.message}
|
|
90
100
|
</>
|
package/src/components/editor/connections/storage/__tests__/__snapshots__/as-code.test.ts.snap
CHANGED
|
@@ -51,6 +51,21 @@ store = S3Store("operator-bucket",
|
|
|
51
51
|
)"
|
|
52
52
|
`;
|
|
53
53
|
|
|
54
|
+
exports[`generateStorageCode > CoreWeave > with container credentials 1`] = `
|
|
55
|
+
"from obstore.store import S3Store
|
|
56
|
+
import os
|
|
57
|
+
|
|
58
|
+
_container_credentials_full_uri = os.environ.get("AWS_CONTAINER_CREDENTIALS_FULL_URI")
|
|
59
|
+
_container_authorization_token_file = os.environ.get("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE")
|
|
60
|
+
store = S3Store("operator-bucket",
|
|
61
|
+
region="US-EAST-04A",
|
|
62
|
+
container_credentials_full_uri=_container_credentials_full_uri,
|
|
63
|
+
container_authorization_token_file=_container_authorization_token_file,
|
|
64
|
+
endpoint="https://operator-bucket.cwobject.com",
|
|
65
|
+
virtual_hosted_style_request=True,
|
|
66
|
+
)"
|
|
67
|
+
`;
|
|
68
|
+
|
|
54
69
|
exports[`generateStorageCode > CoreWeave > with secrets 1`] = `
|
|
55
70
|
"from obstore.store import S3Store
|
|
56
71
|
import os
|
|
@@ -119,6 +134,29 @@ exports[`generateStorageCode > S3 > minimal connection (bucket only) 1`] = `
|
|
|
119
134
|
store = S3Store("my-bucket",)"
|
|
120
135
|
`;
|
|
121
136
|
|
|
137
|
+
exports[`generateStorageCode > S3 > with container credentials 1`] = `
|
|
138
|
+
"from obstore.store import S3Store
|
|
139
|
+
|
|
140
|
+
store = S3Store("my-bucket",
|
|
141
|
+
region="us-east-1",
|
|
142
|
+
container_credentials_full_uri="http://169.254.170.23/v1/credentials",
|
|
143
|
+
container_authorization_token_file="/var/run/secrets/token",
|
|
144
|
+
)"
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
exports[`generateStorageCode > S3 > with container credentials from secrets 1`] = `
|
|
148
|
+
"from obstore.store import S3Store
|
|
149
|
+
import os
|
|
150
|
+
|
|
151
|
+
_container_credentials_full_uri = os.environ.get("AWS_CONTAINER_CREDENTIALS_FULL_URI")
|
|
152
|
+
_container_authorization_token_file = os.environ.get("AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE")
|
|
153
|
+
store = S3Store("my-bucket",
|
|
154
|
+
region="us-east-1",
|
|
155
|
+
container_credentials_full_uri=_container_credentials_full_uri,
|
|
156
|
+
container_authorization_token_file=_container_authorization_token_file,
|
|
157
|
+
)"
|
|
158
|
+
`;
|
|
159
|
+
|
|
122
160
|
exports[`generateStorageCode > S3 > with custom endpoint 1`] = `
|
|
123
161
|
"from obstore.store import S3Store
|
|
124
162
|
|
|
@@ -130,6 +168,18 @@ store = S3Store("my-bucket",
|
|
|
130
168
|
)"
|
|
131
169
|
`;
|
|
132
170
|
|
|
171
|
+
exports[`generateStorageCode > S3 > with plain-http endpoint 1`] = `
|
|
172
|
+
"from obstore.store import S3Store
|
|
173
|
+
|
|
174
|
+
store = S3Store("my-bucket",
|
|
175
|
+
region="us-east-1",
|
|
176
|
+
access_key_id="AKIAIOSFODNN7EXAMPLE",
|
|
177
|
+
secret_access_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
178
|
+
endpoint_url="http://cwlota.com",
|
|
179
|
+
allow_http=True,
|
|
180
|
+
)"
|
|
181
|
+
`;
|
|
182
|
+
|
|
133
183
|
exports[`generateStorageCode > S3 > with secrets 1`] = `
|
|
134
184
|
"from obstore.store import S3Store
|
|
135
185
|
import os
|
|
@@ -9,9 +9,13 @@ describe("generateStorageCode", () => {
|
|
|
9
9
|
type: "s3",
|
|
10
10
|
bucket: "my-bucket",
|
|
11
11
|
region: "us-east-1",
|
|
12
|
-
access_key_id: "AKIAIOSFODNN7EXAMPLE",
|
|
13
|
-
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
14
12
|
endpoint_url: undefined,
|
|
13
|
+
allow_http: false,
|
|
14
|
+
auth: {
|
|
15
|
+
type: "Access keys",
|
|
16
|
+
access_key_id: "AKIAIOSFODNN7EXAMPLE",
|
|
17
|
+
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
18
|
+
},
|
|
15
19
|
};
|
|
16
20
|
|
|
17
21
|
const baseGCS: StorageConnection = {
|
|
@@ -31,8 +35,11 @@ describe("generateStorageCode", () => {
|
|
|
31
35
|
type: "coreweave",
|
|
32
36
|
bucket: "operator-bucket",
|
|
33
37
|
region: "US-EAST-04A",
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
auth: {
|
|
39
|
+
type: "Access keys",
|
|
40
|
+
access_key_id: "AKIAIOSFODNN7EXAMPLE",
|
|
41
|
+
secret_access_key: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
|
|
42
|
+
},
|
|
36
43
|
};
|
|
37
44
|
|
|
38
45
|
const baseGDrive: StorageConnection = {
|
|
@@ -52,6 +59,8 @@ describe("generateStorageCode", () => {
|
|
|
52
59
|
const conn: StorageConnection = {
|
|
53
60
|
type: "s3",
|
|
54
61
|
bucket: "my-bucket",
|
|
62
|
+
allow_http: false,
|
|
63
|
+
auth: { type: "Access keys" },
|
|
55
64
|
};
|
|
56
65
|
expect(
|
|
57
66
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -68,13 +77,61 @@ describe("generateStorageCode", () => {
|
|
|
68
77
|
).toMatchSnapshot();
|
|
69
78
|
});
|
|
70
79
|
|
|
80
|
+
it("with plain-http endpoint", () => {
|
|
81
|
+
const conn: StorageConnection = {
|
|
82
|
+
...baseS3,
|
|
83
|
+
endpoint_url: "http://cwlota.com",
|
|
84
|
+
allow_http: true,
|
|
85
|
+
};
|
|
86
|
+
expect(
|
|
87
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
88
|
+
).toMatchSnapshot();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("with container credentials", () => {
|
|
92
|
+
const conn: StorageConnection = {
|
|
93
|
+
...baseS3,
|
|
94
|
+
auth: {
|
|
95
|
+
type: "Container credentials",
|
|
96
|
+
container_credentials_full_uri:
|
|
97
|
+
"http://169.254.170.23/v1/credentials",
|
|
98
|
+
container_authorization_token_file: "/var/run/secrets/token",
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
expect(
|
|
102
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
103
|
+
).toMatchSnapshot();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("with container credentials from secrets", () => {
|
|
107
|
+
const conn: StorageConnection = {
|
|
108
|
+
...baseS3,
|
|
109
|
+
auth: {
|
|
110
|
+
type: "Container credentials",
|
|
111
|
+
container_credentials_full_uri: prefixSecret(
|
|
112
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
|
|
113
|
+
),
|
|
114
|
+
container_authorization_token_file: prefixSecret(
|
|
115
|
+
"AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE",
|
|
116
|
+
),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
expect(
|
|
120
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
121
|
+
).toMatchSnapshot();
|
|
122
|
+
});
|
|
123
|
+
|
|
71
124
|
it("with secrets", () => {
|
|
72
125
|
const conn: StorageConnection = {
|
|
73
126
|
type: "s3",
|
|
74
127
|
bucket: "my-bucket",
|
|
75
128
|
region: "us-east-1",
|
|
76
|
-
|
|
77
|
-
|
|
129
|
+
allow_http: false,
|
|
130
|
+
auth: {
|
|
131
|
+
type: "Access keys",
|
|
132
|
+
access_key_id: prefixSecret("AWS_ACCESS_KEY_ID"),
|
|
133
|
+
secret_access_key: prefixSecret("AWS_SECRET_ACCESS_KEY"),
|
|
134
|
+
},
|
|
78
135
|
};
|
|
79
136
|
expect(
|
|
80
137
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -143,6 +200,25 @@ describe("generateStorageCode", () => {
|
|
|
143
200
|
type: "coreweave",
|
|
144
201
|
bucket: "operator-bucket",
|
|
145
202
|
region: "US-EAST-04A",
|
|
203
|
+
auth: { type: "Access keys" },
|
|
204
|
+
};
|
|
205
|
+
expect(
|
|
206
|
+
generateStorageCode(conn, { library: "obstore" }),
|
|
207
|
+
).toMatchSnapshot();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("with container credentials", () => {
|
|
211
|
+
const conn: StorageConnection = {
|
|
212
|
+
...baseCoreWeave,
|
|
213
|
+
auth: {
|
|
214
|
+
type: "Container credentials",
|
|
215
|
+
container_credentials_full_uri: prefixSecret(
|
|
216
|
+
"AWS_CONTAINER_CREDENTIALS_FULL_URI",
|
|
217
|
+
),
|
|
218
|
+
container_authorization_token_file: prefixSecret(
|
|
219
|
+
"AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE",
|
|
220
|
+
),
|
|
221
|
+
},
|
|
146
222
|
};
|
|
147
223
|
expect(
|
|
148
224
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -154,8 +230,11 @@ describe("generateStorageCode", () => {
|
|
|
154
230
|
type: "coreweave",
|
|
155
231
|
bucket: "operator-bucket",
|
|
156
232
|
region: "US-EAST-04A",
|
|
157
|
-
|
|
158
|
-
|
|
233
|
+
auth: {
|
|
234
|
+
type: "Access keys",
|
|
235
|
+
access_key_id: prefixSecret("COREWEAVE_OBJECT_STORAGE_KEY"),
|
|
236
|
+
secret_access_key: prefixSecret("COREWEAVE_OBJECT_STORAGE_SECRET"),
|
|
237
|
+
},
|
|
159
238
|
};
|
|
160
239
|
expect(
|
|
161
240
|
generateStorageCode(conn, { library: "obstore" }),
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
import dedent from "string-dedent";
|
|
4
4
|
import { assertNever } from "@/utils/assertNever";
|
|
5
5
|
import { isSecret, unprefixSecret } from "../secrets";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type S3Auth,
|
|
8
|
+
type StorageConnection,
|
|
9
|
+
StorageConnectionSchema,
|
|
10
|
+
} from "./schemas";
|
|
7
11
|
|
|
8
12
|
export type StorageLibrary = "obstore" | "fsspec";
|
|
9
13
|
|
|
@@ -50,6 +54,36 @@ class SecretContainer {
|
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Credential kwargs shared by every S3-compatible store.
|
|
59
|
+
*/
|
|
60
|
+
function s3AuthParams(
|
|
61
|
+
auth: S3Auth | undefined,
|
|
62
|
+
secrets: SecretContainer,
|
|
63
|
+
): string[] {
|
|
64
|
+
// obstore polls the credential endpoint with the token read from the file,
|
|
65
|
+
// refreshing credentials for the lifetime of the store.
|
|
66
|
+
if (auth?.type === "Container credentials") {
|
|
67
|
+
return [
|
|
68
|
+
` container_credentials_full_uri=${secrets.print("container_credentials_full_uri", auth.container_credentials_full_uri)},`,
|
|
69
|
+
` container_authorization_token_file=${secrets.print("container_authorization_token_file", auth.container_authorization_token_file)},`,
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const params: string[] = [];
|
|
74
|
+
if (auth?.access_key_id) {
|
|
75
|
+
params.push(
|
|
76
|
+
` access_key_id=${secrets.print("access_key_id", auth.access_key_id)},`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
if (auth?.secret_access_key) {
|
|
80
|
+
params.push(
|
|
81
|
+
` secret_access_key=${secrets.print("secret_access_key", auth.secret_access_key)},`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
return params;
|
|
85
|
+
}
|
|
86
|
+
|
|
53
87
|
function generateS3Code(
|
|
54
88
|
connection: Extract<StorageConnection, { type: "s3" }>,
|
|
55
89
|
secrets: SecretContainer,
|
|
@@ -61,21 +95,15 @@ function generateS3Code(
|
|
|
61
95
|
if (connection.region) {
|
|
62
96
|
params.push(` region=${secrets.print("region", connection.region)},`);
|
|
63
97
|
}
|
|
64
|
-
|
|
65
|
-
params.push(
|
|
66
|
-
` access_key_id=${secrets.print("access_key_id", connection.access_key_id)},`,
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
if (connection.secret_access_key) {
|
|
70
|
-
params.push(
|
|
71
|
-
` secret_access_key=${secrets.print("secret_access_key", connection.secret_access_key)},`,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
98
|
+
params.push(...s3AuthParams(connection.auth, secrets));
|
|
74
99
|
if (connection.endpoint_url) {
|
|
75
100
|
params.push(
|
|
76
101
|
` endpoint_url=${secrets.print("endpoint_url", connection.endpoint_url)},`,
|
|
77
102
|
);
|
|
78
103
|
}
|
|
104
|
+
if (connection.allow_http) {
|
|
105
|
+
params.push(" allow_http=True,");
|
|
106
|
+
}
|
|
79
107
|
|
|
80
108
|
const paramsStr = params.length > 0 ? `\n${params.join("\n")}\n` : "";
|
|
81
109
|
|
|
@@ -140,16 +168,7 @@ function generateCoreWeaveCode(
|
|
|
140
168
|
` region=${secrets.print("region", connection.region)},`,
|
|
141
169
|
];
|
|
142
170
|
|
|
143
|
-
|
|
144
|
-
params.push(
|
|
145
|
-
` access_key_id=${secrets.print("access_key_id", connection.access_key_id)},`,
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
if (connection.secret_access_key) {
|
|
149
|
-
params.push(
|
|
150
|
-
` secret_access_key=${secrets.print("secret_access_key", connection.secret_access_key)},`,
|
|
151
|
-
);
|
|
152
|
-
}
|
|
171
|
+
params.push(...s3AuthParams(connection.auth, secrets));
|
|
153
172
|
|
|
154
173
|
params.push(
|
|
155
174
|
` endpoint="https://${connection.bucket}.cwobject.com",`,
|
|
@@ -2,6 +2,83 @@
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { FieldOptions } from "@/components/forms/options";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Credentials shared by every S3-compatible store (Amazon S3, CoreWeave, ...).
|
|
7
|
+
*
|
|
8
|
+
* Rendered as tabs: either long-lived access keys, or a credential-vending
|
|
9
|
+
* endpoint (ECS/EKS task roles, CoreWeave sandboxes, ...) that obstore polls
|
|
10
|
+
* with a bearer token read from disk.
|
|
11
|
+
*/
|
|
12
|
+
const s3AuthField = () =>
|
|
13
|
+
z
|
|
14
|
+
.discriminatedUnion("type", [
|
|
15
|
+
z.object({
|
|
16
|
+
type: z.literal("Access keys"),
|
|
17
|
+
access_key_id: z
|
|
18
|
+
.string()
|
|
19
|
+
.optional()
|
|
20
|
+
.describe(
|
|
21
|
+
FieldOptions.of({
|
|
22
|
+
label: "Access Key ID",
|
|
23
|
+
description: "Leave empty to use the default credential chain",
|
|
24
|
+
inputType: "password",
|
|
25
|
+
optionRegex:
|
|
26
|
+
"(access.?key.?id|object.?storage.?key|aws.?access.?key)",
|
|
27
|
+
}),
|
|
28
|
+
),
|
|
29
|
+
secret_access_key: z
|
|
30
|
+
.string()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe(
|
|
33
|
+
FieldOptions.of({
|
|
34
|
+
label: "Secret Access Key",
|
|
35
|
+
inputType: "password",
|
|
36
|
+
optionRegex:
|
|
37
|
+
"(secret.?access.?key|object.?storage.?secret|aws.?secret)",
|
|
38
|
+
}),
|
|
39
|
+
),
|
|
40
|
+
}),
|
|
41
|
+
z.object({
|
|
42
|
+
type: z.literal("Container credentials"),
|
|
43
|
+
container_credentials_full_uri: z
|
|
44
|
+
.string()
|
|
45
|
+
.nonempty()
|
|
46
|
+
.describe(
|
|
47
|
+
FieldOptions.of({
|
|
48
|
+
label: "Credentials URI",
|
|
49
|
+
description: "Endpoint that vends credentials to the container",
|
|
50
|
+
placeholder: "http://169.254.170.23/v1/credentials",
|
|
51
|
+
optionRegex: "container.?credentials",
|
|
52
|
+
}),
|
|
53
|
+
),
|
|
54
|
+
container_authorization_token_file: z
|
|
55
|
+
.string()
|
|
56
|
+
.nonempty()
|
|
57
|
+
.describe(
|
|
58
|
+
FieldOptions.of({
|
|
59
|
+
label: "Authorization Token File",
|
|
60
|
+
description: "File holding the token sent to the credentials URI",
|
|
61
|
+
placeholder: "/var/run/secrets/token",
|
|
62
|
+
optionRegex:
|
|
63
|
+
"(container.?authorization.?token.?file|container.?auth.?token)",
|
|
64
|
+
}),
|
|
65
|
+
),
|
|
66
|
+
}),
|
|
67
|
+
])
|
|
68
|
+
.default({ type: "Access keys" })
|
|
69
|
+
.describe(FieldOptions.of({ label: "Credentials", special: "tabs" }));
|
|
70
|
+
|
|
71
|
+
const allowHttpField = () =>
|
|
72
|
+
z
|
|
73
|
+
.boolean()
|
|
74
|
+
.default(false)
|
|
75
|
+
.describe(
|
|
76
|
+
FieldOptions.of({
|
|
77
|
+
label: "Allow HTTP",
|
|
78
|
+
description: "Required for plain-http (non-TLS) endpoints",
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
|
|
5
82
|
export const S3StorageSchema = z
|
|
6
83
|
.object({
|
|
7
84
|
type: z.literal("s3"),
|
|
@@ -25,36 +102,20 @@ export const S3StorageSchema = z
|
|
|
25
102
|
optionRegex: "(region|aws.?region)",
|
|
26
103
|
}),
|
|
27
104
|
),
|
|
28
|
-
access_key_id: z
|
|
29
|
-
.string()
|
|
30
|
-
.optional()
|
|
31
|
-
.describe(
|
|
32
|
-
FieldOptions.of({
|
|
33
|
-
label: "Access Key ID",
|
|
34
|
-
inputType: "password",
|
|
35
|
-
optionRegex: "(access.?key.?id|aws.?access.?key)",
|
|
36
|
-
}),
|
|
37
|
-
),
|
|
38
|
-
secret_access_key: z
|
|
39
|
-
.string()
|
|
40
|
-
.optional()
|
|
41
|
-
.describe(
|
|
42
|
-
FieldOptions.of({
|
|
43
|
-
label: "Secret Access Key",
|
|
44
|
-
inputType: "password",
|
|
45
|
-
optionRegex: "(secret.?access.?key|aws.?secret)",
|
|
46
|
-
}),
|
|
47
|
-
),
|
|
48
105
|
endpoint_url: z
|
|
49
106
|
.string()
|
|
50
107
|
.optional()
|
|
51
108
|
.describe(
|
|
52
109
|
FieldOptions.of({
|
|
53
110
|
label: "Endpoint URL",
|
|
111
|
+
description:
|
|
112
|
+
"Ignored if the AWS_ENDPOINT_URL_S3 environment variable is set",
|
|
54
113
|
placeholder: "https://s3.amazonaws.com",
|
|
55
114
|
optionRegex: "(endpoint|s3.?url|s3.?endpoint)",
|
|
56
115
|
}),
|
|
57
116
|
),
|
|
117
|
+
allow_http: allowHttpField(),
|
|
118
|
+
auth: s3AuthField(),
|
|
58
119
|
})
|
|
59
120
|
.describe(FieldOptions.of({ direction: "two-columns" }));
|
|
60
121
|
|
|
@@ -139,28 +200,7 @@ export const CoreWeaveStorageSchema = z
|
|
|
139
200
|
placeholder: "US-EAST-04A",
|
|
140
201
|
}),
|
|
141
202
|
),
|
|
142
|
-
|
|
143
|
-
.string()
|
|
144
|
-
.optional()
|
|
145
|
-
.describe(
|
|
146
|
-
FieldOptions.of({
|
|
147
|
-
label: "Access Key ID",
|
|
148
|
-
inputType: "password",
|
|
149
|
-
optionRegex:
|
|
150
|
-
"(access.?key.?id|object.?storage.?key|aws.?access.?key)",
|
|
151
|
-
}),
|
|
152
|
-
),
|
|
153
|
-
secret_access_key: z
|
|
154
|
-
.string()
|
|
155
|
-
.optional()
|
|
156
|
-
.describe(
|
|
157
|
-
FieldOptions.of({
|
|
158
|
-
label: "Secret Access Key",
|
|
159
|
-
inputType: "password",
|
|
160
|
-
optionRegex:
|
|
161
|
-
"(secret.?access.?key|object.?storage.?secret|aws.?secret)",
|
|
162
|
-
}),
|
|
163
|
-
),
|
|
203
|
+
auth: s3AuthField(),
|
|
164
204
|
})
|
|
165
205
|
.describe(FieldOptions.of({ direction: "two-columns" }));
|
|
166
206
|
|
|
@@ -189,3 +229,4 @@ export const StorageConnectionSchema = z.discriminatedUnion("type", [
|
|
|
189
229
|
]);
|
|
190
230
|
|
|
191
231
|
export type StorageConnection = z.infer<typeof StorageConnectionSchema>;
|
|
232
|
+
export type S3Auth = Extract<StorageConnection, { type: "s3" }>["auth"];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
import { cellId } from "@/__tests__/branded";
|
|
6
|
+
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
7
|
+
import { CellOutputId } from "@/core/cells/ids";
|
|
8
|
+
import { createCell, createCellRuntimeState } from "@/core/cells/types";
|
|
9
|
+
import { CellOutputBlock } from "../reveal-component";
|
|
10
|
+
|
|
11
|
+
describe("CellOutputBlock", () => {
|
|
12
|
+
it("renders the cell's data-cell-id and data-cell-name so it can be targeted by custom CSS", () => {
|
|
13
|
+
const id = cellId("test");
|
|
14
|
+
const cell = {
|
|
15
|
+
...createCell({ id, name: "title" }),
|
|
16
|
+
...createCellRuntimeState({
|
|
17
|
+
output: {
|
|
18
|
+
channel: "output",
|
|
19
|
+
mimetype: "text/plain",
|
|
20
|
+
data: "hello",
|
|
21
|
+
timestamp: 0,
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const { container } = render(
|
|
27
|
+
<TooltipProvider>
|
|
28
|
+
<CellOutputBlock cell={cell} />
|
|
29
|
+
</TooltipProvider>,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const cellElement = container.querySelector(`[data-cell-id="${id}"]`);
|
|
33
|
+
expect(cellElement).toBeTruthy();
|
|
34
|
+
expect(cellElement?.getAttribute("data-cell-name")).toBe("title");
|
|
35
|
+
|
|
36
|
+
// The wrapper's `data-cell-id` must coexist with the output's own
|
|
37
|
+
// `CellOutputId`-derived id, without colliding.
|
|
38
|
+
expect(document.getElementById(CellOutputId.create(id))).toBeTruthy();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
|
5
|
+
import { SetupMocks } from "@/__mocks__/common";
|
|
6
|
+
import { cellId } from "@/__tests__/branded";
|
|
7
|
+
import { TooltipProvider } from "@/components/ui/tooltip";
|
|
8
|
+
import { createCell, createCellRuntimeState } from "@/core/cells/types";
|
|
9
|
+
import { SlideCellReadOnlyView } from "../slide-cell-view";
|
|
10
|
+
|
|
11
|
+
beforeAll(() => {
|
|
12
|
+
SetupMocks.resizeObserver();
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("SlideCellReadOnlyView", () => {
|
|
16
|
+
it("renders the cell's data-cell-id and data-cell-name so it can be targeted by custom CSS", () => {
|
|
17
|
+
const id = cellId("test");
|
|
18
|
+
const cell = {
|
|
19
|
+
...createCell({ id, name: "title", code: "x = 1" }),
|
|
20
|
+
...createCellRuntimeState(),
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const { container } = render(
|
|
24
|
+
<TooltipProvider>
|
|
25
|
+
<SlideCellReadOnlyView cell={cell} />
|
|
26
|
+
</TooltipProvider>,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const cellElement = container.querySelector(`[data-cell-id="${id}"]`);
|
|
30
|
+
expect(cellElement).toBeTruthy();
|
|
31
|
+
expect(cellElement?.getAttribute("data-cell-name")).toBe("title");
|
|
32
|
+
});
|
|
33
|
+
});
|