feat(web): add read-only Loader plugin inventory
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
/** Read-only projection of the current Cordis Loader plugin entries. */
|
||||
|
||||
import type { Context, FiberState } from '@deepseek-ai/cordis'
|
||||
import type {} from '@deepseek-ai/cordis-plugin-loader'
|
||||
import { GatewayService, Remote } from '@deepseek-ai/dsh-type-meta'
|
||||
// TypeRT-generated ./typert and ./remote artifacts import Zod at runtime.
|
||||
import type {} from 'zod'
|
||||
import type {
|
||||
PluginEntryId,
|
||||
PluginFiberPhase,
|
||||
PluginInventoryEntry,
|
||||
PluginInventorySnapshot,
|
||||
} from './types.ts'
|
||||
|
||||
export type * from './types.ts'
|
||||
|
||||
/** Brand an existing Loader-tree entry id at the owning boundary. */
|
||||
function pluginEntryId(value: string): PluginEntryId {
|
||||
return value as PluginEntryId
|
||||
}
|
||||
|
||||
/** Runtime mirror: FiberState is a cross-package const enum. */
|
||||
const FIBER_STATE = {
|
||||
PENDING: 0 as FiberState.PENDING,
|
||||
LOADING: 1 as FiberState.LOADING,
|
||||
ACTIVE: 2 as FiberState.ACTIVE,
|
||||
FAILED: 3 as FiberState.FAILED,
|
||||
DISPOSED: 4 as FiberState.DISPOSED,
|
||||
UNLOADING: 5 as FiberState.UNLOADING,
|
||||
} as const
|
||||
|
||||
/** Complete public projection of Cordis Fiber states. */
|
||||
const FIBER_PHASE = {
|
||||
[FIBER_STATE.PENDING]: 'pending',
|
||||
[FIBER_STATE.LOADING]: 'loading',
|
||||
[FIBER_STATE.ACTIVE]: 'active',
|
||||
[FIBER_STATE.FAILED]: 'failed',
|
||||
[FIBER_STATE.DISPOSED]: null,
|
||||
[FIBER_STATE.UNLOADING]: 'unloading',
|
||||
} as const satisfies Record<FiberState, PluginFiberPhase>
|
||||
|
||||
/** Remote-only service exposing the Loader's current non-group entry state. */
|
||||
export class PluginInventoryService extends GatewayService {
|
||||
static inject = ['loader']
|
||||
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'pluginInventory')
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the Loader directly on every call. Cordis's internal plugin/status
|
||||
* events already maintain Entry.fiber and Fiber.state, so a second cache
|
||||
* would only add another lifecycle truth to keep synchronized.
|
||||
* @returns Current non-group Loader entries in Loader order.
|
||||
*/
|
||||
@Remote('list')
|
||||
list(): PluginInventorySnapshot {
|
||||
const entries: PluginInventoryEntry[] = []
|
||||
for (const entry of this.ctx.loader.entries()) {
|
||||
if (entry.options.group) continue
|
||||
entries.push({
|
||||
entryId: pluginEntryId(entry.id),
|
||||
displayId: entry.options.id,
|
||||
enabled: !entry.disabled,
|
||||
fiberPhase: entry.fiber === undefined ? null : FIBER_PHASE[entry.fiber.state],
|
||||
})
|
||||
}
|
||||
return { entries }
|
||||
}
|
||||
}
|
||||
|
||||
export default PluginInventoryService
|
||||
@@ -0,0 +1,20 @@
|
||||
/** Package-owned invariant companion. @module @deepseek-ai/dsh-host-plugin-inventory/invariant */
|
||||
|
||||
/* jscpd:ignore-start */
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import type { InvariantInstaller } from '@deepseek-ai/dsh-invariants'
|
||||
|
||||
const PACKAGE_NAME = '@deepseek-ai/dsh-host-plugin-inventory'
|
||||
|
||||
/** Cordis companion plugin name. */
|
||||
export const name = 'host-plugin-inventory-invariant'
|
||||
/** Service required before the companion can reserve package ownership. */
|
||||
export const inject = ['invariants']
|
||||
|
||||
/** No runtime invariant: every snapshot is projected directly from Loader-owned state. */
|
||||
const install: InvariantInstaller = () => {}
|
||||
|
||||
/** Register this package's invariant companion. */
|
||||
export const apply = (ctx: Context): Promise<() => void> =>
|
||||
Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install))
|
||||
/* jscpd:ignore-end */
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { Branded } from '@deepseek-ai/dsh-brand'
|
||||
|
||||
/** Stable Loader-tree identity of one configured plugin entry. */
|
||||
export type PluginEntryId = Branded<'PluginEntryId'>
|
||||
|
||||
/** Lifecycle state of an entry's root Fiber, or null when it has no live root Fiber. */
|
||||
export type PluginFiberPhase =
|
||||
| 'pending'
|
||||
| 'loading'
|
||||
| 'active'
|
||||
| 'failed'
|
||||
| 'unloading'
|
||||
| null
|
||||
|
||||
/** One non-group Loader entry exposed to trusted clients. */
|
||||
export interface PluginInventoryEntry {
|
||||
readonly entryId: PluginEntryId
|
||||
/** Local Loader id used as the compact card title. */
|
||||
readonly displayId: string
|
||||
/** Effective Loader enablement, including disabled ancestor groups. */
|
||||
readonly enabled: boolean
|
||||
readonly fiberPhase: PluginFiberPhase
|
||||
}
|
||||
|
||||
/** Point-in-time inventory returned by the plugin inventory Remote. */
|
||||
export interface PluginInventorySnapshot {
|
||||
readonly entries: readonly PluginInventoryEntry[]
|
||||
}
|
||||
Reference in New Issue
Block a user