Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
aa8738b
fix(process-directory): add option to change working directory for su…
franklinfollis Nov 26, 2025
0e8181c
test(process-directory): custom working directory tests for ProcessRu…
franklinfollis Nov 26, 2025
a77f8f6
fix(process-directory): update api pins
franklinfollis Nov 27, 2025
61bdf0f
initial skeleton for db studio command
franklinfollis Oct 17, 2025
d83d9bf
feat(database-ui): have `elide db studio` be a simple wrapper around …
franklinfollis Oct 21, 2025
ac1edb7
feat(database-ui): have db studio init a react ssr template for studi…
franklinfollis Oct 25, 2025
6f48851
feat(database-ui): discover db files on disk and select between them
franklinfollis Oct 26, 2025
7926b7b
feat(database-ui): static react app calling on database json api
franklinfollis Oct 28, 2025
3ca9ca4
feat(database-ui): consolidate api and ui for db studio into one folder
franklinfollis Oct 29, 2025
2100cba
feat(database-ui): add shadcn and tailwind to studio frontend
franklinfollis Oct 29, 2025
1325216
feat(database-ui): standardize json api paths
franklinfollis Oct 29, 2025
64b661e
feat(database-ui): denote columns that are primary keys in tables
franklinfollis Oct 31, 2025
56a9457
fix(database-ui): add primaryKeys to TableData type
franklinfollis Oct 31, 2025
e342314
fix(database-ui): move built db studio code under .dev
franklinfollis Nov 4, 2025
62385d9
fix(database-ui): use new elide http server
franklinfollis Nov 10, 2025
7ac4812
feat(database-ui): cleanup server.ts
franklinfollis Nov 10, 2025
82f3a8f
fix(database-ui): use byte length for content length header
franklinfollis Nov 10, 2025
3decfc5
feat(database-ui): provide directory as well as db file path for data…
franklinfollis Nov 10, 2025
e29092a
feat(database-ui): use code mirror for query editor
franklinfollis Nov 11, 2025
a6cc0e6
feat(database-ui): move db-studio src out of samples
franklinfollis Nov 11, 2025
fc6ca4c
feat(database-ui): setup elide.pkl manifest for api
franklinfollis Nov 12, 2025
dfb7c3a
feat(database-ui): spread server routes and handlers out to separate …
franklinfollis Nov 12, 2025
b505bfb
feat(database-ui): add tsconfig to resolve elide:sqlite types
franklinfollis Nov 12, 2025
16a59f9
chore(database-ui): cleanup responses and router code
franklinfollis Nov 12, 2025
fb6392d
feat(database-ui): format null values in table
franklinfollis Nov 17, 2025
2c1461a
feat(database-ui): escape table names with spaces in them
franklinfollis Nov 17, 2025
f162cc7
feat(database-ui): use tanstack table for viewing query results
franklinfollis Nov 17, 2025
08a0054
feat(database-ui): show views from databases as well
franklinfollis Nov 17, 2025
40e24a9
feat(database-ui): refactor api response to include query metadata
franklinfollis Nov 17, 2025
d222c29
feat(database-ui): update query hooks to use new format
franklinfollis Nov 17, 2025
8c06994
feat(database-ui): show detailed column info on hover
franklinfollis Nov 17, 2025
d34d0e1
feat(database-ui): add support for views
franklinfollis Nov 17, 2025
493b7bd
chore(database-ui): clean up context passed in routes
franklinfollis Nov 18, 2025
0d22cdf
feat(database-ui): use limit and offset as query params for pagination
franklinfollis Nov 18, 2025
5b0a548
fix(database-ui): fix up loading state for rows when changing offset
franklinfollis Nov 18, 2025
f51bbb9
fix(database-ui): highlight selected table in sidebar
franklinfollis Nov 18, 2025
1ed7701
feat(database-ui): sticky toolbar and column headers
franklinfollis Nov 18, 2025
4450a8d
chore(database-ui): prettierrc
franklinfollis Nov 18, 2025
e90a664
fix(database-ui): show key info first on column description
franklinfollis Nov 18, 2025
16b046e
feat(database-ui): add props for hiding tools in data table
franklinfollis Nov 18, 2025
6ee1693
feat(database-ui): send sort column and direction as url parameter
franklinfollis Nov 18, 2025
a762005
feat(database-ui): Move table name to toolbar
franklinfollis Nov 18, 2025
bd4c385
feat(database-ui): add filtering for data table
franklinfollis Nov 18, 2025
a70cf38
feat(database-ui): show active where and column filters
franklinfollis Nov 18, 2025
b7cfa18
feat(database-ui): add refresh handler for table data
franklinfollis Nov 18, 2025
115893b
refactor(database-ui): separate components out of data table
franklinfollis Nov 18, 2025
7b01511
feat(database-ui): move contents of navbar to sidebar
franklinfollis Nov 19, 2025
2267bef
fix(database-ui): remove memo on DataTableGrid
franklinfollis Nov 19, 2025
e1d6f19
feat(database-ui): create provider for DataTable
franklinfollis Nov 19, 2025
2a60a90
fix(database-ui): various lint fix ups
franklinfollis Nov 24, 2025
157a981
feat(database-ui): add resizable panels
franklinfollis Nov 24, 2025
e4613d3
feat(database-ui): standardize theme for ui
franklinfollis Nov 24, 2025
251c2a8
feat(database-ui): simplify theme
franklinfollis Nov 24, 2025
17dc0a6
fix(database-ui): fix stale state in columns dropdown
franklinfollis Nov 24, 2025
8ec732c
feat(database-ui): functionality for deleting rows
franklinfollis Nov 25, 2025
3fe4594
feat(database-ui): use zod for parsing responses
franklinfollis Nov 25, 2025
b912565
feat(database-ui): call sub tasks within db studio command
franklinfollis Nov 26, 2025
73a0d12
fix(database-ui): run elide build and install before running api server
franklinfollis Nov 28, 2025
81e5cdb
fix(database-ui): exclude .dev in prepareDbStudio task
franklinfollis Nov 28, 2025
2c8e444
fix(database-ui): exclude server node_modules in build output
franklinfollis Nov 28, 2025
5461846
fix(database-ui): hide delete button for views
franklinfollis Nov 30, 2025
3016eec
feat(database-ui): add refresh tables button
franklinfollis Nov 30, 2025
403d4be
fix(database-ui): fix styling of column names in query editor
franklinfollis Dec 1, 2025
0fae404
feat(database-ui): add drop and truncate table actions
franklinfollis Dec 2, 2025
75aa0a6
test(database-ui): initial playwright config
franklinfollis Dec 2, 2025
3d15217
fix(database-ui): import elide:sqlite directly into middleware
franklinfollis Dec 2, 2025
8152a0d
fix(database-ui): add CORS to api responses
franklinfollis Dec 2, 2025
14c8982
fix(database-ui): refactor data table components
franklinfollis Dec 2, 2025
e800c27
test(database-ui): shorten test commands
franklinfollis Dec 2, 2025
43eb33f
fix(database-ui): small ui fixes
franklinfollis Dec 2, 2025
5f94272
fix(database-ui): make sidebar content more consistent
franklinfollis Dec 2, 2025
527ef6b
feat(database-ui): cell selection
franklinfollis Dec 2, 2025
13ae42a
feat(database-ui): add rows feature
franklinfollis Dec 2, 2025
6eee01a
fix(database-ui): incredibly clear drop and truncate warning dialogs
franklinfollis Dec 2, 2025
baa27a7
fix(database-ui): unsaved changes dialog only on navigate out
franklinfollis Dec 2, 2025
247fa62
fix(database-ui): show proper SQL errors in ui
franklinfollis Dec 2, 2025
7a578c3
fix(database-ui): only show table edit results on success/failure
franklinfollis Dec 2, 2025
64d439b
feat(database-ui): edit and update cells
franklinfollis Dec 3, 2025
f269d14
feat(database-ui): remove retry for failed queries
franklinfollis Dec 3, 2025
21047ac
feat(database-ui): allow selecting NULL and EMPTY STRING for editable…
franklinfollis Dec 3, 2025
15010ef
feat(database-ui): generate unique id's for databases
franklinfollis Dec 4, 2025
e276252
fix(database-ui): make cells still selectable in edit mode
franklinfollis Dec 4, 2025
f8f7584
fix(database-ui): show all columns when adding new rows
franklinfollis Dec 4, 2025
152551b
fix(database-ui): correctly delete when primary key is NULL
franklinfollis Dec 4, 2025
1576490
feat(database-ui): show version number in footer
franklinfollis Dec 9, 2025
a228fe6
feat(database-ui): save query and limit to local storage
franklinfollis Dec 9, 2025
cde514f
feat(database-ui): initial table creator/editor
franklinfollis Dec 9, 2025
15e7225
chore(database-ui): build ui assets
franklinfollis Dec 9, 2025
063ba2a
fix(database-ui): log significant sql statements in api
franklinfollis Dec 9, 2025
57d16d1
fix(database-ui): save local storage values per db
franklinfollis Dec 9, 2025
284140c
docs(database-ui): add README and remove legacy run-db-studio script
franklinfollis Dec 16, 2025
c94579c
fix(database-ui): latest static build of ui
franklinfollis Dec 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
.dev/dependencies
.dev/coverage
.dev/artifacts
.dev/db-studio
*/.dev/artifacts
*/.dev/coverage
*/.dev/dependencies
Expand Down
8 changes: 5 additions & 3 deletions packages/builder/api/builder.api
Original file line number Diff line number Diff line change
Expand Up @@ -2704,14 +2704,16 @@ public final class elide/tooling/runner/ProcessRunner {
}

