ui/docs/ember-engines.md
This is a quickstart guide inspired by ember engine quickstart on how to set up an ember engine in Vault!
ember g in-repo-engine <engine-name>
This blueprint in-repo engine command will add a new folder lib/<engine-name> and add the engine to our main app’s package.json
{
"name": "<engine-name>",
"dependencies": {
"ember-cli-htmlbars": "*",
"ember-cli-babel": "*"
},
"ember-addon": {
"paths": ["../core"]
}
}
For our application, we want to include the ember-addon path ../core
By adding this ember-addon path, we are able to share elements between your in-repo addon and the Vault application1.
In the engine’s index.js file:
/**
* Copyright IBM Corp. 2016, 2025
* SPDX-License-Identifier: BUSL-1.1
*/
/* eslint-disable node/no-extraneous-require */
const { buildEngine } = require('ember-engines/lib/engine-addon');
module.exports = buildEngine({
name: '<engine-name>',
lazyLoading: {
enabled: false,
},
isDevelopingAddon() {
return true;
},
});
Within your Engine’s config/environment.js file:
/**
* SPDX-License-Identifier: BUSL-1.1
*/
// config/environment.js
'use strict';
module.exports = function (environment) {
const ENV = {
modulePrefix: '<engine-name>',
environment: environment,
};
return ENV;
};
Within your Engine’s addon/engine.js file:
/**
* SPDX-License-Identifier: BUSL-1.1
*/
import Engine from '@ember/engine';
import loadInitializers from 'ember-load-initializers';
import Resolver from 'ember-resolver';
import config from './config/environment';
const { modulePrefix } = config;
export default class <EngineName>Engine extends Engine {
modulePrefix = modulePrefix;
Resolver = Resolver;
dependencies = {
services: ['app-router', 'store', 'secret-mount-path', 'flash-messages'],
externalRoutes: ['secrets'],
};
}
loadInitializers(<EngineName>Engine, modulePrefix);
The services in the example above are common services that we often use in our engines. If your engine requires other services from the main application, add them to the services array.
The external route dependencies allow you to link to a route outside of your engine. In this example, we list 'secrets' in the externalRoute and the route is defined in the app.js file.
LinkToExternal component from your engine, you need to add the route to the app/app.js and your engine’s addon/engine.js. More information on Linking to An External Context..application.hbs:application.hbs file (to see if your engine was set up correctly).application.hbs template file. If nothing will be added to it and it remains as just an {{outlet}} it can safely be removed.In our app/app.js file in the engines object, add your engine’s name and dependencies. The router service must be referenced via an alias within engines. The pattern is to use app-router as the alias, see example below.
/**
* SPDX-License-Identifier: BUSL-1.1
*/
import Application from '@ember/application';
import Resolver from 'ember-resolver';
import loadInitializers from 'ember-load-initializers';
import config from 'vault/config/environment';
export default class App extends Application {
...
engines = {
<engine-name>: {
dependencies: {
services: [{ 'app-router': 'router' }, 'store', 'secret-mount-path', 'flash-messages', <any-other-dependencies-you-have>],
externalRoutes: {
secrets: 'vault.cluster.secrets.backends',
},
},
},
};
}
loadInitializers(App, config.modulePrefix);
If you used ember g in-repo-engine <engine-name> to generate the engine’s blueprint, it should have added this.mount(<engine-name>) to the main app’s router.js file (this adds your engine and its associated routes). *Move this.mount(<engine-name>) to match your engine’s route structure. For more information about Routable Engines.
"ember-addon": {
"paths": [
"lib/core",
"lib/your-new-engine"
]
},
pnpm install and RESTART ember server!package.json dependencies or devDependencies, you can copy + paste the dependency into corresponding sections. Most of the time, we will want to use "*" in place of the version number to ensure all the dependencies have the latest version.ember generate route <route-name> --in-repo <in-repo-name> - generates tests and route files and templatesember destroy route <route-name> --in-repo <in-repo-name> - removes tests and route files and templatesember generate component <component-name> --in-repo <in-repo-name>- generates tests and component files and templatesember destroy component <component-name> --in-repo <in-repo-name>- removes tests and component files and templates