@sqlrooms/canvas 0.27.0 → 0.28.0

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/README.md CHANGED
@@ -1,6 +1,102 @@
1
- ReactFlow-based canvas for building and editing DAGs of SQL and Vega nodes, with a Zustand slice for persistence in SQLRooms apps.
1
+ React Flow-based canvas for building SQL + Vega node DAGs in SQLRooms apps.
2
2
 
3
- - CanvasSlice stores nodes and edges under `canvas.config`
4
- - Canvas component renders and edits the graph
3
+ This package includes:
5
4
 
6
- Refer to the [Canvas example](https://github.com/sqlrooms/examples/tree/main/canvas).
5
+ - `createCanvasSlice()` for canvas state/actions
6
+ - `Canvas` component for graph editing/execution
7
+ - `CanvasSliceConfig` Zod schema for persistence
8
+
9
+ The slice stores nodes/edges in `canvas.config` and supports topological downstream execution for SQL nodes.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @sqlrooms/canvas @sqlrooms/room-shell @sqlrooms/duckdb @sqlrooms/ui
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```tsx
20
+ import {Canvas, CanvasSliceState, createCanvasSlice} from '@sqlrooms/canvas';
21
+ import {
22
+ createRoomShellSlice,
23
+ createRoomStore,
24
+ LayoutTypes,
25
+ RoomShellSliceState,
26
+ } from '@sqlrooms/room-shell';
27
+
28
+ type RoomState = RoomShellSliceState & CanvasSliceState;
29
+
30
+ export const {roomStore, useRoomStore} = createRoomStore<RoomState>(
31
+ (set, get, store) => ({
32
+ ...createRoomShellSlice({
33
+ config: {
34
+ dataSources: [
35
+ {
36
+ type: 'url',
37
+ tableName: 'earthquakes',
38
+ url: 'https://huggingface.co/datasets/sqlrooms/earthquakes/resolve/main/earthquakes.parquet',
39
+ },
40
+ ],
41
+ },
42
+ layout: {
43
+ config: {
44
+ type: LayoutTypes.enum.mosaic,
45
+ nodes: 'main',
46
+ },
47
+ panels: {
48
+ main: {
49
+ title: 'Canvas',
50
+ icon: () => null,
51
+ component: Canvas,
52
+ placement: 'main',
53
+ },
54
+ },
55
+ },
56
+ })(set, get, store),
57
+ ...createCanvasSlice({
58
+ ai: {
59
+ getApiKey: () => '',
60
+ // Keep this aligned with your app's recommended low-latency model.
61
+ defaultModel: 'gpt-5.2-mini',
62
+ },
63
+ })(set, get, store),
64
+ }),
65
+ );
66
+ ```
67
+
68
+ ## Programmatic canvas actions
69
+
70
+ ```tsx
71
+ import {Button} from '@sqlrooms/ui';
72
+
73
+ function CanvasActions() {
74
+ const addNode = useRoomStore((state) => state.canvas.addNode);
75
+ const executeSqlNodeQuery = useRoomStore(
76
+ (state) => state.canvas.executeSqlNodeQuery,
77
+ );
78
+
79
+ const addAndRun = async () => {
80
+ const nodeId = addNode({nodeType: 'sql'});
81
+ await executeSqlNodeQuery(nodeId);
82
+ };
83
+
84
+ return <Button onClick={() => void addAndRun()}>Add SQL node</Button>;
85
+ }
86
+ ```
87
+
88
+ ## Persistence
89
+
90
+ Use `CanvasSliceConfig` with `persistSliceConfigs`:
91
+
92
+ ```ts
93
+ import {CanvasSliceConfig} from '@sqlrooms/canvas';
94
+
95
+ sliceConfigSchemas: {
96
+ canvas: CanvasSliceConfig,
97
+ }
98
+ ```
99
+
100
+ ## Example
101
+
102
+ - Canvas example app: https://github.com/sqlrooms/examples/tree/main/canvas
@@ -6,9 +6,9 @@ import { useStoreWithCanvas } from './CanvasSlice';
6
6
  export const CanvasAssistantDrawer = () => {
7
7
  const isAssistantOpen = useStoreWithCanvas((state) => state.canvas.isAssistantOpen);
8
8
  const setAssistantOpen = useStoreWithCanvas((state) => state.canvas.setAssistantOpen);
9
- return (_jsxs(Drawer, { direction: "right", open: isAssistantOpen, onOpenChange: setAssistantOpen, children: [_jsx(DrawerTrigger, { asChild: true, children: _jsx(Button, { variant: "default", className: "absolute top-4 right-4 z-10 h-8 w-8 rounded-full", children: _jsx(SparklesIcon, { className: "h-4 w-4" }) }) }), _jsx(DrawerContent, { className: "border-none bg-transparent p-4 outline-none", style: {
9
+ return (_jsxs(Drawer, { direction: "right", open: isAssistantOpen, onOpenChange: setAssistantOpen, children: [_jsx(DrawerTrigger, { asChild: true, children: _jsx(Button, { variant: "default", className: "absolute top-4 right-4 z-10 h-8 w-8 rounded-full", children: _jsx(SparklesIcon, { className: "h-4 w-4" }) }) }), _jsx(DrawerContent, { className: "border-none bg-transparent p-4 outline-hidden", style: {
10
10
  width: 500,
11
11
  maxWidth: '50%',
12
- }, "data-vaul-drawer-direction": "right", overlayClassName: "bg-transparent", children: _jsx("div", { className: "border-border bg-background relative mx-auto flex h-full w-full flex-col gap-0 overflow-hidden rounded-md border", children: _jsxs(Chat, { children: [_jsxs(DrawerHeader, { children: [_jsx(DrawerTitle, { children: "Assistant" }), _jsx(DrawerClose, { asChild: true, className: "absolute top-2 right-2", children: _jsx(Button, { variant: "ghost", size: "xs", children: _jsx(XIcon, { className: "h-4 w-4" }) }) })] }), _jsx(Chat.Messages, { className: "flex-grow overflow-auto px-4" }), _jsx(DrawerFooter, { children: _jsx(Chat.Composer, { placeholder: "What would you like to do?" }) })] }) }) })] }));
12
+ }, "data-vaul-drawer-direction": "right", overlayClassName: "bg-transparent", children: _jsx("div", { className: "border-border bg-background relative mx-auto flex h-full w-full flex-col gap-0 overflow-hidden rounded-md border", children: _jsxs(Chat, { children: [_jsxs(DrawerHeader, { children: [_jsx(DrawerTitle, { children: "Assistant" }), _jsx(DrawerClose, { asChild: true, className: "absolute top-2 right-2", children: _jsx(Button, { variant: "ghost", size: "xs", children: _jsx(XIcon, { className: "h-4 w-4" }) }) })] }), _jsx(Chat.Messages, { className: "grow overflow-auto px-4" }), _jsx(DrawerFooter, { children: _jsx(Chat.Composer, { placeholder: "What would you like to do?" }) })] }) }) })] }));
13
13
  };
14
14
  //# sourceMappingURL=CanvasAssistantDrawer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasAssistantDrawer.js","sourceRoot":"","sources":["../src/CanvasAssistantDrawer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAC;AAClC,OAAO,EACL,MAAM,EACN,MAAM,EACN,WAAW,EACX,aAAa,EACb,YAAY,EAEZ,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,YAAY,EAAE,KAAK,EAAC,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,MAAM,CAAC,MAAM,qBAAqB,GAAO,GAAG,EAAE;IAC5C,MAAM,eAAe,GAAG,kBAAkB,CACxC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CACxC,CAAC;IACF,MAAM,gBAAgB,GAAG,kBAAkB,CACzC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CACzC,CAAC;IACF,OAAO,CACL,MAAC,MAAM,IACL,SAAS,EAAC,OAAO,EACjB,IAAI,EAAE,eAAe,EACrB,YAAY,EAAE,gBAAgB,aAE9B,KAAC,aAAa,IAAC,OAAO,kBACpB,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,SAAS,EAAC,kDAAkD,YAE5D,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,GAAG,GAC7B,GACK,EAChB,KAAC,aAAa,IACZ,SAAS,EAAC,6CAA6C,EACvD,KAAK,EAAE;oBACL,KAAK,EAAE,GAAG;oBACV,QAAQ,EAAE,KAAK;iBAChB,gCAC0B,OAAO,EAClC,gBAAgB,EAAC,gBAAgB,YAEjC,cAAK,SAAS,EAAC,kHAAkH,YAC/H,MAAC,IAAI,eACH,MAAC,YAAY,eACX,KAAC,WAAW,4BAAwB,EACpC,KAAC,WAAW,IAAC,OAAO,QAAC,SAAS,EAAC,wBAAwB,YACrD,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,YAC/B,KAAC,KAAK,IAAC,SAAS,EAAC,SAAS,GAAG,GACtB,GACG,IACD,EACf,KAAC,IAAI,CAAC,QAAQ,IAAC,SAAS,EAAC,8BAA8B,GAAG,EAC1D,KAAC,YAAY,cACX,KAAC,IAAI,CAAC,QAAQ,IAAC,WAAW,EAAC,4BAA4B,GAAG,GAC7C,IACV,GACH,GACQ,IACT,CACV,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Chat} from '@sqlrooms/ai';\nimport {\n Button,\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerFooter,\n DrawerHandle,\n DrawerHeader,\n DrawerTitle,\n DrawerTrigger,\n} from '@sqlrooms/ui';\nimport {SparklesIcon, XIcon} from 'lucide-react';\nimport {FC} from 'react';\nimport {useStoreWithCanvas} from './CanvasSlice';\n\nexport const CanvasAssistantDrawer: FC = () => {\n const isAssistantOpen = useStoreWithCanvas(\n (state) => state.canvas.isAssistantOpen,\n );\n const setAssistantOpen = useStoreWithCanvas(\n (state) => state.canvas.setAssistantOpen,\n );\n return (\n <Drawer\n direction=\"right\"\n open={isAssistantOpen}\n onOpenChange={setAssistantOpen}\n >\n <DrawerTrigger asChild>\n <Button\n variant=\"default\"\n className=\"absolute top-4 right-4 z-10 h-8 w-8 rounded-full\"\n >\n <SparklesIcon className=\"h-4 w-4\" />\n </Button>\n </DrawerTrigger>\n <DrawerContent\n className=\"border-none bg-transparent p-4 outline-none\"\n style={{\n width: 500,\n maxWidth: '50%',\n }}\n data-vaul-drawer-direction=\"right\"\n overlayClassName=\"bg-transparent\"\n >\n <div className=\"border-border bg-background relative mx-auto flex h-full w-full flex-col gap-0 overflow-hidden rounded-md border\">\n <Chat>\n <DrawerHeader>\n <DrawerTitle>Assistant</DrawerTitle>\n <DrawerClose asChild className=\"absolute top-2 right-2\">\n <Button variant=\"ghost\" size=\"xs\">\n <XIcon className=\"h-4 w-4\" />\n </Button>\n </DrawerClose>\n </DrawerHeader>\n <Chat.Messages className=\"flex-grow overflow-auto px-4\" />\n <DrawerFooter>\n <Chat.Composer placeholder=\"What would you like to do?\" />\n </DrawerFooter>\n </Chat>\n </div>\n </DrawerContent>\n </Drawer>\n );\n};\n"]}
1
+ {"version":3,"file":"CanvasAssistantDrawer.js","sourceRoot":"","sources":["../src/CanvasAssistantDrawer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,cAAc,CAAC;AAClC,OAAO,EACL,MAAM,EACN,MAAM,EACN,WAAW,EACX,aAAa,EACb,YAAY,EAEZ,YAAY,EACZ,WAAW,EACX,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,YAAY,EAAE,KAAK,EAAC,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,MAAM,CAAC,MAAM,qBAAqB,GAAO,GAAG,EAAE;IAC5C,MAAM,eAAe,GAAG,kBAAkB,CACxC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,eAAe,CACxC,CAAC;IACF,MAAM,gBAAgB,GAAG,kBAAkB,CACzC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,CACzC,CAAC;IACF,OAAO,CACL,MAAC,MAAM,IACL,SAAS,EAAC,OAAO,EACjB,IAAI,EAAE,eAAe,EACrB,YAAY,EAAE,gBAAgB,aAE9B,KAAC,aAAa,IAAC,OAAO,kBACpB,KAAC,MAAM,IACL,OAAO,EAAC,SAAS,EACjB,SAAS,EAAC,kDAAkD,YAE5D,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,GAAG,GAC7B,GACK,EAChB,KAAC,aAAa,IACZ,SAAS,EAAC,+CAA+C,EACzD,KAAK,EAAE;oBACL,KAAK,EAAE,GAAG;oBACV,QAAQ,EAAE,KAAK;iBAChB,gCAC0B,OAAO,EAClC,gBAAgB,EAAC,gBAAgB,YAEjC,cAAK,SAAS,EAAC,kHAAkH,YAC/H,MAAC,IAAI,eACH,MAAC,YAAY,eACX,KAAC,WAAW,4BAAwB,EACpC,KAAC,WAAW,IAAC,OAAO,QAAC,SAAS,EAAC,wBAAwB,YACrD,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,YAC/B,KAAC,KAAK,IAAC,SAAS,EAAC,SAAS,GAAG,GACtB,GACG,IACD,EACf,KAAC,IAAI,CAAC,QAAQ,IAAC,SAAS,EAAC,yBAAyB,GAAG,EACrD,KAAC,YAAY,cACX,KAAC,IAAI,CAAC,QAAQ,IAAC,WAAW,EAAC,4BAA4B,GAAG,GAC7C,IACV,GACH,GACQ,IACT,CACV,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Chat} from '@sqlrooms/ai';\nimport {\n Button,\n Drawer,\n DrawerClose,\n DrawerContent,\n DrawerFooter,\n DrawerHandle,\n DrawerHeader,\n DrawerTitle,\n DrawerTrigger,\n} from '@sqlrooms/ui';\nimport {SparklesIcon, XIcon} from 'lucide-react';\nimport {FC} from 'react';\nimport {useStoreWithCanvas} from './CanvasSlice';\n\nexport const CanvasAssistantDrawer: FC = () => {\n const isAssistantOpen = useStoreWithCanvas(\n (state) => state.canvas.isAssistantOpen,\n );\n const setAssistantOpen = useStoreWithCanvas(\n (state) => state.canvas.setAssistantOpen,\n );\n return (\n <Drawer\n direction=\"right\"\n open={isAssistantOpen}\n onOpenChange={setAssistantOpen}\n >\n <DrawerTrigger asChild>\n <Button\n variant=\"default\"\n className=\"absolute top-4 right-4 z-10 h-8 w-8 rounded-full\"\n >\n <SparklesIcon className=\"h-4 w-4\" />\n </Button>\n </DrawerTrigger>\n <DrawerContent\n className=\"border-none bg-transparent p-4 outline-hidden\"\n style={{\n width: 500,\n maxWidth: '50%',\n }}\n data-vaul-drawer-direction=\"right\"\n overlayClassName=\"bg-transparent\"\n >\n <div className=\"border-border bg-background relative mx-auto flex h-full w-full flex-col gap-0 overflow-hidden rounded-md border\">\n <Chat>\n <DrawerHeader>\n <DrawerTitle>Assistant</DrawerTitle>\n <DrawerClose asChild className=\"absolute top-2 right-2\">\n <Button variant=\"ghost\" size=\"xs\">\n <XIcon className=\"h-4 w-4\" />\n </Button>\n </DrawerClose>\n </DrawerHeader>\n <Chat.Messages className=\"grow overflow-auto px-4\" />\n <DrawerFooter>\n <Chat.Composer placeholder=\"What would you like to do?\" />\n </DrawerFooter>\n </Chat>\n </div>\n </DrawerContent>\n </Drawer>\n );\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasSlice.d.ts","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CanvasSlice.d.ts","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"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"}
@@ -269,7 +269,6 @@ export function createCanvasSlice(props) {
269
269
  await get().db.refreshTableSchemas();
270
270
  }
271
271
  catch (e) {
272
- // eslint-disable-next-line no-console
273
272
  console.warn('[canvas.deleteNode] Failed to drop table for node', nodeId, e);
274
273
  }
275
274
  })();
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasSlice.js","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n AiSliceState,\n createAiSlice,\n createDefaultAiInstructions,\n createDefaultAiTools,\n} from '@sqlrooms/ai';\nimport {DuckDbSliceState, escapeId} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-shell';\nimport {createVegaChartTool} from '@sqlrooms/vega';\nimport type {Viewport, XYPosition} from '@xyflow/react';\nimport {\n addEdge,\n applyEdgeChanges,\n applyNodeChanges,\n Connection,\n type EdgeChange,\n type NodeChange,\n} from '@xyflow/react';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {findNodeById, topoSortAll, topoSortDownstream} from './dag';\n\nconst DEFAULT_NODE_WIDTH = 800;\nconst DEFAULT_NODE_HEIGHT = 600;\nconst CANVAS_SCHEMA_NAME = 'canvas';\n\nexport const CanvasNodeTypes = z.enum(['sql', 'vega']);\nexport type CanvasNodeTypes = z.infer<typeof CanvasNodeTypes>;\n\nexport const CanvasNodeData = z.discriminatedUnion('type', [\n z.object({\n title: z.string().default('Untitled'),\n type: z.literal('sql'),\n sql: z.string().optional(),\n }),\n z.object({\n title: z.string().default('Untitled'),\n type: z.literal('vega'),\n sql: z.string().optional(),\n vegaSpec: z.any().optional(),\n }),\n]);\nexport type CanvasNodeData = z.infer<typeof CanvasNodeData>;\n\ntype SqlData = Extract<CanvasNodeData, {type: 'sql'}>;\nfunction isSqlData(data: CanvasNodeData): data is SqlData {\n return data.type === 'sql';\n}\n\nfunction getUniqueSqlTitle(\n nodes: CanvasNodeSchema[],\n baseTitle: string,\n excludeNodeId?: string,\n): string {\n const existing = new Set(\n nodes\n .filter((n) => n.type === 'sql' && n.id !== (excludeNodeId || ''))\n .map((n) => n.data.title || ''),\n );\n if (!existing.has(baseTitle)) return baseTitle;\n let counter = 1;\n while (existing.has(`${baseTitle} ${counter}`)) counter += 1;\n return `${baseTitle} ${counter}`;\n}\n\nexport const CanvasNodeSchema = z.object({\n id: z.string(),\n position: z.object({x: z.number(), y: z.number()}),\n type: CanvasNodeTypes,\n data: CanvasNodeData,\n width: z.number(),\n height: z.number(),\n});\nexport type CanvasNodeSchema = z.infer<typeof CanvasNodeSchema>;\n\nexport const CanvasEdgeSchema = z.object({\n id: z.string(),\n source: z.string(),\n target: z.string(),\n});\nexport type CanvasEdgeSchema = z.infer<typeof CanvasEdgeSchema>;\n\nexport type SqlNodeQueryResult =\n | {status: 'idle'}\n | {status: 'loading'}\n | {status: 'error'; error: string}\n | {status: 'success'; tableName: string; lastQueryStatement: string};\n\nexport const CanvasSliceConfig = z.object({\n viewport: z.object({\n x: z.number(),\n y: z.number(),\n zoom: z.number(),\n }),\n nodes: z.array(CanvasNodeSchema).default([]),\n edges: z.array(CanvasEdgeSchema).default([]),\n});\nexport type CanvasSliceConfig = z.infer<typeof CanvasSliceConfig>;\n\nexport type CanvasSliceState = AiSliceState & {\n canvas: {\n config: CanvasSliceConfig;\n isAssistantOpen: boolean;\n sqlResults: Record<string, SqlNodeQueryResult>;\n initialize: () => Promise<void>;\n setConfig: (config: CanvasSliceConfig) => void;\n setViewport: (viewport: Viewport) => void;\n setAssistantOpen: (isAssistantOpen: boolean) => void;\n addNode: (params: {\n parentId?: string;\n nodeType?: CanvasNodeTypes;\n initialPosition?: XYPosition;\n }) => string;\n executeDownstreamFrom: (nodeId: string) => Promise<void>;\n renameNode: (nodeId: string, newTitle: string) => Promise<void>;\n updateNode: (\n nodeId: string,\n updater: (data: CanvasNodeData) => CanvasNodeData,\n ) => void;\n deleteNode: (nodeId: string) => void;\n applyNodeChanges: (changes: NodeChange<CanvasNodeSchema>[]) => void;\n applyEdgeChanges: (changes: EdgeChange<CanvasEdgeSchema>[]) => void;\n addEdge: (edge: Connection) => void;\n executeSqlNodeQuery: (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => Promise<void>;\n };\n};\n\nexport function createDefaultCanvasConfig(\n props?: Partial<CanvasSliceConfig>,\n): CanvasSliceConfig {\n return {\n viewport: {x: 0, y: 0, zoom: 1},\n nodes: [],\n edges: [],\n ...props,\n };\n}\n\nexport function createCanvasSlice(props: {\n config?: Partial<CanvasSliceConfig>;\n ai?: Partial<Parameters<typeof createAiSlice>[0]>;\n}) {\n return createSlice<\n CanvasSliceState,\n BaseRoomStoreState & DuckDbSliceState & CanvasSliceState\n >((set, get, store) => ({\n ...createAiSlice({\n getInstructions: () => {\n return createDefaultAiInstructions(store);\n },\n tools: {\n ...createDefaultAiTools(store),\n chart: createVegaChartTool(),\n ...props.ai?.tools,\n },\n ...props.ai,\n })(set, get, store),\n canvas: {\n config: createDefaultCanvasConfig(props.config),\n isAssistantOpen: false,\n sqlResults: {},\n setConfig: (config) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config = config;\n }),\n );\n },\n setAssistantOpen: (isAssistantOpen) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.isAssistantOpen = isAssistantOpen;\n }),\n );\n },\n\n async initialize() {\n // Execute SQL nodes in topological order based on edges\n const nodes = get().canvas.config.nodes;\n const edges = get().canvas.config.edges;\n\n const order = topoSortAll(nodes, edges);\n\n // Execute SQL nodes sequentially to ensure parents finish before children\n for (const nodeId of order) {\n const node = findNodeById(get().canvas.config.nodes, nodeId);\n if (!node || !isSqlData(node.data)) continue;\n const sqlText = node.data.sql || '';\n if (!sqlText.trim()) continue;\n // Await ensures table creation completes before children execute\n await get().canvas.executeSqlNodeQuery(nodeId, {cascade: false});\n }\n\n await get().db.refreshTableSchemas();\n },\n\n addNode: ({\n parentId,\n nodeType = 'sql',\n initialPosition,\n }: {\n parentId?: string;\n nodeType?: CanvasNodeTypes;\n initialPosition?: XYPosition;\n }) => {\n const newId = createId();\n set((state) =>\n produce(state, (draft) => {\n const parent = parentId\n ? findNodeById(draft.canvas.config.nodes, parentId)\n : undefined;\n const position: XYPosition = initialPosition\n ? initialPosition\n : parent\n ? {\n x: parent.position.x + parent.width + 100,\n y: parent.position.y,\n }\n : {\n x: draft.canvas.config.viewport.x + 100,\n y: draft.canvas.config.viewport.y + 100,\n };\n const firstTable = draft.db.tables.find(\n (t) => t.table.schema === 'main',\n );\n\n const getInitialSqlForNewSqlNode = () => {\n if (parent && isSqlData(parent.data)) {\n const parentResults = draft.canvas.sqlResults[parent.id];\n const parentTitle = parent.data.title || 'Query';\n const fallbackParentTable = `${CANVAS_SCHEMA_NAME}.${escapeId(parentTitle)}`;\n const parentTableName =\n parentResults && parentResults.status === 'success'\n ? parentResults.tableName\n : fallbackParentTable;\n return `SELECT * FROM ${parentTableName}`;\n }\n return firstTable\n ? `SELECT * FROM ${firstTable.table.table}`\n : `SELECT 1`;\n };\n\n const newSqlTitle = getUniqueSqlTitle(\n draft.canvas.config.nodes,\n 'Query',\n );\n const initialSql = getInitialSqlForNewSqlNode();\n\n draft.canvas.config.nodes.push({\n id: newId,\n position,\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n type: nodeType,\n data: (nodeType === 'sql'\n ? {\n title: newSqlTitle,\n type: 'sql',\n sql: initialSql,\n }\n : {\n title: 'Chart',\n type: 'vega',\n }) as CanvasNodeData,\n });\n if (parentId) {\n draft.canvas.config.edges.push({\n id: `${parentId}-${newId}`,\n source: parentId,\n target: newId,\n });\n }\n }),\n );\n return newId;\n },\n\n executeDownstreamFrom: async (nodeId: string) => {\n const allNodes = get().canvas.config.nodes;\n const allEdges = get().canvas.config.edges;\n const downstreamOrder = topoSortDownstream(nodeId, allNodes, allEdges);\n for (const childId of downstreamOrder) {\n const child = findNodeById(allNodes, childId);\n if (!child || !isSqlData(child.data)) continue;\n const text = child.data.sql || '';\n if (!text.trim()) continue;\n await get().canvas.executeSqlNodeQuery(childId, {cascade: false});\n }\n await get().db.refreshTableSchemas();\n },\n\n addEdge: (connection) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.edges = addEdge(\n connection,\n draft.canvas.config.edges,\n );\n }),\n );\n },\n\n updateNode: (nodeId, updater) => {\n set((state) =>\n produce(state, (draft) => {\n const node = findNodeById(draft.canvas.config.nodes, nodeId);\n if (node) {\n node.data = updater(node.data as CanvasNodeData);\n }\n }),\n );\n },\n\n renameNode: async (nodeId: string, newTitle: string) => {\n const node = findNodeById(get().canvas.config.nodes, nodeId);\n if (!node) throw new Error('Node not found');\n if (!isSqlData(node.data)) {\n set((state) =>\n produce(state, (draft) => {\n const dnode = findNodeById(draft.canvas.config.nodes, nodeId);\n if (dnode) dnode.data.title = newTitle;\n }),\n );\n return;\n }\n\n const prevTitle = node.data.title || 'result';\n if (prevTitle === newTitle) return;\n\n // Ensure title uniqueness among SQL nodes by adjusting to a unique variant\n const uniqueTitle = getUniqueSqlTitle(\n get().canvas.config.nodes,\n newTitle,\n nodeId,\n );\n\n const connector = await get().db.getConnector();\n await connector.query(\n `CREATE SCHEMA IF NOT EXISTS ${CANVAS_SCHEMA_NAME}`,\n );\n\n const result = get().canvas.sqlResults[nodeId];\n const oldTableName =\n result && result.status === 'success'\n ? result.tableName\n : `${CANVAS_SCHEMA_NAME}.${escapeId(prevTitle)}`;\n\n await connector.query(\n `ALTER TABLE ${oldTableName} RENAME TO ${escapeId(uniqueTitle)}`,\n );\n\n const newQualified = `${CANVAS_SCHEMA_NAME}.${escapeId(uniqueTitle)}`;\n set((state) =>\n produce(state, (draft) => {\n const dnode = findNodeById(draft.canvas.config.nodes, nodeId);\n if (dnode) dnode.data.title = uniqueTitle;\n const r = draft.canvas.sqlResults[nodeId];\n if (r && r.status === 'success') r.tableName = newQualified;\n }),\n );\n\n await get().db.refreshTableSchemas();\n\n // Recompute children since upstream table name changed\n await get().canvas.executeDownstreamFrom(nodeId);\n },\n\n deleteNode: (nodeId) => {\n const current = get();\n const node = findNodeById(current.canvas.config.nodes, nodeId);\n let tableToDrop: string | undefined;\n if (node && isSqlData(node.data)) {\n const title = node.data.title || 'result';\n const res = current.canvas.sqlResults[nodeId];\n tableToDrop =\n res && res.status === 'success'\n ? res.tableName\n : `${CANVAS_SCHEMA_NAME}.${escapeId(title)}`;\n }\n\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.nodes = draft.canvas.config.nodes.filter(\n (n) => n.id !== nodeId,\n );\n draft.canvas.config.edges = draft.canvas.config.edges.filter(\n (e) => e.source !== nodeId && e.target !== nodeId,\n );\n // Clear stored result for the node\n delete draft.canvas.sqlResults[nodeId];\n if (draft.canvas.config.nodes.length === 0) {\n draft.canvas.config.viewport.x = 0;\n draft.canvas.config.viewport.y = 0;\n }\n }),\n );\n\n if (tableToDrop) {\n (async () => {\n try {\n const connector = await get().db.getConnector();\n await connector.query(`DROP TABLE IF EXISTS ${tableToDrop}`);\n await get().db.refreshTableSchemas();\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn(\n '[canvas.deleteNode] Failed to drop table for node',\n nodeId,\n e,\n );\n }\n })();\n }\n },\n\n applyNodeChanges: (changes) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.nodes = applyNodeChanges(\n changes,\n draft.canvas.config.nodes,\n );\n }),\n );\n },\n\n applyEdgeChanges: (changes) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.edges = applyEdgeChanges(\n changes,\n draft.canvas.config.edges,\n );\n }),\n );\n },\n\n setViewport: (viewport) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.viewport = viewport;\n }),\n );\n },\n\n executeSqlNodeQuery: async (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => {\n const node = findNodeById(get().canvas.config.nodes, nodeId);\n if (!node || !isSqlData(node.data)) return;\n const sql = node.data.sql || '';\n const title = node.data.title || 'result';\n\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.sqlResults[nodeId] = {status: 'loading'};\n }),\n );\n\n try {\n // Validate it's a single select\n const parsed = await get().db.sqlSelectToJson(sql);\n if (parsed.error) {\n throw new Error(\n parsed.error_message || 'Not a valid SELECT statement',\n );\n }\n\n // Create schema and table\n const connector = await get().db.getConnector();\n await connector.query(\n `CREATE SCHEMA IF NOT EXISTS ${CANVAS_SCHEMA_NAME}`,\n );\n\n const tableName = `${CANVAS_SCHEMA_NAME}.${escapeId(title)}`;\n await connector.query(\n `CREATE OR REPLACE TABLE ${tableName} AS ${sql}`,\n );\n\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.sqlResults[nodeId] = {\n status: 'success',\n tableName,\n lastQueryStatement: sql,\n };\n }),\n );\n\n // Cascade execution to downstream SQL nodes (topologically) unless disabled\n if (opts?.cascade !== false) {\n await get().canvas.executeDownstreamFrom(nodeId);\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.sqlResults[nodeId] = {\n status: 'error',\n error: message,\n };\n }),\n );\n }\n },\n },\n }));\n}\n\nexport type DuckDbSliceStateWithCanvas = DuckDbSliceState & CanvasSliceState;\n\nexport function useStoreWithCanvas<T>(\n selector: (state: DuckDbSliceStateWithCanvas) => T,\n): T {\n return useBaseRoomStore<BaseRoomStoreState, T>((state) =>\n selector(state as unknown as DuckDbSliceStateWithCanvas),\n );\n}\n"]}
1
+ {"version":3,"file":"CanvasSlice.js","sourceRoot":"","sources":["../src/CanvasSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n AiSliceState,\n createAiSlice,\n createDefaultAiInstructions,\n createDefaultAiTools,\n} from '@sqlrooms/ai';\nimport {DuckDbSliceState, escapeId} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-shell';\nimport {createVegaChartTool} from '@sqlrooms/vega';\nimport type {Viewport, XYPosition} from '@xyflow/react';\nimport {\n addEdge,\n applyEdgeChanges,\n applyNodeChanges,\n Connection,\n type EdgeChange,\n type NodeChange,\n} from '@xyflow/react';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {findNodeById, topoSortAll, topoSortDownstream} from './dag';\n\nconst DEFAULT_NODE_WIDTH = 800;\nconst DEFAULT_NODE_HEIGHT = 600;\nconst CANVAS_SCHEMA_NAME = 'canvas';\n\nexport const CanvasNodeTypes = z.enum(['sql', 'vega']);\nexport type CanvasNodeTypes = z.infer<typeof CanvasNodeTypes>;\n\nexport const CanvasNodeData = z.discriminatedUnion('type', [\n z.object({\n title: z.string().default('Untitled'),\n type: z.literal('sql'),\n sql: z.string().optional(),\n }),\n z.object({\n title: z.string().default('Untitled'),\n type: z.literal('vega'),\n sql: z.string().optional(),\n vegaSpec: z.any().optional(),\n }),\n]);\nexport type CanvasNodeData = z.infer<typeof CanvasNodeData>;\n\ntype SqlData = Extract<CanvasNodeData, {type: 'sql'}>;\nfunction isSqlData(data: CanvasNodeData): data is SqlData {\n return data.type === 'sql';\n}\n\nfunction getUniqueSqlTitle(\n nodes: CanvasNodeSchema[],\n baseTitle: string,\n excludeNodeId?: string,\n): string {\n const existing = new Set(\n nodes\n .filter((n) => n.type === 'sql' && n.id !== (excludeNodeId || ''))\n .map((n) => n.data.title || ''),\n );\n if (!existing.has(baseTitle)) return baseTitle;\n let counter = 1;\n while (existing.has(`${baseTitle} ${counter}`)) counter += 1;\n return `${baseTitle} ${counter}`;\n}\n\nexport const CanvasNodeSchema = z.object({\n id: z.string(),\n position: z.object({x: z.number(), y: z.number()}),\n type: CanvasNodeTypes,\n data: CanvasNodeData,\n width: z.number(),\n height: z.number(),\n});\nexport type CanvasNodeSchema = z.infer<typeof CanvasNodeSchema>;\n\nexport const CanvasEdgeSchema = z.object({\n id: z.string(),\n source: z.string(),\n target: z.string(),\n});\nexport type CanvasEdgeSchema = z.infer<typeof CanvasEdgeSchema>;\n\nexport type SqlNodeQueryResult =\n | {status: 'idle'}\n | {status: 'loading'}\n | {status: 'error'; error: string}\n | {status: 'success'; tableName: string; lastQueryStatement: string};\n\nexport const CanvasSliceConfig = z.object({\n viewport: z.object({\n x: z.number(),\n y: z.number(),\n zoom: z.number(),\n }),\n nodes: z.array(CanvasNodeSchema).default([]),\n edges: z.array(CanvasEdgeSchema).default([]),\n});\nexport type CanvasSliceConfig = z.infer<typeof CanvasSliceConfig>;\n\nexport type CanvasSliceState = AiSliceState & {\n canvas: {\n config: CanvasSliceConfig;\n isAssistantOpen: boolean;\n sqlResults: Record<string, SqlNodeQueryResult>;\n initialize: () => Promise<void>;\n setConfig: (config: CanvasSliceConfig) => void;\n setViewport: (viewport: Viewport) => void;\n setAssistantOpen: (isAssistantOpen: boolean) => void;\n addNode: (params: {\n parentId?: string;\n nodeType?: CanvasNodeTypes;\n initialPosition?: XYPosition;\n }) => string;\n executeDownstreamFrom: (nodeId: string) => Promise<void>;\n renameNode: (nodeId: string, newTitle: string) => Promise<void>;\n updateNode: (\n nodeId: string,\n updater: (data: CanvasNodeData) => CanvasNodeData,\n ) => void;\n deleteNode: (nodeId: string) => void;\n applyNodeChanges: (changes: NodeChange<CanvasNodeSchema>[]) => void;\n applyEdgeChanges: (changes: EdgeChange<CanvasEdgeSchema>[]) => void;\n addEdge: (edge: Connection) => void;\n executeSqlNodeQuery: (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => Promise<void>;\n };\n};\n\nexport function createDefaultCanvasConfig(\n props?: Partial<CanvasSliceConfig>,\n): CanvasSliceConfig {\n return {\n viewport: {x: 0, y: 0, zoom: 1},\n nodes: [],\n edges: [],\n ...props,\n };\n}\n\nexport function createCanvasSlice(props: {\n config?: Partial<CanvasSliceConfig>;\n ai?: Partial<Parameters<typeof createAiSlice>[0]>;\n}) {\n return createSlice<\n CanvasSliceState,\n BaseRoomStoreState & DuckDbSliceState & CanvasSliceState\n >((set, get, store) => ({\n ...createAiSlice({\n getInstructions: () => {\n return createDefaultAiInstructions(store);\n },\n tools: {\n ...createDefaultAiTools(store),\n chart: createVegaChartTool(),\n ...props.ai?.tools,\n },\n ...props.ai,\n })(set, get, store),\n canvas: {\n config: createDefaultCanvasConfig(props.config),\n isAssistantOpen: false,\n sqlResults: {},\n setConfig: (config) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config = config;\n }),\n );\n },\n setAssistantOpen: (isAssistantOpen) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.isAssistantOpen = isAssistantOpen;\n }),\n );\n },\n\n async initialize() {\n // Execute SQL nodes in topological order based on edges\n const nodes = get().canvas.config.nodes;\n const edges = get().canvas.config.edges;\n\n const order = topoSortAll(nodes, edges);\n\n // Execute SQL nodes sequentially to ensure parents finish before children\n for (const nodeId of order) {\n const node = findNodeById(get().canvas.config.nodes, nodeId);\n if (!node || !isSqlData(node.data)) continue;\n const sqlText = node.data.sql || '';\n if (!sqlText.trim()) continue;\n // Await ensures table creation completes before children execute\n await get().canvas.executeSqlNodeQuery(nodeId, {cascade: false});\n }\n\n await get().db.refreshTableSchemas();\n },\n\n addNode: ({\n parentId,\n nodeType = 'sql',\n initialPosition,\n }: {\n parentId?: string;\n nodeType?: CanvasNodeTypes;\n initialPosition?: XYPosition;\n }) => {\n const newId = createId();\n set((state) =>\n produce(state, (draft) => {\n const parent = parentId\n ? findNodeById(draft.canvas.config.nodes, parentId)\n : undefined;\n const position: XYPosition = initialPosition\n ? initialPosition\n : parent\n ? {\n x: parent.position.x + parent.width + 100,\n y: parent.position.y,\n }\n : {\n x: draft.canvas.config.viewport.x + 100,\n y: draft.canvas.config.viewport.y + 100,\n };\n const firstTable = draft.db.tables.find(\n (t) => t.table.schema === 'main',\n );\n\n const getInitialSqlForNewSqlNode = () => {\n if (parent && isSqlData(parent.data)) {\n const parentResults = draft.canvas.sqlResults[parent.id];\n const parentTitle = parent.data.title || 'Query';\n const fallbackParentTable = `${CANVAS_SCHEMA_NAME}.${escapeId(parentTitle)}`;\n const parentTableName =\n parentResults && parentResults.status === 'success'\n ? parentResults.tableName\n : fallbackParentTable;\n return `SELECT * FROM ${parentTableName}`;\n }\n return firstTable\n ? `SELECT * FROM ${firstTable.table.table}`\n : `SELECT 1`;\n };\n\n const newSqlTitle = getUniqueSqlTitle(\n draft.canvas.config.nodes,\n 'Query',\n );\n const initialSql = getInitialSqlForNewSqlNode();\n\n draft.canvas.config.nodes.push({\n id: newId,\n position,\n width: DEFAULT_NODE_WIDTH,\n height: DEFAULT_NODE_HEIGHT,\n type: nodeType,\n data: (nodeType === 'sql'\n ? {\n title: newSqlTitle,\n type: 'sql',\n sql: initialSql,\n }\n : {\n title: 'Chart',\n type: 'vega',\n }) as CanvasNodeData,\n });\n if (parentId) {\n draft.canvas.config.edges.push({\n id: `${parentId}-${newId}`,\n source: parentId,\n target: newId,\n });\n }\n }),\n );\n return newId;\n },\n\n executeDownstreamFrom: async (nodeId: string) => {\n const allNodes = get().canvas.config.nodes;\n const allEdges = get().canvas.config.edges;\n const downstreamOrder = topoSortDownstream(nodeId, allNodes, allEdges);\n for (const childId of downstreamOrder) {\n const child = findNodeById(allNodes, childId);\n if (!child || !isSqlData(child.data)) continue;\n const text = child.data.sql || '';\n if (!text.trim()) continue;\n await get().canvas.executeSqlNodeQuery(childId, {cascade: false});\n }\n await get().db.refreshTableSchemas();\n },\n\n addEdge: (connection) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.edges = addEdge(\n connection,\n draft.canvas.config.edges,\n );\n }),\n );\n },\n\n updateNode: (nodeId, updater) => {\n set((state) =>\n produce(state, (draft) => {\n const node = findNodeById(draft.canvas.config.nodes, nodeId);\n if (node) {\n node.data = updater(node.data as CanvasNodeData);\n }\n }),\n );\n },\n\n renameNode: async (nodeId: string, newTitle: string) => {\n const node = findNodeById(get().canvas.config.nodes, nodeId);\n if (!node) throw new Error('Node not found');\n if (!isSqlData(node.data)) {\n set((state) =>\n produce(state, (draft) => {\n const dnode = findNodeById(draft.canvas.config.nodes, nodeId);\n if (dnode) dnode.data.title = newTitle;\n }),\n );\n return;\n }\n\n const prevTitle = node.data.title || 'result';\n if (prevTitle === newTitle) return;\n\n // Ensure title uniqueness among SQL nodes by adjusting to a unique variant\n const uniqueTitle = getUniqueSqlTitle(\n get().canvas.config.nodes,\n newTitle,\n nodeId,\n );\n\n const connector = await get().db.getConnector();\n await connector.query(\n `CREATE SCHEMA IF NOT EXISTS ${CANVAS_SCHEMA_NAME}`,\n );\n\n const result = get().canvas.sqlResults[nodeId];\n const oldTableName =\n result && result.status === 'success'\n ? result.tableName\n : `${CANVAS_SCHEMA_NAME}.${escapeId(prevTitle)}`;\n\n await connector.query(\n `ALTER TABLE ${oldTableName} RENAME TO ${escapeId(uniqueTitle)}`,\n );\n\n const newQualified = `${CANVAS_SCHEMA_NAME}.${escapeId(uniqueTitle)}`;\n set((state) =>\n produce(state, (draft) => {\n const dnode = findNodeById(draft.canvas.config.nodes, nodeId);\n if (dnode) dnode.data.title = uniqueTitle;\n const r = draft.canvas.sqlResults[nodeId];\n if (r && r.status === 'success') r.tableName = newQualified;\n }),\n );\n\n await get().db.refreshTableSchemas();\n\n // Recompute children since upstream table name changed\n await get().canvas.executeDownstreamFrom(nodeId);\n },\n\n deleteNode: (nodeId) => {\n const current = get();\n const node = findNodeById(current.canvas.config.nodes, nodeId);\n let tableToDrop: string | undefined;\n if (node && isSqlData(node.data)) {\n const title = node.data.title || 'result';\n const res = current.canvas.sqlResults[nodeId];\n tableToDrop =\n res && res.status === 'success'\n ? res.tableName\n : `${CANVAS_SCHEMA_NAME}.${escapeId(title)}`;\n }\n\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.nodes = draft.canvas.config.nodes.filter(\n (n) => n.id !== nodeId,\n );\n draft.canvas.config.edges = draft.canvas.config.edges.filter(\n (e) => e.source !== nodeId && e.target !== nodeId,\n );\n // Clear stored result for the node\n delete draft.canvas.sqlResults[nodeId];\n if (draft.canvas.config.nodes.length === 0) {\n draft.canvas.config.viewport.x = 0;\n draft.canvas.config.viewport.y = 0;\n }\n }),\n );\n\n if (tableToDrop) {\n (async () => {\n try {\n const connector = await get().db.getConnector();\n await connector.query(`DROP TABLE IF EXISTS ${tableToDrop}`);\n await get().db.refreshTableSchemas();\n } catch (e) {\n console.warn(\n '[canvas.deleteNode] Failed to drop table for node',\n nodeId,\n e,\n );\n }\n })();\n }\n },\n\n applyNodeChanges: (changes) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.nodes = applyNodeChanges(\n changes,\n draft.canvas.config.nodes,\n );\n }),\n );\n },\n\n applyEdgeChanges: (changes) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.edges = applyEdgeChanges(\n changes,\n draft.canvas.config.edges,\n );\n }),\n );\n },\n\n setViewport: (viewport) => {\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.config.viewport = viewport;\n }),\n );\n },\n\n executeSqlNodeQuery: async (\n nodeId: string,\n opts?: {cascade?: boolean},\n ) => {\n const node = findNodeById(get().canvas.config.nodes, nodeId);\n if (!node || !isSqlData(node.data)) return;\n const sql = node.data.sql || '';\n const title = node.data.title || 'result';\n\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.sqlResults[nodeId] = {status: 'loading'};\n }),\n );\n\n try {\n // Validate it's a single select\n const parsed = await get().db.sqlSelectToJson(sql);\n if (parsed.error) {\n throw new Error(\n parsed.error_message || 'Not a valid SELECT statement',\n );\n }\n\n // Create schema and table\n const connector = await get().db.getConnector();\n await connector.query(\n `CREATE SCHEMA IF NOT EXISTS ${CANVAS_SCHEMA_NAME}`,\n );\n\n const tableName = `${CANVAS_SCHEMA_NAME}.${escapeId(title)}`;\n await connector.query(\n `CREATE OR REPLACE TABLE ${tableName} AS ${sql}`,\n );\n\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.sqlResults[nodeId] = {\n status: 'success',\n tableName,\n lastQueryStatement: sql,\n };\n }),\n );\n\n // Cascade execution to downstream SQL nodes (topologically) unless disabled\n if (opts?.cascade !== false) {\n await get().canvas.executeDownstreamFrom(nodeId);\n }\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n set((state) =>\n produce(state, (draft) => {\n draft.canvas.sqlResults[nodeId] = {\n status: 'error',\n error: message,\n };\n }),\n );\n }\n },\n },\n }));\n}\n\nexport type DuckDbSliceStateWithCanvas = DuckDbSliceState & CanvasSliceState;\n\nexport function useStoreWithCanvas<T>(\n selector: (state: DuckDbSliceStateWithCanvas) => T,\n): T {\n return useBaseRoomStore<BaseRoomStoreState, T>((state) =>\n selector(state as unknown as DuckDbSliceStateWithCanvas),\n );\n}\n"]}
package/dist/dag.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,MAAM,MAAM,OAAO,GAAG;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,CAAC;AACnC,iDAAiD;AACjD,MAAM,MAAM,OAAO,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AACvD,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,CAQ5E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,EACjD,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,MAAM,GACT,CAAC,GAAG,SAAS,CAEf;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAkCxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,EAAE,EAChB,KAAK,EAAE,OAAO,EAAE,GACf,MAAM,EAAE,CA8CV"}
1
+ {"version":3,"file":"dag.d.ts","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,MAAM,MAAM,OAAO,GAAG;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,CAAC;AACnC,iDAAiD;AACjD,MAAM,MAAM,OAAO,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,CAAC;AACvD,oEAAoE;AACpE,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAEjD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,CAQ5E;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS;IAAC,EAAE,EAAE,MAAM,CAAA;CAAC,EACjD,KAAK,EAAE,CAAC,EAAE,EACV,EAAE,EAAE,MAAM,GACT,CAAC,GAAG,SAAS,CAEf;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAiCxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,EAAE,EAChB,KAAK,EAAE,OAAO,EAAE,GACf,MAAM,EAAE,CA6CV"}
package/dist/dag.js CHANGED
@@ -59,7 +59,6 @@ export function topoSortAll(nodes, edges) {
59
59
  const remaining = nodes
60
60
  .map((n) => n.id)
61
61
  .filter((id) => !order.includes(id));
62
- // eslint-disable-next-line no-console
63
62
  console.warn('[dag.topoSortAll] Cycle detected; appending remaining nodes arbitrarily:', remaining);
64
63
  order.push(...remaining);
65
64
  }