public final class elide/tooling/runner/ProcessRunner$ProcessOptions : java/lang/Record {
public fun <init> (Lelide/tooling/runner/ProcessRunner$ProcessShell;)V
public fun <init> (Lelide/tooling/runner/ProcessRunner$ProcessShell;Ljava/nio/file/Path;)V
public final fun component1 ()Lelide/tooling/runner/ProcessRunner$ProcessShell;
public final fun copy (Lelide/tooling/runner/ProcessRunner$ProcessShell;)Lelide/tooling/runner/ProcessRunner$ProcessOptions;
public static synthetic fun copy$default (Lelide/tooling/runner/ProcessRunner$ProcessOptions;Lelide/tooling/runner/ProcessRunner$ProcessShell;ILjava/lang/Object;)Lelide/tooling/runner/ProcessRunner$ProcessOptions;
public final fun component2 ()Ljava/nio/file/Path;
public final fun copy (Lelide/tooling/runner/ProcessRunner$ProcessShell;Ljava/nio/file/Path;)Lelide/tooling/runner/ProcessRunner$ProcessOptions;
public static synthetic fun copy$default (Lelide/tooling/runner/ProcessRunner$ProcessOptions;Lelide/tooling/runner/ProcessRunner$ProcessShell;Ljava/nio/file/Path;ILjava/lang/Object;)Lelide/tooling/runner/ProcessRunner$ProcessOptions;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public final fun shell ()Lelide/tooling/runner/ProcessRunner$ProcessShell;
public fun toString ()Ljava/lang/String;
public final fun workingDirectory ()Ljava/nio/file/Path;
}

