@marimo-team/islands 0.23.14-dev34 → 0.23.14-dev36
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/{code-visibility-BLnXV6lv.js → code-visibility-D3MXw5WY.js} +1 -1
- package/dist/main.js +2 -2
- package/dist/{reveal-component-D6H16dMJ.js → reveal-component-DuFZrdj1.js} +1 -1
- package/package.json +1 -1
- package/src/core/network/__tests__/api.test.ts +17 -0
- package/src/core/network/__tests__/requests-toasting.test.tsx +46 -0
- package/src/core/network/api.ts +17 -6
- package/src/core/network/requests-toasting.tsx +9 -1
- package/src/utils/errors.ts +15 -0
|
@@ -36198,7 +36198,7 @@ ${d}`,
|
|
|
36198
36198
|
return Logger.warn("Failed to get version from mount config"), null;
|
|
36199
36199
|
}
|
|
36200
36200
|
}
|
|
36201
|
-
marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.14-
|
|
36201
|
+
marimoVersionAtom = atom(getVersionFromMountConfig() || "0.23.14-dev36");
|
|
36202
36202
|
showCodeInRunModeAtom = atom(true);
|
|
36203
36203
|
atom(null);
|
|
36204
36204
|
var import_compiler_runtime = require_compiler_runtime();
|
package/dist/main.js
CHANGED
|
@@ -26,7 +26,7 @@ import { $ as reducer, $t as requestClientAtom, A as ChevronDownIcon, At as Path
|
|
|
26
26
|
import { __tla as __tla_1 } from "./chunk-5FQGJX7Z-BbqSm5gU.js";
|
|
27
27
|
import { o as useSize, s as Root$1, u as createLucideIcon } from "./dist--2Bqjvs0.js";
|
|
28
28
|
import { A as SquareFunction, C as DEFAULT_COLOR_SCHEME, D as SCALE_TYPE_DESCRIPTIONS, E as EMPTY_VALUE$1, O as TIME_UNIT_DESCRIPTIONS, S as DEFAULT_AGGREGATION, T as DEFAULT_TIME_UNIT, _ as AGGREGATION_TYPE_DESCRIPTIONS, a as AGGREGATION_FNS$1, b as COLOR_SCHEMES, c as COLOR_BY_FIELDS, d as NONE_VALUE, f as SELECTABLE_DATA_TYPES, g as TIME_UNITS, h as STRING_AGGREGATION_FNS, i as convertDataTypeToSelectable, j as ChartColumn, k as escapeFieldName, l as COMBINED_TIME_UNITS, m as SORT_TYPES, n as createSpecWithoutData, o as BIN_AGGREGATION, p as SINGLE_TIME_UNITS, r as isFieldSet, s as CHART_TYPES, t as augmentSpecWithData, u as ChartType, v as AGGREGATION_TYPE_ICON, w as DEFAULT_MAX_BINS_FACET, x as COUNT_FIELD, y as CHART_TYPE_ICON } from "./spec-CnTgI25l.js";
|
|
29
|
-
import { $ as PANEL_TYPES, $t as HtmlOutput, A as prettifyRowCount, At as INDEX_COLUMN_NAME, B as CompactChipRow, Bt as dateToLocalISODateTime, C as downloadSizeLimitAtom, Ct as ColumnChartSpecModel, D as ErrorState, Dt as getPageIndexForRow, E as EmptyState, Et as usePrevious$1, F as ContextMenuItem, Ft as hasFunctionProperty, G as Command, Gt as TabsTrigger, H as DateRangePicker, Ht as Tabs, I as ContextMenuSeparator, It as isRecord, J as CommandItem, Jt as ChartLoadingState, K as CommandEmpty, Kt as ChartErrorState, L as ContextMenuTrigger, Lt as isNullishFilter, M as getUserColumnVisibilityCounts, Mt as TOO_MANY_ROWS, N as ContextMenu, Nt as toFieldTypes, O as LoadingState, Ot as loadTableAndRawData, P as ContextMenuContent, Pt as getMimeValues, Q as ContextAwarePanelItem, Qt as Kbd, R as useInternalStateWithSync, Rt as Maps, S as Filenames, St as ColumnChartContext, T as ColumnPreviewContainer, Tt as useIntersectionObserver, U as Combobox, Ut as TabsContent, V as DatePicker, Vt as dateToLocalISOTime, W as ComboboxItem, Wt as TabsList, X as CommandSeparator, Xt as useOverflowDetection, Y as CommandList, Yt as LazyVegaEmbed, Z as smartMatch, Zt as RenderTextWithLinks, _ as ADD_PRINTING_CLASS, _t as TableRow, an as Funnel, at as slotsController, b as downloadHTMLAsImage, bt as inferFieldTypes, c as Slide, cn as Ellipsis, d as RadioGroupItem, dn as ChevronsUpDown, dt as Provider$1, en as EmotionCacheProvider, et as contextAwarePanelOpen, f as JsonOutput, fn as ChevronsRight, ft as Table, g as InstallPackageButton, gn as ArrowDownWideNarrow, gt as TableHeader, h as DataTable, hn as ChevronLeft, ht as TableHead, in as GripHorizontal, it as SlotNames, j as getColumnCountForDisplay, jt as SELECT_COLUMN_ID, k as prettifyRowColumnCount, kt as loadTableData, l as Switch, ln as Download, m as OutputRenderer, mn as ChevronsDownUp, mt as TableCell, n as marimoVersionAtom, nn as $fae977aafc393c5c$export$6b862160d295c8e, nt as contextAwarePanelType, o as SLIDE_TYPE_OPTIONS_BY_VALUE, on as EyeOff, ot as Toggle, p as OutputArea, pn as ChevronsLeft, pt as TableBody, q as CommandInput, qt as ChartInfoState, r as showCodeInRunModeAtom, rn as TextWrap, rt as isCellAwareAtom, t as useNotebookCodeAvailable, tn as $fae977aafc393c5c$export$588937bcd60ade55, tt as contextAwarePanelOwner, u as RadioGroup, un as Code, ut as Fill, v as downloadBlob, vt as NAMELESS_COLUMN_PREFIX, w as ColumnName, wt as DelayMount, x as Progress, xt as renderCellValue, y as downloadByURL, yt as generateColumns, z as useSelectList, zt as dateToLocalISODate, __tla as __tla_2 } from "./code-visibility-
|
|
29
|
+
import { $ as PANEL_TYPES, $t as HtmlOutput, A as prettifyRowCount, At as INDEX_COLUMN_NAME, B as CompactChipRow, Bt as dateToLocalISODateTime, C as downloadSizeLimitAtom, Ct as ColumnChartSpecModel, D as ErrorState, Dt as getPageIndexForRow, E as EmptyState, Et as usePrevious$1, F as ContextMenuItem, Ft as hasFunctionProperty, G as Command, Gt as TabsTrigger, H as DateRangePicker, Ht as Tabs, I as ContextMenuSeparator, It as isRecord, J as CommandItem, Jt as ChartLoadingState, K as CommandEmpty, Kt as ChartErrorState, L as ContextMenuTrigger, Lt as isNullishFilter, M as getUserColumnVisibilityCounts, Mt as TOO_MANY_ROWS, N as ContextMenu, Nt as toFieldTypes, O as LoadingState, Ot as loadTableAndRawData, P as ContextMenuContent, Pt as getMimeValues, Q as ContextAwarePanelItem, Qt as Kbd, R as useInternalStateWithSync, Rt as Maps, S as Filenames, St as ColumnChartContext, T as ColumnPreviewContainer, Tt as useIntersectionObserver, U as Combobox, Ut as TabsContent, V as DatePicker, Vt as dateToLocalISOTime, W as ComboboxItem, Wt as TabsList, X as CommandSeparator, Xt as useOverflowDetection, Y as CommandList, Yt as LazyVegaEmbed, Z as smartMatch, Zt as RenderTextWithLinks, _ as ADD_PRINTING_CLASS, _t as TableRow, an as Funnel, at as slotsController, b as downloadHTMLAsImage, bt as inferFieldTypes, c as Slide, cn as Ellipsis, d as RadioGroupItem, dn as ChevronsUpDown, dt as Provider$1, en as EmotionCacheProvider, et as contextAwarePanelOpen, f as JsonOutput, fn as ChevronsRight, ft as Table, g as InstallPackageButton, gn as ArrowDownWideNarrow, gt as TableHeader, h as DataTable, hn as ChevronLeft, ht as TableHead, in as GripHorizontal, it as SlotNames, j as getColumnCountForDisplay, jt as SELECT_COLUMN_ID, k as prettifyRowColumnCount, kt as loadTableData, l as Switch, ln as Download, m as OutputRenderer, mn as ChevronsDownUp, mt as TableCell, n as marimoVersionAtom, nn as $fae977aafc393c5c$export$6b862160d295c8e, nt as contextAwarePanelType, o as SLIDE_TYPE_OPTIONS_BY_VALUE, on as EyeOff, ot as Toggle, p as OutputArea, pn as ChevronsLeft, pt as TableBody, q as CommandInput, qt as ChartInfoState, r as showCodeInRunModeAtom, rn as TextWrap, rt as isCellAwareAtom, t as useNotebookCodeAvailable, tn as $fae977aafc393c5c$export$588937bcd60ade55, tt as contextAwarePanelOwner, u as RadioGroup, un as Code, ut as Fill, v as downloadBlob, vt as NAMELESS_COLUMN_PREFIX, w as ColumnName, wt as DelayMount, x as Progress, xt as renderCellValue, y as downloadByURL, yt as generateColumns, z as useSelectList, zt as dateToLocalISODate, __tla as __tla_2 } from "./code-visibility-D3MXw5WY.js";
|
|
30
30
|
import { c as Calendar, i as createReducerAndAtoms, n as useOnUnmount, o as ToggleLeft, t as useOnMount } from "./useLifecycle-CxffarYV.js";
|
|
31
31
|
import { t as Check } from "./check-C9OoNtR4.js";
|
|
32
32
|
import { A as Icon, C as logNever, D as $18f2051aff69b9bf$export$a54013f0d02a8f82, E as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7, F as createCollection, I as X, M as clamp$2, N as usePrevious$2, P as useDirection, R as ChevronDown, S as assertNever, a as SelectGroup, c as SelectSeparator, d as NativeSelect, i as SelectContent, j as Trigger$1, l as SelectTrigger, n as capitalize, o as SelectItem, r as Select, s as SelectLabel, t as Strings, u as SelectValue, w as $a916eb452884faea$export$b7a616150fdb9f44 } from "./strings-Dq_j3Rxw.js";
|
|
@@ -36313,7 +36313,7 @@ ${c}
|
|
|
36313
36313
|
function _temp2$2(e) {
|
|
36314
36314
|
e.target === e.currentTarget && e.key === "Enter" && (e.preventDefault(), e.stopPropagation(), e.currentTarget.click());
|
|
36315
36315
|
}
|
|
36316
|
-
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-
|
|
36316
|
+
var LazySlidesComponent = import_react.lazy(() => import("./reveal-component-DuFZrdj1.js"));
|
|
36317
36317
|
const SlidesLayoutRenderer = ({ layout: e, setLayout: r, cells: c, mode: l }) => {
|
|
36318
36318
|
var _a3;
|
|
36319
36319
|
let u = useAtomValue(kioskModeAtom), d = l === "read" || u, f = useAtomValue(numColumnsAtom) > 1, [p, m] = (0, import_react.useState)(null), { slideCells: h, skippedIds: g, noOutputIds: _, slideTypes: v, startCellIndex: y } = (0, import_react.useMemo)(() => computeSlideCellsInfo(c, e), [
|
|
@@ -9,7 +9,7 @@ import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
|
|
|
9
9
|
import { lt as kioskModeAtom, pt as outputIsStale } from "./html-to-image-DLSOS-bE.js";
|
|
10
10
|
import "./chunk-5FQGJX7Z-BbqSm5gU.js";
|
|
11
11
|
import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
|
|
12
|
-
import { a as DEFAULT_SLIDE_TYPE, c as Slide, ct as PanelGroup, i as DEFAULT_DECK_TRANSITION, lt as PanelResizeHandle, on as EyeOff, s as SlideSidebar, sn as Expand, st as Panel, t as useNotebookCodeAvailable, un as Code } from "./code-visibility-
|
|
12
|
+
import { a as DEFAULT_SLIDE_TYPE, c as Slide, ct as PanelGroup, i as DEFAULT_DECK_TRANSITION, lt as PanelResizeHandle, on as EyeOff, s as SlideSidebar, sn as Expand, st as Panel, t as useNotebookCodeAvailable, un as Code } from "./code-visibility-D3MXw5WY.js";
|
|
13
13
|
import { X as useDebouncedCallback } from "./input-BSdZp5Ng.js";
|
|
14
14
|
import "./toDate-D1Z7ZXWh.js";
|
|
15
15
|
import "./react-dom-BTJzcVJ9.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { HTTPError } from "@/utils/errors";
|
|
4
5
|
import { API } from "../api";
|
|
5
6
|
|
|
6
7
|
// Mock fetch globally
|
|
@@ -77,4 +78,20 @@ describe("API", () => {
|
|
|
77
78
|
expect.objectContaining({ method: "POST" }),
|
|
78
79
|
);
|
|
79
80
|
});
|
|
81
|
+
|
|
82
|
+
it("openapi-client error rejects with HTTPError carrying the status", async () => {
|
|
83
|
+
const body = { detail: "This connection is read-only for this action." };
|
|
84
|
+
await expect(
|
|
85
|
+
API.handleResponseReturnNull({
|
|
86
|
+
error: body,
|
|
87
|
+
response: { status: 403, statusText: "Forbidden" } as Response,
|
|
88
|
+
}),
|
|
89
|
+
).rejects.toMatchObject({ status: 403, cause: body });
|
|
90
|
+
await expect(
|
|
91
|
+
API.handleResponseReturnNull({
|
|
92
|
+
error: body,
|
|
93
|
+
response: { status: 403, statusText: "Forbidden" } as Response,
|
|
94
|
+
}),
|
|
95
|
+
).rejects.toBeInstanceOf(HTTPError);
|
|
96
|
+
});
|
|
80
97
|
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { HTTPError } from "@/utils/errors";
|
|
5
|
+
|
|
6
|
+
const toastMock = vi.fn();
|
|
7
|
+
vi.mock("@/components/ui/use-toast", () => ({
|
|
8
|
+
toast: (...args: unknown[]) => toastMock(...args),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
import { createErrorToastingRequests } from "../requests-toasting";
|
|
12
|
+
import type { EditRequests, RunRequests } from "../types";
|
|
13
|
+
|
|
14
|
+
function requestsThatReject(error: unknown): EditRequests & RunRequests {
|
|
15
|
+
return createErrorToastingRequests({
|
|
16
|
+
sendRun: vi.fn().mockRejectedValue(error),
|
|
17
|
+
} as unknown as EditRequests & RunRequests);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("createErrorToastingRequests", () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
toastMock.mockClear();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("suppresses the error toast for a capability 403", async () => {
|
|
26
|
+
const requests = requestsThatReject(
|
|
27
|
+
new HTTPError(403, "Forbidden", {
|
|
28
|
+
detail: "This connection is read-only for this action.",
|
|
29
|
+
}),
|
|
30
|
+
);
|
|
31
|
+
await expect(requests.sendRun({} as never)).rejects.toBeInstanceOf(
|
|
32
|
+
HTTPError,
|
|
33
|
+
);
|
|
34
|
+
expect(toastMock).not.toHaveBeenCalled();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("shows a danger toast for other request errors", async () => {
|
|
38
|
+
const requests = requestsThatReject(new HTTPError(500, "Server Error"));
|
|
39
|
+
await expect(requests.sendRun({} as never)).rejects.toBeInstanceOf(
|
|
40
|
+
HTTPError,
|
|
41
|
+
);
|
|
42
|
+
expect(toastMock).toHaveBeenCalledWith(
|
|
43
|
+
expect.objectContaining({ variant: "danger" }),
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
});
|
package/src/core/network/api.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { createMarimoClient } from "@marimo-team/marimo-api";
|
|
4
|
+
import { HTTPError } from "../../utils/errors";
|
|
4
5
|
import { Logger } from "../../utils/Logger";
|
|
5
6
|
import { Strings } from "../../utils/strings";
|
|
6
7
|
import { getRuntimeManager } from "../runtime/config";
|
|
@@ -50,7 +51,7 @@ export const API = {
|
|
|
50
51
|
const errorBody = isJson
|
|
51
52
|
? await response.json()
|
|
52
53
|
: await response.text();
|
|
53
|
-
throw new
|
|
54
|
+
throw new HTTPError(response.status, response.statusText, errorBody);
|
|
54
55
|
}
|
|
55
56
|
if (isJson) {
|
|
56
57
|
return response.json() as RESP;
|
|
@@ -83,7 +84,7 @@ export const API = {
|
|
|
83
84
|
})
|
|
84
85
|
.then((response) => {
|
|
85
86
|
if (!response.ok) {
|
|
86
|
-
throw new
|
|
87
|
+
throw new HTTPError(response.status, response.statusText);
|
|
87
88
|
}
|
|
88
89
|
if (
|
|
89
90
|
response.headers.get("Content-Type")?.startsWith("application/json")
|
|
@@ -108,8 +109,13 @@ export const API = {
|
|
|
108
109
|
response: Response;
|
|
109
110
|
}): Promise<T> => {
|
|
110
111
|
if (response.error) {
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
return Promise.reject(
|
|
113
|
+
new HTTPError(
|
|
114
|
+
response.response.status,
|
|
115
|
+
response.response.statusText,
|
|
116
|
+
response.error,
|
|
117
|
+
),
|
|
118
|
+
);
|
|
113
119
|
}
|
|
114
120
|
return Promise.resolve(response.data as T);
|
|
115
121
|
},
|
|
@@ -118,8 +124,13 @@ export const API = {
|
|
|
118
124
|
response: Response;
|
|
119
125
|
}): Promise<null> => {
|
|
120
126
|
if (response.error) {
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
return Promise.reject(
|
|
128
|
+
new HTTPError(
|
|
129
|
+
response.response.status,
|
|
130
|
+
response.response.statusText,
|
|
131
|
+
response.error,
|
|
132
|
+
),
|
|
133
|
+
);
|
|
123
134
|
}
|
|
124
135
|
return Promise.resolve(null);
|
|
125
136
|
},
|
|
@@ -5,7 +5,7 @@ import { useAtomValue } from "jotai";
|
|
|
5
5
|
import { Spinner } from "@/components/icons/spinner";
|
|
6
6
|
import { Button } from "@/components/ui/button";
|
|
7
7
|
import { toast } from "@/components/ui/use-toast";
|
|
8
|
-
import { NoKernelConnectedError, prettyError } from "@/utils/errors";
|
|
8
|
+
import { HTTPError, NoKernelConnectedError, prettyError } from "@/utils/errors";
|
|
9
9
|
import { Logger } from "@/utils/Logger";
|
|
10
10
|
import { useConnectToRuntime } from "../runtime/config";
|
|
11
11
|
import { store } from "../state/jotai";
|
|
@@ -109,6 +109,14 @@ export function createErrorToastingRequests(
|
|
|
109
109
|
throw error;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// A capability 403: the connection is read-only for this action. The
|
|
113
|
+
// live capability notification already moved the UI to viewer state,
|
|
114
|
+
// so don't alarm the user with an error toast.
|
|
115
|
+
if (error instanceof HTTPError && error.status === 403) {
|
|
116
|
+
Logger.warn(`Request refused, connection is read-only: ${key}`);
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
|
|
112
120
|
const title = MESSAGES[keyString];
|
|
113
121
|
const message = prettyError(error);
|
|
114
122
|
if (title) {
|
package/src/utils/errors.ts
CHANGED
|
@@ -62,6 +62,21 @@ function safeJSONParse(message: string): unknown {
|
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* A failed HTTP response. Carries the status code so callers can branch on it
|
|
67
|
+
* (e.g. treat a capability 403 as a benign viewer state). The response body is
|
|
68
|
+
* kept as `cause` so `prettyError` can surface its `detail`.
|
|
69
|
+
*/
|
|
70
|
+
export class HTTPError extends Error {
|
|
71
|
+
readonly status: number;
|
|
72
|
+
|
|
73
|
+
constructor(status: number, statusText: string, body?: unknown) {
|
|
74
|
+
super(statusText, { cause: body });
|
|
75
|
+
this.name = "HTTPError";
|
|
76
|
+
this.status = status;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
65
80
|
export class CellNotInitializedError extends Error {
|
|
66
81
|
constructor(
|
|
67
82
|
message = "The cell containing this UI element has not been run yet. Please run the cell first.",
|