@@ -117,7 +116,6 @@ export function topoSortDownstream(startId, nodes, edges) {
117
116
  }
118
117
  if (order.length < reachable.size) {
119
118
  const remaining = Array.from(reachable).filter((id) => !order.includes(id));
120
- // eslint-disable-next-line no-console
121
119
  console.warn('[dag.topoSortDownstream] Cycle detected in downstream graph:', remaining);
122
120
  order.push(...remaining);
123
121
  }
package/dist/dag.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dag.js","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"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","sourcesContent":["/** A minimal graph node with an `id`. */\nexport type DagNode = {id: string};\n/** A directed edge from `source` to `target`. */\nexport type DagEdge = {source: string; target: string};\n/** Forward adjacency list mapping node id to its child node ids. */\nexport type Adjacency = Record<string, string[]>;\n\n/**\n * Build a forward adjacency list for a directed graph.\n * Ensures that every node id exists in the adjacency map, even if it has no outgoing edges.\n *\n * @param nodes - The set of nodes to include in the graph.\n * @param edges - Directed edges where `source` points to `target`.\n * @returns A mapping from node id to an array of child node ids.\n */\nexport function buildAdjacency(nodes: DagNode[], edges: DagEdge[]): Adjacency {\n const adjacency: Adjacency = {};\n for (const n of nodes) adjacency[n.id] = [];\n for (const e of edges) {\n const list = adjacency[e.source] || (adjacency[e.source] = []);\n list.push(e.target);\n }\n return adjacency;\n}\n\n/**\n * Find a node by id in a list of nodes.\n *\n * @param nodes - Array of nodes with an `id` field.\n * @param id - The node id to find.\n * @returns The node if found, otherwise undefined.\n */\nexport function findNodeById<T extends {id: string}>(\n nodes: T[],\n id: string,\n): T | undefined {\n return nodes.find((n) => n.id === id);\n}\n\n/**\n * Topologically sort all nodes in the graph using Kahn's algorithm.\n * If a cycle is detected, the remaining nodes are appended in arbitrary order,\n * and a warning is logged.\n *\n * @param nodes - The set of nodes to sort.\n * @param edges - Directed edges defining dependencies.\n * @returns An array of node ids in dependency order (parents before children).\n */\nexport function topoSortAll(nodes: DagNode[], edges: DagEdge[]): string[] {\n const adjacency = buildAdjacency(nodes, edges);\n const inDegree: Record<string, number> = {};\n for (const n of nodes) inDegree[n.id] = 0;\n for (const e of edges) {\n inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;\n }\n\n const queue: string[] = Object.keys(inDegree).filter(\n (id) => (inDegree[id] ?? 0) === 0,\n );\n const order: string[] = [];\n while (queue.length) {\n const cur = queue.shift() as string;\n order.push(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) {\n inDegree[nb] = (inDegree[nb] ?? 0) - 1;\n if (inDegree[nb] === 0) queue.push(nb);\n }\n }\n\n if (order.length < nodes.length) {\n const remaining = nodes\n .map((n) => n.id)\n .filter((id) => !order.includes(id));\n // eslint-disable-next-line no-console\n console.warn(\n '[dag.topoSortAll] Cycle detected; appending remaining nodes arbitrarily:',\n remaining,\n );\n order.push(...remaining);\n }\n return order;\n}\n\n/**\n * Get a topological order for the downstream subgraph reachable from `startId`.\n * Only nodes reachable from the start are included (the starting node is excluded).\n * If a cycle exists within the reachable subgraph, the remaining nodes are appended\n * at the end in arbitrary order and a warning is logged.\n *\n * @param startId - The node id to start traversal from.\n * @param nodes - The set of nodes in the full graph.\n * @param edges - Directed edges defining the full graph dependencies.\n * @returns Node ids reachable from `startId`, in dependency order.\n */\nexport function topoSortDownstream(\n startId: string,\n nodes: DagNode[],\n edges: DagEdge[],\n): string[] {\n const adjacency = buildAdjacency(nodes, edges);\n // Collect reachable nodes from startId (excluding start)\n const reachable = new Set<string>();\n const queue: string[] = [...(adjacency[startId] || [])];\n while (queue.length) {\n const cur = queue.shift() as string;\n if (reachable.has(cur)) continue;\n reachable.add(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) queue.push(nb);\n }\n if (reachable.size === 0) return [];\n\n // Kahn's algorithm for topological sort within subgraph\n const inDegree: Record<string, number> = {};\n for (const id of reachable) inDegree[id] = 0;\n for (const e of edges) {\n if (reachable.has(e.source) && reachable.has(e.target)) {\n inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;\n }\n }\n const queue2: string[] = Array.from(reachable).filter(\n (id) => (inDegree[id] ?? 0) === 0,\n );\n const order: string[] = [];\n while (queue2.length) {\n const cur = queue2.shift() as string;\n order.push(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) {\n if (!reachable.has(nb)) continue;\n inDegree[nb] = (inDegree[nb] ?? 0) - 1;\n if (inDegree[nb] === 0) queue2.push(nb);\n }\n }\n if (order.length < reachable.size) {\n const remaining = Array.from(reachable).filter((id) => !order.includes(id));\n // eslint-disable-next-line no-console\n console.warn(\n '[dag.topoSortDownstream] Cycle detected in downstream graph:',\n remaining,\n );\n order.push(...remaining);\n }\n return order;\n}\n"]}
1
+ {"version":3,"file":"dag.js","sourceRoot":"","sources":["../src/dag.ts"],"names":[],"mappings":"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","sourcesContent":["/** A minimal graph node with an `id`. */\nexport type DagNode = {id: string};\n/** A directed edge from `source` to `target`. */\nexport type DagEdge = {source: string; target: string};\n/** Forward adjacency list mapping node id to its child node ids. */\nexport type Adjacency = Record<string, string[]>;\n\n/**\n * Build a forward adjacency list for a directed graph.\n * Ensures that every node id exists in the adjacency map, even if it has no outgoing edges.\n *\n * @param nodes - The set of nodes to include in the graph.\n * @param edges - Directed edges where `source` points to `target`.\n * @returns A mapping from node id to an array of child node ids.\n */\nexport function buildAdjacency(nodes: DagNode[], edges: DagEdge[]): Adjacency {\n const adjacency: Adjacency = {};\n for (const n of nodes) adjacency[n.id] = [];\n for (const e of edges) {\n const list = adjacency[e.source] || (adjacency[e.source] = []);\n list.push(e.target);\n }\n return adjacency;\n}\n\n/**\n * Find a node by id in a list of nodes.\n *\n * @param nodes - Array of nodes with an `id` field.\n * @param id - The node id to find.\n * @returns The node if found, otherwise undefined.\n */\nexport function findNodeById<T extends {id: string}>(\n nodes: T[],\n id: string,\n): T | undefined {\n return nodes.find((n) => n.id === id);\n}\n\n/**\n * Topologically sort all nodes in the graph using Kahn's algorithm.\n * If a cycle is detected, the remaining nodes are appended in arbitrary order,\n * and a warning is logged.\n *\n * @param nodes - The set of nodes to sort.\n * @param edges - Directed edges defining dependencies.\n * @returns An array of node ids in dependency order (parents before children).\n */\nexport function topoSortAll(nodes: DagNode[], edges: DagEdge[]): string[] {\n const adjacency = buildAdjacency(nodes, edges);\n const inDegree: Record<string, number> = {};\n for (const n of nodes) inDegree[n.id] = 0;\n for (const e of edges) {\n inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;\n }\n\n const queue: string[] = Object.keys(inDegree).filter(\n (id) => (inDegree[id] ?? 0) === 0,\n );\n const order: string[] = [];\n while (queue.length) {\n const cur = queue.shift() as string;\n order.push(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) {\n inDegree[nb] = (inDegree[nb] ?? 0) - 1;\n if (inDegree[nb] === 0) queue.push(nb);\n }\n }\n\n if (order.length < nodes.length) {\n const remaining = nodes\n .map((n) => n.id)\n .filter((id) => !order.includes(id));\n console.warn(\n '[dag.topoSortAll] Cycle detected; appending remaining nodes arbitrarily:',\n remaining,\n );\n order.push(...remaining);\n }\n return order;\n}\n\n/**\n * Get a topological order for the downstream subgraph reachable from `startId`.\n * Only nodes reachable from the start are included (the starting node is excluded).\n * If a cycle exists within the reachable subgraph, the remaining nodes are appended\n * at the end in arbitrary order and a warning is logged.\n *\n * @param startId - The node id to start traversal from.\n * @param nodes - The set of nodes in the full graph.\n * @param edges - Directed edges defining the full graph dependencies.\n * @returns Node ids reachable from `startId`, in dependency order.\n */\nexport function topoSortDownstream(\n startId: string,\n nodes: DagNode[],\n edges: DagEdge[],\n): string[] {\n const adjacency = buildAdjacency(nodes, edges);\n // Collect reachable nodes from startId (excluding start)\n const reachable = new Set<string>();\n const queue: string[] = [...(adjacency[startId] || [])];\n while (queue.length) {\n const cur = queue.shift() as string;\n if (reachable.has(cur)) continue;\n reachable.add(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) queue.push(nb);\n }\n if (reachable.size === 0) return [];\n\n // Kahn's algorithm for topological sort within subgraph\n const inDegree: Record<string, number> = {};\n for (const id of reachable) inDegree[id] = 0;\n for (const e of edges) {\n if (reachable.has(e.source) && reachable.has(e.target)) {\n inDegree[e.target] = (inDegree[e.target] ?? 0) + 1;\n }\n }\n const queue2: string[] = Array.from(reachable).filter(\n (id) => (inDegree[id] ?? 0) === 0,\n );\n const order: string[] = [];\n while (queue2.length) {\n const cur = queue2.shift() as string;\n order.push(cur);\n const neighbors = adjacency[cur] || [];\n for (const nb of neighbors) {\n if (!reachable.has(nb)) continue;\n inDegree[nb] = (inDegree[nb] ?? 0) - 1;\n if (inDegree[nb] === 0) queue2.push(nb);\n }\n }\n if (order.length < reachable.size) {\n const remaining = Array.from(reachable).filter((id) => !order.includes(id));\n console.warn(\n '[dag.topoSortDownstream] Cycle detected in downstream graph:',\n remaining,\n );\n order.push(...remaining);\n }\n return order;\n}\n"]}
@@ -47,6 +47,6 @@ export const SqlNode = ({ id, data }) => {
47
47
  fixedOverflowWidgets: false,
48
48
  }
