@marimo-team/frontend 0.22.1-dev2 → 0.22.1-dev4
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/package.json +1 -1
- package/src/__tests__/branded.ts +6 -0
- package/src/core/cells/__tests__/apply-transaction.test.ts +12 -11
- package/src/core/cells/document-changes.ts +9 -9
- package/src/core/islands/__tests__/bridge.test.ts +20 -10
- package/src/core/network/__tests__/requests-lazy.test.ts +30 -14
- package/src/core/websocket/useMarimoKernelConnection.tsx +5 -11
- package/src/utils/time.ts +4 -2
- package/src/utils/typed.ts +2 -2
package/package.json
CHANGED
package/src/__tests__/branded.ts
CHANGED
|
@@ -10,11 +10,17 @@
|
|
|
10
10
|
* everywhere.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import type { components } from "@marimo-team/marimo-api";
|
|
13
14
|
import type { CellId, UIElementId } from "@/core/cells/ids";
|
|
14
15
|
import type { RequestId } from "@/core/network/DeferredRequestRegistry";
|
|
15
16
|
import type { VariableName } from "@/core/variables/types";
|
|
16
17
|
|
|
18
|
+
type WidgetModelId = components["schemas"]["WidgetModelId"];
|
|
19
|
+
type Base64String = components["schemas"]["Base64String"];
|
|
20
|
+
|
|
17
21
|
export const cellId = (s: string) => s as CellId;
|
|
18
22
|
export const variableName = (s: string) => s as VariableName;
|
|
19
23
|
export const requestId = (s: string) => s as RequestId;
|
|
20
24
|
export const uiElementId = (s: string) => s as UIElementId;
|
|
25
|
+
export const widgetModelId = (s: string) => s as WidgetModelId;
|
|
26
|
+
export const base64String = (s: string) => s as Base64String;
|
|
@@ -18,6 +18,7 @@ import { python } from "@codemirror/lang-python";
|
|
|
18
18
|
import { EditorState } from "@codemirror/state";
|
|
19
19
|
import { EditorView } from "@codemirror/view";
|
|
20
20
|
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|
21
|
+
import { cellId } from "@/__tests__/branded";
|
|
21
22
|
import type { CellHandle } from "@/components/editor/notebook-cell";
|
|
22
23
|
import { adaptiveLanguageConfiguration } from "@/core/codemirror/language/extension";
|
|
23
24
|
import { OverridingHotkeyProvider } from "@/core/hotkeys/hotkeys";
|
|
@@ -121,7 +122,7 @@ describe("applyTransactionChanges edge cases", () => {
|
|
|
121
122
|
apply([
|
|
122
123
|
{
|
|
123
124
|
type: "create-cell",
|
|
124
|
-
cellId: "new-cell",
|
|
125
|
+
cellId: cellId("new-cell"),
|
|
125
126
|
code: "configured",
|
|
126
127
|
name: "",
|
|
127
128
|
config: { hide_code: true, disabled: true, column: 1 },
|
|
@@ -141,12 +142,12 @@ describe("applyTransactionChanges edge cases", () => {
|
|
|
141
142
|
apply([
|
|
142
143
|
{
|
|
143
144
|
type: "create-cell",
|
|
144
|
-
cellId: "new-cell",
|
|
145
|
+
cellId: cellId("new-cell"),
|
|
145
146
|
code: "new",
|
|
146
147
|
name: "",
|
|
147
148
|
config: {},
|
|
148
149
|
},
|
|
149
|
-
{ type: "move-cell", cellId: "new-cell", before: a },
|
|
150
|
+
{ type: "move-cell", cellId: cellId("new-cell"), before: a },
|
|
150
151
|
]);
|
|
151
152
|
expect(pretty(state)).toMatchInlineSnapshot(`
|
|
152
153
|
"
|
|
@@ -162,12 +163,12 @@ describe("applyTransactionChanges edge cases", () => {
|
|
|
162
163
|
apply([
|
|
163
164
|
{
|
|
164
165
|
type: "create-cell",
|
|
165
|
-
cellId: "new-cell",
|
|
166
|
+
cellId: cellId("new-cell"),
|
|
166
167
|
code: "initial",
|
|
167
168
|
name: "",
|
|
168
169
|
config: {},
|
|
169
170
|
},
|
|
170
|
-
{ type: "set-code", cellId: "new-cell", code: "updated" },
|
|
171
|
+
{ type: "set-code", cellId: cellId("new-cell"), code: "updated" },
|
|
171
172
|
]);
|
|
172
173
|
expect(pretty(state)).toMatchInlineSnapshot(`
|
|
173
174
|
"
|
|
@@ -182,12 +183,12 @@ describe("applyTransactionChanges edge cases", () => {
|
|
|
182
183
|
apply([
|
|
183
184
|
{
|
|
184
185
|
type: "create-cell",
|
|
185
|
-
cellId: "ephemeral",
|
|
186
|
+
cellId: cellId("ephemeral"),
|
|
186
187
|
code: "tmp",
|
|
187
188
|
name: "",
|
|
188
189
|
config: {},
|
|
189
190
|
},
|
|
190
|
-
{ type: "delete-cell", cellId: "ephemeral" },
|
|
191
|
+
{ type: "delete-cell", cellId: cellId("ephemeral") },
|
|
191
192
|
]);
|
|
192
193
|
expect(pretty(state)).toMatchInlineSnapshot(`
|
|
193
194
|
"
|
|
@@ -228,7 +229,7 @@ describe("applyTransactionChanges edge cases", () => {
|
|
|
228
229
|
it("move-cell with missing after anchor falls back to end", () => {
|
|
229
230
|
setup("a", "b");
|
|
230
231
|
const [a] = state.cellIds.inOrderIds;
|
|
231
|
-
apply([{ type: "move-cell", cellId: a, after: "nonexistent"
|
|
232
|
+
apply([{ type: "move-cell", cellId: a, after: cellId("nonexistent") }]);
|
|
232
233
|
expect(pretty(state)).toMatchInlineSnapshot(`
|
|
233
234
|
"
|
|
234
235
|
1: 'b'
|
|
@@ -240,7 +241,7 @@ describe("applyTransactionChanges edge cases", () => {
|
|
|
240
241
|
it("move-cell with missing before anchor falls back to start", () => {
|
|
241
242
|
setup("a", "b");
|
|
242
243
|
const [, b] = state.cellIds.inOrderIds;
|
|
243
|
-
apply([{ type: "move-cell", cellId: b, before: "nonexistent"
|
|
244
|
+
apply([{ type: "move-cell", cellId: b, before: cellId("nonexistent") }]);
|
|
244
245
|
expect(pretty(state)).toMatchInlineSnapshot(`
|
|
245
246
|
"
|
|
246
247
|
1: 'b'
|
|
@@ -254,8 +255,8 @@ describe("applyTransactionChanges edge cases", () => {
|
|
|
254
255
|
apply([
|
|
255
256
|
{
|
|
256
257
|
type: "move-cell",
|
|
257
|
-
cellId: "nonexistent"
|
|
258
|
-
after: "0"
|
|
258
|
+
cellId: cellId("nonexistent"),
|
|
259
|
+
after: cellId("0"),
|
|
259
260
|
},
|
|
260
261
|
]);
|
|
261
262
|
expect(pretty(state)).toMatchInlineSnapshot(`
|
|
@@ -425,7 +425,7 @@ export function fromDocumentChanges(
|
|
|
425
425
|
cellId,
|
|
426
426
|
before,
|
|
427
427
|
code: change.code,
|
|
428
|
-
newCellId: change.cellId
|
|
428
|
+
newCellId: change.cellId,
|
|
429
429
|
autoFocus: false,
|
|
430
430
|
hideCode: change.config?.hide_code ?? false,
|
|
431
431
|
},
|
|
@@ -433,14 +433,14 @@ export function fromDocumentChanges(
|
|
|
433
433
|
if (change.name) {
|
|
434
434
|
actions.push({
|
|
435
435
|
type: "updateCellName",
|
|
436
|
-
payload: { cellId: change.cellId
|
|
436
|
+
payload: { cellId: change.cellId, name: change.name },
|
|
437
437
|
});
|
|
438
438
|
}
|
|
439
439
|
if (change.config?.disabled != null || change.config?.column != null) {
|
|
440
440
|
actions.push({
|
|
441
441
|
type: "updateCellConfig",
|
|
442
442
|
payload: {
|
|
443
|
-
cellId: change.cellId
|
|
443
|
+
cellId: change.cellId,
|
|
444
444
|
config: {
|
|
445
445
|
...(change.config.disabled != null && {
|
|
446
446
|
disabled: change.config.disabled,
|
|
@@ -460,7 +460,7 @@ export function fromDocumentChanges(
|
|
|
460
460
|
case "delete-cell":
|
|
461
461
|
actions.push({
|
|
462
462
|
type: "deleteCell",
|
|
463
|
-
payload: { cellId: change.cellId
|
|
463
|
+
payload: { cellId: change.cellId },
|
|
464
464
|
});
|
|
465
465
|
break;
|
|
466
466
|
|
|
@@ -471,7 +471,7 @@ export function fromDocumentChanges(
|
|
|
471
471
|
// missing. No-ops if the cell itself doesn't exist.
|
|
472
472
|
case "move-cell": {
|
|
473
473
|
const ids = [...getCurrentCellIds()];
|
|
474
|
-
const cellId = change.cellId
|
|
474
|
+
const cellId = change.cellId;
|
|
475
475
|
const idx = ids.indexOf(cellId);
|
|
476
476
|
if (idx < 0) {
|
|
477
477
|
break;
|
|
@@ -507,7 +507,7 @@ export function fromDocumentChanges(
|
|
|
507
507
|
case "reorder-cells":
|
|
508
508
|
actions.push({
|
|
509
509
|
type: "setCellIds",
|
|
510
|
-
payload: { cellIds: change.cellIds
|
|
510
|
+
payload: { cellIds: change.cellIds },
|
|
511
511
|
});
|
|
512
512
|
break;
|
|
513
513
|
|
|
@@ -518,7 +518,7 @@ export function fromDocumentChanges(
|
|
|
518
518
|
actions.push({
|
|
519
519
|
type: "setCellCodes",
|
|
520
520
|
payload: {
|
|
521
|
-
ids: [change.cellId
|
|
521
|
+
ids: [change.cellId],
|
|
522
522
|
codes: [change.code],
|
|
523
523
|
codeIsStale: true,
|
|
524
524
|
},
|
|
@@ -530,7 +530,7 @@ export function fromDocumentChanges(
|
|
|
530
530
|
case "set-name":
|
|
531
531
|
actions.push({
|
|
532
532
|
type: "updateCellName",
|
|
533
|
-
payload: { cellId: change.cellId
|
|
533
|
+
payload: { cellId: change.cellId, name: change.name },
|
|
534
534
|
});
|
|
535
535
|
break;
|
|
536
536
|
|
|
@@ -542,7 +542,7 @@ export function fromDocumentChanges(
|
|
|
542
542
|
actions.push({
|
|
543
543
|
type: "updateCellConfig",
|
|
544
544
|
payload: {
|
|
545
|
-
cellId: change.cellId
|
|
545
|
+
cellId: change.cellId,
|
|
546
546
|
config: {
|
|
547
547
|
...(change.hideCode != null && { hide_code: change.hideCode }),
|
|
548
548
|
...(change.disabled != null && { disabled: change.disabled }),
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type { components } from "@marimo-team/marimo-api";
|
|
2
4
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import {
|
|
6
|
+
cellId,
|
|
7
|
+
requestId,
|
|
8
|
+
uiElementId,
|
|
9
|
+
widgetModelId,
|
|
10
|
+
} from "@/__tests__/branded";
|
|
11
|
+
|
|
12
|
+
type Base64String = components["schemas"]["Base64String"];
|
|
3
13
|
|
|
4
14
|
// Mock browser APIs before any imports
|
|
5
15
|
vi.stubGlobal(
|
|
@@ -89,7 +99,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
89
99
|
describe("sendComponentValues", () => {
|
|
90
100
|
it("should include type field and token in control request", async () => {
|
|
91
101
|
const request = {
|
|
92
|
-
objectIds: ["Hbol-0"],
|
|
102
|
+
objectIds: [uiElementId("Hbol-0")],
|
|
93
103
|
values: [58],
|
|
94
104
|
};
|
|
95
105
|
|
|
@@ -108,7 +118,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
108
118
|
|
|
109
119
|
it("should preserve all request properties", async () => {
|
|
110
120
|
const request = {
|
|
111
|
-
objectIds: ["slider-1", "slider-2"],
|
|
121
|
+
objectIds: [uiElementId("slider-1"), uiElementId("slider-2")],
|
|
112
122
|
values: [10, 20],
|
|
113
123
|
};
|
|
114
124
|
|
|
@@ -128,7 +138,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
128
138
|
describe("sendFunctionRequest", () => {
|
|
129
139
|
it("should include type field in control request", async () => {
|
|
130
140
|
const request = {
|
|
131
|
-
functionCallId: "call-123",
|
|
141
|
+
functionCallId: requestId("call-123"),
|
|
132
142
|
namespace: "test_namespace",
|
|
133
143
|
functionName: "my_function",
|
|
134
144
|
args: { x: 1, y: 2 },
|
|
@@ -152,7 +162,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
152
162
|
describe("sendRun", () => {
|
|
153
163
|
it("should include type field in control request", async () => {
|
|
154
164
|
const request = {
|
|
155
|
-
cellIds: ["cell-1", "cell-2"],
|
|
165
|
+
cellIds: [cellId("cell-1"), cellId("cell-2")],
|
|
156
166
|
codes: ["print('hello')", "print('world')"],
|
|
157
167
|
};
|
|
158
168
|
|
|
@@ -170,7 +180,7 @@ describe("IslandsPyodideBridge", () => {
|
|
|
170
180
|
|
|
171
181
|
it("should call loadPackages before putControlRequest", async () => {
|
|
172
182
|
const request = {
|
|
173
|
-
cellIds: ["cell-1"],
|
|
183
|
+
cellIds: [cellId("cell-1")],
|
|
174
184
|
codes: ["import pandas"],
|
|
175
185
|
};
|
|
176
186
|
|
|
@@ -190,13 +200,13 @@ describe("IslandsPyodideBridge", () => {
|
|
|
190
200
|
describe("sendModelValue", () => {
|
|
191
201
|
it("should include type field in control request", async () => {
|
|
192
202
|
const request = {
|
|
193
|
-
modelId: "widget-1",
|
|
203
|
+
modelId: widgetModelId("widget-1"),
|
|
194
204
|
message: {
|
|
195
205
|
method: "update" as const,
|
|
196
206
|
state: { value: 42 },
|
|
197
207
|
bufferPaths: [],
|
|
198
208
|
},
|
|
199
|
-
buffers: [],
|
|
209
|
+
buffers: [] as Base64String[],
|
|
200
210
|
};
|
|
201
211
|
|
|
202
212
|
await bridge.sendModelValue(request);
|
|
@@ -222,16 +232,16 @@ describe("IslandsPyodideBridge", () => {
|
|
|
222
232
|
// Test all methods to ensure they include the type field
|
|
223
233
|
await bridge.sendComponentValues({ objectIds: [], values: [] });
|
|
224
234
|
await bridge.sendFunctionRequest({
|
|
225
|
-
functionCallId: "",
|
|
235
|
+
functionCallId: requestId(""),
|
|
226
236
|
namespace: "",
|
|
227
237
|
functionName: "",
|
|
228
238
|
args: {},
|
|
229
239
|
});
|
|
230
240
|
await bridge.sendRun({ cellIds: [], codes: [] });
|
|
231
241
|
await bridge.sendModelValue({
|
|
232
|
-
modelId: "",
|
|
242
|
+
modelId: widgetModelId(""),
|
|
233
243
|
message: { method: "update", state: {}, bufferPaths: [] },
|
|
234
|
-
buffers: [],
|
|
244
|
+
buffers: [] as Base64String[],
|
|
235
245
|
});
|
|
236
246
|
|
|
237
247
|
// All calls should have the type field
|
|
@@ -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 { cellId, requestId, uiElementId } from "@/__tests__/branded";
|
|
4
5
|
import type { RuntimeManager } from "../../runtime/runtime";
|
|
5
6
|
import { createLazyRequests } from "../requests-lazy";
|
|
6
7
|
import type { EditRequests, RunRequests } from "../types";
|
|
@@ -59,7 +60,7 @@ describe("createLazyRequests", () => {
|
|
|
59
60
|
mockGetRuntimeManager,
|
|
60
61
|
);
|
|
61
62
|
|
|
62
|
-
await lazyRequests.sendRun({ cellIds: ["cell1"], codes: ["code"] });
|
|
63
|
+
await lazyRequests.sendRun({ cellIds: [cellId("cell1")], codes: ["code"] });
|
|
63
64
|
|
|
64
65
|
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
65
66
|
});
|
|
@@ -70,10 +71,13 @@ describe("createLazyRequests", () => {
|
|
|
70
71
|
mockGetRuntimeManager,
|
|
71
72
|
);
|
|
72
73
|
|
|
73
|
-
await lazyRequests.sendRun({ cellIds: ["cell1"], codes: ["code"] });
|
|
74
|
-
await lazyRequests.sendInstantiate({
|
|
74
|
+
await lazyRequests.sendRun({ cellIds: [cellId("cell1")], codes: ["code"] });
|
|
75
|
+
await lazyRequests.sendInstantiate({
|
|
76
|
+
objectIds: [uiElementId("obj1")],
|
|
77
|
+
values: [],
|
|
78
|
+
});
|
|
75
79
|
await lazyRequests.sendFunctionRequest({
|
|
76
|
-
functionCallId: "func1",
|
|
80
|
+
functionCallId: requestId("func1"),
|
|
77
81
|
functionName: "testFunc",
|
|
78
82
|
args: {},
|
|
79
83
|
namespace: "test",
|
|
@@ -89,7 +93,7 @@ describe("createLazyRequests", () => {
|
|
|
89
93
|
mockGetRuntimeManager,
|
|
90
94
|
);
|
|
91
95
|
|
|
92
|
-
await lazyRequests.sendRun({ cellIds: ["cell1"], codes: ["code"] });
|
|
96
|
+
await lazyRequests.sendRun({ cellIds: [cellId("cell1")], codes: ["code"] });
|
|
93
97
|
|
|
94
98
|
expect(waitForConnectionOpen).toHaveBeenCalled();
|
|
95
99
|
});
|
|
@@ -100,7 +104,7 @@ describe("createLazyRequests", () => {
|
|
|
100
104
|
mockGetRuntimeManager,
|
|
101
105
|
);
|
|
102
106
|
|
|
103
|
-
const args = { cellIds: ["cell1"], codes: ["code"] };
|
|
107
|
+
const args = { cellIds: [cellId("cell1")], codes: ["code"] };
|
|
104
108
|
await lazyRequests.sendRun(args);
|
|
105
109
|
|
|
106
110
|
expect(mockDelegate.sendRun).toHaveBeenCalledWith(args);
|
|
@@ -113,7 +117,7 @@ describe("createLazyRequests", () => {
|
|
|
113
117
|
);
|
|
114
118
|
|
|
115
119
|
const result = await lazyRequests.sendFunctionRequest({
|
|
116
|
-
functionCallId: "func1",
|
|
120
|
+
functionCallId: requestId("func1"),
|
|
117
121
|
functionName: "testFunc",
|
|
118
122
|
args: {},
|
|
119
123
|
namespace: "test",
|
|
@@ -143,7 +147,7 @@ describe("createLazyRequests", () => {
|
|
|
143
147
|
);
|
|
144
148
|
|
|
145
149
|
await expect(
|
|
146
|
-
lazyRequests.sendRun({ cellIds: ["cell1"], codes: ["code"] }),
|
|
150
|
+
lazyRequests.sendRun({ cellIds: [cellId("cell1")], codes: ["code"] }),
|
|
147
151
|
).rejects.toThrow("Init failed");
|
|
148
152
|
});
|
|
149
153
|
|
|
@@ -157,7 +161,7 @@ describe("createLazyRequests", () => {
|
|
|
157
161
|
);
|
|
158
162
|
|
|
159
163
|
await expect(
|
|
160
|
-
lazyRequests.sendRun({ cellIds: ["cell1"], codes: ["code"] }),
|
|
164
|
+
lazyRequests.sendRun({ cellIds: [cellId("cell1")], codes: ["code"] }),
|
|
161
165
|
).rejects.toThrow("Request failed");
|
|
162
166
|
});
|
|
163
167
|
|
|
@@ -169,7 +173,10 @@ describe("createLazyRequests", () => {
|
|
|
169
173
|
);
|
|
170
174
|
|
|
171
175
|
// First request with first runtime manager
|
|
172
|
-
await lazyRequests.sendRun({
|
|
176
|
+
await lazyRequests.sendRun({
|
|
177
|
+
cellIds: [cellId("cell1")],
|
|
178
|
+
codes: ["code"],
|
|
179
|
+
});
|
|
173
180
|
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
174
181
|
|
|
175
182
|
// Create a new runtime manager
|
|
@@ -187,7 +194,10 @@ describe("createLazyRequests", () => {
|
|
|
187
194
|
);
|
|
188
195
|
|
|
189
196
|
// Second request with second runtime manager
|
|
190
|
-
await lazyRequests2.sendRun({
|
|
197
|
+
await lazyRequests2.sendRun({
|
|
198
|
+
cellIds: [cellId("cell2")],
|
|
199
|
+
codes: ["code2"],
|
|
200
|
+
});
|
|
191
201
|
|
|
192
202
|
// Both inits should have been called
|
|
193
203
|
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
@@ -201,9 +211,15 @@ describe("createLazyRequests", () => {
|
|
|
201
211
|
);
|
|
202
212
|
|
|
203
213
|
// Multiple requests
|
|
204
|
-
await lazyRequests.sendRun({
|
|
205
|
-
|
|
206
|
-
|
|
214
|
+
await lazyRequests.sendRun({
|
|
215
|
+
cellIds: [cellId("cell1")],
|
|
216
|
+
codes: ["code"],
|
|
217
|
+
});
|
|
218
|
+
await lazyRequests.sendDeleteCell({ cellId: cellId("cell2") });
|
|
219
|
+
await lazyRequests.sendInstantiate({
|
|
220
|
+
objectIds: [uiElementId("obj1")],
|
|
221
|
+
values: [],
|
|
222
|
+
});
|
|
207
223
|
|
|
208
224
|
// Init should only be called once
|
|
209
225
|
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
@@ -186,7 +186,7 @@ export function useMarimoKernelConnection(opts: {
|
|
|
186
186
|
return;
|
|
187
187
|
|
|
188
188
|
case "completion-result":
|
|
189
|
-
AUTOCOMPLETER.resolve(msg.data.completion_id
|
|
189
|
+
AUTOCOMPLETER.resolve(msg.data.completion_id, msg.data);
|
|
190
190
|
return;
|
|
191
191
|
case "function-call-result":
|
|
192
192
|
FUNCTIONS_REGISTRY.resolve(msg.data.function_call_id, msg.data);
|
|
@@ -207,20 +207,14 @@ export function useMarimoKernelConnection(opts: {
|
|
|
207
207
|
case "variables":
|
|
208
208
|
setVariables(
|
|
209
209
|
msg.data.variables.map((v) => ({
|
|
210
|
-
name: v.name
|
|
210
|
+
name: v.name,
|
|
211
211
|
declaredBy: v.declared_by,
|
|
212
212
|
usedBy: v.used_by,
|
|
213
213
|
})),
|
|
214
214
|
);
|
|
215
|
-
filterDatasetsFromVariables(
|
|
216
|
-
|
|
217
|
-
);
|
|
218
|
-
filterDataSourcesFromVariables(
|
|
219
|
-
msg.data.variables.map((v) => v.name as VariableName),
|
|
220
|
-
);
|
|
221
|
-
filterStorageFromVariables(
|
|
222
|
-
msg.data.variables.map((v) => v.name as VariableName),
|
|
223
|
-
);
|
|
215
|
+
filterDatasetsFromVariables(msg.data.variables.map((v) => v.name));
|
|
216
|
+
filterDataSourcesFromVariables(msg.data.variables.map((v) => v.name));
|
|
217
|
+
filterStorageFromVariables(msg.data.variables.map((v) => v.name));
|
|
224
218
|
return;
|
|
225
219
|
case "variable-values":
|
|
226
220
|
setMetadata(
|
package/src/utils/time.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import type { TypedNumber } from "./typed";
|
|
4
4
|
|
|
5
|
-
export type
|
|
5
|
+
export type Milliseconds = TypedNumber<"milliseconds">;
|
|
6
|
+
|
|
7
|
+
export type Seconds = TypedNumber<"seconds">;
|
|
6
8
|
|
|
7
9
|
export class Time {
|
|
8
10
|
private readonly ms: Milliseconds;
|
package/src/utils/typed.ts
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* This is a compile-time type only and does not exist at runtime.
|
|
6
6
|
* It is used to distinguish between different types of numbers.
|
|
7
7
|
*/
|
|
8
|
-
export type TypedNumber<T> = number & {
|
|
8
|
+
export type TypedNumber<T> = number & { __brand: T };
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* A typed string.
|
|
12
12
|
* This is a compile-time type only and does not exist at runtime.
|
|
13
13
|
* It is used to distinguish between different types of strings.
|
|
14
14
|
*/
|
|
15
|
-
export type TypedString<T> = string & {
|
|
15
|
+
export type TypedString<T> = string & { __brand: T };
|
|
16
16
|
|
|
17
17
|
export type Identified<T> = { id: string } & T;
|