feat(assets): port Nuxt DevTools' Assets tab as a framework-neutral plugin - #138
Open
antfubot wants to merge 10 commits into
Open
feat(assets): port Nuxt DevTools' Assets tab as a framework-neutral plugin#138antfubot wants to merge 10 commits into
antfubot wants to merge 10 commits into
Conversation
…lugin
Adds @devframes/plugin-assets, a Preact SPA that browses, previews,
uploads, renames, and deletes the files in a managed directory
(default <cwd>/public). Full RPC surface (list/capabilities/read-text/
read-image-meta/upload/rename/delete/mkdir/write-text/open-in-editor/
reveal-in-folder), a live chokidar-backed change broadcast, real byte
serving via ctx.views.hostStatic(), and binary uploads over devframe's
streaming-channel primitive. Preact ports the same @antfu/design class
vocabulary every other plugin uses.
Core changes in support of this:
- DevframeDefinition.capabilities.build now actually does something:
createCac skips the build subcommand when it's false, and
createBuild throws DF0042 for the same case unless {force: true} is
passed. The assets plugin uses this by default since a static export
can never carry real bytes or write actions.
- Wired into alias.ts/tsconfig.base.json/turbo.json/vitest.config.ts
and dogfooded in examples/minimal-vite-devframe-hub.
Co-authored-by: opencode <noreply@opencode.ai>
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
…o upload - Fold the search box, asset count, and action buttons into the single top nav bar instead of a second toolbar row; the error banner moves to its own slim strip below. - DropZone now listens for file drags across the whole frame whenever write is enabled, so dropping files opens the upload overlay without first clicking Upload. A drag-depth counter keeps the overlay from flickering, and only drags carrying files (not text/element drags) trigger it. Co-authored-by: opencode <noreply@opencode.ai>
…text Adds a small, varied public/ fixture set (SVG + raster PNG images, nested folders, JSON/Markdown/CSS/txt) so the plugin's dev server and Storybook show real content out of the box. public/ is dev-only — it's not in the package's published files. Also broadens the text-type classifier to cover common web text formats (css/scss/less/html/xml/vue/svelte/astro/env/ini/conf/sh) so they get an inline preview + text editor instead of the download-only 'other' fallback. Co-authored-by: opencode <noreply@opencode.ai>
…ne type filter - Fix broken images in the plugin dev server: in devMiddleware mode the SPA is served by Vite while ctx.views.hostStatic() mounts the raw bytes on the side-car origin, so origin-relative <img> URLs 404'd against Vite. Re-serve the managed directory on Vite's own origin in the dev config so the relative publicPath resolves. - Details view is now an in-layout right side panel (the listing shrinks beside it) instead of an overlay drawer; removed the Drawer component. - Replace the extension-filter dropdown with an always-visible inline type-filter chip row (image/video/audio/font/text/other) modeled on vitejs/devtools' DataSearchPanel; shared TYPE_META drives the chips and the tree icons. Co-authored-by: opencode <noreply@opencode.ai>
The managed public/ directory is already served by whatever host the plugin is mounted into (Vite, Nuxt, any framework serves public/ at /), so the plugin no longer stands up its own /__…-raw/ route. Each asset's publicPath is now baseURL + its path (baseURL default '/'), pointing at the host's own URLs. - Add baseURL option (where the host serves the dir) and serveStatic (self-serve, off by default). setupAssets only calls ctx.views. hostStatic() when serveStatic is set. - The standalone CLI is its own host, so createAssetsCli() enables serveStatic (under a dedicated base so it doesn't collide with the SPA). - Plugin dev server: point Vite's own publicDir at the managed dir so Vite serves the fixtures at /, and drop the ad-hoc raw-serving middleware. Gated to 'serve' so fixtures never bake into dist. - Docs + README + API snapshots updated. Co-authored-by: opencode <noreply@opencode.ai>
# Conflicts: # pnpm-lock.yaml # pnpm-workspace.yaml
…upload modal - Details panel is now a resizable right-hand side panel (default 480px, drag its left edge; width persists to localStorage) instead of a fixed w-96 column. - Upload button opens the native file picker directly and uploads the chosen files immediately — the file-grid/confirm modal is gone. Whole-frame drag-and-drop still works, now uploading dropped files directly with a lightweight non-blocking hint overlay (useFileDrop). - Remove the 'Edit' action from the details panel, and with it the now-orphaned write-text RPC (its only consumer). Text files still preview via read-text. Docs + API snapshots updated; the registration test no longer invokes the external-launching RPCs (which spawned OS processes and hung the runner) — it asserts registration on the server context instead. Co-authored-by: opencode <noreply@opencode.ai>
Swap the Preact SPA for Vue 3 SFCs consuming @antfu/design's Vue components directly (ActionButton, ActionIconButton, DisplayBadge, FormTextInput, FormCheckbox, LayoutTabs, LayoutToolbar, OverlayModal), matching the inspect/og plugins. Deletes the hand-rolled Preact UI kit (components/ui/*) in favour of the shared components; hooks become Vue composables; utils and the framework-neutral node/RPC layer are unchanged, so the package's public API (and its snapshots) is untouched. - package.json: preact/@preact/preset-vite/@storybook/preact-vite → vue/@vitejs/plugin-vue/@storybook/vue3-vite, plus reka-ui, floating-vue, colorjs.io (peer deps of the @antfu/design components used). tsconfig drops the Preact JSX options; uno content globs add .vue. - Preserves every behaviour: resizable side panel, inline type-filter chips, direct file-dialog upload + whole-frame drag hint, live refresh, multi-select bulk delete, host-served previews. - cleanupUnusedCatalogs pruned the now-unused @storybook/preact-vite catalog entry. Co-authored-by: opencode <noreply@opencode.ai>
# Conflicts: # pnpm-lock.yaml # turbo.json # vitest.config.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
@devframes/plugin-assets— a framework-neutral port of Nuxt DevTools' Assets tab. Manages the files under a directory (<cwd>/publicby default): search/filter, grid and tree views, a details panel (preview + metadata + ready-to-copy snippets), drag-and-drop upload, rename, multi-select delete, folder creation, and inline text editing. A livechokidarwatcher keeps every connected client in sync. Built as a Preact SPA — the first plugin to use Preact, further proving devframe's framework-neutral client layer (now Vue, React, Solid, Svelte, and Preact).Real byte serving (
<img>/<video>/downloads) goes throughctx.views.hostStatic(), and uploads stream over devframe's binary streaming-channel primitive rather than a base64-in-JSON action, so large files don't bloat the wire payload.Core changes in support of this
DevframeDefinition.capabilities.buildwas declared in the types but never consumed anywhere. Since a static export of this plugin can never carry real bytes (no live host to serve them) or write actions (excluded from every static dump already), it isn't a meaningful deployment target — so this wires that existing field up for real:createCacskips registering thebuildsubcommand whencapabilities.build === false.createBuildthrowsDF0042for the same case unless{ force: true }is passed, closing the gap for callers who invoke it directly, bypassing the CLI.capabilities: { build: false }by default (overridable via{ build: true }).Both covered by new tests (
packages/devframe/src/adapters/__tests__/{cac,build}.test.ts).Plugin surface
RPC (
devframes:plugin:assets:*):list,capabilities,read-image-meta,read-text(always registered) andupload,rename,delete,mkdir,write-text(registered only whenwriteis enabled — on by default;--read-only/{ write: false }to disable).open-in-editor/reveal-in-folderreuse devframe'slaunchEditor/openutilities, always registered regardless ofwrite.Options:
dir(default<cwd>/public),write(defaulttrue),uploadExtensions(defaults to Nuxt DevTools' own allow-list),build(defaultfalse, see above).Testing
plugins/assets/test/assets.test.ts— 14 integration tests over real HTTP+WS: list/capabilities, mkdir+streaming-upload+list, image/text reads, rename (extension-preserving, collision-checked), bulk delete, write-text, path-traversal and disallowed-extension rejection,write: falsegating, and the live change-broadcast.capabilities.buildincreateCac/createBuild.AssetPreview,AssetGridItem,Toolbar,CodeSnippets,AssetDetails).examples/minimal-vite-devframe-hubalongside every other built-in plugin.Full repo:
pnpm lint && pnpm typecheck && pnpm buildand the fullvitest run(907 tests) all pass locally.Docs
docs/plugins/assets.md(+ index/sidebar entries),docs/errors/DF0042.md.This PR was created with the help of an agent.