Skip to content

Commit 47cd0a1

Browse files
committed
Merge origin/main into feat/git-inhouse-diff-shiki
Reconcile the in-house diff renderer with #263's @devframes/service-git refactor: the shared git types (GitDiff, FileStatusCode, CommitDetail) now come from @devframes/service-git, and the RPC scope moved to devframes:service:git:*. Combine the two service declarations (service-git + service-shiki) into one array on the git devframe, and drop the leftover @pierre/diffs/@pierre/theme lockfile entries.
2 parents 2ec0347 + 01d8d08 commit 47cd0a1

137 files changed

Lines changed: 3136 additions & 1591 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

alias.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const alias = {
1111
'devframe/rpc/transports/sse-client': r('devframe/src/rpc/transports/sse-client.ts'),
1212
'devframe/rpc/transports/sse-server': r('devframe/src/rpc/transports/sse-server.ts'),
1313
'devframe/rpc/transports/ws-bun': r('devframe/src/rpc/transports/ws-bun.ts'),
14+
'devframe/rpc/transports/ws-deno': r('devframe/src/rpc/transports/ws-deno.ts'),
1415
'devframe/rpc/transports/ws-server': r('devframe/src/rpc/transports/ws-server.ts'),
1516
'devframe/rpc/transports/ws-client': r('devframe/src/rpc/transports/ws-client.ts'),
1617
'devframe/rpc/client': r('devframe/src/rpc/client.ts'),
@@ -132,6 +133,7 @@ export const alias = {
132133
'@devframes/plugin-assets/cli': p('assets/src/cli.ts'),
133134
'@devframes/plugin-assets/vite': p('assets/src/vite.ts'),
134135
'@devframes/plugin-assets': p('assets/src/index.ts'),
136+
'@devframes/service-git': s('git/src/index.ts'),
135137
'@devframes/service-open': s('open/src/index.ts'),
136138
'@devframes/service-shiki': s('shiki/src/index.ts'),
137139
}

docs/.vitepress/config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ function examplesItems(prefix: string) {
129129
{ text: 'hub-next-minimal', link: `${prefix}/examples/hub-next-minimal` },
130130
{ text: 'hub-nitro-minimal', link: `${prefix}/examples/hub-nitro-minimal` },
131131
{ text: 'hub-hono-minimal', link: `${prefix}/examples/hub-hono-minimal` },
132+
{ text: 'hub-fastify-minimal', link: `${prefix}/examples/hub-fastify-minimal` },
133+
{ text: 'hub-sveltekit-minimal', link: `${prefix}/examples/hub-sveltekit-minimal` },
134+
{ text: 'hub-deno-minimal', link: `${prefix}/examples/hub-deno-minimal` },
132135
{ text: 'hub-rsbuild-minimal', link: `${prefix}/examples/hub-rsbuild-minimal` },
133136
] satisfies DefaultTheme.NavItemWithLink[]
134137
}

