Contracts
Reference for every contract in @fleetbase/ember-core/contracts — MenuItem, MenuPanel, Widget, Hook, ExtensionComponent, Registry, TemplateHelper, BaseContract.
Contracts
The contracts in @fleetbase/ember-core/contracts are the canonical shapes you pass to the Universe sub-services. Use them — they validate inputs, normalize defaults, and serialize correctly when stored in registries.
Importing
import {
MenuItem,
MenuPanel,
Widget,
Hook,
ExtensionComponent,
Registry,
BaseContract,
} from '@fleetbase/ember-core/contracts';
// TemplateHelper is not in the index — import directly:
import TemplateHelper from '@fleetbase/ember-core/contracts/template-helper';MenuItem
Represents an entry in a menu — header, settings, admin, organization, user dropdown, or custom registry. Every menu registration accepts either a MenuItem instance or a plain object.
Construction
// Form 1: title + route (plus optional chainables)
new MenuItem('Fleet-Ops', 'console.fleet-ops')
.withIcon('route')
.withPriority(0)
.withDescription('Manage fleets, drivers, and live orders');
// Form 2: full definition object
new MenuItem({
title: 'Settings',
slug: 'my-extension',
icon: 'gear',
component: new ExtensionComponent('@my-org/my-engine', 'settings'),
});Properties
| Property | Default | Description |
|---|---|---|
title | — | Display text |
text, label | falls back to title | Aliases |
id | dasherized title | Stable identifier |
slug | dasherized title | URL-safe key — used as the registry key |
route | — | Ember route name |
section | — | Sub-section grouping (e.g. 'support') |
queryParams | {} | Forwarded to the Ember route |
routeParams | [] | Positional params |
view | dasherized title | View identifier (used for virtual routes) |
icon | 'circle-dot' | FontAwesome icon |
iconPrefix, iconSize, iconClass, iconComponent, iconComponentOptions | — | Icon overrides |
component | — | An ExtensionComponent for the rendered content |
componentParams | {} | Args forwarded to the component |
renderComponentInPlace | false | Render the component in-place rather than via a portal |
class, inlineClass, wrapperClass, overwriteWrapperClass | — | Styling hooks |
priority | 9 | Lower = appears first |
index | 0 | Secondary sort within priority |
type | 'default' | 'default' or 'link' |
buttonType | — | Button-style type |
onClick | — | (menuItem, universe) => void — auto-wrapped |
disabled, isLoading | false | UI state |
permission, intl | — | Permission key, i18n key |
items | — | Sub-items |
description | — | Shown in overflow / shortcuts |
shortcuts | [] | Array of { title, description, icon, route } for header items |
tags | [] | Searchable tags |
Chainables
withIcon, withPriority, withComponent, onClick, withSlug, withQueryParams, withRouteParams, inSection, atIndex, withType, withWrapperClass, withComponentParams, renderInPlace, withDescription, withShortcuts, withTags, addShortcut.
MenuPanel
A grouping of MenuItems — used for admin-settings panels.
import { MenuPanel, MenuItem } from '@fleetbase/ember-core/contracts';
const panel = new MenuPanel({
title: 'Fleet-Ops Config',
slug: 'fleet-ops',
items: [
new MenuItem({ title: 'Routing', icon: 'route', component: ... }),
new MenuItem({ title: 'Map', icon: 'map', component: ... }),
],
});Properties
| Property | Default | Description |
|---|---|---|
title | — | Panel heading |
slug | dasherized title | Key used as the registry slot |
icon | — | FontAwesome icon |
open | true | Initial expand state |
priority | 9 | Sort order |
items | [] | MenuItem array |
Chainables
withSlug, withIcon, withPriority, addItem, addItems.
In practice you don't construct MenuPanel directly — menuService.registerAdminMenuPanel(label, items, options) does it for you.
Widget
A dashboard widget descriptor.
Construction
new Widget({
id: 'fleet-ops-metrics',
name: 'Fleet-Ops Metrics',
description: 'Key metrics from Fleet-Ops',
icon: 'truck',
component: new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/fleet-ops-key-metrics'),
grid_options: { w: 12, h: 12, minW: 8, minH: 12 },
options: { title: 'Fleet-Ops Metrics' },
default: true,
});
// Or using chaining
new Widget('fleet-ops-metrics')
.withName('Fleet-Ops Metrics')
.withIcon('truck')
.withComponent(new ExtensionComponent('@fleetbase/fleetops-engine', 'widget/fleet-ops-key-metrics'))
.withGridOptions({ w: 12, h: 12, minW: 8, minH: 12 })
.asDefault();Properties
| Property | Default | Description |
|---|---|---|
id | — | Required unique widget identifier (alias widgetId accepted) |
name | — | Display name in the picker |
description | — | Short description shown in the picker |
icon | — | FontAwesome icon |
component | — | ExtensionComponent instance, plain object, or string component path |
grid_options | {} | { w, h, minW, minH } for grid-stack |
options | {} | Default options forwarded to the widget component |
category | 'default' | Picker category |
default (constructor only) | false | If true, auto-added to the default widget list |
Chainables
withName, withDescription, withIcon, withComponent, withGridOptions, withOptions, withCategory, asDefault, isDefault, withTitle, withRefreshInterval.
Hook
A lifecycle hook attached to a named event.
Construction
new Hook('console:after-model', (session, router) => {
// …
});
// With options
new Hook({
name: 'application:before-model',
handler: (session, router, transition) => { /* … */ },
priority: 10,
once: false,
enabled: true,
});
// Chaining
new Hook('console:before-model')
.execute((session, router) => { /* … */ })
.withPriority(20)
.once();Properties
| Property | Default | Description |
|---|---|---|
name | — | Event name ('console:after-model', 'application:before-model', etc.) |
handler | — | The callback function |
priority | 0 | Lower numbers run first |
runOnce | false | If true, the hook removes itself after firing |
id | auto-guid | Unique identifier — pass to removeHook(name, id) |
enabled | true | When false, the hook is skipped |
Chainables
execute, withPriority, once, withId, setEnabled, enable, disable, withMetadata.
ExtensionComponent
A reference to a component that lives in another engine. Used wherever a component is rendered cross-engine — menu items, widgets, registries.
Construction
Three forms:
// Form 1: string component path inside an engine
new ExtensionComponent('@fleetbase/storefront-engine', 'storefront-order-summary');
// Form 2: a component class directly
import MyComponent from '../components/my-component';
new ExtensionComponent('@my-org/my-engine', MyComponent);
// Form 3: full options object
new ExtensionComponent('@my-org/my-engine', {
path: 'components/my-component',
loadingComponent: 'spinner',
errorComponent: 'error-fallback',
});Properties
| Property | Description |
|---|---|
engine | Engine name ('@fleetbase/storefront-engine') |
path | Component path within the engine (string form) |
class | Component class (when constructed from a class) |
name | Resolved component name |
isClass | true when constructed from a class |
loadingComponent | Component shown while the engine is loading |
errorComponent | Component shown if loading fails |
Chainables
withLoadingComponent, withErrorComponent, withData, withTimeout.
Registry
Represents a named registry. Most code refers to registries by string name ('header', 'fleet-ops:component:order:details', etc.) — Registry is an explicit class for cases where you want to manipulate or namespace one in code.
new Registry('my-extension:sidebar');Chainables
withNamespace, withSubNamespace. toString() returns the registry name.
In practice, prefer registryService.createRegistry('my-extension:sidebar') — it normalizes and registers the name in one step.
TemplateHelper
A reference to a helper that lives in another engine. Used by registryService.registerHelper() for lazy-loaded helpers.
import TemplateHelper from '@fleetbase/ember-core/contracts/template-helper';
// Lazy from another engine
new TemplateHelper('@fleetbase/storefront-engine', 'helpers/calculate-delivery-fee');
// Or a direct class
new TemplateHelper(null, MyHelperClass);| Property | Description |
|---|---|
engineName | Engine name (or null for direct class) |
path | Helper path within the engine |
class | Helper class (when constructed directly) |
isClass | true for direct-class form |
name | Resolved helper name |
BaseContract
The shared base class. You won't construct it directly, but every contract above extends it.
| Method | Description |
|---|---|
setup() | Subclasses call this after setting properties — triggers validation |
validate() | Override to add validation logic |
toObject() | Plain JS object for serialization |
setOption(k, v), getOption(k, default?), hasOption(k), removeOption(k), getOptions() | Arbitrary options bag stored on _options |
Internal-Only Contracts
These exist in source but aren't intended for direct extension use. They power Universe internals:
ExtensionBootState— shared boot stateHookRegistry— internal hook storageUniverseRegistry— internal registry storage
You'll only encounter them when reading source or extending Universe itself.
Source
| File | Description |
|---|---|
addon/contracts/index.js | Public exports |
addon/contracts/menu-item.js | MenuItem |
addon/contracts/menu-panel.js | MenuPanel |
addon/contracts/widget.js | Widget |
addon/contracts/hook.js | Hook |
addon/contracts/extension-component.js | ExtensionComponent |
addon/contracts/registry.js | Registry |
addon/contracts/template-helper.js | TemplateHelper |
addon/contracts/base-contract.js | BaseContract |