Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Change the mount method to accept a function for defining engine routes
This change updates the mount API method to accept a function similar
to how the route API currently works so that engine routes can be defined
in the host application's router.js file.

Some Ember applications utilize in-repo ember-engines strictly for their
lazy loading and code organization features and not for their isolation features.

In this context it makes more sense to define engine routes in the host application's
router.js file.
  • Loading branch information
jsturgis committed Feb 12, 2021
commit 41a48dedd9ec5b9f493078a5fb385126bf9b10d9
37 changes: 33 additions & 4 deletions packages/@ember/-internals/routing/lib/system/dsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ export interface DSL {
route(name: string, options: RouteOptions, callback: DSLCallback): void;

mount(name: string): void;
mount(name: string, callback: DSLCallback): void;
mount(name: string, options: MountOptions): void;
mount(name: string, options: MountOptions, callback: DSLCallback): void;
}

function isCallback(value?: RouteOptions | DSLCallback): value is DSLCallback {
Expand Down Expand Up @@ -173,9 +175,32 @@ export default class DSLImpl implements DSL {
};
}

mount(_name: string, options: MountOptions = {}): void {
let engineRouteMap = this.options.resolveRouteMap(_name);
mount(_name: string): void;
mount(_name: string, mountCallback: DSLCallback): void;
mount(_name: string, options: MountOptions): void;
mount(_name: string, options: MountOptions, mountCallback: DSLCallback): void;
mount(_name: string, _options?: MountOptions | DSLCallback, _mountCallback?: DSLCallback): void {
let engineRouteMap = null;
let name = _name;
let options: MountOptions;
let mountCallback: Option<DSLCallback> = null;

if (isCallback(_options)) {
assert('Unexpected arguments', arguments.length === 2);
options = {};
mountCallback = _options;
} else if (isCallback(_mountCallback)) {
assert('Unexpected arguments', arguments.length === 3);
assert('Unexpected arguments', isOptions(_options));
options = _options;
mountCallback = _mountCallback;
} else {
options = _options || {};
}

if (!mountCallback) {
engineRouteMap = this.options.resolveRouteMap(name);
}

if (options.as) {
name = options.as;
Expand All @@ -198,7 +223,7 @@ export default class DSLImpl implements DSL {

let callback;
let dummyErrorRoute = `/_unused_dummy_error_path_route_${name}/:error`;
if (engineRouteMap) {
if (engineRouteMap || mountCallback) {
let shouldResetEngineInfo = false;
let oldEngineInfo = this.options.engineInfo;
if (oldEngineInfo) {
Expand All @@ -212,7 +237,11 @@ export default class DSLImpl implements DSL {
createRoute(childDSL, 'loading');
createRoute(childDSL, 'error', { path: dummyErrorRoute });

engineRouteMap.class.call(childDSL);
if (mountCallback) {
mountCallback.call(childDSL);
} else if (engineRouteMap) {
engineRouteMap.class.call(childDSL);
}

callback = childDSL.generate();

Expand Down
82 changes: 82 additions & 0 deletions packages/@ember/-internals/routing/tests/system/dsl_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,88 @@ moduleFor(
);
}

['@test should allow engine routes to be defined instead of options when mounting an engine'](
assert
) {
assert.expect(4);

Router = Router.map(function () {
this.route('bleep', function () {
this.route('bloop', function () {
this.mount('chat', function chatRoutes() {
this.route('foobar');
});
});
});
});

let engineInstance = buildOwner({
ownerOptions: { routable: true },
});

let router = Router.create();
setOwner(router, engineInstance);
router._initRouterJs();

assert.ok(
router._routerMicrolib.recognizer.names['bleep'],
'parent name was used as base of nested routes'
);
assert.ok(
router._routerMicrolib.recognizer.names['bleep.bloop'],
'parent name was used as base of nested routes'
);
assert.ok(
router._routerMicrolib.recognizer.names['bleep.bloop.chat'],
'parent name was used as base of mounted engine'
);
assert.ok(
router._routerMicrolib.recognizer.names['bleep.bloop.chat.foobar'],
'engine route was passed in from mount'
);
}

['@test should allow engine routes to be defined in addition to options when mounting an engine'](
assert
) {
assert.expect(4);

Router = Router.map(function () {
this.route('bleep', function () {
this.route('bloop', function () {
this.mount('chat', {}, function chatRoutes() {
this.route('foobar');
});
});
});
});

let engineInstance = buildOwner({
ownerOptions: { routable: true },
});

let router = Router.create();
setOwner(router, engineInstance);
router._initRouterJs();

assert.ok(
router._routerMicrolib.recognizer.names['bleep'],
'parent name was used as base of nested routes'
);
assert.ok(
router._routerMicrolib.recognizer.names['bleep.bloop'],
'parent name was used as base of nested routes'
);
assert.ok(
router._routerMicrolib.recognizer.names['bleep.bloop.chat'],
'parent name was used as base of mounted engine'
);
assert.ok(
router._routerMicrolib.recognizer.names['bleep.bloop.chat.foobar'],
'engine route was passed in from mount'
);
}

['@test should allow mounting of engines at a custom path'](assert) {
assert.expect(1);

Expand Down