a plugin owns the routing under its mount
Reverts the manifest route table. Declaring a plugin's URLs to the platform put the platform in the middle of a decision that is not its own, and it was more code than what it replaced. One splat where there were two routes. A splat matches zero segments, so the bare route still works, and the plugin reads its own position off the location. The platform owns where a plugin starts and nothing after it — the same line mountPrefix already draws around its API. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -323,30 +323,7 @@ export type PluginManifest = {
|
||||
* third parties to `/p/<publisher>/` — so a third-party plugin declaring `screens` is refused. Without
|
||||
* that check this field would be a way for any installed plugin to shadow a core route.
|
||||
*/
|
||||
screens?: { segment: string; label: string; icon?: string; routes?: PluginRoute[] }[];
|
||||
|
||||
/**
|
||||
* The routes THIS screen has, when its sections deserve to be URLs rather than a query string.
|
||||
*
|
||||
* For the flat single-screen plugin. A plugin declaring `screens` puts its table on the screen entry
|
||||
* instead, because a route belongs to the screen it renders inside.
|
||||
*
|
||||
* ── Why a table and not a wildcard ──
|
||||
*
|
||||
* Every plugin screen already gets `/<route>` and `/<route>/:section` — enough to put a section in the
|
||||
* path and nothing more. What it cannot express is a SECOND segment (`/layout/header`, `/pages/home`)
|
||||
* or the thing that follows from it: a route arranging its panels differently from its neighbour.
|
||||
*
|
||||
* The platform could have guessed a deeper wildcard, and that is the version this replaces. Guessing
|
||||
* gives every plugin the same shape whether it wants it or not, and gives none of them a way to say
|
||||
* which arrangement belongs to which URL. A declared table says both, in the plugin's own words.
|
||||
*
|
||||
* ── Absent means unchanged ──
|
||||
*
|
||||
* No table and the screen gets the pair it always had. That is every plugin but this one, and the
|
||||
* reason nothing else had to change when this arrived — the same property `screens` was designed with.
|
||||
*/
|
||||
routes?: PluginRoute[];
|
||||
screens?: { segment: string; label: string; icon?: string }[];
|
||||
|
||||
/**
|
||||
* Paths under this plugin's own mount that are served ABOVE the account gate.
|
||||
@@ -675,35 +652,6 @@ export type DiscoveredPlugin = {
|
||||
} | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* One route within a screen: a path, and optionally its own arrangement of the screen's panels.
|
||||
*
|
||||
* ── The path is react-router's, appended to the screen's own ──
|
||||
*
|
||||
* `'layout/:band?'` on a plugin mounted at `/fofos-admin` matches `/fofos-admin/layout` and
|
||||
* `/fofos-admin/layout/header`. Optional segments are why one entry covers both; a plugin that wants
|
||||
* them to differ writes two entries and gives them different layouts.
|
||||
*
|
||||
* `''` is the index — the bare screen route.
|
||||
*
|
||||
* ── The layout is optional, and usually absent ──
|
||||
*
|
||||
* Omitted, the route renders the screen's own `web/layout.ts`. That is the common case: a route table
|
||||
* is worth declaring for the URLs alone, and most screens want one arrangement across all of them.
|
||||
*
|
||||
* Named, it is a path under `web/` to a module exporting `defaultLayout` — the same contract
|
||||
* `web/layout.ts` has, so a per-route layout is a file of the kind the author already writes.
|
||||
*
|
||||
* A layout gets its OWN persisted sizes, keyed by this path pattern. Two arrangements sharing one key
|
||||
* would have each remembering the other's dividers, which reads as a layout that will not stay put.
|
||||
*/
|
||||
export type PluginRoute = {
|
||||
/** React-router path, relative to the screen's route. `''` is the index. */
|
||||
path: string;
|
||||
/** `web/…` module exporting `defaultLayout`. Omitted = the screen's own. */
|
||||
layout?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* One frontend screen: a route, the panels on it, and how they are arranged.
|
||||
*
|
||||
@@ -740,14 +688,6 @@ export type DiscoveredScreen = {
|
||||
art: string | null;
|
||||
panels: string;
|
||||
layout: string;
|
||||
/**
|
||||
* The screen's route table, resolved.
|
||||
*
|
||||
* Empty for a screen that declared none, which is what keeps the old pair — `/<route>` and
|
||||
* `/<route>/:section` — the default. Each `layout` here is an absolute path, already checked to
|
||||
* exist at discovery, so the generator can import it without deciding anything.
|
||||
*/
|
||||
routes: { path: string; layout: string }[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user