@marimo-team/islands 0.23.16-dev2 → 0.23.16-dev21
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/{ConnectedDataExplorerComponent-CJaUI-S-.js → ConnectedDataExplorerComponent-f9vLjQiF.js} +13 -13
- package/dist/{ErrorBoundary-DXlxsrTF.js → ErrorBoundary-DhLqwSWA.js} +3 -3
- package/dist/{any-language-editor-P9tjkj4n.js → any-language-editor-DifE-fl7.js} +5 -5
- package/dist/{button-BcSml68y.js → button-BSm8IXRU.js} +2 -4
- package/dist/{capabilities-BYLFYTYv.js → capabilities-C6OQ5YBO.js} +1 -1
- package/dist/{chat-ui-BdSDiVjk.js → chat-ui-BMBk8I78.js} +3129 -3129
- package/dist/{check-Cs-KV5XY.js → check-DP7U0H0G.js} +1 -1
- package/dist/{code-visibility-mgBayy67.js → code-visibility-Dt0oSVz1.js} +778 -755
- package/dist/{copy-Cs3yt6Vt.js → copy-DNq8q3zw.js} +2 -2
- package/dist/{dist-B96tMAst.js → dist-DIlxLFXG.js} +2 -2
- package/dist/{error-banner-DR7o3CbX.js → error-banner-B_GQfxxD.js} +2 -2
- package/dist/{esm-k8PIvuZW.js → esm-DzZVaNH4.js} +1 -1
- package/dist/{extends-Cq2JYHKy.js → extends-w2_S44bV.js} +4 -4
- package/dist/{formats-BFhkZJwd.js → formats-Dwq1THhr.js} +3 -3
- package/dist/{glide-data-editor--CaN-f27.js → glide-data-editor-B9K6-MJe.js} +9 -9
- package/dist/{html-to-image-DDENewl2.js → html-to-image-27MFfyOf.js} +4121 -2739
- package/dist/{input-DStQIuqD.js → input-C5K4VBvB.js} +7 -7
- package/dist/{label-DIk0QoFe.js → label-DjoYwqmj.js} +2 -2
- package/dist/{loader-CTHCI-qe.js → loader-DX-IDS7n.js} +1 -1
- package/dist/main.js +915 -923
- package/dist/{mermaid-CdSvixW2.js → mermaid-hv6IckVw.js} +5 -5
- package/dist/{node-sql-parser-DLl_zNw0.js → node-sql-parser-v1Vi-Fft.js} +16867 -16665
- package/dist/{process-output-2QPcgBQg.js → process-output-BpssYna4.js} +3 -3
- package/dist/{reveal-component-BDdfO6U_.js → reveal-component-BW-0eLEt.js} +702 -628
- package/dist/{spec-CnaxwDqy.js → spec-CQKL_D3i.js} +4 -4
- package/dist/{strings-BYAhZnQi.js → strings-DIy9NAmg.js} +4 -4
- package/dist/style.css +1 -1
- package/dist/{swiper-component-DE94711u.js → swiper-component-CEdAYjb7.js} +2 -2
- package/dist/toDate-CqhBWjvO.js +713 -0
- package/dist/{tooltip-B-qh7UPB.js → tooltip-f-qR0iUx.js} +3 -3
- package/dist/{types-DQl7jVYK.js → types-DicH9Oi0.js} +1 -1
- package/dist/{useAsyncData-CvO8WUy3.js → useAsyncData-CYOQb1EW.js} +1 -1
- package/dist/{useDateFormatter-BSoGim-G.js → useDateFormatter-Bt2qr_XS.js} +2 -2
- package/dist/{useDeepCompareMemoize-J3MKRdA4.js → useDeepCompareMemoize-CSHQeQEI.js} +1 -1
- package/dist/{useIframeCapabilities-POcFXHbw.js → useIframeCapabilities-kA09ykNq.js} +1 -1
- package/dist/{useLifecycle-DqPxHgAN.js → useLifecycle-CMJGqBaY.js} +3 -3
- package/dist/{useTheme-XMq9mNf_.js → useTheme-DYfby65G.js} +2 -2
- package/dist/{vega-component-CrFoZT1S.js → vega-component-C7nO5zcf.js} +10 -10
- package/dist/{zod-D0yOqoGe.js → zod-BUcyXSdR.js} +1 -1
- package/package.json +2 -2
- package/src/components/data-table/column-formatting/feature.ts +2 -1
- 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/file-tree/__tests__/file-render-mode.test.ts +27 -0
- package/src/components/editor/file-tree/__tests__/file-viewer.test.tsx +150 -0
- package/src/components/editor/file-tree/file-preview-metadata.tsx +51 -0
- package/src/components/editor/file-tree/file-render-mode.ts +32 -0
- package/src/components/editor/file-tree/file-viewer.tsx +76 -50
- package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +198 -0
- package/src/components/slides/reveal-component.tsx +3 -2
- package/src/components/slides/slide-scroll-hint.tsx +161 -0
- package/src/components/ui/input.tsx +1 -1
- 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/sql/completion-store.ts +5 -1
- package/src/core/codemirror/language/languages/sql/sql.ts +210 -3
- package/src/core/hotkeys/hotkeys.ts +0 -2
- package/src/core/i18n/__tests__/locale-provider.test.tsx +54 -118
- package/src/core/i18n/__tests__/locale.test.ts +113 -0
- package/src/core/i18n/locale-provider.tsx +1 -19
- package/src/core/i18n/locale.ts +71 -0
- package/src/core/islands/__tests__/bridge.test.ts +107 -0
- package/src/core/islands/bridge.ts +15 -0
- package/src/core/mode.ts +10 -0
- package/src/core/network/__tests__/connection.test.ts +45 -0
- package/src/core/network/__tests__/requests-network.test.ts +13 -0
- package/src/core/network/connection.ts +15 -0
- package/src/core/network/requests-network.ts +6 -3
- package/src/core/network/types.ts +3 -1
- package/src/plugins/impl/FormPlugin.tsx +1 -1
- package/src/plugins/impl/__tests__/FormPlugin.test.tsx +162 -0
- package/dist/toDate-B3IRfHhw.js +0 -692
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
|
-
import { d as createSlottable, h as cn, p as useComposedRefs } from "./button-
|
|
2
|
+
import { d as createSlottable, h as cn, p as useComposedRefs } from "./button-BSm8IXRU.js";
|
|
3
3
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
4
4
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
5
|
-
import { a as createPopperScope, i as Root2, n as Arrow, r as Content, s as Root, t as Anchor } from "./dist-
|
|
5
|
+
import { a as createPopperScope, i as Root2, n as Arrow, r as Content, s as Root, t as Anchor } from "./dist-DIlxLFXG.js";
|
|
6
6
|
import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
|
|
7
|
-
import { Q as withSmartCollisionBoundary, Z as withFullScreenAsRoot, _t as createContextScope, at as Portal, ct as DismissableLayer, dt as useId, et as StyleNamespace, ft as Presence, ht as composeEventHandlers, pt as useControllableState, vt as Primitive } from "./zod-
|
|
7
|
+
import { Q as withSmartCollisionBoundary, Z as withFullScreenAsRoot, _t as createContextScope, at as Portal, ct as DismissableLayer, dt as useId, et as StyleNamespace, ft as Presence, ht as composeEventHandlers, pt as useControllableState, vt as Primitive } from "./zod-BUcyXSdR.js";
|
|
8
8
|
var import_react = /* @__PURE__ */ __toESM(require_react(), 1), import_jsx_runtime = /* @__PURE__ */ __toESM(require_jsx_runtime(), 1), [createTooltipContext, createTooltipScope] = createContextScope("Tooltip", [createPopperScope]), usePopperScope = createPopperScope(), PROVIDER_NAME = "TooltipProvider", DEFAULT_DELAY_DURATION = 700, TOOLTIP_OPEN = "tooltip.open", [TooltipProviderContextProvider, useTooltipProviderContext] = createTooltipContext(PROVIDER_NAME), TooltipProvider$1 = (n) => {
|
|
9
9
|
let { __scopeTooltip: j, delayDuration: M = DEFAULT_DELAY_DURATION, skipDelayDuration: N = 300, disableHoverableContent: P = false, children: F } = n, I = import_react.useRef(true), L = import_react.useRef(false), R = import_react.useRef(0);
|
|
10
10
|
return import_react.useEffect(() => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as createLucideIcon } from "./dist-
|
|
1
|
+
import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
|
|
2
2
|
var Pencil = createLucideIcon("pencil", [["path", {
|
|
3
3
|
d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
|
|
4
4
|
key: "1a8usu"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
2
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
3
3
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
4
|
-
import { A as useEvent_default } from "./useTheme-
|
|
4
|
+
import { A as useEvent_default } from "./useTheme-DYfby65G.js";
|
|
5
5
|
import { t as invariant } from "./invariant-wRzNXIsJ.js";
|
|
6
6
|
var import_compiler_runtime = require_compiler_runtime(), import_react = /* @__PURE__ */ __toESM(require_react(), 1), Result = {
|
|
7
7
|
error(e, s) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
2
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
3
|
-
import { u as createLucideIcon } from "./dist-
|
|
4
|
-
import { E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 } from "./strings-
|
|
3
|
+
import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
|
|
4
|
+
import { E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 } from "./strings-DIy9NAmg.js";
|
|
5
5
|
var ChartPie = createLucideIcon("chart-pie", [["path", {
|
|
6
6
|
d: "M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z",
|
|
7
7
|
key: "pzmjnu"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
2
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
3
|
-
import { k as dequal } from "./useTheme-
|
|
3
|
+
import { k as dequal } from "./useTheme-DYfby65G.js";
|
|
4
4
|
var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
|
|
5
5
|
function useDeepCompareMemoize(e) {
|
|
6
6
|
let i = import_react.useRef(e);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
2
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
3
3
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
4
|
-
import { t as getIframeCapabilities } from "./capabilities-
|
|
4
|
+
import { t as getIframeCapabilities } from "./capabilities-C6OQ5YBO.js";
|
|
5
5
|
var import_compiler_runtime = require_compiler_runtime();
|
|
6
6
|
require_react();
|
|
7
7
|
function useIframeCapabilities() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
|
-
import { g as Logger, h as cn, r as cva } from "./button-
|
|
2
|
+
import { g as Logger, h as cn, r as cva } from "./button-BSm8IXRU.js";
|
|
3
3
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
4
4
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
5
|
-
import { u as createLucideIcon } from "./dist-
|
|
5
|
+
import { u as createLucideIcon } from "./dist-DIlxLFXG.js";
|
|
6
6
|
import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
|
|
7
|
-
import { C as useSetAtom, T as atom } from "./useTheme-
|
|
7
|
+
import { C as useSetAtom, T as atom } from "./useTheme-DYfby65G.js";
|
|
8
8
|
var Calendar = createLucideIcon("calendar", [
|
|
9
9
|
["path", {
|
|
10
10
|
d: "M8 2v4",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
|
-
import { a as OverridingHotkeyProvider, g as Logger, s as resolvePlatform } from "./button-
|
|
2
|
+
import { a as OverridingHotkeyProvider, g as Logger, s as resolvePlatform } from "./button-BSm8IXRU.js";
|
|
3
3
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
4
4
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
5
|
-
import { A as looseObject, B as union, I as record, N as number, P as object, R as string, T as boolean, b as _enum, w as array } from "./zod-
|
|
5
|
+
import { A as looseObject, B as union, I as record, N as number, P as object, R as string, T as boolean, b as _enum, w as array } from "./zod-BUcyXSdR.js";
|
|
6
6
|
import { t as merge_default } from "./merge-Be1CqGnU.js";
|
|
7
7
|
var import_react = /* @__PURE__ */ __toESM(require_react()), useInsertionEffect = typeof window < "u" ? import_react.useInsertionEffect || import_react.useLayoutEffect : () => {
|
|
8
8
|
};
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
|
-
import { g as Logger, h as cn, m as Events } from "./button-
|
|
2
|
+
import { g as Logger, h as cn, m as Events } from "./button-BSm8IXRU.js";
|
|
3
3
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
4
4
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
5
|
-
import { c as asRemoteURL,
|
|
5
|
+
import { c as asRemoteURL, w as CircleQuestionMark } from "./toDate-CqhBWjvO.js";
|
|
6
6
|
import "./react-dom-BTJzcVJ9.js";
|
|
7
7
|
import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
|
|
8
|
-
import "./zod-
|
|
9
|
-
import { n as ErrorBanner } from "./error-banner-
|
|
10
|
-
import { t as Tooltip } from "./tooltip-
|
|
8
|
+
import "./zod-BUcyXSdR.js";
|
|
9
|
+
import { n as ErrorBanner } from "./error-banner-B_GQfxxD.js";
|
|
10
|
+
import { t as Tooltip } from "./tooltip-f-qR0iUx.js";
|
|
11
11
|
import { t as debounce_default } from "./debounce-BOD3DbfP.js";
|
|
12
|
-
import { A as useEvent_default, n as useTheme } from "./useTheme-
|
|
12
|
+
import { A as useEvent_default, n as useTheme } from "./useTheme-DYfby65G.js";
|
|
13
13
|
import { s as uniq } from "./arrays-sEtDRoG4.js";
|
|
14
14
|
import { t as Objects } from "./objects-De59twF-.js";
|
|
15
|
-
import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-
|
|
15
|
+
import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-Dwq1THhr.js";
|
|
16
16
|
import { V as getContainerWidth, n as formats } from "./vega-loader.browser-DmpxCJqx.js";
|
|
17
|
-
import { a as tooltipHandler, n as vegaLoadData } from "./loader-
|
|
17
|
+
import { a as tooltipHandler, n as vegaLoadData } from "./loader-DX-IDS7n.js";
|
|
18
18
|
import { t as j } from "./react-vega-BazDALhI.js";
|
|
19
19
|
import "./defaultLocale-BpsHxBd7.js";
|
|
20
20
|
import "./defaultLocale-DoeErsX2.js";
|
|
21
|
-
import { t as useAsyncData } from "./useAsyncData-
|
|
22
|
-
import { t as useDeepCompareMemoize } from "./useDeepCompareMemoize-
|
|
21
|
+
import { t as useAsyncData } from "./useAsyncData-CYOQb1EW.js";
|
|
22
|
+
import { t as useDeepCompareMemoize } from "./useDeepCompareMemoize-CSHQeQEI.js";
|
|
23
23
|
import { t as Semaphore } from "./semaphore-C8rmHdhj.js";
|
|
24
24
|
import { t as useVegaContainerRemeasure } from "./use-vega-container-remeasure-DGNrIQSk.js";
|
|
25
25
|
var import_compiler_runtime = require_compiler_runtime(), import_react = /* @__PURE__ */ __toESM(require_react(), 1);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as __export, s as __toESM } from "./chunk-BNovOVIE.js";
|
|
2
|
-
import { c as useEventListener, p as useComposedRefs, u as createSlot } from "./button-
|
|
2
|
+
import { c as useEventListener, p as useComposedRefs, u as createSlot } from "./button-BSm8IXRU.js";
|
|
3
3
|
import { t as require_react } from "./react-DA-nE2FX.js";
|
|
4
4
|
import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
5
5
|
import { t as require_react_dom } from "./react-dom-BTJzcVJ9.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marimo-team/islands",
|
|
3
|
-
"version": "0.23.16-
|
|
3
|
+
"version": "0.23.16-dev21",
|
|
4
4
|
"main": "dist/main.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@marimo-team/codemirror-ai": "^0.3.7",
|
|
58
58
|
"@marimo-team/codemirror-languageserver": "^1.16.12",
|
|
59
59
|
"@marimo-team/codemirror-mcp": "^0.1.7",
|
|
60
|
-
"@marimo-team/codemirror-sql": "^0.
|
|
60
|
+
"@marimo-team/codemirror-sql": "^0.3.0",
|
|
61
61
|
"@marimo-team/llm-info": "workspace:*",
|
|
62
62
|
"@marimo-team/marimo-api": "workspace:*",
|
|
63
63
|
"@marimo-team/react-slotz": "^0.2.0",
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
type TableFeature,
|
|
10
10
|
type Updater,
|
|
11
11
|
} from "@tanstack/react-table";
|
|
12
|
+
import { browserLocale } from "@/core/i18n/locale";
|
|
12
13
|
import type { DataType } from "@/core/kernel/messages";
|
|
13
14
|
import { logNever } from "@/utils/assertNever";
|
|
14
15
|
import {
|
|
@@ -40,7 +41,7 @@ export const ColumnFormattingFeature: TableFeature = {
|
|
|
40
41
|
return {
|
|
41
42
|
enableColumnFormatting: true,
|
|
42
43
|
onColumnFormattingChange: makeStateUpdater("columnFormatting", table),
|
|
43
|
-
locale:
|
|
44
|
+
locale: browserLocale(),
|
|
44
45
|
} as ColumnFormattingOptions;
|
|
45
46
|
},
|
|
46
47
|
|
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,27 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, it } from "vitest";
|
|
4
|
+
import { getFileRenderMode } from "../file-render-mode";
|
|
5
|
+
|
|
6
|
+
describe("getFileRenderMode", () => {
|
|
7
|
+
it.each([
|
|
8
|
+
["text/plain", false, "text"],
|
|
9
|
+
["text/x-rust", false, "text"],
|
|
10
|
+
["application/json", false, "text"],
|
|
11
|
+
["application/xml", false, "text"],
|
|
12
|
+
["text/csv", false, "csv"],
|
|
13
|
+
["image/png", true, "media"],
|
|
14
|
+
["video/mp4", true, "media"],
|
|
15
|
+
["application/pdf", true, "media"],
|
|
16
|
+
["application/x-apple-diskimage", true, "unsupported"],
|
|
17
|
+
["application/zip", true, "unsupported"],
|
|
18
|
+
["application/octet-stream", false, "unsupported"],
|
|
19
|
+
[null, false, "text"],
|
|
20
|
+
[null, true, "unsupported"],
|
|
21
|
+
] as const)(
|
|
22
|
+
"maps %s with isBase64=%s to %s",
|
|
23
|
+
(mimeType, isBase64, expected) => {
|
|
24
|
+
expect(getFileRenderMode(mimeType, isBase64)).toBe(expected);
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
});
|