feat: service-open + service-shiki wire services, with plugin migrations - #260
Merged
Conversation
The first two wire-service packages, under a new services/* workspace
glob:
- @devframes/service-open (devframes:service:open) — open-in-editor /
open-in-finder shared by every plugin: absolute paths only, contained
to the workspace root plus configured extra roots, editor commands
gated to KNOWN_EDITORS; options { editor?, roots? } merge across
installers (editor later-wins, roots union). Supersedes the per-plugin
recipes registrations, now marked deprecated.
- @devframes/service-shiki (devframes:service:shiki) — server-side
syntax highlighting so plugins stop re-bundling highlighters:
highlight (dual light/dark HTML), code-to-hast, code-to-tokens; all
cacheable + LRU-cached per (code, lang, themes); unknown languages
degrade to plain text; shiki loads lazily on first use; options
{ themes?, langs? } merge (themes later-wins, langs union).
Both ship their factory as the default export and contribute typed
declaration merges (RPC ids, node API, package→scope), so server and
client consumers are fully typed with zero shipped client code.
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
The expectations built paths with node:path (backslashes on Windows) while the service resolves through pathe (forward slashes). Also declare the pathe runtime dependency the service was getting via hoisting.
- messages: drops its commonRpcFunctions registration for a devframes:plugin:messages:open-file bridge that resolves workspace-relative file positions server-side and delegates to @devframes/service-open (declared in the definition's services); the panel gates its affordance on the service advertisement - assets: open-in-editor / reveal-in-folder delegate to service-open, installed at setup with the managed dir as an extra allowed root; the SPA hides both buttons until the service is advertised, and text-asset previews render server-highlighted through @devframes/service-shiki (declared optional) with the plain <pre> as fallback - docs + skill point at the service over the deprecated recipes
Invert the wire-services lifecycle so services are constructed and ready
BEFORE any setup() runs, and setup consumes them synchronously.
- adapters (initiate/build/mcp/embedded) install-loop -> ready() -> setup
- hub: two passes — dock+collect across all devframes (+ new
initHub({ services }) host-level channel) -> ready() once -> setups ->
configure -> ui.setup; installDevframe/prepareDevframe split accordingly
- ready() is internal; install() stays as the dynamic escape hatch
(immediate post-ready construct)
- descriptor options deep-merge by default (objects recurse, arrays
union-dedupe, scalars last-wins); both shipped services drop their
custom mergeOptions (hook kept as override)
- drop the first-connect safety net + DF0071
Consumers:
- assets declares both services (service-open with the factory-computed
managed dir as an allowed root) — no imperative install in setup;
drops its open-in-editor/reveal-in-folder RPCs (+ DP_ASSETS_0008) and
the client calls service-open directly with a new dev-only absolute
AssetInfo.fsPath (reveal passes the parent dir)
- messages harness mirrors the new ordering
Docs: guide/services.md rewritten to the pre-setup lifecycle; DF0071
page removed; error pages reworded.
# Conflicts: # docs/guide/services.md # packages/devframe/src/adapters/build.ts # packages/devframe/src/adapters/embedded.ts # packages/devframe/src/adapters/initiate.ts # packages/devframe/src/adapters/mcp/build-server.ts # packages/hub/src/node/install-devframe.ts
service-open now resolves a relative `path` against its workspaceRoot (absolute paths unchanged), so a client holding only a workspace-relative path can call it directly. The messages panel drops its `devframes:plugin:messages:open-file` bridge (and DP_MESSAGES_0002) and calls `devframes:service:open:open-in-editor` straight from the client. Removes the now-dead DS_OPEN_0001 (paths are no longer required absolute).
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.
What
PRs 2+3 of the wire-services series (#256 landed the core mechanism): the first two service packages under a new
services/*workspace tier, plus the plugin migrations onto them.@devframes/service-open—devframes:service:openOne host-level installation of open-in-editor / open-in-finder, replacing the per-plugin registrations of the
devframe/recipes/common-rpc-functionsrecipes (now@deprecated; removal is a future major).open-in-editortakes{ path, line?, column?, editor? };open-in-findertakes{ path }roots(DS_OPEN_0001/DS_OPEN_0002)KNOWN_EDITORSpicklist at the RPC boundary{ editor?, roots? }merge across installers: editor later-wins, roots union@devframes/service-shiki—devframes:service:shikiServer-side Shiki so plugin bundles stop shipping grammars and themes.
queryRPCs:highlight(dual light/dark HTML),code-to-hast,code-to-tokens— allcacheableclient-side, LRU-cached server-side per(code, lang, themes); unknown languages degrade to plain textlangswarm eagerly{ themes?, langs? }merge: themes later-wins (defaultsvitesse-light/vitesse-dark), langs unionMigrations
messages — drops its
commonRpcFunctionsregistration for adevframes:plugin:messages:open-filebridge: the plugin resolves workspace-relative file positions server-side and delegates to the open service's node API (no RPC hop), so the client never needs the server's filesystem layout. The panel's affordance is gated on the service advertisement (rpc.services.has(...), reactive viaservices.state()).assets —
open-in-editor/reveal-in-folderkeep their root-relative client posture and delegate to service-open, which the plugin installs at setup with the managed dir as an extra allowed root (it can live outside the workspace). The SPA hides both buttons until the service is advertised. Text-asset previews render server-highlighted through service-shiki (declared as an optionalservicesentry) with the plain<pre>as fallback — both fallback styles of the conditional-UI story exercised in one real plugin.git — stays as-is: its only code surface is the
@pierre/diffsdiff view, whose shiki adoption is the deferred diff-rebuild follow-up.Conventions
DS_<SLUG>_prefix; plugin additions use theirDP_<SLUG>_bandsservices/*glob wired through pnpm workspaces, turbo, knip, vitest projects, and source aliasesguide/services.mdBuilt-in services section; recipe/helper/plugin pages point at the servicesValidation
pnpm lint && pnpm knip && pnpm test && pnpm typecheck && pnpm buildall green (1201 tests, 108 files)ready()flowCreated with the help of an agent.