- Notifications
You must be signed in to change notification settings - Fork0
Lightweight JavaScript library that transforms static SQL code blocks into interactive, browser-based SQL execution environments using DuckDB WASM
License
tobilg/sql-workbench-embedded
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
A lightweight JavaScript library that transforms static SQL code blocks into interactive, browser-based SQL execution environments using DuckDB WASM.
Repository:https://github.com/tobilg/sql-workbench-embedded
- Zero Backend Required: All SQL execution happens in the browser
- Lightweight: 9.54 kB gzipped bundle (29.81 kB minified)
- Easy Integration: Just add a CSS class to your code blocks
- Interactive Editing: Edit SQL queries with real-time syntax highlighting
- Framework Agnostic: Works with vanilla JS, React, Vue, and more
- Privacy-Focused: No data transmission to external servers
- Lazy Loading: DuckDB WASM loads only when needed
- Init Queries: Execute initialization queries once for extension management
- Path Resolution: Automatic resolution of relative file paths in SQL queries
- Flexible Theming: Three-tier priority system (data-attribute > config > default)
- Custom Themes: Create themes that extend built-ins or define new color schemes
- Typography Customization: Customize fonts and sizes per theme
<!DOCTYPE html><html><head><title>SQL Workbench Example</title></head><body><preclass="sql-workbench-embedded"><code>SELECT 'Hello, World!' AS greeting;</code></pre><!-- Latest version --><scriptsrc="https://unpkg.com/sql-workbench-embedded@latest"></script><!-- Specific version (recommended for production) --><scriptsrc="https://unpkg.com/sql-workbench-embedded@0.1.4"></script></body></html>
<!DOCTYPE html><html><head><title>SQL Workbench Example</title></head><body><preclass="sql-workbench-embedded"><code>SELECT 'Hello, World!' AS greeting;</code></pre><!-- Latest version --><scriptsrc="https://cdn.jsdelivr.net/npm/sql-workbench-embedded@latest"></script><!-- Specific version (recommended for production) --><scriptsrc="https://cdn.jsdelivr.net/npm/sql-workbench-embedded@0.1.4"></script></body></html>
# Install dependenciesnpm install# Start development server (http://localhost:5173/examples/index.html)npm run dev# Build for productionnpm run build# Preview production build (http://localhost:4173/examples/index.html)npm run preview:prod
- Basic Example:examples/index.html - Vanilla JavaScript integration
- Init Queries Example:examples/init-queries.html - DuckDB extension management with initQueries
- unpkg CDN (UMD):examples/unpkg.html - Loading from unpkg as UMD module
- unpkg CDN (ESM):examples/unpkg-esm.html - Loading from unpkg as ES module
- Typography Example:examples/typography.html - Font customization examples
- React Example:examples/react.html - React component integration
- Vue Example:examples/vue.html - Vue 3 component integration
By default, the library automatically scans for elements with the classsql-workbench-embedded and transforms them:
<preclass="sql-workbench-embedded"><code> SELECT * FROM generate_series(1, 10);</code></pre><!-- You can also set the theme directly on the element --><preclass="sql-workbench-embedded"data-theme="dark"><code> SELECT * FROM users WHERE active = true;</code></pre>
import{SQLWorkbench}from'sql-workbench-embedded';// Configure globallySQLWorkbench.config({selector:'.my-sql-code',theme:'dark',baseUrl:'https://my-data-server.com',});// Initialize all embedsSQLWorkbench.init();// Or create a single embed programmaticallyconstembed=newSQLWorkbench.Embedded(element,{editable:true,theme:'light',});
<!-- Using unpkg --><scriptsrc="https://unpkg.com/sql-workbench-embedded@0.1.4"></script><!-- Or using jsDelivr --><scriptsrc="https://cdn.jsdelivr.net/npm/sql-workbench-embedded@0.1.4"></script><script>// Configure globallySQLWorkbench.config({selector:'.my-sql-code',theme:'dark',baseUrl:'https://my-data-server.com',});// Initialize all embedsSQLWorkbench.init();// Or create a single embed programmaticallyconstembed=newSQLWorkbench.Embedded(element,{editable:true,theme:'light',});</script>
SQLWorkbench.config({selector:'pre.sql-workbench-embedded, .sql-workbench-embedded pre',// CSS selector for auto-discoverybaseUrl:'https://data.sql-workbench.com',// Base URL for file pathstheme:'auto',// 'light', 'dark', or 'auto'autoInit:true,// Auto-initialize on DOMContentLoadedduckdbVersion:'1.31.1-dev1.0',// DuckDB versionduckdbCDN:'https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm',editable:true,// Allow code editingshowOpenButton:true,// Show "Open in SQL Workbench" buttoninitQueries:[],// Initialization queries to execute once before first user query});
constembed=newSQLWorkbench.Embedded(element,{initialCode:'SELECT 1;',theme:'dark',editable:false,showOpenButton:false,// Hide "Open in SQL Workbench" button for this instance});
TheinitQueries configuration allows you to execute SQL queries once before any user query runs. This is perfect for installing and loading DuckDB extensions, setting configuration options, or creating user-defined functions.
- ✅ Executes only once across all embeds on the page
- ✅ Runs sequentially in array order
- ✅ Lazy execution - only when the first "Run" button is pressed
- ✅ All embeds share the same DuckDB instance and extensions
SQLWorkbench.config({initQueries:["INSTALL spatial","LOAD spatial","INSTALL a5 FROM community","LOAD a5"]});
Now all embeds can use spatial functions and community extensions:
<preclass="sql-workbench-embedded"> SELECT ST_Distance( ST_Point(-74.0060, 40.7128), ST_Point(-118.2437, 34.0522) ) / 1000 AS distance_km;</pre><preclass="sql-workbench-embedded"> -- Generate GeoJSON for A5 cell SELECT ST_AsGeoJSON( ST_MakePolygon( ST_MakeLine( list_transform( a5_cell_to_boundary(a5_lonlat_to_cell(-3.7037, 40.41677, 10)), x -> ST_Point(x[1], x[2]) ) ) ) ) as geojson;</pre>
SQLWorkbench.config({initQueries:["SET memory_limit='2GB'","SET threads=4"]});
SQLWorkbench.config({initQueries:["CREATE MACRO add_tax(price, rate) AS price * (1 + rate)","CREATE MACRO full_name(first, last) AS first || ' ' || last"]});
If an initialization query fails:
- The error is shown to the user
- The user query is not executed
- The init query state is reset, allowing retry on next run
Seeexamples/init-queries.html for a complete working example with the spatial and a5 community extensions.
Themes are resolved in the following priority order (highest to lowest):
- HTML
data-themeattribute -<pre data-theme="ocean">(highest) - Per-instance options -
new Embedded(element, { theme: 'dark' }) - Global configuration -
SQLWorkbench.config({ theme: 'auto' })(lowest)
You can define custom themes that either extend existing light/dark themes or define completely new color schemes.
Custom themes are automatically inherited by programmatic embeds, so you only need to define them once globally.
SQLWorkbench.config({customThemes:{// Extend existing theme with custom colorsocean:{extends:'dark',config:{primaryBg:'#0ea5e9',primaryHover:'#0284c7',editorBg:'#1e3a5f',// Optionally customize syntax highlightingsyntaxKeyword:'#4fc3f7',syntaxString:'#80cbc4'}},// Standalone theme with all colors definedsunset:{config:{bgColor:'#fef3c7',textColor:'#92400e',borderColor:'#f59e0b',editorBg:'#fef7cd',editorText:'#92400e',editorFocusBg:'#fef3c7',controlsBg:'#fef7cd',primaryBg:'#f97316',primaryText:'#ffffff',primaryHover:'#ea580c',secondaryBg:'#f59e0b',secondaryText:'#92400e',secondaryHover:'#d97706',mutedText:'#a16207',errorText:'#dc2626',errorBg:'#fef2f2',errorBorder:'#f87171',tableHeaderBg:'#fef3c7',tableHeaderText:'#92400e',tableHover:'#fef7cd'}}},theme:'ocean'// Global default theme});// Use via data-attribute (highest priority)// <pre data-theme="sunset">// Or programmatically (inherits customThemes automatically)newSQLWorkbench.Embedded(element,{theme:'ocean'// Overrides global default});
When defining custom themes, you can override any of these properties:
Color Properties:
bgColor- Main background colortextColor- Primary text colorborderColor- Border coloreditorBg- Editor backgroundeditorText- Editor text coloreditorFocusBg- Editor focus backgroundcontrolsBg- Controls backgroundprimaryBg- Primary button backgroundprimaryText- Primary button textprimaryHover- Primary button hoversecondaryBg- Secondary button backgroundsecondaryText- Secondary button textsecondaryHover- Secondary button hovermutedText- Muted text colorerrorText- Error text colorerrorBg- Error backgrounderrorBorder- Error border colortableHeaderBg- Table header backgroundtableHeaderText- Table header texttableHover- Table row hover background
Syntax Highlighting Colors (Optional):
syntaxKeyword- SQL keywords (SELECT, FROM, WHERE, etc.)syntaxString- String literalssyntaxNumber- Numeric valuessyntaxComment- SQL commentssyntaxFunction- Function namessyntaxOperator- Operators (+, -, =, etc.)
Typography Properties (Optional):
fontFamily- Font family for container and UI elementseditorFontFamily- Font family for the SQL editorfontSize- Base font size (e.g., '14px', '1rem')editorFontSize- Font size for the SQL editorbuttonFontSize- Font size for buttonsmetadataFontSize- Font size for metadata text
You can customize font families and sizes in your themes:
SQLWorkbench.config({customThemes:{// Large accessible theme for better readability'large-accessible':{extends:'light',config:{fontSize:'18px',editorFontSize:'16px',buttonFontSize:'16px',metadataFontSize:'14px',}},// Custom editor font with ligatures'fira-code':{extends:'dark',config:{editorFontFamily:'"Fira Code", "JetBrains Mono", monospace',editorFontSize:'15px',}},// Compact theme for dense displays'compact':{extends:'dark',config:{fontSize:'12px',editorFontSize:'12px',buttonFontSize:'12px',metadataFontSize:'10px',}}}});
Seeexamples/typography.html for a complete demonstration of typography customization.
- With
extends: Only define the properties you want to override. The base theme provides defaults for all others. - Without
extends: You must define all required color properties. The library will throw an error if any are missing.
Thesql-workbench-embedded-themes package provides 66 ready-to-use themes converted from popular CodeMirror 5 themes (50 dark + 16 light themes).
npm install sql-workbench-embedded-themes
import{SQLWorkbench}from'sql-workbench-embedded';import{dracula,monokai,elegant}from'sql-workbench-embedded-themes';// Configure with pre-built themesSQLWorkbench.config({customThemes:{dracula:{config:dracula.config},monokai:{config:monokai.config}},theme:'dracula'});
For browser usage without a bundler, load individual theme bundles (~1.4KB each):
<!DOCTYPE html><html><head><title>SQL Workbench with Themes</title></head><body><preclass="sql-workbench-embedded"><code>SELECT * FROM generate_series(1, 10);</code></pre><!-- Load SQL Workbench --><scriptsrc="https://unpkg.com/sql-workbench-embedded@latest"></script><!-- Load specific themes from CDN --><scriptsrc="https://unpkg.com/sql-workbench-embedded-themes/dist/umd/themes/dracula.js"></script><scriptsrc="https://unpkg.com/sql-workbench-embedded-themes/dist/umd/themes/monokai.js"></script><script>// Themes are available on window.SQLWorkbenchThemesSQLWorkbench.config({customThemes:{dracula:{config:window.SQLWorkbenchThemes.dracula.config},monokai:{config:window.SQLWorkbenchThemes.monokai.config}},theme:'dracula'});</script></body></html>
The package includes 66 themes categorized as:
- Dark themes (50): dracula, monokai, material, nord, oceanic-next, and many more
- Light themes (16): elegant, idea, neat, paraiso-light, and more
For a complete list of available themes, visit thesql-workbench-embedded-themes repository.
The library automatically resolves relative file paths in SQL queries:
-- Relative pathSELECT*FROM'data.parquet';-- Resolves to: https://data.sql-workbench.com/data.parquet-- Dot-relative pathSELECT*FROM'./path/to/data.parquet';-- Resolves to: https://data.sql-workbench.com/path/to/data.parquet-- Absolute pathSELECT*FROM'/data.parquet';-- Resolves to: https://your-domain.com/data.parquet-- Already absolute URL (unchanged)SELECT*FROM'https://example.com/data.parquet';
Configure the base URL:
SQLWorkbench.config({baseUrl:'https://my-data-cdn.com',});
Each embed includes an "Open in SQL Workbench" button (enabled by default) that opens the current query in the fullSQL Workbench web application. The query is encoded in the URL hash using URL-safe Base64 encoding for sharing and persistence.
To disable this button globally:
SQLWorkbench.config({showOpenButton:false,});
Or for a specific instance:
constembed=newSQLWorkbench.Embedded(element,{showOpenButton:false,});
- Ctrl+Enter (Mac:Cmd+Enter): Execute query
- Ctrl+Shift+Enter (Mac:Cmd+Shift+Enter): Open in SQL Workbench
- Ctrl+Backspace (Mac:Cmd+Backspace): Reset to original code
- Tab: Navigate between buttons
Initialize all embeds matching the configured selector.
Destroy all embeds and cleanup resources.
Set global configuration options.
Class for creating individual embeds.
constembed=newSQLWorkbench.Embedded(element,options);// Methodsembed.run();// Execute queryembed.destroy();// Cleanupembed.isDestroyed();// Check if destroyedembed.getContainer();// Get container element
Option 1: CDN (Recommended for quick setup)
<!-- Add to your HTML head --><scripttype="module"src="https://unpkg.com/sql-workbench-embedded@0.1.4/dist/sql-workbench-embedded.esm.js"></script>
Option 2: npm
npm install sql-workbench-embedded
import{useRef,useEffect}from'react';functionSQLWorkbenchEmbedded({ code, options}){constcontainerRef=useRef(null);constembedRef=useRef(null);useEffect(()=>{if(containerRef.current&&window.SQLWorkbench){// Create a pre element with the SQL codeconstpreElement=document.createElement('pre');preElement.className='sql-workbench-embedded';preElement.innerHTML=`<code>${code}</code>`;containerRef.current.appendChild(preElement);// Initialize the embedembedRef.current=newwindow.SQLWorkbench.Embedded(preElement,options);}return()=>{embedRef.current?.destroy();};},[code,options]);return<divref={containerRef}/>;}// Usage in your appfunctionApp(){return(<SQLWorkbenchEmbeddedcode="SELECT 'Hello, World!' AS greeting;"options={{editable:true,theme:'light'}}/>);}
<template> <divref="container"></div></template><script>import {ref,onMounted,onUnmounted }from'vue';exportdefault { props: { code:String, options:Object },setup(props) {constcontainerRef=ref(null);constembedRef=ref(null);onMounted(()=> {if (containerRef.value&&window.SQLWorkbench) {// Create a pre element with the SQL codeconstpreElement=document.createElement('pre');preElement.className='sql-workbench-embedded';preElement.innerHTML=`<code>${props.code}</code>`;containerRef.value.appendChild(preElement);// Initialize the embedembedRef.value=newwindow.SQLWorkbench.Embedded(preElement,props.options); } });onUnmounted(()=> {embedRef.value?.destroy(); });return { containerRef }; }};</script>
<template> <divref="container"></div></template><script>exportdefault { props: ['code','options'],mounted() {if (this.$refs.container&&window.SQLWorkbench) {constelement=document.createElement('pre');element.className='sql-workbench-embedded';element.innerHTML=`<code>${this.code}</code>`;this.$refs.container.appendChild(element);this.embed=newwindow.SQLWorkbench.Embedded(element,this.options); } },beforeUnmount() {this.embed?.destroy(); },};</script>
The library is optimized for production with minimal bundle size:
- UMD Bundle: 29.81 kB minified, 9.54 kB gzipped
- ES Module: 30.59 kB minified, 9.59 kB gzipped
- DuckDB WASM: Loaded separately from CDN (~5MB on first use)
- SQL Workbench Embed: ~20 kB (UI, syntax highlighting, path resolution, theming)
- DuckDB Client Library: ~6 kB (minimal DuckDB bindings)
- Build Overhead: ~3 kB (UMD wrapper, utilities)
- Initial Load: 9.54 kB gzipped (extremely lightweight)
- First Query: Additional ~5MB for DuckDB WASM binary (cached thereafter)
- Subsequent Loads: Only 9.54 kB (DuckDB cached)
The production build maintains a compact size while providing full functionality including flexible theming and typography customization.
- Chrome/Edge 88+
- Firefox 89+
- Safari 15+
Requires: WebAssembly, Web Workers, ES2018+
src/├── index.ts # Main entry point├── embedded.ts # Core Embedded class├── types.ts # TypeScript definitions├── duckdb-manager.ts # DuckDB connection management├── path-resolver.ts # File path resolution├── syntax-highlight.ts # SQL syntax highlighting└── styles.ts # CSS injectionexamples/├── index.html # Basic vanilla JS example├── init-queries.html # Init queries / extension management example├── unpkg.html # unpkg CDN example (UMD)├── unpkg-esm.html # unpkg CDN example (ESM)├── typography.html # Typography customization examples├── react.html # React integration example└── vue.html # Vue 3 integration exampleMIT License - seeLICENSE file for details.
About
Lightweight JavaScript library that transforms static SQL code blocks into interactive, browser-based SQL execution environments using DuckDB WASM
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.