public abstract interface class elide/tooling/runner/ProcessRunner$ProcessShell {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public object ProcessRunner {
*/
@JvmRecord public data class ProcessOptions(
public val shell: ProcessShell,
public val workingDirectory: Path,
)

/**
Expand Down Expand Up @@ -128,6 +129,9 @@ public object ProcessRunner {
}
}
val procBuilder = ProcessBuilder(resolvedArgs).apply {
// handle working directory
directory(task.options.workingDirectory.toFile())

// handle task environment
when (task.env) {
// inject host environment
Expand Down Expand Up @@ -185,7 +189,10 @@ public object ProcessRunner {
val mutEnv = env.toMutable()
var executablePath: Path = exec
var effectiveStreams: StdStreams = streams ?: StdStreams.Defaults
var effectiveOptions: ProcessOptions = options ?: ProcessOptions(ProcessShell.None)
var effectiveOptions: ProcessOptions = options ?: ProcessOptions(
shell = ProcessShell.None,
workingDirectory = Path.of(System.getProperty("user.dir")),
)

return object : ProcessTaskBuilder {
override var executable: Path = executablePath
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2024-2025 Elide Technologies, Inc.
*
* Licensed under the MIT license (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* https://opensource.org/license/mit/
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under the License.
*/
package elide.tooling.runner

import java.nio.file.Path
import kotlin.test.*
import elide.tooling.runner.ProcessRunner.ProcessOptions
import elide.tooling.runner.ProcessRunner.ProcessShell

class ProcessRunnerTest {
@Test fun `ProcessOptions should allow specifying a custom working directory`() {
val customDir = Path.of("/tmp")
val options = ProcessOptions(
shell = ProcessShell.None,
workingDirectory = customDir,
)

assertEquals(customDir, options.workingDirectory)
}

@Test fun `ProcessRunner build should accept a custom working directory`() {
val customDir = Path.of("/tmp")
val exec = Path.of("/bin/ls")

val builder = ProcessRunner.build(exec) {
options = ProcessOptions(
shell = ProcessShell.None,
workingDirectory = customDir,
)
}

assertEquals(customDir, builder.options.workingDirectory)
assertEquals(exec, builder.executable)
}

@Test fun `ProcessRunner build should allow changing the working directory after building`() {
val initialDir = Path.of("/tmp")
val newDir = Path.of("/var")
val exec = Path.of("/bin/echo")

val builder = ProcessRunner.build(exec) {
options = ProcessOptions(
shell = ProcessShell.None,
workingDirectory = initialDir,
)
}

assertEquals(initialDir, builder.options.workingDirectory)

// Change the working directory
builder.options = ProcessOptions(
shell = ProcessShell.None,
workingDirectory = newDir,
)

assertEquals(newDir, builder.options.workingDirectory)
}

@Test fun `ProcessRunner buildFrom should use current working directory by default`() {
val exec = Path.of("/bin/echo")
val args = elide.tooling.Arguments.empty()
val env = elide.tooling.Environment.empty()

val builder = ProcessRunner.buildFrom(exec, args, env)

assertNotNull(builder.options.workingDirectory)
assertEquals(Path.of(System.getProperty("user.dir")), builder.options.workingDirectory)
}

@Test fun `ProcessRunner buildFrom should accept custom working directory`() {
val exec = Path.of("/bin/echo")
val args = elide.tooling.Arguments.empty()
val env = elide.tooling.Environment.empty()
val customDir = Path.of("/tmp")
val customOptions = ProcessOptions(
shell = ProcessShell.None,
workingDirectory = customDir,
)

val builder = ProcessRunner.buildFrom(exec, args, env, options = customOptions)

assertEquals(customDir, builder.options.workingDirectory)
}
}
22 changes: 21 additions & 1 deletion packages/cli/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2414,7 +2414,7 @@ tasks {
val allSamples = layout.projectDirectory.dir("src/projects")
.asFile
.listFiles()
.filter { it.isDirectory() }
.filter { it.isDirectory() && it.name != "db-studio" }
.map { it.toPath() to it.name }

val builtSamples = layout.buildDirectory.dir("packed-samples")
Expand All @@ -2436,10 +2436,30 @@ tasks {
dependsOn(allSamplePackTasks)
}

val prepareDbStudioResources by registering(Copy::class) {
group = "build"
description = "Prepare Database Studio resources for embedding in CLI"

from(layout.projectDirectory.dir("src/db-studio/api")) {
into("api")
exclude("config.ts") // Generated at runtime with injected config
exclude(".dev/**") // Exclude development-only dependencies directory
exclude("node_modules/**") // Dependencies installed at runtime
}

// Copy built UI (dist/ folder only, not source or node_modules)
from(layout.projectDirectory.dir("src/db-studio/ui/dist")) {
into("ui")
}

into(layout.buildDirectory.dir("resources/main/META-INF/elide/db-studio"))
}

processResources {
dependsOn(
":packages:graalvm:buildRustNativesForHostDebug",
prepKotlinResources,
prepareDbStudioResources,
packSamples,
allSamplePackTasks,
)
Expand Down
44 changes: 44 additions & 0 deletions packages/cli/src/db-studio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Database Studio

Web-based database management UI that runs on the Elide runtime. At the moment it only supports SQLite with Elide's `elide:sqlite` js bindings. We assume that an existing valid database file exists for the `elide db studio` command to find. If you need a database file to run this on, [Northwind](https://github.com/jpwhite3/northwind-SQLite3) and [Chinook](https://github.com/lerocha/chinook-database/releases) are some good prepopulated examples.

## Directory Structure

```
db-studio/
├── api/ # TypeScript REST API server
│ ├── ...
│ ├── index.ts # Server entrypoint
│ └── elide.pkl
└── ui/ # React frontend application
├── src/
└── dist/ # Vite production build
```

## Running Locally

### Using the Gradle Command

The best way to run this locally is through the CLI in JVM mode. Simply passing `db studio` as args.

**Note:** In order to see UI changes you've made, you'll need to run `pnpm build` in the `ui/` directory first.

```bash
# Build the UI
cd packages/cli/src/db-studio/ui
pnpm build

# Go back to the elide repo root
# Then run the db studio command
./gradlew :packages:cli:run --args="db studio"

# With a specific database
./gradlew :packages:cli:run --args="db studio path/to/database.db"
```

### Running api or ui independently

Database Studio consists of two separate projects that can be run independently:

- `api`: run directly by calling `elide run index.ts` within the directory.
- `ui`: using `pnpm dev` within the directory.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "db-studio-api",
"version": "1.0.0",
"description": "Database Studio API Server",
"main": "index.ts",
"scripts": {},
"dependencies": {
"zod": "4"
},
"devDependencies": {
"@elide-dev/types": "1.0.0-beta10"
}
}
Binary file added packages/cli/src/db-studio/api/.dev/elide.lock.bin
Binary file not shown.
22 changes: 22 additions & 0 deletions packages/cli/src/db-studio/api/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { DiscoveredDatabase } from "./database.ts";

/**
* Database Studio Configuration
*
* This is a sample configuration file. In production, this would be
* generated by DbStudioCommand.kt based on discovered databases.
*/

const config = {
port: 4984,
databases: [
{
path: "./sample.db",
name: "sample.db",
size: 0,
lastModified: Date.now(),
}
] as DiscoveredDatabase[],
};

export default config;
Loading
Loading