@sqlrooms/sql-editor 0.28.0-rc.0 → 0.28.1-rc.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,435 +1,117 @@
1
- This package is part of the SQLRooms framework.
1
+ SQL editor UI and state slice for SQLRooms apps.
2
2
 
3
- # SQL Editor
3
+ This package provides:
4
4
 
5
- A powerful SQL editor component for SQLRooms applications. This package provides React components and hooks for creating interactive SQL query interfaces with Monaco editor integration, table management, and results visualization.
6
-
7
- ## Features
8
-
9
- - 🔍 **Advanced SQL Editing**: Monaco-based SQL editor with syntax highlighting and auto-completion
10
- - 📊 **Data Visualization**: View query results in interactive data tables
11
- - 📑 **Multiple Tabs**: Support for multiple query tabs with save/rename/delete functionality
12
- - 🔄 **State Management**: Zustand-based state management for SQL editor state
13
- - 📦 **Table Management**: Browser for tables in the database with schema information
14
- - 📤 **Data Export**: Export query results to CSV files
15
- - 📝 **Documentation**: Optional documentation panel for SQL reference
5
+ - `createSqlEditorSlice()` for query tabs, execution, and results state
6
+ - `SqlEditor` and `SqlEditorModal` UI
7
+ - `SqlMonacoEditor` standalone SQL editor
8
+ - helpers/components for query results, table structure, and SQL data sources
16
9
 
17
10
  ## Installation
18
11
 
19
12
  ```bash
20
- npm install @sqlrooms/sql-editor
21
- ```
22
-
23
- ## Basic Usage
24
-
25
- ### SqlEditor and SqlEditorModal Components
26
-
27
- These components must be used within a `RoomShell` which provides the room store context as they rely on the SQLRooms store:
28
-
29
- ```tsx
30
- import {RoomShell} from '@sqlrooms/room-shell';
31
- import {SqlEditorModal} from '@sqlrooms/sql-editor';
32
- import {useDisclosure} from '@sqlrooms/ui';
33
- import {TerminalIcon} from 'lucide-react';
34
- import {roomStore} from './store';
35
-
36
- function MyApp() {
37
- const sqlEditorDisclosure = useDisclosure();
38
-
39
- return (
40
- <RoomShell className="h-screen" roomStore={roomStore}>
41
- <RoomShell.Sidebar>
42
- <RoomShell.SidebarButton
43
- title="SQL Editor"
44
- onClick={sqlEditorDisclosure.onToggle}
45
- isSelected={false}
46
- icon={TerminalIcon}
47
- />
48
- </RoomShell.Sidebar>
49
- <RoomShell.LayoutComposer />
50
- <RoomShell.LoadingProgress />
51
- <SqlEditorModal
52
- isOpen={sqlEditorDisclosure.isOpen}
53
- onClose={sqlEditorDisclosure.onClose}
54
- />
55
- </RoomShell>
56
- );
57
- }
13
+ npm install @sqlrooms/sql-editor @sqlrooms/room-shell @sqlrooms/duckdb @sqlrooms/ui
58
14
  ```
59
15
 
60
- ### Store Setup for SQL Editor
61
-
62
- The SQL Editor requires a properly configured store with the SQL Editor slice:
16
+ ## Store setup
63
17
 
64
18
  ```tsx
65
19
  import {
66
20
  createRoomShellSlice,
67
21
  createRoomStore,
68
- RoomState,
22
+ RoomShellSliceState,
69
23
  } from '@sqlrooms/room-shell';
70
- import {BaseRoomConfig} from '@sqlrooms/room-config';
71
- import {
72
- createDefaultSqlEditorConfig,
73
- createSqlEditorSlice,
74
- SqlEditorSliceConfig,
75
- SqlEditorSliceState,
76
- } from '@sqlrooms/sql-editor';
77
- import {z} from 'zod';
78
-
79
- // Define combined config schema
80
- export const RoomConfig = BaseRoomConfig.merge(SqlEditorSliceConfig);
81
- export type RoomConfig = z.infer<typeof RoomConfig>;
24
+ import {createSqlEditorSlice, SqlEditorSliceState} from '@sqlrooms/sql-editor';
82
25
 
83
- // Define combined state type
84
- export type RoomState = RoomState<RoomConfig> & SqlEditorSliceState;
26
+ type RoomState = RoomShellSliceState & SqlEditorSliceState;
85
27
 
86
- // Create combined store
87
- export const {roomStore, useRoomStore} = createRoomStore<RoomConfig, RoomState>(
28
+ export const {roomStore, useRoomStore} = createRoomStore<RoomState>(
88
29
  (set, get, store) => ({
89
- // Base room slice
90
- ...createRoomShellSlice<RoomConfig>({
30
+ ...createRoomShellSlice({
91
31
  config: {
92
- title: 'SQL Workspace',
32
+ dataSources: [
33
+ {
34
+ type: 'url',
35
+ tableName: 'earthquakes',
36
+ url: 'https://huggingface.co/datasets/sqlrooms/earthquakes/resolve/main/earthquakes.parquet',
37
+ },
38
+ ],
93
39
  },
94
40
  })(set, get, store),
95
-
96
- // Sql editor slice
97
41
  ...createSqlEditorSlice()(set, get, store),
98
42
  }),
99
43
  );
100
44
  ```
101
45
 
102
- ### Standalone SqlMonacoEditor Component
103
-
104
- Unlike the full SQL Editor components, the `SqlMonacoEditor` can be used as a standalone component without requiring the store:
105
-
106
- ```tsx
107
- import {SqlMonacoEditor} from '@sqlrooms/sql-editor';
108
- import {useState} from 'react';
109
-
110
- function SimpleSqlEditor() {
111
- const [query, setQuery] = useState('SELECT * FROM products');
112
-
113
- const handleExecute = () => {
114
- // Execute the query using your own logic
115
- console.log('Executing query:', query);
116
- };
117
-
118
- return (
119
- <>
120
- <SqlMonacoEditor value={query} onChange={setQuery} height="400px" />
121
- <button onClick={handleExecute}>Execute</button>
122
- </>
123
- );
124
- }
125
- ```
126
-
127
- ### With Custom Documentation Panel
128
-
129
- Adding a custom documentation panel to the SQL Editor:
46
+ ## Render SQL editor modal
130
47
 
131
48
  ```tsx
49
+ import {RoomShell} from '@sqlrooms/room-shell';
132
50
  import {SqlEditorModal} from '@sqlrooms/sql-editor';
133
51
  import {useDisclosure} from '@sqlrooms/ui';
134
- import {RoomShell} from '@sqlrooms/room-shell';
52
+ import {TerminalIcon} from 'lucide-react';
135
53
  import {roomStore} from './store';
136
54
 
137
- function AdvancedSqlEditor() {
138
- const {isOpen, onOpen, onClose} = useDisclosure();
139
-
140
- // Custom documentation component
141
- const Documentation = () => (
142
- <div className="p-4">
143
- <h2 className="mb-4 text-xl font-bold">SQL Reference</h2>
144
- <div className="space-y-4">
145
- <div>
146
- <h3 className="text-lg font-semibold">SELECT</h3>
147
- <p>Retrieves data from a table</p>
148
- <pre className="mt-2 rounded bg-gray-100 p-2">
149
- SELECT column1, column2 FROM table_name;
150
- </pre>
151
- </div>
152
- {/* More documentation items */}
153
- </div>
154
- </div>
155
- );
55
+ export function App() {
56
+ const sqlEditor = useDisclosure();
156
57
 
157
58
  return (
158
- <SqlEditorModal
159
- isOpen={isOpen}
160
- onClose={onClose}
161
- documentationPanel={<Documentation />}
162
- />
59
+ <RoomShell roomStore={roomStore} className="h-screen">
60
+ <RoomShell.Sidebar>
61
+ <RoomShell.SidebarButton
62
+ title="SQL Editor"
63
+ icon={TerminalIcon}
64
+ isSelected={sqlEditor.isOpen}
65
+ onClick={sqlEditor.onToggle}
66
+ />
67
+ </RoomShell.Sidebar>
68
+ <RoomShell.LayoutComposer />
69
+ <SqlEditorModal isOpen={sqlEditor.isOpen} onClose={sqlEditor.onClose} />
70
+ </RoomShell>
163
71
  );
164
72
  }
165
73
  ```
166
74
 
167
- ## State Management
168
-
169
- The SQL editor provides a Zustand slice for managing state. Here's how to set it up:
170
-
171
- ### Using in a Combined SQLRooms Store
172
-
173
- This approach is recommended when integrating multiple SQLRooms components:
75
+ ## Run queries programmatically
174
76
 
175
77
  ```tsx
176
- import {
177
- createSqlEditorSlice,
178
- createDefaultSqlEditorConfig,
179
- SqlEditorSliceState,
180
- SqlEditorSliceConfig,
181
- } from '@sqlrooms/sql-editor';
182
- import {
183
- createRoomShellSlice,
184
- createRoomStore,
185
- RoomState,
186
- RoomShell,
187
- } from '@sqlrooms/room-shell';
188
- import {BaseRoomConfig} from '@sqlrooms/room-config';
189
- import {z} from 'zod';
190
-
191
- // 1. Define combined config schema
192
- export const RoomConfig = BaseRoomConfig.merge(SqlEditorSliceConfig);
193
- export type RoomConfig = z.infer<typeof RoomConfig>;
194
-
195
- // 2. Define combined state type
196
- export type RoomState = RoomState<RoomConfig> & SqlEditorSliceState;
197
-
198
- // 3. Create combined store
199
- export const {roomStore, useRoomStore} = createRoomStore<RoomConfig, RoomState>(
200
- (set, get, store) => ({
201
- // Base room slice
202
- ...createRoomShellSlice<RoomConfig>({
203
- config: {
204
- title: 'SQL Workspace',
205
- },
206
- })(set, get, store),
207
-
208
- // Sql editor slice
209
- ...createSqlEditorSlice()(set, get, store),
210
- }),
211
- );
78
+ import {useRoomStore} from './store';
79
+ import {Button} from '@sqlrooms/ui';
212
80
 
213
- // 4. Use the store in components
214
- function MyComponent() {
215
- // Access SQL editor state and actions
216
- const runQuery = useRoomStore((state) => state.sqlEditor.runQuery);
217
- const createQueryTab = useRoomStore(
218
- (state) => state.sqlEditor.createQueryTab,
219
- );
81
+ function RunQueryButton() {
82
+ const parseAndRunQuery = useRoomStore((state) => state.sqlEditor.parseAndRunQuery);
83
+ const createQueryTab = useRoomStore((state) => state.sqlEditor.createQueryTab);
220
84
 
221
- // Use actions
222
- const handleExecute = () => {
223
- runQuery('SELECT * FROM users LIMIT 10');
224
- runQuery('SELECT * FROM users LIMIT 10');
85
+ const run = async () => {
86
+ createQueryTab('SELECT COUNT(*) AS total FROM earthquakes');
87
+ await parseAndRunQuery('SELECT COUNT(*) AS total FROM earthquakes');
225
88
  };
226
89
 
227
- return (
228
- <RoomShell roomStore={roomStore}>
229
- <div>
230
- <button onClick={handleExecute}>Run Query</button>
231
- <SqlEditorModal isOpen={true} onClose={() => {}} />
232
- </div>
233
- </RoomShell>
234
- );
90
+ return <Button onClick={() => void run()}>Run query</Button>;
235
91
  }
236
92
  ```