docs/examples/hub-deno-minimal.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# hub-deno-minimal
6+
7+
The minimal [Deno](https://deno.com) host for [`@devframes/hub`](/guide/hub): one `initHub()` call served through `Deno.serve`, the UI supplied by `@devframes/hub-ui`.
8+
9+
Package: `hub-deno-minimal` · framework: **Deno**
10+
11+
## What it shows
12+
13+
- `initHub({ base, devframes, ui: createUi() })` in `src/hub.ts`, memoized on `globalThis`. No transport option, so the entry wires the socket itself.
14+
- `Deno.serve(options, handler)` serves HTTP (web `Request``Response`), and the whole namespace flows through `hub.handler(request)`.
15+
- WebSockets arrive as fetch upgrades, so `src/server.ts` binds Deno's transport with `createContextRpcServer` + `attachDenoWsTransport` (crossws' Deno adapter) and answers `${hub.base}__ws` on the app's own origin. crossws attaches the socket to the `Response` its `handleUpgrade` returns, so there is no separate `websocket` handler object.
16+
17+
## Run it
18+
19+
```sh
20+
pnpm install
21+
pnpm --filter hub-deno-minimal dev
22+
```
23+
24+
## Source
25+
26+
[`examples/hub-deno-minimal`](https://github.com/devframes/devframe/tree/main/examples/hub-deno-minimal)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# hub-fastify-minimal
6+
7+
The minimal [Fastify](https://fastify.dev) host for [`@devframes/hub`](/guide/hub): one `initHub()` call mounted through Fastify's connect-middleware layer, the UI supplied by `@devframes/hub-ui`.
8+
9+
Package: `hub-fastify-minimal` · framework: **Fastify**
10+
11+
## What it shows
12+
13+
- `initHub({ base, devframes, ui: createUi() })` in `src/hub.ts`, memoized on `globalThis`. No transport option, so the socket rides Fastify's own server.
14+
- Fastify is the `nodeMiddleware` host: `src/server.ts` registers `hub.nodeMiddleware` — the same `(req, res, next)` shape Vite's dev server consumes — through [`@fastify/middie`](https://github.com/fastify/middie). Requests under `${hub.base}` are served by the hub; the rest fall through `next()` to Fastify's routes.
15+
- `hub.attach(fastify.server)` routes the HTTP server's upgrade events to the RPC socket at `${hub.base}__ws`, on the app's own origin — no side-car port.
16+
17+
## Run it
18+
19+
```sh
20+
pnpm install
21+
pnpm --filter hub-fastify-minimal dev
22+
```
23+
24+
## Source
25+
26+
[`examples/hub-fastify-minimal`](https://github.com/devframes/devframe/tree/main/examples/hub-fastify-minimal)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# hub-sveltekit-minimal
6+
7+
The minimal [SvelteKit](https://svelte.dev/docs/kit) host for [`@devframes/hub`](/guide/hub): one `initHub()` call behind a single catch-all endpoint, the UI supplied by `@devframes/hub-ui`.
8+
9+
Package: `hub-sveltekit-minimal` · framework: **SvelteKit**
10+
11+
## What it shows
12+
13+
- `initHub({ base, devframes, ui: createUi() })` in `src/hub.ts`, memoized on `globalThis`. The RPC socket runs on a side-car port (`ws: { sidecar: true }`) advertised via `__connection.json` — SvelteKit's `+server.ts` handlers hand over `Request`s and never see WebSocket upgrades, so the hub takes a socket of its own.
14+
- `src/routes/__devframes/[...path]/+server.ts` mounts the whole namespace: `fallback` answers every method with `hub.handler(event.request)`, and the `[...path]` rest param matches the namespace root as well as everything beneath it.
15+
- The endpoint exports `trailingSlash = 'ignore'` so SvelteKit serves the hub's trailing-slash URLs (the standalone viewer and each frame SPA) verbatim instead of 308-redirecting them, and `src/app.html` injects `${hub.base}embedded.js` to mount the floating dock.
16+
17+
## Run it
18+
19+
```sh
20+
pnpm install
21+
pnpm --filter hub-sveltekit-minimal dev
22+
```
23+
24+
## Source
25+
26+
[`examples/hub-sveltekit-minimal`](https://github.com/devframes/devframe/tree/main/examples/hub-sveltekit-minimal)

docs/examples/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ The **minimal** family instead mounts one `initHub({ ui: createUi() })` handler
2323
| [hub-next-minimal](./hub-next-minimal) | Next.js | The hub handler on an App Router catch-all route. |
2424
| [hub-nitro-minimal](./hub-nitro-minimal) | Nitro | The hub handler on a Nitro catch-all route. |
2525
| [hub-hono-minimal](./hub-hono-minimal) | Hono | The hub handler on Hono, running on Node and Bun. |
26+
| [hub-fastify-minimal](./hub-fastify-minimal) | Fastify | The hub handler on Fastify via `nodeMiddleware`. |
27+
| [hub-sveltekit-minimal](./hub-sveltekit-minimal) | SvelteKit | The hub handler on a SvelteKit catch-all endpoint. |
28+
| [hub-deno-minimal](./hub-deno-minimal) | Deno | The hub handler on `Deno.serve`, with a Deno fetch-upgrade socket. |
2629
| [hub-rsbuild-minimal](./hub-rsbuild-minimal) | Rsbuild | The hub handler on Rsbuild's dev middleware. |
2730

2831
## Run any example

docs/guide/devframe-definition.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export default defineDevframe({
5454
| `duplicationStrategy` | `'warn' \| 'silent' \| 'throw' \| 'duplicate'` | How a hub reacts when another devframe sharing this `id` is mounted onto the same hub. Defaults to `'warn'`. See [Hub](./hub). Hub adapters consult it; standalone adapters ignore it. |
5555
| `capabilities` | `{ dev?, build? }` | Per-runtime feature flags. A `boolean` applies to the runtime as a whole; an object enables individual features. |
5656
| `services` | `DevframeServiceInput[]` | Wire services this devframe consumes — descriptors (`{ package, version?, required?, options? }`) the adapter imports against the plugin's own dependencies, or ready definitions. See [Cross-Plugin Services](./services#wire-services). |
57+
| `rpc` | `{ snapshot?: (string \| { method, inputs })[] }` | RPC-level config. `rpc.snapshot` opts an RPC function this devframe doesn't own (e.g. a wire service's) into the static build's dump. A bare method id bakes the no-argument call; `{ method, inputs }` bakes one record per argument-tuple, where `inputs` is a list of tuples or an async `(ctx) => tuples` provider (so it can enumerate at build time via the service's node API). The first tuple's result becomes the fallback. |
5758
| `setup` | `(ctx, info?) => void \| Promise<void>` | **Required.** Server-side entry point. Runs in every runtime. The optional second argument carries runtime metadata — most notably the parsed CLI `flags` when running under `createCac`. |
5859
| `cli` | `DevframeCliOptions` | Defaults for the CLI adapter. See [CLI options](#cli-options) below. |
5960

docs/guide/hub-initiate.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const hub = initHub({
2222

2323
## The shared socket
2424

25-
One transport serves the whole namespace, and the hub binds nothing on its own — the same four choices `initDevframe` offers, in the same precedence: `ws.port` pins a side-car, `server` shares the host's `node:http` upgrade at `<base>__ws`, `ws: { sidecar: true }` takes a free port (for Next.js, Nitro and Rsbuild hosts, whose handlers never see upgrades), and passing none of them leaves the socket to the host:
25+
One transport serves the whole namespace, and the hub binds nothing on its own — the same four choices `initDevframe` offers, in the same precedence: `ws.port` pins a side-car, `server` shares the host's `node:http` upgrade at `<base>__ws`, `ws: { sidecar: true }` takes a free port (for Next.js, Nitro, SvelteKit and Rsbuild hosts, whose handlers never see upgrades), and passing none of them leaves the socket to the host — a Node host hands over its server with `hub.attach(server)`, and Bun and Deno hosts complete the upgrade on their own origin with `attachBunWsTransport` / `attachDenoWsTransport`:
2626

2727
```ts
2828
import { serve } from '@hono/node-server'
@@ -125,4 +125,4 @@ Hosts that assemble `createHubContext` + `ctx.install` themselves (with their ow
125125
const hub = initHub({ base: DEVFRAMES_HUB_BASE, context: ctx })
126126
```
127127

128-
The instance then serves the hub-level endpoints and transport only; serve each frame's meta from `hub.connectionMeta()` yourself. The two reference examples — `examples/hub-vite` and `examples/hub-next` — use the declarative mode with their own hand-built viewer UIs, while the `hub-*-minimal` family (`hub-vite-minimal`, `hub-next-minimal`, `hub-nitro-minimal`, `hub-hono-minimal`, `hub-rsbuild-minimal`) shows the minimal `createUi()` mount across frameworks (the Hono one on Node and Bun).
128+
The instance then serves the hub-level endpoints and transport only; serve each frame's meta from `hub.connectionMeta()` yourself. The two reference examples — `examples/hub-vite` and `examples/hub-next` — use the declarative mode with their own hand-built viewer UIs, while the `hub-*-minimal` family (`hub-vite-minimal`, `hub-next-minimal`, `hub-nitro-minimal`, `hub-hono-minimal`, `hub-fastify-minimal`, `hub-sveltekit-minimal`, `hub-deno-minimal`, `hub-rsbuild-minimal`) shows the minimal `createUi()` mount across frameworks (the Hono one on Node and Bun, the Deno one on `Deno.serve`).

docs/guide/services.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ state.on('updated', render)
155155

156156
**`@devframes/service-open`** (`devframes:service:open`) opens files in the user's editor (`open-in-editor`, with optional `line`/`column`) or reveals them in the OS file explorer (`open-in-finder`). Paths may be absolute or relative to the workspace root (so a client with only a workspace-relative path — a message's file position, say — calls it directly); the service refuses anything outside the workspace root and the configured extra `roots` (`DS_OPEN_0002`), and gates editor commands to the `KNOWN_EDITORS` picklist. Options: `{ editor?, roots? }` — the preferred editor (later installer wins) and additional openable directories (merged as a union). It supersedes the per-plugin `devframe/recipes/common-rpc-functions` registrations, now deprecated.
157157

158+
**`@devframes/service-git`** (`devframes:service:git`) runs read/write git operations over RPC — `status`, `log`, `show`, `diff`, `branches`, `stage`, `unstage`, `commit` — with parsed, typed results, so a devframe (the git plugin, or any tool) consumes git without shelling out itself. It operates on a single repo fixed at install (`{ cwd? }`, defaulting to the context cwd; root discovered once). Write ops are always exposed — authorization is the host's connection-trust boundary. The service defines no `dump`/`snapshot`; a devframe bakes the read ops it wants into a static build via [`rpc.snapshot`](./devframe-definition). Client-supplied revisions are guarded against option injection.
159+
158160
**`@devframes/service-shiki`** (`devframes:service:shiki`) renders [Shiki](https://shiki.style) syntax highlighting on the server, so plugin bundles stop shipping grammars and themes. Three RPC queries — `highlight` (dual-theme HTML), `code-to-hast`, and `code-to-tokens` (for renderers that own their DOM, e.g. diff views) — all client-`cacheable` and LRU-cached server-side per `(code, lang, themes)`. Unknown languages degrade to plain text. Options: `{ themes?, langs? }` — the default light/dark pair (defaults `vitesse-light`/`vitesse-dark`, matching the design system; later installer wins) and languages to eagerly load (merged as a union).
159161

160162
## Services, RPC, or shared state?

examples/a11y-messages-playground/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "a11y-messages-playground",
33
"type": "module",
4-
"version": "0.9.1",
4+
"version": "0.9.2",
55
"private": true,
66
"description": "Hub playground that pairs the a11y and messages plugins over a demo app full of accessibility issues.",
77
"homepage": "https://github.com/devframes/devframe/tree/main/examples/a11y-messages-playground",

0 commit comments

Comments
 (0)