@marimo-team/islands 0.23.16-dev51 → 0.23.16-dev53
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/{chat-ui-1e7PcW56.js → chat-ui-9neL0bYw.js} +2 -2
- package/dist/{common-CD6phlRu.js → common-BxtRKijk.js} +2 -2
- package/dist/{html-to-image-3w0AakWW.js → html-to-image-DzQw9y4M.js} +2113 -2103
- package/dist/main.js +7 -5
- package/dist/{process-output-BRwR4QGs.js → process-output-tYmEI9FZ.js} +1 -1
- package/dist/{reveal-component-DmGGKS8z.js → reveal-component-DuXe-jZN.js} +2 -2
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/__mocks__/requests.ts +1 -0
- package/src/components/editor/connections/__tests__/quick-add-data-sources.test.tsx +113 -0
- package/src/components/editor/connections/add-connection-dialog.tsx +2 -0
- package/src/components/editor/connections/quick-add-data-sources.tsx +106 -0
- package/src/core/codemirror/language/__tests__/sql.test.ts +191 -7
- package/src/core/codemirror/language/languages/sql/sql.ts +41 -13
- package/src/core/datasets/data-source-discovery.ts +5 -0
- package/src/core/datasets/request-registry.ts +11 -0
- package/src/core/islands/bootstrap.ts +1 -0
- package/src/core/islands/bridge.ts +1 -0
- package/src/core/kernel/messages.ts +2 -0
- package/src/core/network/__tests__/requests-lazy.test.ts +15 -0
- package/src/core/network/__tests__/requests-network.test.ts +14 -0
- package/src/core/network/requests-lazy.ts +1 -0
- package/src/core/network/requests-network.ts +8 -0
- package/src/core/network/requests-static.ts +1 -0
- package/src/core/network/requests-toasting.tsx +1 -0
- package/src/core/network/types.ts +2 -0
- package/src/core/wasm/bridge.ts +10 -0
- package/src/core/websocket/useMarimoKernelConnection.tsx +4 -0
- package/src/hooks/__tests__/useDataSourceDiscovery.test.ts +80 -0
- package/src/hooks/useDataSourceDiscovery.ts +18 -0
|
@@ -114,6 +114,21 @@ describe("createLazyRequests", () => {
|
|
|
114
114
|
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
+
it("starts the kernel for datasource discovery", async () => {
|
|
118
|
+
mockDelegate.discoverDataSources = vi.fn().mockResolvedValue(null);
|
|
119
|
+
const lazyRequests = createLazyRequests(
|
|
120
|
+
mockDelegate,
|
|
121
|
+
mockGetRuntimeManager,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
await lazyRequests.discoverDataSources({
|
|
125
|
+
requestId: requestId("discovery"),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
expect(mockInit).toHaveBeenCalledOnce();
|
|
129
|
+
expect(mockDelegate.discoverDataSources).toHaveBeenCalledOnce();
|
|
130
|
+
});
|
|
131
|
+
|
|
117
132
|
it("should only call init once across multiple requests", async () => {
|
|
118
133
|
const lazyRequests = createLazyRequests(
|
|
119
134
|
mockDelegate,
|
|
@@ -130,6 +130,20 @@ describe("createNetworkRequests", () => {
|
|
|
130
130
|
expect(mockClient.GET).toHaveBeenCalledWith("/api/export/availability");
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
+
it("discoverDataSources should POST to the discovery endpoint", async () => {
|
|
134
|
+
const requests = createNetworkRequests();
|
|
135
|
+
const request = { requestId: "discovery-request" } as any;
|
|
136
|
+
await requests.discoverDataSources(request);
|
|
137
|
+
|
|
138
|
+
expect(mockClient.POST).toHaveBeenCalledWith(
|
|
139
|
+
"/api/datasources/discover",
|
|
140
|
+
expect.objectContaining({
|
|
141
|
+
body: request,
|
|
142
|
+
params: expect.anything(),
|
|
143
|
+
}),
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
133
147
|
it("getPackageList should not require a kernel connection", async () => {
|
|
134
148
|
const { waitForConnectionOpen, waitForConnectionOpenIfNotebook } =
|
|
135
149
|
await import("../connection");
|
|
@@ -51,6 +51,7 @@ const ACTIONS: Record<keyof AllRequests, Action> = {
|
|
|
51
51
|
sendRunScratchpad: "startConnection",
|
|
52
52
|
saveAppConfig: "startConnection",
|
|
53
53
|
saveCellConfig: "startConnection",
|
|
54
|
+
discoverDataSources: "startConnection",
|
|
54
55
|
|
|
55
56
|
// Export operations start a connection
|
|
56
57
|
exportAsHTML: "startConnection",
|
|
@@ -267,6 +267,14 @@ export function createNetworkRequests(): EditRequests & RunRequests {
|
|
|
267
267
|
})
|
|
268
268
|
.then(handleResponseReturnNull);
|
|
269
269
|
},
|
|
270
|
+
discoverDataSources: (request) => {
|
|
271
|
+
return getClient()
|
|
272
|
+
.POST("/api/datasources/discover", {
|
|
273
|
+
body: request,
|
|
274
|
+
params: getParams(),
|
|
275
|
+
})
|
|
276
|
+
.then(handleResponseReturnNull);
|
|
277
|
+
},
|
|
270
278
|
validateSQL: (request) => {
|
|
271
279
|
return getClient()
|
|
272
280
|
.POST("/api/sql/validate", {
|
|
@@ -62,6 +62,7 @@ export function createStaticRequests(): EditRequests & RunRequests {
|
|
|
62
62
|
previewSQLTableList: throwNotInEditMode,
|
|
63
63
|
previewSQLSchemaList: throwNotInEditMode,
|
|
64
64
|
previewDataSourceConnection: throwNotInEditMode,
|
|
65
|
+
discoverDataSources: throwNotInEditMode,
|
|
65
66
|
validateSQL: throwNotInEditMode,
|
|
66
67
|
openFile: throwNotInEditMode,
|
|
67
68
|
getUsageStats: throwNotInEditMode,
|
|
@@ -43,6 +43,7 @@ export function createErrorToastingRequests(
|
|
|
43
43
|
previewSQLTableList: "Failed to fetch SQL table list",
|
|
44
44
|
previewSQLSchemaList: "Failed to fetch SQL schema list",
|
|
45
45
|
previewDataSourceConnection: "Failed to preview data source connection",
|
|
46
|
+
discoverDataSources: "Failed to discover data sources",
|
|
46
47
|
validateSQL: "Failed to validate SQL",
|
|
47
48
|
openFile: "Failed to open file",
|
|
48
49
|
getUsageStats: "", // No toast
|
|
@@ -75,6 +75,7 @@ export type ListSQLTablesRequest = schemas["ListSQLTablesRequest"];
|
|
|
75
75
|
export type ListSQLSchemasRequest = schemas["ListSQLSchemasRequest"];
|
|
76
76
|
export type ListDataSourceConnectionRequest =
|
|
77
77
|
schemas["ListDataSourceConnectionRequest"];
|
|
78
|
+
export type DiscoverDataSourcesRequest = schemas["DiscoverDataSourcesRequest"];
|
|
78
79
|
export type ValidateSQLRequest = schemas["ValidateSQLRequest"];
|
|
79
80
|
export type DebugCellRequest = schemas["DebugCellRequest"];
|
|
80
81
|
export type SetBreakpointsRequest = schemas["SetBreakpointsRequest"];
|
|
@@ -181,6 +182,7 @@ export interface EditRequests {
|
|
|
181
182
|
previewDataSourceConnection: (
|
|
182
183
|
request: ListDataSourceConnectionRequest,
|
|
183
184
|
) => Promise<null>;
|
|
185
|
+
discoverDataSources: (request: DiscoverDataSourcesRequest) => Promise<null>;
|
|
184
186
|
validateSQL: (request: ValidateSQLRequest) => Promise<null>;
|
|
185
187
|
openFile: (request: { path: string; lineNumber?: number }) => Promise<null>;
|
|
186
188
|
getUsageStats: () => Promise<UsageResponse>;
|
package/src/core/wasm/bridge.ts
CHANGED
|
@@ -630,6 +630,16 @@ export class PyodideBridge implements RunRequests, EditRequests {
|
|
|
630
630
|
return null;
|
|
631
631
|
};
|
|
632
632
|
|
|
633
|
+
discoverDataSources: EditRequests["discoverDataSources"] = async (
|
|
634
|
+
request,
|
|
635
|
+
) => {
|
|
636
|
+
await this.putControlRequest({
|
|
637
|
+
type: "discover-data-sources",
|
|
638
|
+
...request,
|
|
639
|
+
});
|
|
640
|
+
return null;
|
|
641
|
+
};
|
|
642
|
+
|
|
633
643
|
getUsageStats = throwNotImplemented;
|
|
634
644
|
getEnvironmentInfo: EditRequests["getEnvironmentInfo"] = async () => {
|
|
635
645
|
const response = await this.rpc.proxy.request.bridge({
|
|
@@ -42,6 +42,7 @@ import { connectionTransportTypeAtom, useSetAppConfig } from "../config/config";
|
|
|
42
42
|
import { useDataSourceActions } from "../datasets/data-source-connections";
|
|
43
43
|
import type { ConnectionName } from "../datasets/engines";
|
|
44
44
|
import {
|
|
45
|
+
DiscoverDataSources,
|
|
45
46
|
PreviewSQLSchemaList,
|
|
46
47
|
PreviewSQLTable,
|
|
47
48
|
PreviewSQLTableList,
|
|
@@ -394,6 +395,9 @@ export function useMarimoKernelConnection(opts: {
|
|
|
394
395
|
case "validate-sql-result":
|
|
395
396
|
ValidateSQL.resolve(msg.data.request_id as RequestId, msg.data);
|
|
396
397
|
return;
|
|
398
|
+
case "data-source-discovery-result":
|
|
399
|
+
DiscoverDataSources.resolve(msg.data.request_id as RequestId, msg.data);
|
|
400
|
+
return;
|
|
397
401
|
case "secret-keys-result":
|
|
398
402
|
SECRETS_REGISTRY.resolve(msg.data.request_id, msg.data);
|
|
399
403
|
return;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { DiscoverDataSources } from "@/core/datasets/request-registry";
|
|
5
|
+
import { loadDataSourceDiscovery } from "../useDataSourceDiscovery";
|
|
6
|
+
|
|
7
|
+
describe("loadDataSourceDiscovery", () => {
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
vi.restoreAllMocks();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("returns the kernel's secret-free discovery model", async () => {
|
|
13
|
+
const sources = [
|
|
14
|
+
{
|
|
15
|
+
id: "pyiceberg-prod",
|
|
16
|
+
integration: "pyiceberg",
|
|
17
|
+
category: "catalog" as const,
|
|
18
|
+
displayName: "PyIceberg (prod)",
|
|
19
|
+
confidence: "high" as const,
|
|
20
|
+
origins: [
|
|
21
|
+
{
|
|
22
|
+
type: "configuration" as const,
|
|
23
|
+
label: "Resolved PyIceberg configuration",
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
configuration: [
|
|
27
|
+
{
|
|
28
|
+
field: "Catalog",
|
|
29
|
+
value: {
|
|
30
|
+
kind: "safe-literal" as const,
|
|
31
|
+
value: "prod",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
code: 'catalog = load_catalog("prod")',
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
const request = vi.spyOn(DiscoverDataSources, "request").mockResolvedValue({
|
|
39
|
+
request_id: "request-id",
|
|
40
|
+
sources,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const detected = await loadDataSourceDiscovery();
|
|
44
|
+
|
|
45
|
+
expect({ detected, requests: request.mock.calls }).toMatchInlineSnapshot(`
|
|
46
|
+
{
|
|
47
|
+
"detected": [
|
|
48
|
+
{
|
|
49
|
+
"category": "catalog",
|
|
50
|
+
"code": "catalog = load_catalog("prod")",
|
|
51
|
+
"confidence": "high",
|
|
52
|
+
"configuration": [
|
|
53
|
+
{
|
|
54
|
+
"field": "Catalog",
|
|
55
|
+
"value": {
|
|
56
|
+
"kind": "safe-literal",
|
|
57
|
+
"value": "prod",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
"displayName": "PyIceberg (prod)",
|
|
62
|
+
"id": "pyiceberg-prod",
|
|
63
|
+
"integration": "pyiceberg",
|
|
64
|
+
"origins": [
|
|
65
|
+
{
|
|
66
|
+
"label": "Resolved PyIceberg configuration",
|
|
67
|
+
"type": "configuration",
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
"requests": [
|
|
73
|
+
[
|
|
74
|
+
{},
|
|
75
|
+
],
|
|
76
|
+
],
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type { DetectedDataSource } from "@/core/datasets/data-source-discovery";
|
|
4
|
+
import { DiscoverDataSources } from "@/core/datasets/request-registry";
|
|
5
|
+
import { useAsyncData } from "./useAsyncData";
|
|
6
|
+
|
|
7
|
+
export async function loadDataSourceDiscovery(): Promise<DetectedDataSource[]> {
|
|
8
|
+
const result = await DiscoverDataSources.request({});
|
|
9
|
+
return result.sources;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Reusable UI-facing hook for kernel-managed datasource discovery.
|
|
14
|
+
* Consumers decide how to render, filter, or act on the detected model.
|
|
15
|
+
*/
|
|
16
|
+
export function useDataSourceDiscovery() {
|
|
17
|
+
return useAsyncData(loadDataSourceDiscovery, []);
|
|
18
|
+
}
|