49
49
  : EDITOR_OPTIONS, [overflowWidgetsDomNode]);
50
- return (_jsx(CanvasNodeContainer, { id: id, headerRight: _jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", variant: "secondary", onClick: () => execute(id), children: "Run" }), _jsx("span", { className: "text-[10px] uppercase text-gray-500", children: "SQL" })] }), children: _jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsx("div", { className: "relative flex-1", children: _jsx(SqlMonacoEditor, { className: "absolute inset-0 p-1", value: sql, options: editorOptions, onChange: (v) => updateNode(id, (d) => ({ ...d, sql: v || '' })), tableSchemas: tables }) }), result?.status === 'error' && (_jsx("div", { className: "flex-1 overflow-auto whitespace-pre-wrap border-t p-4 font-mono text-xs text-red-600", children: result.error })), result?.status === 'success' && (_jsx("div", { className: "flex-[2] overflow-hidden border-t", children: _jsx(QueryDataTable, { query: `SELECT * FROM ${result.tableName}`, fontSize: "text-xs" }) }))] }) }));
50
+ return (_jsx(CanvasNodeContainer, { id: id, headerRight: _jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", variant: "secondary", onClick: () => execute(id), children: "Run" }), _jsx("span", { className: "text-[10px] text-gray-500 uppercase", children: "SQL" })] }), children: _jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsx("div", { className: "relative flex-1", children: _jsx(SqlMonacoEditor, { className: "absolute inset-0 p-1", value: sql, options: editorOptions, onChange: (v) => updateNode(id, (d) => ({ ...d, sql: v || '' })), tableSchemas: tables }) }), result?.status === 'error' && (_jsx("div", { className: "flex-1 overflow-auto border-t p-4 font-mono text-xs whitespace-pre-wrap text-red-600", children: result.error })), result?.status === 'success' && (_jsx("div", { className: "flex-2 overflow-hidden border-t", children: _jsx(QueryDataTable, { query: `SELECT * FROM ${result.tableName}`, fontSize: "text-xs" }) }))] }) }));
51
51
  };
52
52
  //# sourceMappingURL=SqlNode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SqlNode.js","sourceRoot":"","sources":["../../src/nodes/SqlNode.tsx"],"names":[],"mappings":"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","sourcesContent":["import {QueryDataTable} from '@sqlrooms/data-table';\nimport {SqlMonacoEditor} from '@sqlrooms/sql-editor';\nimport {Button, useToast} from '@sqlrooms/ui';\nimport {FC, useMemo, useState} from 'react';\nimport {CanvasNodeData, useStoreWithCanvas} from '../CanvasSlice';\nimport {CanvasNodeContainer} from './CanvasNodeContainer';\n// import type * as Monaco from 'monaco-editor';\n// type EditorInstance = Monaco.editor.IStandaloneCodeEditor;\n// type MonacoInstance = typeof Monaco;\n\nconst EDITOR_OPTIONS: Parameters<typeof SqlMonacoEditor>[0]['options'] = {\n minimap: {enabled: false},\n lineNumbers: 'off',\n scrollbar: {\n handleMouseWheel: false,\n },\n fixedOverflowWidgets: false,\n};\n\ntype SqlData = Extract<CanvasNodeData, {type: 'sql'}>;\n\nexport const SqlNode: FC<{id: string; data: SqlData}> = ({id, data}) => {\n const sql = data.sql || '';\n const updateNode = useStoreWithCanvas((s) => s.canvas.updateNode);\n const tables = useStoreWithCanvas((s) => s.db.tables);\n const execute = useStoreWithCanvas((s) => s.canvas.executeSqlNodeQuery);\n const result = useStoreWithCanvas((s) => s.canvas.sqlResults[id]);\n const {toast} = useToast();\n\n // const handleEditorMount = useCallback(\n // (editor: EditorInstance, monaco: MonacoInstance) => {\n // editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {\n // if (editor.hasTextFocus()) {\n // execute(id);\n // }\n // });\n // },\n // [execute],\n // );\n\n // const reactFlowContainerRef = useRef<HTMLDivElement>(null);\n // useEffect(() => {\n // reactFlowContainerRef.current = document.querySelector<HTMLDivElement>(\n // '.react-flow__renderer',\n // );\n // }, []);\n const [overflowWidgetsDomNode, setOverflowWidgetsDomNode] =\n useState<HTMLDivElement | null>(null);\n\n const editorOptions = useMemo(\n (): typeof EDITOR_OPTIONS =>\n overflowWidgetsDomNode\n ? {\n ...EDITOR_OPTIONS,\n overflowWidgetsDomNode: overflowWidgetsDomNode ?? undefined,\n fixedOverflowWidgets: false,\n }\n : EDITOR_OPTIONS,\n [overflowWidgetsDomNode],\n );\n\n return (\n <CanvasNodeContainer\n id={id}\n headerRight={\n <>\n <Button size=\"sm\" variant=\"secondary\" onClick={() => execute(id)}>\n Run\n </Button>\n <span className=\"text-[10px] uppercase text-gray-500\">SQL</span>\n </>\n }\n >\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"relative flex-1\">\n <SqlMonacoEditor\n className=\"absolute inset-0 p-1\"\n value={sql}\n options={editorOptions}\n onChange={(v) =>\n updateNode(id, (d) => ({...(d as SqlData), sql: v || ''}))\n }\n tableSchemas={tables}\n // onMount={handleEditorMount}\n />\n </div>\n {result?.status === 'error' && (\n <div className=\"flex-1 overflow-auto whitespace-pre-wrap border-t p-4 font-mono text-xs text-red-600\">\n {result.error}\n </div>\n )}\n {result?.status === 'success' && (\n <div className=\"flex-[2] overflow-hidden border-t\">\n <QueryDataTable\n query={`SELECT * FROM ${result.tableName}`}\n fontSize=\"text-xs\"\n />\n </div>\n )}\n </div>\n {/* {reactFlowContainerRef.current &&\n createPortal(\n <div\n ref={(node) => {\n if (node && !overflowWidgetsDomNode) {\n setOverflowWidgetsDomNode(node);\n }\n }}\n // CRITICAL: You must re-apply the monaco class here!\n className=\"monaco-editor\"\n // CRITICAL: Styles to ensure overlays position correctly relative to window\n style={{position: 'absolute', top: 0, left: 0}}\n />,\n reactFlowContainerRef.current,\n )} */}\n </CanvasNodeContainer>\n );\n};\n"]}
1
+ {"version":3,"file":"SqlNode.js","sourceRoot":"","sources":["../../src/nodes/SqlNode.tsx"],"names":[],"mappings":"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","sourcesContent":["import {QueryDataTable} from '@sqlrooms/data-table';\nimport {SqlMonacoEditor} from '@sqlrooms/sql-editor';\nimport {Button, useToast} from '@sqlrooms/ui';\nimport {FC, useMemo, useState} from 'react';\nimport {CanvasNodeData, useStoreWithCanvas} from '../CanvasSlice';\nimport {CanvasNodeContainer} from './CanvasNodeContainer';\n// import type * as Monaco from 'monaco-editor';\n// type EditorInstance = Monaco.editor.IStandaloneCodeEditor;\n// type MonacoInstance = typeof Monaco;\n\nconst EDITOR_OPTIONS: Parameters<typeof SqlMonacoEditor>[0]['options'] = {\n minimap: {enabled: false},\n lineNumbers: 'off',\n scrollbar: {\n handleMouseWheel: false,\n },\n fixedOverflowWidgets: false,\n};\n\ntype SqlData = Extract<CanvasNodeData, {type: 'sql'}>;\n\nexport const SqlNode: FC<{id: string; data: SqlData}> = ({id, data}) => {\n const sql = data.sql || '';\n const updateNode = useStoreWithCanvas((s) => s.canvas.updateNode);\n const tables = useStoreWithCanvas((s) => s.db.tables);\n const execute = useStoreWithCanvas((s) => s.canvas.executeSqlNodeQuery);\n const result = useStoreWithCanvas((s) => s.canvas.sqlResults[id]);\n const {toast} = useToast();\n\n // const handleEditorMount = useCallback(\n // (editor: EditorInstance, monaco: MonacoInstance) => {\n // editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {\n // if (editor.hasTextFocus()) {\n // execute(id);\n // }\n // });\n // },\n // [execute],\n // );\n\n // const reactFlowContainerRef = useRef<HTMLDivElement>(null);\n // useEffect(() => {\n // reactFlowContainerRef.current = document.querySelector<HTMLDivElement>(\n // '.react-flow__renderer',\n // );\n // }, []);\n const [overflowWidgetsDomNode, setOverflowWidgetsDomNode] =\n useState<HTMLDivElement | null>(null);\n\n const editorOptions = useMemo(\n (): typeof EDITOR_OPTIONS =>\n overflowWidgetsDomNode\n ? {\n ...EDITOR_OPTIONS,\n overflowWidgetsDomNode: overflowWidgetsDomNode ?? undefined,\n fixedOverflowWidgets: false,\n }\n : EDITOR_OPTIONS,\n [overflowWidgetsDomNode],\n );\n\n return (\n <CanvasNodeContainer\n id={id}\n headerRight={\n <>\n <Button size=\"sm\" variant=\"secondary\" onClick={() => execute(id)}>\n Run\n </Button>\n <span className=\"text-[10px] text-gray-500 uppercase\">SQL</span>\n </>\n }\n >\n <div className=\"flex h-full w-full flex-col\">\n <div className=\"relative flex-1\">\n <SqlMonacoEditor\n className=\"absolute inset-0 p-1\"\n value={sql}\n options={editorOptions}\n onChange={(v) =>\n updateNode(id, (d) => ({...(d as SqlData), sql: v || ''}))\n }\n tableSchemas={tables}\n // onMount={handleEditorMount}\n />\n </div>\n {result?.status === 'error' && (\n <div className=\"flex-1 overflow-auto border-t p-4 font-mono text-xs whitespace-pre-wrap text-red-600\">\n {result.error}\n </div>\n )}\n {result?.status === 'success' && (\n <div className=\"flex-2 overflow-hidden border-t\">\n <QueryDataTable\n query={`SELECT * FROM ${result.tableName}`}\n fontSize=\"text-xs\"\n />\n </div>\n )}\n </div>\n {/* {reactFlowContainerRef.current &&\n createPortal(\n <div\n ref={(node) => {\n if (node && !overflowWidgetsDomNode) {\n setOverflowWidgetsDomNode(node);\n }\n }}\n // CRITICAL: You must re-apply the monaco class here!\n className=\"monaco-editor\"\n // CRITICAL: Styles to ensure overlays position correctly relative to window\n style={{position: 'absolute', top: 0, left: 0}}\n />,\n reactFlowContainerRef.current,\n )} */}\n </CanvasNodeContainer>\n );\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/canvas",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "module": "dist/index.js",
@@ -32,14 +32,14 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@paralleldrive/cuid2": "^3.0.0",
35
- "@sqlrooms/ai": "0.27.0",
36
- "@sqlrooms/crdt": "0.27.0",
37
- "@sqlrooms/data-table": "0.27.0",
38
- "@sqlrooms/duckdb": "0.27.0",
39
- "@sqlrooms/room-shell": "0.27.0",
40
- "@sqlrooms/sql-editor": "0.27.0",
41
- "@sqlrooms/ui": "0.27.0",
42
- "@sqlrooms/vega": "0.27.0",
35
+ "@sqlrooms/ai": "0.28.0",
36
+ "@sqlrooms/crdt": "0.28.0",
37
+ "@sqlrooms/data-table": "0.28.0",
38
+ "@sqlrooms/duckdb": "0.28.0",
39
+ "@sqlrooms/room-shell": "0.28.0",
40
+ "@sqlrooms/sql-editor": "0.28.0",
41
+ "@sqlrooms/ui": "0.28.0",
42
+ "@sqlrooms/vega": "0.28.0",
43
43
  "@xyflow/react": "^12.8.5",
44
44
  "immer": "^11.0.1",
45
45
  "loro-mirror": "^1.1.2",
@@ -57,5 +57,5 @@
57
57
  "typecheck": "tsc --noEmit",
58
58
  "typedoc": "typedoc"
59
59
  },
60
- "gitHead": "f215995ab4adeac4c58171739261a15cbba9e82b"
60
+ "gitHead": "dcac54f8adf77240e293c93d224a0ce9fd8142a9"
61
61
  }