Conversation
Move dev-playground route and UI to a separate branch (plugin/files-playground). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Atila Fassina <atila@fassina.eu>
8fa2314 to
60b1bcd
Compare
744d776 to
5200066
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a comprehensive Files plugin for AppKit that enables Unity Catalog volume file operations. The plugin provides both HTTP routes and a programmatic API for common file operations including list, read, download, upload, delete, and preview. It integrates with AppKit's execution interceptor pipeline for caching, retry, and timeout handling.
The PR also modifies the server plugin to support bypassing JSON body parsing for specific routes (needed for file upload streaming), introducing a new skipBodyParsing route configuration option and getSkipBodyParsingPaths() plugin interface method.
Changes:
- New Files plugin with full CRUD operations for Unity Catalog volumes
- Server plugin modification to support raw body streaming for file uploads
- Comprehensive test coverage including unit, integration, and connector tests
- Documentation updates including README, API docs, and plugin guide
Reviewed changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
packages/appkit/src/plugins/files/plugin.ts |
Main FilesPlugin class with HTTP routes and programmatic API |
packages/appkit/src/plugins/files/types.ts |
TypeScript type definitions for file operations |
packages/appkit/src/plugins/files/defaults.ts |
Execution defaults for different operation tiers (read/download/write) |
packages/appkit/src/plugins/files/manifest.json |
Plugin manifest declaring resource requirements |
packages/appkit/src/connectors/files/client.ts |
FilesConnector implementing core file operations with telemetry |
packages/appkit/src/connectors/files/defaults.ts |
Content-type resolution and text detection helpers |
packages/appkit/src/plugins/server/index.ts |
Modified to support selective body parsing bypass |
packages/shared/src/plugin.ts |
Added getSkipBodyParsingPaths() to BasePlugin interface |
packages/appkit/src/plugin/plugin.ts |
Implementation of skipBodyParsing tracking and path registration |
packages/appkit/src/plugins/files/tests/* |
Comprehensive test suites for plugin, connector, and integration |
packages/appkit/src/plugins/server/tests/server.test.ts |
Tests for body parsing bypass functionality |
docs/docs/plugins.md |
Plugin guide with Files plugin documentation and examples |
packages/appkit/src/index.ts |
Export of files plugin and contentTypeFromPath helper |
apps/dev-playground/server/index.ts |
Dev playground integration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cd3d855 to
1c5805b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 33 changed files in this pull request and generated 7 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
e86e4a4 to
bb57226
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 32 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 32 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
The plugin looks awesome, great work! 👌
Could you please record a short demo how it works with the databricks apps init command and whether the apps deploy passes? Thanks in advance!
# in cli repo
make build
sudo ln -s "$(pwd)/cli" /usr/local/bin/dbx
# in appkit repo
DATABRICKS_APPKIT_TEMPLATE_PATH="/Users/pawel.kosiec/repositories/databricks-os/appkit/template" dbx apps init
| - `format: "JSON"` (default) returns JSON rows | ||
| - `format: "ARROW"` returns an Arrow "statement_id" payload over SSE, then the client fetches binary Arrow from `/api/analytics/arrow-result/:jobId` | ||
|
|
||
| ### Files plugin |
There was a problem hiding this comment.
Just a heads-up - no changes needed for now: I split the plugins.md into multiple files here: #126
Not sure which PR will get merged first, probably yours, so of course I'll update the docs to split the files into a dedicated document 👍
There was a problem hiding this comment.
oh great! I was thinking about doing it on a follow-up PR as well 🏆
| telemetryExamples(), | ||
| analytics({}), | ||
| lakebaseExamples(), | ||
| files({ defaultVolume: process.env.DATABRICKS_DEFAULT_VOLUME }), |
There was a problem hiding this comment.
Do we need to pass the DATABRICKS_DEFAULT_VOLUME env value if it is already read by the plugin itself (at least that's what the plugin manifest says)? Looks redundant unless I'm missing something 🤔
| host: "127.0.0.1", | ||
| autoStart: false, | ||
| }), | ||
| files({ defaultVolume: "/Volumes/catalog/schema/vol" }), |
There was a problem hiding this comment.
should it be empty if we set up the DATABRICKS_DEFAULT_VOLUME env?
| files({ defaultVolume: "/Volumes/catalog/schema/vol" }), | |
| files(), |
?
fjakobs
left a comment
There was a problem hiding this comment.
Blocking - we need to solve access control before we can merge it
| totalSpend: number; | ||
| /** @sqlType DATE */ | ||
| createdAt: string; | ||
| ; |
There was a problem hiding this comment.
the reverted types look like a regression
| telemetryExamples(), | ||
| analytics({}), | ||
| lakebaseExamples(), | ||
| files({ defaultVolume: process.env.DATABRICKS_DEFAULT_VOLUME }), |
There was a problem hiding this comment.
how to we manage permissions. Can all users read and upload all the files?
|
|
||
| Routes are mounted at `/api/files/*`. | ||
|
|
||
| #### Configuration |
There was a problem hiding this comment.
I see to problems with the proposed API:
- We only support a single volume. We have no way of serving files from multiple vlumes
- We have no access control. The API suggests that every user can read, delete, upload every file and upload to every.
I've tried to address this in my PoC like this:
| }); | ||
| ``` | ||
|
|
||
| #### User-scoped operations in a route handler |
| | `GET` | `/api/files/preview?path=` | Get a file preview with text excerpt. | | ||
| | `POST` | `/api/files/upload?path=` | Upload a file (stream the request body). | | ||
| | `POST` | `/api/files/mkdir` | Create a directory (`{ path }` in body). | | ||
| | `POST` | `/api/files/delete` | Delete a file or directory (`{ path }` in body). | |
There was a problem hiding this comment.
We also need something like createSignedUrl() (see https://supabase.com/docs/reference/javascript/storage-from-createsignedurl) so we can download files that take longer than 60s to download.
This PR implements a first version of the Files API plugin according to the internal RFC.
Features
Important
this PR also touches the server plugin to bypass the
express.jsonmiddleware for upload routes, otherwise the stream does not passthroughFor testing functionality, I recommend using the adjacent PR that adds it to the Dev Playground ( #114 ), I split PR so code is easier to review here.