237
93
 
238
- ### Available State Actions
239
-
240
- - `sqlEditor.runQuery(query: string)`: Execute a SQL query
241
- - `sqlEditor.createQueryTab(initialQuery?: string)`: Create a new query tab
242
- - `sqlEditor.deleteQueryTab(queryId: string)`: Delete a query tab
243
- - `sqlEditor.renameQueryTab(queryId: string, newName: string)`: Rename a query tab
244
- - `sqlEditor.updateQueryText(queryId: string, queryText: string)`: Update query text
245
- - `sqlEditor.setSelectedQueryId(queryId: string)`: Set the selected query tab
246
- - `sqlEditor.getCurrentQuery(defaultQuery?: string)`: Get current query text
247
-
248
- ## Available Components
249
-
250
- ### SqlEditor
94
+ ## Standalone editor (without SQLRooms store)
251
95
 
252
- The main component providing a full-featured SQL editor interface. Must be used within a RoomShell.
253
-
254
- ```tsx
255
- import {SqlEditor} from '@sqlrooms/sql-editor';
256
- import {RoomShell} from '@sqlrooms/room-shell';
257
- import {roomStore} from './store';
258
-
259
- <RoomShell roomStore={roomStore}>
260
- <SqlEditor
261
- isOpen={boolean}
262
- onClose={() => void}
263
- schema="main"
264
- documentationPanel={ReactNode}
265
- />
266
- </RoomShell>
267
- ```
268
-
269
- ### SqlMonacoEditor
270
-
271
- A standalone SQL-specific Monaco editor component. Can be used independently without RoomShell.
96
+ `SqlMonacoEditor` can be used independently:
272
97
 
273
98
  ```tsx
274
99
  import {SqlMonacoEditor} from '@sqlrooms/sql-editor';
275
100
  import {useState} from 'react';
276
101
 
277
- function SimpleSqlEditor() {
278
- const [query, setQuery] = useState('SELECT * FROM products');
279
-
280
- const handleExecute = () => {
281
- // Execute the query using your own logic
282
- console.log('Executing query:', query);
283
- };
284
-
285
- return (
286
- <>
287
- <SqlMonacoEditor value={query} onChange={setQuery} height="400px" />
288
- <button onClick={handleExecute}>Execute</button>
289
- </>
290
- );
291
- }
292
- ```
293
-
294
- ### SqlEditorModal
295
-
296
- A modal wrapper around the SQL editor. Must be used within a RoomShell.
297
-
298
- ```tsx
299
- import {SqlEditorModal} from '@sqlrooms/sql-editor';
300
- import {useDisclosure} from '@sqlrooms/ui';
301
- import {RoomShell} from '@sqlrooms/room-shell';
302
- import {roomStore} from './store';
303
-
304
- function EditorWithModal() {
305
- const {isOpen, onOpen, onClose} = useDisclosure();
306
-
307
- return (
308
- <RoomShell roomStore={roomStore}>
309
- <button onClick={onOpen}>Open SQL Editor</button>
310
- <SqlEditorModal isOpen={isOpen} onClose={onClose} />
311
- </RoomShell>
312
- );
102
+ export function StandaloneEditor() {
103
+ const [sql, setSql] = useState('SELECT 1');
104
+ return <SqlMonacoEditor value={sql} onChange={(v) => setSql(v ?? '')} height="320px" />;
313
105
  }
314
106
  ```
315
107
 
316
- ### CreateTableModal
108
+ ## Related packages
317
109
 
318
- A modal for creating new tables from SQL queries. Must be used within a RoomShell.
110
+ - `@sqlrooms/sql-editor-config` for persisted SQL editor config schema
111
+ - `@sqlrooms/duckdb` for query execution and table state
112
+ - `@sqlrooms/schema-tree` for database tree rendering
319
113
 
320
- ```tsx
321
- import {CreateTableModal} from '@sqlrooms/sql-editor';
322
- import {useDisclosure} from '@sqlrooms/ui';
323
- import {RoomShell} from '@sqlrooms/room-shell';
324
- import {roomStore} from './store';
325
- import {useRoomStore} from './store';
326
-
327
- function TableCreator() {
328
- const {isOpen, onOpen, onClose} = useDisclosure();
329
- const addOrUpdateSqlQueryDataSource = useRoomStore(
330
- (state) => state.room.addOrUpdateSqlQueryDataSource,
331
- );
332
-
333
- return (
334
- <RoomShell roomStore={roomStore}>
335
- <button onClick={onOpen}>Create Table from Results</button>
336
- <CreateTableModal
337
- isOpen={isOpen}
338
- onClose={onClose}
339
- onAddOrUpdateSqlQuery={addOrUpdateSqlQueryDataSource}
340
- query="SELECT * FROM users"
341
- />
342
- </RoomShell>
343
- );
344
- }
345
- ```
346
-
347
- ### SqlQueryDataSourcesPanel
348
-
349
- A panel showing available data sources for SQL queries. Must be used within a RoomShell.
350
-
351
- ```tsx
352
- import {SqlQueryDataSourcesPanel} from '@sqlrooms/sql-editor';
353
- import {RoomShell} from '@sqlrooms/room-shell';
354
- import {roomStore} from './store';
355
-
356
- <RoomShell roomStore={roomStore}>
357
- <SqlQueryDataSourcesPanel
358
- onSelectTable={(tableName) => {
359
- console.log(`Selected table: ${tableName}`);
360
- }}
361
- />
362
- </RoomShell>;
363
- ```
364
-
365
- ## Props
366
-
367
- ### SqlEditor Props
368
-
369
- | Prop | Type | Default | Description |
370
- | ------------------ | --------- | --------- | ------------------------------------- |
371
- | isOpen | boolean | - | Whether the editor is open |
372
- | onClose | function | - | Callback when the editor is closed |
373
- | schema | string | 'main' | Default schema to use for queries |
374
- | documentationPanel | ReactNode | undefined | Custom documentation panel to display |
375
-
376
- ### SqlMonacoEditor Props
377
-
378
- | Prop | Type | Default | Description |
379
- | ---------------- | ----------- | ------- | --------------------------------------- |
380
- | value | string | '' | The SQL query text |
381
- | onChange | function | - | Callback when the query text changes |
382
- | height | string | '300px' | Height of the editor |
383
- | readOnly | boolean | false | Whether the editor is read-only |
384
- | theme | string | 'dark' | Editor theme ('dark' or 'light') |
385
- | tableSchemas | DataTable[] | [] | Table schemas for autocompletion |
386
- | customKeywords | string[] | [] | Custom SQL keywords for autocompletion |
387
- | customFunctions | string[] | [] | Custom SQL functions for autocompletion |
388
- | getLatestSchemas | function | - | Callback to get latest table schemas |
389
- | className | string | - | Additional CSS class names |
390
- | options | object | - | Monaco editor options |
391
- | onMount | function | - | Callback when editor is mounted |
392
-
393
- ### SqlEditorModal Props
394
-
395
- | Prop | Type | Default | Description |
396
- | ------------------ | --------- | --------- | ------------------------------------- |
397
- | isOpen | boolean | - | Whether the modal is open |
398
- | onClose | function | - | Callback when the modal is closed |
399
- | schema | string | 'main' | Default schema to use for queries |
400
- | documentationPanel | ReactNode | undefined | Custom documentation panel to display |
401
-
402
- ### CreateTableModal Props
403
-
404
- | Prop | Type | Default | Description |
405
- | --------------------- | -------- | ------- | --------------------------------- |
406
- | isOpen | boolean | - | Whether the modal is open |
407
- | onClose | function | - | Callback when the modal is closed |
408
- | onAddOrUpdateSqlQuery | function | - | Callback when a table is created |
409
- | query | string | - | SQL query that generated the data |
410
-
411
- ## Configuration
412
-
413
- The SQL editor can be configured through the Zustand store.
414
-
415
- ```tsx
416
- const config = createDefaultSqlEditorConfig();
417
- // Customize if needed
418
- sqlEditor.config.queries = [
419
- {id: 'default', name: 'Untitled', query: 'SELECT * FROM users LIMIT 10;'},
420
- ];
421
- sqlEditor.config.selectedQueryId = 'default';
422
-
423
- // Use in store creation
424
- const {roomStore} = createRoomStore({
425
- ...createRoomShellSlice({
426
- config: {
427
- ...config,
428
- // other config options
429
- },
430
- }),
431
- ...createSqlEditorSlice(),
432
- });
433
- ```
114
+ ## Example apps
434
115
 
435
- For more information, visit the SQLRooms documentation.
116
+ - https://github.com/sqlrooms/examples/tree/main/query
117
+ - https://github.com/sqlrooms/examples/tree/main/query-websocket
@@ -28,6 +28,8 @@ export declare function isQueryWithResult(queryResult: QueryResult | undefined):
28
28
  };
