@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.
Files changed (30) hide show
  1. package/dist/{chat-ui-1e7PcW56.js → chat-ui-9neL0bYw.js} +2 -2
  2. package/dist/{common-CD6phlRu.js → common-BxtRKijk.js} +2 -2
  3. package/dist/{html-to-image-3w0AakWW.js → html-to-image-DzQw9y4M.js} +2113 -2103
  4. package/dist/main.js +7 -5
  5. package/dist/{process-output-BRwR4QGs.js → process-output-tYmEI9FZ.js} +1 -1
  6. package/dist/{reveal-component-DmGGKS8z.js → reveal-component-DuXe-jZN.js} +2 -2
  7. package/dist/style.css +1 -1
  8. package/package.json +1 -1
  9. package/src/__mocks__/requests.ts +1 -0
  10. package/src/components/editor/connections/__tests__/quick-add-data-sources.test.tsx +113 -0
  11. package/src/components/editor/connections/add-connection-dialog.tsx +2 -0
  12. package/src/components/editor/connections/quick-add-data-sources.tsx +106 -0
  13. package/src/core/codemirror/language/__tests__/sql.test.ts +191 -7
  14. package/src/core/codemirror/language/languages/sql/sql.ts +41 -13
  15. package/src/core/datasets/data-source-discovery.ts +5 -0
  16. package/src/core/datasets/request-registry.ts +11 -0
  17. package/src/core/islands/bootstrap.ts +1 -0
  18. package/src/core/islands/bridge.ts +1 -0
  19. package/src/core/kernel/messages.ts +2 -0
  20. package/src/core/network/__tests__/requests-lazy.test.ts +15 -0
  21. package/src/core/network/__tests__/requests-network.test.ts +14 -0
  22. package/src/core/network/requests-lazy.ts +1 -0
  23. package/src/core/network/requests-network.ts +8 -0
  24. package/src/core/network/requests-static.ts +1 -0
  25. package/src/core/network/requests-toasting.tsx +1 -0
  26. package/src/core/network/types.ts +2 -0
  27. package/src/core/wasm/bridge.ts +10 -0
  28. package/src/core/websocket/useMarimoKernelConnection.tsx +4 -0
  29. package/src/hooks/__tests__/useDataSourceDiscovery.test.ts +80 -0
  30. 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>;
@@ -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
+ }