@ortha/admin-platform-plugin-registry
v0.0.4
Published
The foundational types and service factories for the Ortha admin plugin system. Every admin package depends on this — it defines the plugin contract, provides the plugin registry, routing and slot services, validation, and topological sort for dependency
Readme
@ortha/admin-platform-plugin-registry
The foundational types and service factories for the Ortha admin plugin system. Every admin package depends on this — it defines the plugin contract, provides the plugin registry, routing and slot services, validation, and topological sort for dependency resolution.
Installation
Internal monorepo dependency — import directly:
import type {
AdminPlugin,
AdminPluginContext
} from '@ortha/admin-platform-plugin-registry';
import {
pluginRegistry,
routerService,
slotService
} from '@ortha/admin-platform-plugin-registry';Usage
Defining a plugin
import type { AdminPlugin } from '@ortha/admin-platform-plugin-registry';
const myPlugin = (): AdminPlugin =>
Object.freeze({
id: 'my-plugin',
name: 'My Plugin',
dependencies: ['core'],
setup(ctx) {
ctx.router.addRoute({
path: '/my-page',
component: MyPage
});
ctx.slots.fill(SLOT_TOPBAR_NAV_MAIN_ACTIONS, MyNavButton, {
order: 10
});
}
});Creating services
import {
pluginRegistry,
routerService,
slotService,
pluginContext
} from '@ortha/admin-platform-plugin-registry';
const registry = pluginRegistry();
const router = routerService();
const slots = slotService();
// Create a scoped context for a specific plugin
const ctx = pluginContext({
pluginId: 'my-plugin',
registry,
router,
slots,
config: {}
});Validation and load ordering
import {
validate,
resolveLoadOrder
} from '@ortha/admin-platform-plugin-registry';
// Validate plugins before setup
validate(plugins);
// Resolve topological order based on dependencies
const sorted = resolveLoadOrder(plugins);API Reference
Types
| Export | Kind | Description |
| --------------------- | ---- | ------------------------------------------------------------------------ |
| AdminPlugin | type | Contract every plugin must satisfy (id, name, setup) |
| AdminPluginContext | type | DI context passed to setup() — registry, router, slots, config |
| AdminPluginRegistry | type | Central registry — register(), get(), getAll(), isRegistered() |
| RouteDefinition | type | Route descriptor (path, component, meta) |
| SlotDefinition | type | Slot fill descriptor (key, component, order) |
| SlotFill | type | Resolved fill stored by SlotService |
| RouterService | type | Route collection — addRoute(), getRoutes() |
| SlotService | type | Slot management — fill(), getSlot(), getAll() |
| AdminConfig | type | Open config object (basePath, debug, extensible) |
Factories
| Export | Kind | Description |
| ------------------ | ------- | --------------------------------------------------------- |
| pluginRegistry() | factory | Creates a Map-backed plugin registry |
| routerService() | factory | Creates a route collection service |
| slotService() | factory | Creates a slot management service (auto-sorts by order) |
| pluginContext() | factory | Creates a scoped context for a single plugin's setup() |
Utilities
| Export | Kind | Description |
| -------------------- | ---- | ------------------------------------------------------------ |
| validate() | util | Checks required fields, duplicate IDs, and resolvable deps |
| resolveLoadOrder() | util | Topological sort via Kahn's algorithm; detects circular deps |
Internal Structure
src/lib/
├── types/index.ts # All shared type definitions
├── pluginRegistry/index.ts # Map-backed registry factory
├── pluginContext/index.ts # Scoped context builder
├── services/
│ ├── index.ts # Barrel
│ ├── routerService/index.ts # Route collection
│ └── slotService/index.ts # Slot fill management
└── utils/
├── index.ts # Barrel
├── validate/index.ts # Plugin validation
└── resolveLoadOrder/index.ts # Kahn's topological sortKey Patterns
- All factory return values are frozen with
Object.freeze(). validate()runs before any services are instantiated — fail fast.resolveLoadOrder()uses Kahn's algorithm; throws on circular dependencies.pluginContext()wrapsSlotService.fill()to auto-inject the calling plugin's ID.- Plugins must never import each other directly — all cross-plugin communication goes through context services.
Building
nx build admin-platform-plugin-registry