FleetbaseFleetbase

Decorators

Property decorators from @fleetbase/ember-core for cross-engine service injection and lazy data loading: @engineService, @fromStore, and @fetchFrom.

Decorators

@fleetbase/ember-core ships three custom property decorators for the patterns Ember's built-in @service doesn't cover: pulling a service from another engine, lazily querying the store on first access, and lazily fetching from the API on first access.

@engineService

Inject a service that lives in another engine. Useful when an extension needs Fleet-Ops's location service, Storefront's cart, etc. — a regular @service can't see across engine boundaries.

import Component from '@glimmer/component';
import engineService from '@fleetbase/ember-core/decorators/engine-service';

export default class OrderTrackingLookup extends Component {
    @engineService('@fleetbase/fleetops-engine') location;
    @engineService('@fleetbase/fleetops-engine') movementTracker;
    // …
}

Real example: packages/fleetops/addon/components/order-tracking-lookup.js:21.

Signature

@engineService(engineName, options?) propertyName;
ArgumentDescription
engineNameThe engine package name (e.g. '@fleetbase/fleetops-engine')
optionsOptional { serviceName } — defaults to the property name if you want a different service name
Property nameDefaults to the lookup name (locationservice:location in the target engine)

How It Works

The decorator resolves to a computed property that, on first access, loads the target engine via extensionManager.ensureEngineLoaded(engineName) and looks up the service from the engine's container. The first access is async — guard it accordingly. Subsequent accesses return the cached service synchronously.

When to Use

  • Cross-engine integrations that can't be expressed via ExtensionComponent or registry slots
  • Triggering an action in another engine from your component or controller
  • Reading state from a service whose owning engine is loaded on demand

When in doubt, prefer registering a renderable component via the Registry Service — it avoids touching the target engine's container at all.

@fromStore

Lazily query the Ember Data store on first access of a tracked property:

import fromStore from '@fleetbase/ember-core/decorators/from-store';

export default class WebhooksController extends Controller {
    @fromStore('api-credential', { limit: -1 }) apiCredentials;
}

Equivalent to writing:

get apiCredentials() {
    return this.store.query('api-credential', { limit: -1 });
}

…except it caches the resolved value instead of re-querying on every access, and you don't have to keep referencing this.store.

Signature

@fromStore(modelName, query?, options?) propertyName;
ArgumentDescription
modelNameEmber Data model name (e.g. 'api-credential')
queryQuery hash forwarded to store.query()
optionsAdapter options forwarded as the third arg, plus onComplete(response, this) callback

The first read returns a Promise; assign-on-resolve lets a template auto-rerender once the data lands. If the query fails the property is set to null.

There's also a legacy-from-store variant for code on classic Ember objects (computed-style); the modern decorator is the default.

@fetchFrom

Same idea as @fromStore, but for raw API endpoints via the fetch service — not Ember Data:

import fetchFrom from '@fleetbase/ember-core/decorators/fetch-from';

export default class WebhooksViewController extends Controller {
    @fetchFrom('webhook-endpoints/events') webhookEvents;
    @fetchFrom('webhook-endpoints/versions') apiVersions;
}

Equivalent to:

get webhookEvents() {
    return this.fetch.get('webhook-endpoints/events');
}

…with the same caching + auto-set behavior as @fromStore.

Signature

@fetchFrom(endpoint, query?, options?) propertyName;
ArgumentDescription
endpointPath passed to fetch.get() (relative to your API base)
queryQuery parameters serialized into the URL
optionsForwarded to fetch.get() as the options bag, plus onComplete(response, this)

Real example: packages/dev-engine/addon/controllers/webhooks/view.js:25.

When to Reach for Each

Want…Use
A service from another engine@engineService
Ember Data records, lazy-loaded@fromStore
Raw API JSON, lazy-loaded@fetchFrom
A service from your own enginePlain @service (Ember built-in)
Eager data needed before renderRoute's model() hook

Source

FileDescription
addon/decorators/engine-service.jsCross-engine service decorator
addon/decorators/from-store.jsLazy store.query decorator
addon/decorators/fetch-from.jsLazy fetch.get decorator
addon/utils/inject-engine-service.jsUnderlying engine-service resolver
Decorators | Fleetbase