29
29
  export type SqlEditorSliceState = {
30
30
  sqlEditor: {
31
+ initialize?: () => Promise<void>;
32
+ destroy?: () => Promise<void>;
31
33
  config: SqlEditorSliceConfig;
32
34
  /**
33
35
  * Query results keyed by queryId (tab id).
@@ -1 +1 @@
1
- {"version":3,"file":"SqlEditorSlice.d.ts","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SqlEditorSlice.d.ts","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"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"}
@@ -1,11 +1,13 @@
1
1
  import { createId } from '@paralleldrive/cuid2';
2
2
  import { getSqlErrorWithPointer, joinStatements, makeLimitQuery, separateLastStatement, } from '@sqlrooms/duckdb';
3
- import { createSlice, useBaseRoomShellStore, } from '@sqlrooms/room-shell';
3
+ import { createSlice, registerCommandsForOwner, unregisterCommandsForOwner, useBaseRoomShellStore, } from '@sqlrooms/room-shell';
4
4
  import { createDefaultSqlEditorConfig, } from '@sqlrooms/sql-editor-config';
5
5
  import { generateUniqueName } from '@sqlrooms/utils';
6
6
  import { csvFormat } from 'd3-dsv';
7
7
  import { saveAs } from 'file-saver';
8
8
  import { produce } from 'immer';
9
+ import { z } from 'zod';
10
+ const SQL_EDITOR_COMMAND_OWNER = '@sqlrooms/sql-editor';
9
11
  export function isQueryWithResult(queryResult) {
10
12
  return (queryResult?.status === 'success' &&
11
13
  (queryResult.type === 'pragma' ||
@@ -13,9 +15,15 @@ export function isQueryWithResult(queryResult) {
13
15
  queryResult.type === 'select'));
14
16
  }
15
17
  export function createSqlEditorSlice({ config = createDefaultSqlEditorConfig(), queryResultLimit = 100, queryResultLimitOptions = [100, 500, 1000], } = {}) {
16
- return createSlice((set, get) => {
18
+ return createSlice((set, get, store) => {
17
19
  return {
18
20
  sqlEditor: {
21
+ initialize: async () => {
22
+ registerCommandsForOwner(store, SQL_EDITOR_COMMAND_OWNER, createSqlEditorCommands());
23
+ },
24
+ destroy: async () => {
25
+ unregisterCommandsForOwner(store, SQL_EDITOR_COMMAND_OWNER);
26
+ },
19
27
  config,
20
28
  // Initialize runtime state
21
29
  queryResultsById: {},
@@ -311,6 +319,257 @@ export function createSqlEditorSlice({ config = createDefaultSqlEditorConfig(),
311
319
  };
312
320
  });
313
321
  }
322
+ const SqlEditorRunQueryCommandInput = z.object({
323
+ query: z.string().describe('SQL query text to run.'),
324
+ });
325
+ const SqlEditorTabIdInput = z.object({
326
+ queryId: z.string().describe('ID of the query tab.'),
327
+ });
328
+ const SqlEditorRenameTabInput = z.object({
329
+ queryId: z.string().describe('ID of the query tab to rename.'),
330
+ name: z.string().min(1).describe('New tab name.'),
331
+ });
332
+ const SqlEditorResultLimitInput = z.object({
333
+ limit: z.number().int().positive().describe('Row limit for query results.'),
334
+ });
335
+ function createSqlEditorCommands() {
336
+ const ensureQueryTabExists = (state, queryId) => {
337
+ if (!state.sqlEditor.config.queries.some((query) => query.id === queryId)) {
338
+ throw new Error(`Unknown query tab "${queryId}".`);
339
+ }
340
+ };
341
+ return [
342
+ {
343
+ id: 'sql-editor.run-current-query',
344
+ name: 'Run current query',
345
+ description: 'Execute the selected SQL query tab',
346
+ group: 'SQL Editor',
347
+ keywords: ['sql', 'run', 'execute', 'query'],
348
+ metadata: {
349
+ readOnly: false,
350
+ idempotent: false,
351
+ riskLevel: 'medium',
352
+ },
353
+ ui: {
354
+ keystrokes: 'Mod+Enter',
355
+ },
356
+ isEnabled: ({ getState }) => {
357
+ const state = getState();
358
+ const selectedQueryId = state.sqlEditor.config.selectedQueryId;
359
+ const queryResult = state.sqlEditor.queryResultsById[selectedQueryId];
360
+ return (queryResult?.status !== 'loading' &&
361
+ state.sqlEditor.getCurrentQuery().trim().length > 0);
362
+ },
363
+ execute: async ({ getState }) => {
364
+ await getState().sqlEditor.parseAndRunCurrentQuery();
365
+ return {
366
+ success: true,
367
+ commandId: 'sql-editor.run-current-query',
368
+ message: 'Executed current query.',
369
+ };
370
+ },
371
+ },
372
+ {
373
+ id: 'sql-editor.run-query',
374
+ name: 'Run query text',
375
+ description: 'Execute an explicitly provided SQL query',
376
+ group: 'SQL Editor',
377
+ keywords: ['sql', 'run', 'execute', 'query', 'text'],
378
+ inputSchema: SqlEditorRunQueryCommandInput,
379
+ inputDescription: 'Provide query SQL to execute.',
380
+ metadata: {
381
+ readOnly: false,
382
+ idempotent: false,
383
+ riskLevel: 'medium',
384
+ },
385
+ execute: async ({ getState }, input) => {
386
+ const { query } = input;
387
+ await getState().sqlEditor.parseAndRunQuery(query);
388
+ return {
389
+ success: true,
390
+ commandId: 'sql-editor.run-query',
391
+ message: 'Executed SQL query.',
392
+ };
393
+ },
394
+ },
395
+ {
396
+ id: 'sql-editor.abort-current-query',
397
+ name: 'Abort current query',
398
+ description: 'Cancel the currently running SQL query',
399
+ group: 'SQL Editor',
400
+ keywords: ['sql', 'abort', 'cancel', 'query'],
401
+ metadata: {
402
+ readOnly: false,
403
+ idempotent: true,
404
+ riskLevel: 'low',
405
+ },
406
+ isEnabled: ({ getState }) => {
407
+ const state = getState();
408
+ const selectedQueryId = state.sqlEditor.config.selectedQueryId;
409
+ return (state.sqlEditor.queryResultsById[selectedQueryId]?.status ===
410
+ 'loading');
411
+ },
412
+ execute: ({ getState }) => {
413
+ getState().sqlEditor.abortCurrentQuery();
414
+ return {
415
+ success: true,
416
+ commandId: 'sql-editor.abort-current-query',
417
+ message: 'Abort signal sent to current query.',
418
+ };
419
+ },
420
+ },
421
+ {
422
+ id: 'sql-editor.create-query-tab',
423
+ name: 'Create query tab',
424
+ description: 'Open a new SQL query tab',
425
+ group: 'SQL Editor',
426
+ keywords: ['sql', 'tab', 'new', 'query'],
427
+ metadata: {
428
+ readOnly: false,
429
+ idempotent: false,
430
+ riskLevel: 'low',
431
+ },
432
+ execute: ({ getState }) => {
433
+ const newTab = getState().sqlEditor.createQueryTab();
434
+ return {
435
+ success: true,
436
+ commandId: 'sql-editor.create-query-tab',
437
+ message: `Created query tab "${newTab.name}".`,
438
+ data: {
439
+ queryId: newTab.id,
440
+ },
441
+ };
442
+ },
443
+ },
444
+ {
445
+ id: 'sql-editor.select-query-tab',
446
+ name: 'Select query tab',
447
+ description: 'Switch active SQL query tab by ID',
448
+ group: 'SQL Editor',
449
+ keywords: ['sql', 'tab', 'select', 'switch'],
450
+ inputSchema: SqlEditorTabIdInput,
451
+ inputDescription: 'Provide queryId to activate.',
452
+ metadata: {
453
+ readOnly: false,
454
+ idempotent: true,
455
+ riskLevel: 'low',
456
+ },
457
+ validateInput: (input, { getState }) => {
458
+ ensureQueryTabExists(getState(), input.queryId);
459
+ },
460
+ execute: ({ getState }, input) => {
461
+ const { queryId } = input;
462
+ getState().sqlEditor.setSelectedQueryId(queryId);
463
+ return {
464
+ success: true,
465
+ commandId: 'sql-editor.select-query-tab',
466
+ message: `Selected query tab "${queryId}".`,
467
+ };
468
+ },
469
+ },
470
+ {
471
+ id: 'sql-editor.rename-query-tab',
472
+ name: 'Rename query tab',
473
+ description: 'Rename a SQL query tab by ID',
474
+ group: 'SQL Editor',
475
+ keywords: ['sql', 'tab', 'rename'],
476
+ inputSchema: SqlEditorRenameTabInput,
477
+ inputDescription: 'Provide queryId and name.',
478
+ metadata: {
479
+ readOnly: false,
480
+ idempotent: true,
481
+ riskLevel: 'low',
482
+ },
483
+ validateInput: (input, { getState }) => {
484
+ ensureQueryTabExists(getState(), input.queryId);
485
+ },
486
+ execute: ({ getState }, input) => {
487
+ const { queryId, name } = input;
488
+ getState().sqlEditor.renameQueryTab(queryId, name);
489
+ return {
490
+ success: true,
491
+ commandId: 'sql-editor.rename-query-tab',
492
+ message: `Renamed query tab "${queryId}".`,
493
+ };
494
+ },
495
+ },
496
+ {
497
+ id: 'sql-editor.delete-query-tab',
498
+ name: 'Delete query tab',
499
+ description: 'Delete a SQL query tab by ID',
500
+ group: 'SQL Editor',
501
+ keywords: ['sql', 'tab', 'delete', 'remove'],
502
+ inputSchema: SqlEditorTabIdInput,
503
+ inputDescription: 'Provide queryId to delete.',
504
+ metadata: {
505
+ readOnly: false,
506
+ idempotent: true,
507
+ riskLevel: 'medium',
508
+ requiresConfirmation: true,
509
+ },
510
+ validateInput: (input, { getState }) => {
511
+ const state = getState();
512
+ ensureQueryTabExists(state, input.queryId);
513
+ if (state.sqlEditor.config.queries.length <= 1) {
514
+ throw new Error('Cannot delete the last remaining query tab.');
515
+ }
516
+ },
517
+ execute: ({ getState }, input) => {
518
+ const { queryId } = input;
519
+ getState().sqlEditor.deleteQueryTab(queryId);
520
+ return {
521
+ success: true,
522
+ commandId: 'sql-editor.delete-query-tab',
523
+ message: `Deleted query tab "${queryId}".`,
524
+ };
525
+ },
526
+ },
527
+ {
528
+ id: 'sql-editor.clear-query-results',
529
+ name: 'Clear query results',
530
+ description: 'Clear all cached SQL query results',
531
+ group: 'SQL Editor',
532
+ keywords: ['sql', 'clear', 'results'],
533
+ metadata: {
534
+ readOnly: false,
535
+ idempotent: true,
536
+ riskLevel: 'low',
537
+ },
538
+ isEnabled: ({ getState }) => Object.keys(getState().sqlEditor.queryResultsById).length > 0,
539
+ execute: ({ getState }) => {
540
+ getState().sqlEditor.clearQueryResults();
541
+ return {
542
+ success: true,
543
+ commandId: 'sql-editor.clear-query-results',
544
+ message: 'Cleared query results.',
545
+ };
546
+ },
547
+ },
548
+ {
549
+ id: 'sql-editor.set-result-limit',
550
+ name: 'Set query result limit',
551
+ description: 'Set max rows returned for query result previews',
552
+ group: 'SQL Editor',
553
+ keywords: ['sql', 'limit', 'rows', 'result'],
554
+ inputSchema: SqlEditorResultLimitInput,
555
+ inputDescription: 'Provide positive integer limit.',
556
+ metadata: {
557
+ readOnly: false,
558
+ idempotent: true,
559
+ riskLevel: 'low',
560
+ },
561
+ execute: ({ getState }, input) => {
562
+ const { limit } = input;
563
+ getState().sqlEditor.setQueryResultLimit(limit);
564
+ return {
565
+ success: true,
566
+ commandId: 'sql-editor.set-result-limit',
567
+ message: `Set query result limit to ${limit}.`,
568
+ };
569
+ },
570
+ },
571
+ ];
572
+ }
314
573
  export function useStoreWithSqlEditor(selector) {
315
574
  return useBaseRoomShellStore((state) => selector(state));
316
575
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SqlEditorSlice.js","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n DuckDbSliceState,\n getSqlErrorWithPointer,\n joinStatements,\n makeLimitQuery,\n separateLastStatement,\n} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n RoomShellSliceState,\n StateCreator,\n useBaseRoomShellStore,\n} from '@sqlrooms/room-shell';\nimport {\n createDefaultSqlEditorConfig,\n SqlEditorSliceConfig,\n} from '@sqlrooms/sql-editor-config';\nimport {generateUniqueName} from '@sqlrooms/utils';\nimport * as arrow from 'apache-arrow';\nimport {csvFormat} from 'd3-dsv';\nimport {saveAs} from 'file-saver';\nimport {produce} from 'immer';\n\nexport type QueryResult =\n | {status: 'loading'; isBeingAborted?: boolean; controller: AbortController}\n | {status: 'aborted'}\n | {status: 'error'; error: string}\n | {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n result: arrow.Table | undefined;\n query: string;\n lastQueryStatement: string;\n }\n | {\n status: 'success';\n type: 'exec';\n query: string;\n lastQueryStatement: string;\n };\n\nexport function isQueryWithResult(\n queryResult: QueryResult | undefined,\n): queryResult is QueryResult & {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n} {\n return (\n queryResult?.status === 'success' &&\n (queryResult.type === 'pragma' ||\n queryResult.type === 'explain' ||\n queryResult.type === 'select')\n );\n}\n\nexport type SqlEditorSliceState = {\n sqlEditor: {\n config: SqlEditorSliceConfig;\n // Runtime state\n /**\n * Query results keyed by queryId (tab id).\n */\n queryResultsById: Record<string, QueryResult | undefined>;\n /** @deprecated */\n selectedTable?: string;\n /** @deprecated Use `useStoreWithSqlEditor((s) => s.db.isRefreshingTableSchemas)` instead. */\n isTablesLoading: boolean;\n /** @deprecated */\n tablesError?: string;\n\n queryResultLimit: number;\n /** Options for the result limit dropdown */\n queryResultLimitOptions: number[];\n\n /**\n * Set the config for the sql editor slice.\n */\n setConfig(config: SqlEditorSliceConfig): void;\n\n /**\n * Run the currently selected query.\n */\n parseAndRunQuery(query: string): Promise<void>;\n\n /**\n * Run the currently selected query.\n */\n parseAndRunCurrentQuery(): Promise<void>;\n\n /**\n * Abort the currently running query.\n */\n abortCurrentQuery(): void;\n\n /**\n * Export query results to CSV.\n * @deprecated Use `useExportToCsv` from `@sqlrooms/duckdb` instead.\n */\n exportResultsToCsv(results: arrow.Table, filename?: string): void;\n\n /**\n * Create a new query tab.\n * @param initialQuery - Optional initial query text.\n */\n createQueryTab(initialQuery?: string): {\n id: string;\n name: string;\n query: string;\n };\n\n /**\n * Delete a query tab.\n * @param queryId - The ID of the query to delete.\n */\n deleteQueryTab(queryId: string): void;\n\n /**\n * Rename a query tab.\n * @param queryId - The ID of the query to rename.\n * @param newName - The new name for the query.\n */\n renameQueryTab(queryId: string, newName: string): void;\n\n /**\n * Close a query tab.\n * @param queryId - The ID of the query to close.\n */\n closeQueryTab(queryId: string): void;\n\n /**\n * Open a closed tab id.\n * @param queryId - The ID of the query to open.\n */\n openQueryTab(queryId: string): void;\n\n /**\n * Set the list of open tab IDs. Used for reordering or opening tabs.\n * @param tabIds - The new list of open tab IDs.\n */\n setOpenTabs(tabIds: string[]): void;\n\n /**\n * Update the SQL text for a query.\n * @param queryId - The ID of the query to update.\n * @param queryText - The new SQL text.\n */\n updateQueryText(queryId: string, queryText: string): void;\n\n /**\n * Set the selected query tab.\n * @param queryId - The ID of the query to select.\n */\n setSelectedQueryId(queryId: string): void;\n\n /**\n * Get the currently selected query's SQL text.\n */\n getCurrentQuery(): string;\n\n /** @deprecated */\n selectTable(table: string | undefined): void;\n\n clearQueryResults(): void;\n\n setQueryResultLimit(limit: number): void;\n };\n};\n\nexport function createSqlEditorSlice({\n config = createDefaultSqlEditorConfig(),\n queryResultLimit = 100,\n queryResultLimitOptions = [100, 500, 1000],\n}: {\n config?: SqlEditorSliceConfig;\n queryResultLimit?: number;\n queryResultLimitOptions?: number[];\n} = {}): StateCreator<SqlEditorSliceState> {\n return createSlice<\n SqlEditorSliceState,\n BaseRoomStoreState & DuckDbSliceState & SqlEditorSliceState\n >((set, get) => {\n return {\n sqlEditor: {\n config,\n // Initialize runtime state\n queryResultsById: {},\n isTablesLoading: false,\n queryResultLimit,\n queryResultLimitOptions,\n\n setConfig: (config) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config = config;\n }),\n );\n },\n\n exportResultsToCsv: (results, filename) => {\n if (!results) return;\n const blob = new Blob([csvFormat(results.toArray())], {\n type: 'text/plain;charset=utf-8',\n });\n saveAs(blob, filename || `export-${createId().substring(0, 5)}.csv`);\n },\n\n createQueryTab: (initialQuery = '') => {\n const sqlEditorConfig = get().sqlEditor.config;\n const now = Date.now();\n const newQuery = {\n id: createId(),\n name: generateUniqueName(\n 'Untitled',\n sqlEditorConfig.queries.map((q) => q.name),\n ),\n query: initialQuery,\n lastOpenedAt: now,\n };\n\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.queries.push(newQuery);\n draft.sqlEditor.config.openTabs.push(newQuery.id);\n draft.sqlEditor.config.selectedQueryId = newQuery.id;\n }),\n );\n\n return newQuery;\n },\n\n deleteQueryTab: (queryId) => {\n const sqlEditorConfig = get().sqlEditor.config;\n const queries = sqlEditorConfig.queries;\n const openTabs = sqlEditorConfig.openTabs;\n\n if (queries.length <= 1) {\n // Don't delete the last query\n return;\n }\n\n const wasSelected = sqlEditorConfig.selectedQueryId === queryId;\n const deletingOpenIndex = openTabs.indexOf(queryId);\n const filteredQueries = queries.filter((q) => q.id !== queryId);\n\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.queries = filteredQueries;\n draft.sqlEditor.config.openTabs = openTabs.filter(\n (id) => id !== queryId,\n );\n const {[queryId]: _removed, ...rest} =\n draft.sqlEditor.queryResultsById;\n draft.sqlEditor.queryResultsById = rest;\n\n // If we deleted the selected query, select another one\n if (wasSelected) {\n const newOpenTabs = draft.sqlEditor.config.openTabs;\n const remainingQueries = draft.sqlEditor.config.queries;\n\n if (newOpenTabs.length > 0) {\n // Select from remaining open tabs\n const newIndex =\n deletingOpenIndex === 0\n ? 0\n : Math.min(deletingOpenIndex - 1, newOpenTabs.length - 1);\n const newSelectedId = newOpenTabs[newIndex];\n if (newSelectedId) {\n draft.sqlEditor.config.selectedQueryId = newSelectedId;\n const newSelectedQuery =\n draft.sqlEditor.config.queries.find(\n (q) => q.id === newSelectedId,\n );\n if (newSelectedQuery) {\n newSelectedQuery.lastOpenedAt = Date.now();\n }\n }\n } else if (remainingQueries.length > 0) {\n // No open tabs left, open a closed query\n const queryToOpen = remainingQueries[0];\n if (queryToOpen) {\n draft.sqlEditor.config.openTabs.push(queryToOpen.id);\n draft.sqlEditor.config.selectedQueryId = queryToOpen.id;\n queryToOpen.lastOpenedAt = Date.now();\n }\n }\n }\n }),\n );\n },\n\n renameQueryTab: (queryId, newName) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.name = newName || query.name;\n }\n }),\n );\n },\n\n closeQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.openTabs =\n draft.sqlEditor.config.openTabs.filter((id) => id !== queryId);\n }),\n );\n },\n\n openQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n if (!draft.sqlEditor.config.openTabs.includes(queryId)) {\n draft.sqlEditor.config.openTabs.push(queryId);\n }\n draft.sqlEditor.config.selectedQueryId = queryId;\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.lastOpenedAt = Date.now();\n }\n }),\n );\n },\n\n setOpenTabs: (tabIds) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.openTabs = tabIds;\n }),\n );\n },\n\n updateQueryText: (queryId, queryText) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.query = queryText;\n }\n }),\n );\n },\n\n setSelectedQueryId: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.selectedQueryId = queryId;\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.lastOpenedAt = Date.now();\n }\n }),\n );\n },\n\n getCurrentQuery: () => {\n const sqlEditorConfig = get().sqlEditor.config;\n const selectedId = sqlEditorConfig.selectedQueryId;\n const query = sqlEditorConfig.queries.find(\n (q) => q.id === selectedId,\n );\n return query?.query || '';\n },\n\n /** @deprecated */\n selectTable: (table) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = table;\n }),\n );\n },\n\n clearQueryResults: () => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.queryResultsById = {};\n }),\n );\n },\n\n parseAndRunCurrentQuery: async (): Promise<void> =>\n get().sqlEditor.parseAndRunQuery(get().sqlEditor.getCurrentQuery()),\n\n abortCurrentQuery: () => {\n const selectedQueryId = get().sqlEditor.config.selectedQueryId;\n const currentResult =\n get().sqlEditor.queryResultsById[selectedQueryId];\n if (currentResult?.status === 'loading' && currentResult.controller) {\n currentResult.controller.abort();\n }\n\n set((state) =>\n produce(state, (draft) => {\n const result = draft.sqlEditor.queryResultsById[selectedQueryId];\n if (result?.status === 'loading') {\n result.isBeingAborted = true;\n }\n }),\n );\n },\n\n setQueryResultLimit: (limit) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.queryResultLimit = limit;\n }),\n );\n },\n\n parseAndRunQuery: async (query): Promise<void> => {\n const selectedQueryId = get().sqlEditor.config.selectedQueryId;\n const existingResult =\n get().sqlEditor.queryResultsById[selectedQueryId];\n if (existingResult?.status === 'loading') {\n throw new Error('Query already running');\n }\n if (!query.trim()) {\n return;\n }\n\n // Create abort controller for this query execution\n const queryController = new AbortController();\n\n // First update loading state and clear results\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = undefined;\n draft.sqlEditor.queryResultsById[selectedQueryId] = {\n status: 'loading',\n isBeingAborted: false,\n controller: queryController,\n };\n }),\n );\n\n let queryResult: QueryResult;\n try {\n const connector = await get().db.getConnector();\n const signal = queryController.signal;\n\n const {precedingStatements, lastStatement: lastQueryStatement} =\n separateLastStatement(query);\n const hasMultipleStatements = precedingStatements.length > 0;\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const parsedLastStatement =\n await get().db.sqlSelectToJson(lastQueryStatement);\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const isValidSelectQuery = !parsedLastStatement.error;\n\n if (isValidSelectQuery) {\n // Add limit to the last statement\n const limitedLastStatement = makeLimitQuery(lastQueryStatement, {\n sanitize: false, // should already be sanitized\n limit: get().sqlEditor.queryResultLimit,\n });\n const queryWithLimit = joinStatements(\n precedingStatements,\n limitedLastStatement,\n );\n const result = await connector.query(queryWithLimit, {signal});\n queryResult = {\n status: 'success',\n type: 'select',\n query,\n lastQueryStatement,\n result,\n };\n } else {\n // Run the complete query as it is\n if (\n parsedLastStatement.error &&\n parsedLastStatement.error_type !== 'not implemented'\n ) {\n throw (\n `${parsedLastStatement.error_type} ${parsedLastStatement.error_subtype}: ${parsedLastStatement.error_message}` +\n `\\n${getSqlErrorWithPointer(lastQueryStatement, Number(parsedLastStatement.position)).formatted}`\n );\n }\n\n const result = await connector.query(query, {signal});\n // EXPLAIN and PRAGMA are not detected as select queries\n // and we cannot wrap them in a SELECT * FROM,\n // but we can still execute them and return the result\n if (/^(EXPLAIN)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'explain',\n query,\n lastQueryStatement,\n result,\n };\n } else if (/^(PRAGMA)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'pragma',\n query,\n lastQueryStatement,\n result,\n };\n } else {\n queryResult = {\n status: 'success',\n type: 'exec',\n query,\n lastQueryStatement,\n };\n }\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n // Refresh table schemas if there are multiple statements or if the\n // last statement is not a select query\n if (hasMultipleStatements || !isValidSelectQuery) {\n get().db.refreshTableSchemas();\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n } catch (e) {\n console.error(e);\n const errorMessage = e instanceof Error ? e.message : String(e);\n if (\n errorMessage === 'Query aborted' ||\n queryController.signal.aborted\n ) {\n queryResult = {status: 'aborted'};\n } else {\n queryResult = {\n status: 'error',\n error: errorMessage,\n };\n }\n }\n\n // Update state without Immer since Arrow Tables don't play well with drafts.\n set((state) => ({\n ...state,\n sqlEditor: {\n ...state.sqlEditor,\n queryResultsById: {\n ...state.sqlEditor.queryResultsById,\n [selectedQueryId]: queryResult,\n },\n },\n }));\n },\n },\n } satisfies SqlEditorSliceState;\n });\n}\n\ntype RoomStateWithSqlEditor = RoomShellSliceState & SqlEditorSliceState;\n\nexport function useStoreWithSqlEditor<T>(\n selector: (state: RoomStateWithSqlEditor) => T,\n): T {\n return useBaseRoomShellStore<RoomShellSliceState, T>((state) =>\n selector(state as unknown as RoomStateWithSqlEditor),\n );\n}\n"]}
1
+ {"version":3,"file":"SqlEditorSlice.js","sourceRoot":"","sources":["../src/SqlEditorSlice.tsx"],"names":[],"mappings":"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","sourcesContent":["import {createId} from '@paralleldrive/cuid2';\nimport {\n DuckDbSliceState,\n getSqlErrorWithPointer,\n joinStatements,\n makeLimitQuery,\n separateLastStatement,\n} from '@sqlrooms/duckdb';\nimport {\n BaseRoomStoreState,\n createSlice,\n registerCommandsForOwner,\n RoomCommand,\n RoomShellSliceState,\n StateCreator,\n unregisterCommandsForOwner,\n useBaseRoomShellStore,\n} from '@sqlrooms/room-shell';\nimport {\n createDefaultSqlEditorConfig,\n SqlEditorSliceConfig,\n} from '@sqlrooms/sql-editor-config';\nimport {generateUniqueName} from '@sqlrooms/utils';\nimport * as arrow from 'apache-arrow';\nimport {csvFormat} from 'd3-dsv';\nimport {saveAs} from 'file-saver';\nimport {produce} from 'immer';\nimport {z} from 'zod';\n\nconst SQL_EDITOR_COMMAND_OWNER = '@sqlrooms/sql-editor';\n\nexport type QueryResult =\n | {status: 'loading'; isBeingAborted?: boolean; controller: AbortController}\n | {status: 'aborted'}\n | {status: 'error'; error: string}\n | {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n result: arrow.Table | undefined;\n query: string;\n lastQueryStatement: string;\n }\n | {\n status: 'success';\n type: 'exec';\n query: string;\n lastQueryStatement: string;\n };\n\nexport function isQueryWithResult(\n queryResult: QueryResult | undefined,\n): queryResult is QueryResult & {\n status: 'success';\n type: 'pragma' | 'explain' | 'select';\n} {\n return (\n queryResult?.status === 'success' &&\n (queryResult.type === 'pragma' ||\n queryResult.type === 'explain' ||\n queryResult.type === 'select')\n );\n}\n\nexport type SqlEditorSliceState = {\n sqlEditor: {\n initialize?: () => Promise<void>;\n destroy?: () => Promise<void>;\n config: SqlEditorSliceConfig;\n // Runtime state\n /**\n * Query results keyed by queryId (tab id).\n */\n queryResultsById: Record<string, QueryResult | undefined>;\n /** @deprecated */\n selectedTable?: string;\n /** @deprecated Use `useStoreWithSqlEditor((s) => s.db.isRefreshingTableSchemas)` instead. */\n isTablesLoading: boolean;\n /** @deprecated */\n tablesError?: string;\n\n queryResultLimit: number;\n /** Options for the result limit dropdown */\n queryResultLimitOptions: number[];\n\n /**\n * Set the config for the sql editor slice.\n */\n setConfig(config: SqlEditorSliceConfig): void;\n\n /**\n * Run the currently selected query.\n */\n parseAndRunQuery(query: string): Promise<void>;\n\n /**\n * Run the currently selected query.\n */\n parseAndRunCurrentQuery(): Promise<void>;\n\n /**\n * Abort the currently running query.\n */\n abortCurrentQuery(): void;\n\n /**\n * Export query results to CSV.\n * @deprecated Use `useExportToCsv` from `@sqlrooms/duckdb` instead.\n */\n exportResultsToCsv(results: arrow.Table, filename?: string): void;\n\n /**\n * Create a new query tab.\n * @param initialQuery - Optional initial query text.\n */\n createQueryTab(initialQuery?: string): {\n id: string;\n name: string;\n query: string;\n };\n\n /**\n * Delete a query tab.\n * @param queryId - The ID of the query to delete.\n */\n deleteQueryTab(queryId: string): void;\n\n /**\n * Rename a query tab.\n * @param queryId - The ID of the query to rename.\n * @param newName - The new name for the query.\n */\n renameQueryTab(queryId: string, newName: string): void;\n\n /**\n * Close a query tab.\n * @param queryId - The ID of the query to close.\n */\n closeQueryTab(queryId: string): void;\n\n /**\n * Open a closed tab id.\n * @param queryId - The ID of the query to open.\n */\n openQueryTab(queryId: string): void;\n\n /**\n * Set the list of open tab IDs. Used for reordering or opening tabs.\n * @param tabIds - The new list of open tab IDs.\n */\n setOpenTabs(tabIds: string[]): void;\n\n /**\n * Update the SQL text for a query.\n * @param queryId - The ID of the query to update.\n * @param queryText - The new SQL text.\n */\n updateQueryText(queryId: string, queryText: string): void;\n\n /**\n * Set the selected query tab.\n * @param queryId - The ID of the query to select.\n */\n setSelectedQueryId(queryId: string): void;\n\n /**\n * Get the currently selected query's SQL text.\n */\n getCurrentQuery(): string;\n\n /** @deprecated */\n selectTable(table: string | undefined): void;\n\n clearQueryResults(): void;\n\n setQueryResultLimit(limit: number): void;\n };\n};\n\nexport function createSqlEditorSlice({\n config = createDefaultSqlEditorConfig(),\n queryResultLimit = 100,\n queryResultLimitOptions = [100, 500, 1000],\n}: {\n config?: SqlEditorSliceConfig;\n queryResultLimit?: number;\n queryResultLimitOptions?: number[];\n} = {}): StateCreator<SqlEditorSliceState> {\n return createSlice<\n SqlEditorSliceState,\n BaseRoomStoreState & DuckDbSliceState & SqlEditorSliceState\n >((set, get, store) => {\n return {\n sqlEditor: {\n initialize: async () => {\n registerCommandsForOwner(\n store,\n SQL_EDITOR_COMMAND_OWNER,\n createSqlEditorCommands(),\n );\n },\n destroy: async () => {\n unregisterCommandsForOwner(store, SQL_EDITOR_COMMAND_OWNER);\n },\n config,\n // Initialize runtime state\n queryResultsById: {},\n isTablesLoading: false,\n queryResultLimit,\n queryResultLimitOptions,\n\n setConfig: (config) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config = config;\n }),\n );\n },\n\n exportResultsToCsv: (results, filename) => {\n if (!results) return;\n const blob = new Blob([csvFormat(results.toArray())], {\n type: 'text/plain;charset=utf-8',\n });\n saveAs(blob, filename || `export-${createId().substring(0, 5)}.csv`);\n },\n\n createQueryTab: (initialQuery = '') => {\n const sqlEditorConfig = get().sqlEditor.config;\n const now = Date.now();\n const newQuery = {\n id: createId(),\n name: generateUniqueName(\n 'Untitled',\n sqlEditorConfig.queries.map((q) => q.name),\n ),\n query: initialQuery,\n lastOpenedAt: now,\n };\n\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.queries.push(newQuery);\n draft.sqlEditor.config.openTabs.push(newQuery.id);\n draft.sqlEditor.config.selectedQueryId = newQuery.id;\n }),\n );\n\n return newQuery;\n },\n\n deleteQueryTab: (queryId) => {\n const sqlEditorConfig = get().sqlEditor.config;\n const queries = sqlEditorConfig.queries;\n const openTabs = sqlEditorConfig.openTabs;\n\n if (queries.length <= 1) {\n // Don't delete the last query\n return;\n }\n\n const wasSelected = sqlEditorConfig.selectedQueryId === queryId;\n const deletingOpenIndex = openTabs.indexOf(queryId);\n const filteredQueries = queries.filter((q) => q.id !== queryId);\n\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.queries = filteredQueries;\n draft.sqlEditor.config.openTabs = openTabs.filter(\n (id) => id !== queryId,\n );\n const {[queryId]: _removed, ...rest} =\n draft.sqlEditor.queryResultsById;\n draft.sqlEditor.queryResultsById = rest;\n\n // If we deleted the selected query, select another one\n if (wasSelected) {\n const newOpenTabs = draft.sqlEditor.config.openTabs;\n const remainingQueries = draft.sqlEditor.config.queries;\n\n if (newOpenTabs.length > 0) {\n // Select from remaining open tabs\n const newIndex =\n deletingOpenIndex === 0\n ? 0\n : Math.min(deletingOpenIndex - 1, newOpenTabs.length - 1);\n const newSelectedId = newOpenTabs[newIndex];\n if (newSelectedId) {\n draft.sqlEditor.config.selectedQueryId = newSelectedId;\n const newSelectedQuery =\n draft.sqlEditor.config.queries.find(\n (q) => q.id === newSelectedId,\n );\n if (newSelectedQuery) {\n newSelectedQuery.lastOpenedAt = Date.now();\n }\n }\n } else if (remainingQueries.length > 0) {\n // No open tabs left, open a closed query\n const queryToOpen = remainingQueries[0];\n if (queryToOpen) {\n draft.sqlEditor.config.openTabs.push(queryToOpen.id);\n draft.sqlEditor.config.selectedQueryId = queryToOpen.id;\n queryToOpen.lastOpenedAt = Date.now();\n }\n }\n }\n }),\n );\n },\n\n renameQueryTab: (queryId, newName) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.name = newName || query.name;\n }\n }),\n );\n },\n\n closeQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.openTabs =\n draft.sqlEditor.config.openTabs.filter((id) => id !== queryId);\n }),\n );\n },\n\n openQueryTab: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n if (!draft.sqlEditor.config.openTabs.includes(queryId)) {\n draft.sqlEditor.config.openTabs.push(queryId);\n }\n draft.sqlEditor.config.selectedQueryId = queryId;\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.lastOpenedAt = Date.now();\n }\n }),\n );\n },\n\n setOpenTabs: (tabIds) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.openTabs = tabIds;\n }),\n );\n },\n\n updateQueryText: (queryId, queryText) => {\n set((state) =>\n produce(state, (draft) => {\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.query = queryText;\n }\n }),\n );\n },\n\n setSelectedQueryId: (queryId) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.config.selectedQueryId = queryId;\n const query = draft.sqlEditor.config.queries.find(\n (q) => q.id === queryId,\n );\n if (query) {\n query.lastOpenedAt = Date.now();\n }\n }),\n );\n },\n\n getCurrentQuery: () => {\n const sqlEditorConfig = get().sqlEditor.config;\n const selectedId = sqlEditorConfig.selectedQueryId;\n const query = sqlEditorConfig.queries.find(\n (q) => q.id === selectedId,\n );\n return query?.query || '';\n },\n\n /** @deprecated */\n selectTable: (table) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = table;\n }),\n );\n },\n\n clearQueryResults: () => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.queryResultsById = {};\n }),\n );\n },\n\n parseAndRunCurrentQuery: async (): Promise<void> =>\n get().sqlEditor.parseAndRunQuery(get().sqlEditor.getCurrentQuery()),\n\n abortCurrentQuery: () => {\n const selectedQueryId = get().sqlEditor.config.selectedQueryId;\n const currentResult =\n get().sqlEditor.queryResultsById[selectedQueryId];\n if (currentResult?.status === 'loading' && currentResult.controller) {\n currentResult.controller.abort();\n }\n\n set((state) =>\n produce(state, (draft) => {\n const result = draft.sqlEditor.queryResultsById[selectedQueryId];\n if (result?.status === 'loading') {\n result.isBeingAborted = true;\n }\n }),\n );\n },\n\n setQueryResultLimit: (limit) => {\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.queryResultLimit = limit;\n }),\n );\n },\n\n parseAndRunQuery: async (query): Promise<void> => {\n const selectedQueryId = get().sqlEditor.config.selectedQueryId;\n const existingResult =\n get().sqlEditor.queryResultsById[selectedQueryId];\n if (existingResult?.status === 'loading') {\n throw new Error('Query already running');\n }\n if (!query.trim()) {\n return;\n }\n\n // Create abort controller for this query execution\n const queryController = new AbortController();\n\n // First update loading state and clear results\n set((state) =>\n produce(state, (draft) => {\n draft.sqlEditor.selectedTable = undefined;\n draft.sqlEditor.queryResultsById[selectedQueryId] = {\n status: 'loading',\n isBeingAborted: false,\n controller: queryController,\n };\n }),\n );\n\n let queryResult: QueryResult;\n try {\n const connector = await get().db.getConnector();\n const signal = queryController.signal;\n\n const {precedingStatements, lastStatement: lastQueryStatement} =\n separateLastStatement(query);\n const hasMultipleStatements = precedingStatements.length > 0;\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const parsedLastStatement =\n await get().db.sqlSelectToJson(lastQueryStatement);\n\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n\n const isValidSelectQuery = !parsedLastStatement.error;\n\n if (isValidSelectQuery) {\n // Add limit to the last statement\n const limitedLastStatement = makeLimitQuery(lastQueryStatement, {\n sanitize: false, // should already be sanitized\n limit: get().sqlEditor.queryResultLimit,\n });\n const queryWithLimit = joinStatements(\n precedingStatements,\n limitedLastStatement,\n );\n const result = await connector.query(queryWithLimit, {signal});\n queryResult = {\n status: 'success',\n type: 'select',\n query,\n lastQueryStatement,\n result,\n };\n } else {\n // Run the complete query as it is\n if (\n parsedLastStatement.error &&\n parsedLastStatement.error_type !== 'not implemented'\n ) {\n throw (\n `${parsedLastStatement.error_type} ${parsedLastStatement.error_subtype}: ${parsedLastStatement.error_message}` +\n `\\n${getSqlErrorWithPointer(lastQueryStatement, Number(parsedLastStatement.position)).formatted}`\n );\n }\n\n const result = await connector.query(query, {signal});\n // EXPLAIN and PRAGMA are not detected as select queries\n // and we cannot wrap them in a SELECT * FROM,\n // but we can still execute them and return the result\n if (/^(EXPLAIN)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'explain',\n query,\n lastQueryStatement,\n result,\n };\n } else if (/^(PRAGMA)/i.test(lastQueryStatement)) {\n queryResult = {\n status: 'success',\n type: 'pragma',\n query,\n lastQueryStatement,\n result,\n };\n } else {\n queryResult = {\n status: 'success',\n type: 'exec',\n query,\n lastQueryStatement,\n };\n }\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n // Refresh table schemas if there are multiple statements or if the\n // last statement is not a select query\n if (hasMultipleStatements || !isValidSelectQuery) {\n get().db.refreshTableSchemas();\n }\n if (signal.aborted) {\n throw new Error('Query aborted');\n }\n } catch (e) {\n console.error(e);\n const errorMessage = e instanceof Error ? e.message : String(e);\n if (\n errorMessage === 'Query aborted' ||\n queryController.signal.aborted\n ) {\n queryResult = {status: 'aborted'};\n } else {\n queryResult = {\n status: 'error',\n error: errorMessage,\n };\n }\n }\n\n // Update state without Immer since Arrow Tables don't play well with drafts.\n set((state) => ({\n ...state,\n sqlEditor: {\n ...state.sqlEditor,\n queryResultsById: {\n ...state.sqlEditor.queryResultsById,\n [selectedQueryId]: queryResult,\n },\n },\n }));\n },\n },\n } satisfies SqlEditorSliceState;\n });\n}\n\ntype RoomStateWithSqlEditor = RoomShellSliceState & SqlEditorSliceState;\n\ntype SqlEditorCommandStoreState = BaseRoomStoreState &\n DuckDbSliceState &\n SqlEditorSliceState;\n\nconst SqlEditorRunQueryCommandInput = z.object({\n query: z.string().describe('SQL query text to run.'),\n});\ntype SqlEditorRunQueryCommandInput = z.infer<\n typeof SqlEditorRunQueryCommandInput\n>;\n\nconst SqlEditorTabIdInput = z.object({\n queryId: z.string().describe('ID of the query tab.'),\n});\ntype SqlEditorTabIdInput = z.infer<typeof SqlEditorTabIdInput>;\n\nconst SqlEditorRenameTabInput = z.object({\n queryId: z.string().describe('ID of the query tab to rename.'),\n name: z.string().min(1).describe('New tab name.'),\n});\ntype SqlEditorRenameTabInput = z.infer<typeof SqlEditorRenameTabInput>;\n\nconst SqlEditorResultLimitInput = z.object({\n limit: z.number().int().positive().describe('Row limit for query results.'),\n});\ntype SqlEditorResultLimitInput = z.infer<typeof SqlEditorResultLimitInput>;\n\nfunction createSqlEditorCommands(): RoomCommand<SqlEditorCommandStoreState>[] {\n const ensureQueryTabExists = (\n state: SqlEditorCommandStoreState,\n queryId: string,\n ) => {\n if (!state.sqlEditor.config.queries.some((query) => query.id === queryId)) {\n throw new Error(`Unknown query tab \"${queryId}\".`);\n }\n };\n\n return [\n {\n id: 'sql-editor.run-current-query',\n name: 'Run current query',\n description: 'Execute the selected SQL query tab',\n group: 'SQL Editor',\n keywords: ['sql', 'run', 'execute', 'query'],\n metadata: {\n readOnly: false,\n idempotent: false,\n riskLevel: 'medium',\n },\n ui: {\n keystrokes: 'Mod+Enter',\n },\n isEnabled: ({getState}) => {\n const state = getState();\n const selectedQueryId = state.sqlEditor.config.selectedQueryId;\n const queryResult = state.sqlEditor.queryResultsById[selectedQueryId];\n return (\n queryResult?.status !== 'loading' &&\n state.sqlEditor.getCurrentQuery().trim().length > 0\n );\n },\n execute: async ({getState}) => {\n await getState().sqlEditor.parseAndRunCurrentQuery();\n return {\n success: true,\n commandId: 'sql-editor.run-current-query',\n message: 'Executed current query.',\n };\n },\n },\n {\n id: 'sql-editor.run-query',\n name: 'Run query text',\n description: 'Execute an explicitly provided SQL query',\n group: 'SQL Editor',\n keywords: ['sql', 'run', 'execute', 'query', 'text'],\n inputSchema: SqlEditorRunQueryCommandInput,\n inputDescription: 'Provide query SQL to execute.',\n metadata: {\n readOnly: false,\n idempotent: false,\n riskLevel: 'medium',\n },\n execute: async ({getState}, input) => {\n const {query} = input as SqlEditorRunQueryCommandInput;\n await getState().sqlEditor.parseAndRunQuery(query);\n return {\n success: true,\n commandId: 'sql-editor.run-query',\n message: 'Executed SQL query.',\n };\n },\n },\n {\n id: 'sql-editor.abort-current-query',\n name: 'Abort current query',\n description: 'Cancel the currently running SQL query',\n group: 'SQL Editor',\n keywords: ['sql', 'abort', 'cancel', 'query'],\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'low',\n },\n isEnabled: ({getState}) => {\n const state = getState();\n const selectedQueryId = state.sqlEditor.config.selectedQueryId;\n return (\n state.sqlEditor.queryResultsById[selectedQueryId]?.status ===\n 'loading'\n );\n },\n execute: ({getState}) => {\n getState().sqlEditor.abortCurrentQuery();\n return {\n success: true,\n commandId: 'sql-editor.abort-current-query',\n message: 'Abort signal sent to current query.',\n };\n },\n },\n {\n id: 'sql-editor.create-query-tab',\n name: 'Create query tab',\n description: 'Open a new SQL query tab',\n group: 'SQL Editor',\n keywords: ['sql', 'tab', 'new', 'query'],\n metadata: {\n readOnly: false,\n idempotent: false,\n riskLevel: 'low',\n },\n execute: ({getState}) => {\n const newTab = getState().sqlEditor.createQueryTab();\n return {\n success: true,\n commandId: 'sql-editor.create-query-tab',\n message: `Created query tab \"${newTab.name}\".`,\n data: {\n queryId: newTab.id,\n },\n };\n },\n },\n {\n id: 'sql-editor.select-query-tab',\n name: 'Select query tab',\n description: 'Switch active SQL query tab by ID',\n group: 'SQL Editor',\n keywords: ['sql', 'tab', 'select', 'switch'],\n inputSchema: SqlEditorTabIdInput,\n inputDescription: 'Provide queryId to activate.',\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'low',\n },\n validateInput: (input, {getState}) => {\n ensureQueryTabExists(\n getState(),\n (input as SqlEditorTabIdInput).queryId,\n );\n },\n execute: ({getState}, input) => {\n const {queryId} = input as SqlEditorTabIdInput;\n getState().sqlEditor.setSelectedQueryId(queryId);\n return {\n success: true,\n commandId: 'sql-editor.select-query-tab',\n message: `Selected query tab \"${queryId}\".`,\n };\n },\n },\n {\n id: 'sql-editor.rename-query-tab',\n name: 'Rename query tab',\n description: 'Rename a SQL query tab by ID',\n group: 'SQL Editor',\n keywords: ['sql', 'tab', 'rename'],\n inputSchema: SqlEditorRenameTabInput,\n inputDescription: 'Provide queryId and name.',\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'low',\n },\n validateInput: (input, {getState}) => {\n ensureQueryTabExists(\n getState(),\n (input as SqlEditorRenameTabInput).queryId,\n );\n },\n execute: ({getState}, input) => {\n const {queryId, name} = input as SqlEditorRenameTabInput;\n getState().sqlEditor.renameQueryTab(queryId, name);\n return {\n success: true,\n commandId: 'sql-editor.rename-query-tab',\n message: `Renamed query tab \"${queryId}\".`,\n };\n },\n },\n {\n id: 'sql-editor.delete-query-tab',\n name: 'Delete query tab',\n description: 'Delete a SQL query tab by ID',\n group: 'SQL Editor',\n keywords: ['sql', 'tab', 'delete', 'remove'],\n inputSchema: SqlEditorTabIdInput,\n inputDescription: 'Provide queryId to delete.',\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'medium',\n requiresConfirmation: true,\n },\n validateInput: (input, {getState}) => {\n const state = getState();\n ensureQueryTabExists(state, (input as SqlEditorTabIdInput).queryId);\n if (state.sqlEditor.config.queries.length <= 1) {\n throw new Error('Cannot delete the last remaining query tab.');\n }\n },\n execute: ({getState}, input) => {\n const {queryId} = input as SqlEditorTabIdInput;\n getState().sqlEditor.deleteQueryTab(queryId);\n return {\n success: true,\n commandId: 'sql-editor.delete-query-tab',\n message: `Deleted query tab \"${queryId}\".`,\n };\n },\n },\n {\n id: 'sql-editor.clear-query-results',\n name: 'Clear query results',\n description: 'Clear all cached SQL query results',\n group: 'SQL Editor',\n keywords: ['sql', 'clear', 'results'],\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'low',\n },\n isEnabled: ({getState}) =>\n Object.keys(getState().sqlEditor.queryResultsById).length > 0,\n execute: ({getState}) => {\n getState().sqlEditor.clearQueryResults();\n return {\n success: true,\n commandId: 'sql-editor.clear-query-results',\n message: 'Cleared query results.',\n };\n },\n },\n {\n id: 'sql-editor.set-result-limit',\n name: 'Set query result limit',\n description: 'Set max rows returned for query result previews',\n group: 'SQL Editor',\n keywords: ['sql', 'limit', 'rows', 'result'],\n inputSchema: SqlEditorResultLimitInput,\n inputDescription: 'Provide positive integer limit.',\n metadata: {\n readOnly: false,\n idempotent: true,\n riskLevel: 'low',\n },\n execute: ({getState}, input) => {\n const {limit} = input as SqlEditorResultLimitInput;\n getState().sqlEditor.setQueryResultLimit(limit);\n return {\n success: true,\n commandId: 'sql-editor.set-result-limit',\n message: `Set query result limit to ${limit}.`,\n };\n },\n },\n ];\n}\n\nexport function useStoreWithSqlEditor<T>(\n selector: (state: RoomStateWithSqlEditor) => T,\n): T {\n return useBaseRoomShellStore<RoomShellSliceState, T>((state) =>\n selector(state as unknown as RoomStateWithSqlEditor),\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"RenameSqlQueryModal.d.ts","sourceRoot":"","sources":["../../src/components/RenameSqlQueryModal.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAWvC,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAyDA,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"RenameSqlQueryModal.d.ts","sourceRoot":"","sources":["../../src/components/RenameSqlQueryModal.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAWvC,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAwDA,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -9,7 +9,6 @@ const formSchema = z.object({
9
9
  });
10
10
  const RenameSqlQueryModal = ({ isOpen, onClose, initialName, onRename }) => {
11
11
  const form = useForm({
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
12
  resolver: zodResolver(formSchema),
14
13
  defaultValues: {
15
14
  queryName: initialName,
@@ -1 +1 @@
1
- {"version":3,"file":"RenameSqlQueryModal.js","sourceRoot":"","sources":["../../src/components/RenameSqlQueryModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,MAAM,EACN,IAAI,EACJ,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAc,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACvC,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAEpD,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;CACvD,CAAC,CAAC;AAIH,MAAM,mBAAmB,GAKpB,CAAC,EAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAC,EAAE,EAAE;IAChD,MAAM,IAAI,GAAG,OAAO,CAAW;QAC7B,8DAA8D;QAC9D,QAAQ,EAAE,WAAW,CAAC,UAAiB,CAAC;QACxC,aAAa,EAAE;YACb,SAAS,EAAE,WAAW;SACvB;KACF,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,WAAW,EAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IAEhC,SAAS,QAAQ,CAAC,MAAgB;QAChC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,CACL,KAAC,MAAM,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,EAAE,YAC9D,MAAC,aAAa,eACZ,MAAC,YAAY,eACX,KAAC,WAAW,yBAAqB,EACjC,KAAC,iBAAiB,kDAAoD,IACzD,EACf,KAAC,IAAI,OAAK,IAAI,YACZ,gBAAM,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAC,WAAW,aAChE,KAAC,SAAS,IACR,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,IAAI,EAAC,WAAW,EAChB,MAAM,EAAE,CAAC,EAAC,KAAK,EAAC,EAAE,EAAE,CAAC,CACnB,MAAC,QAAQ,eACP,KAAC,SAAS,6BAAuB,EACjC,KAAC,WAAW,cACV,KAAC,KAAK,OACA,KAAK,EACT,SAAS,QACT,WAAW,EAAC,kBAAkB,GAC9B,GACU,EACd,KAAC,WAAW,KAAG,IACN,CACZ,GACD,EACF,MAAC,YAAY,eACX,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,OAAO,uBAE/C,EACT,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,qBAAc,IACtB,IACV,GACF,IACO,GACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,mBAAmB,CAAC","sourcesContent":["import {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n DialogDescription,\n} from '@sqlrooms/ui';\nimport React, {useEffect} from 'react';\nimport {useForm} from 'react-hook-form';\nimport * as z from 'zod';\nimport {zodResolver} from '@hookform/resolvers/zod';\n\nconst formSchema = z.object({\n queryName: z.string().min(1, 'Query name is required'),\n});\n\ntype FormData = z.infer<typeof formSchema>;\n\nconst RenameSqlQueryModal: React.FC<{\n isOpen: boolean;\n onClose: () => void;\n initialName: string;\n onRename: (newName: string) => void;\n}> = ({isOpen, onClose, initialName, onRename}) => {\n const form = useForm<FormData>({\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n resolver: zodResolver(formSchema as any),\n defaultValues: {\n queryName: initialName,\n },\n });\n\n useEffect(() => {\n if (isOpen) {\n form.reset({queryName: initialName});\n }\n }, [isOpen, initialName, form]);\n\n function onSubmit(values: FormData) {\n onRename(values.queryName);\n onClose();\n }\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Rename</DialogTitle>\n <DialogDescription>Rename the query to a new name.</DialogDescription>\n </DialogHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"queryName\"\n render={({field}) => (\n <FormItem>\n <FormLabel>Query Name</FormLabel>\n <FormControl>\n <Input\n {...field}\n autoFocus\n placeholder=\"Enter query name\"\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button type=\"submit\">Save</Button>\n </DialogFooter>\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default RenameSqlQueryModal;\n"]}
1
+ {"version":3,"file":"RenameSqlQueryModal.js","sourceRoot":"","sources":["../../src/components/RenameSqlQueryModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,MAAM,EACN,IAAI,EACJ,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAc,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACvC,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAEpD,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;CACvD,CAAC,CAAC;AAIH,MAAM,mBAAmB,GAKpB,CAAC,EAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAC,EAAE,EAAE;IAChD,MAAM,IAAI,GAAG,OAAO,CAAW;QAC7B,QAAQ,EAAE,WAAW,CAAC,UAAiB,CAAC;QACxC,aAAa,EAAE;YACb,SAAS,EAAE,WAAW;SACvB;KACF,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,WAAW,EAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IAEhC,SAAS,QAAQ,CAAC,MAAgB;QAChC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,CACL,KAAC,MAAM,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,EAAE,YAC9D,MAAC,aAAa,eACZ,MAAC,YAAY,eACX,KAAC,WAAW,yBAAqB,EACjC,KAAC,iBAAiB,kDAAoD,IACzD,EACf,KAAC,IAAI,OAAK,IAAI,YACZ,gBAAM,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAC,WAAW,aAChE,KAAC,SAAS,IACR,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,IAAI,EAAC,WAAW,EAChB,MAAM,EAAE,CAAC,EAAC,KAAK,EAAC,EAAE,EAAE,CAAC,CACnB,MAAC,QAAQ,eACP,KAAC,SAAS,6BAAuB,EACjC,KAAC,WAAW,cACV,KAAC,KAAK,OACA,KAAK,EACT,SAAS,QACT,WAAW,EAAC,kBAAkB,GAC9B,GACU,EACd,KAAC,WAAW,KAAG,IACN,CACZ,GACD,EACF,MAAC,YAAY,eACX,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,OAAO,uBAE/C,EACT,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,qBAAc,IACtB,IACV,GACF,IACO,GACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,mBAAmB,CAAC","sourcesContent":["import {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n DialogDescription,\n} from '@sqlrooms/ui';\nimport React, {useEffect} from 'react';\nimport {useForm} from 'react-hook-form';\nimport * as z from 'zod';\nimport {zodResolver} from '@hookform/resolvers/zod';\n\nconst formSchema = z.object({\n queryName: z.string().min(1, 'Query name is required'),\n});\n\ntype FormData = z.infer<typeof formSchema>;\n\nconst RenameSqlQueryModal: React.FC<{\n isOpen: boolean;\n onClose: () => void;\n initialName: string;\n onRename: (newName: string) => void;\n}> = ({isOpen, onClose, initialName, onRename}) => {\n const form = useForm<FormData>({\n resolver: zodResolver(formSchema as any),\n defaultValues: {\n queryName: initialName,\n },\n });\n\n useEffect(() => {\n if (isOpen) {\n form.reset({queryName: initialName});\n }\n }, [isOpen, initialName, form]);\n\n function onSubmit(values: FormData) {\n onRename(values.queryName);\n onClose();\n }\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Rename</DialogTitle>\n <DialogDescription>Rename the query to a new name.</DialogDescription>\n </DialogHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"queryName\"\n render={({field}) => (\n <FormItem>\n <FormLabel>Query Name</FormLabel>\n <FormControl>\n <Input\n {...field}\n autoFocus\n placeholder=\"Enter query name\"\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button type=\"submit\">Save</Button>\n </DialogFooter>\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default RenameSqlQueryModal;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sqlrooms/sql-editor",
3
- "version": "0.28.0-rc.0",
3
+ "version": "0.28.1-rc.0",
4
4
  "author": "SQLRooms Contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -29,14 +29,14 @@
29
29
  "@hookform/resolvers": "^5.0.0",
30
30
  "@monaco-editor/react": "^4.7.0",
31
31
  "@paralleldrive/cuid2": "^3.0.0",
32
- "@sqlrooms/data-table": "0.28.0-rc.0",
33
- "@sqlrooms/duckdb": "0.28.0-rc.0",
34
- "@sqlrooms/monaco-editor": "0.28.0-rc.0",
35
- "@sqlrooms/room-shell": "0.28.0-rc.0",
36
- "@sqlrooms/schema-tree": "0.28.0-rc.0",
37
- "@sqlrooms/sql-editor-config": "0.28.0-rc.0",
38
- "@sqlrooms/ui": "0.28.0-rc.0",
39
- "@sqlrooms/utils": "0.28.0-rc.0",
32
+ "@sqlrooms/data-table": "0.28.1-rc.0",
33
+ "@sqlrooms/duckdb": "0.28.1-rc.0",
34
+ "@sqlrooms/monaco-editor": "0.28.1-rc.0",
35
+ "@sqlrooms/room-shell": "0.28.1-rc.0",
36
+ "@sqlrooms/schema-tree": "0.28.1-rc.0",
37
+ "@sqlrooms/sql-editor-config": "0.28.1-rc.0",
38
+ "@sqlrooms/ui": "0.28.1-rc.0",
39
+ "@sqlrooms/utils": "0.28.1-rc.0",
40
40
  "@tanstack/react-table": "^8.21.3",
41
41
  "d3-dsv": "^3.0.1",
42
42
  "file-saver": "^2.0.5",
@@ -58,5 +58,5 @@
58
58
  "@types/react": "^19.1.13",
59
59
  "@types/react-dom": "^19.1.9"
60
60
  },
61
- "gitHead": "87a478edbff690e04c38cc717db8e11e844565c8"
61
+ "gitHead": "1e0dcae95d1ccdbcd1b32df1d647d0f794b94e5e"
62
62
  }