add defaultTarget to ExternalRouteRef
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -117,4 +117,48 @@ describe('resolveRouteBindings', () => {
|
||||
"Invalid config at app.routes.bindings['mySource'], 'myTarget' is not a valid route",
|
||||
);
|
||||
});
|
||||
|
||||
it('can have default targets, but at the lowest priority', () => {
|
||||
const source = createExternalRouteRef({ defaultTarget: 'target1' });
|
||||
const target1 = createRouteRef();
|
||||
const target2 = createRouteRef();
|
||||
const routesById = {
|
||||
routes: new Map([
|
||||
['target1', target1],
|
||||
['target2', target2],
|
||||
]),
|
||||
externalRoutes: new Map([['source', source]]),
|
||||
};
|
||||
|
||||
// defaultTarget wins only if no bind or config matches
|
||||
let result = resolveRouteBindings(
|
||||
() => {},
|
||||
new ConfigReader({}),
|
||||
routesById,
|
||||
);
|
||||
|
||||
expect(result.get(source)).toBe(target1);
|
||||
|
||||
// config wins over defaultTarget
|
||||
result = resolveRouteBindings(
|
||||
() => {},
|
||||
new ConfigReader({
|
||||
app: { routes: { bindings: { source: 'target2' } } },
|
||||
}),
|
||||
routesById,
|
||||
);
|
||||
|
||||
expect(result.get(source)).toBe(target2);
|
||||
|
||||
// bind wins over defaultTarget
|
||||
result = resolveRouteBindings(
|
||||
({ bind }) => {
|
||||
bind({ a: source }, { a: target2 });
|
||||
},
|
||||
new ConfigReader({}),
|
||||
routesById,
|
||||
);
|
||||
|
||||
expect(result.get(source)).toBe(target2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -22,6 +22,8 @@ import {
|
||||
import { RouteRefsById } from './collectRouteIds';
|
||||
import { Config } from '@backstage/config';
|
||||
import { JsonObject } from '@backstage/types';
|
||||
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
|
||||
import { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef';
|
||||
|
||||
/**
|
||||
* Extracts a union of the keys in a map whose value extends the given type
|
||||
@@ -82,6 +84,7 @@ export function resolveRouteBindings(
|
||||
): Map<ExternalRouteRef, RouteRef | SubRouteRef> {
|
||||
const result = new Map<ExternalRouteRef, RouteRef | SubRouteRef>();
|
||||
|
||||
// Perform callback bindings first with highest priority
|
||||
if (bindRoutes) {
|
||||
const bind: CreateAppRouteBinder = (
|
||||
externalRoutes,
|
||||
@@ -105,37 +108,50 @@ export function resolveRouteBindings(
|
||||
bindRoutes({ bind });
|
||||
}
|
||||
|
||||
const bindingsConfig = config.getOptionalConfig('app.routes.bindings');
|
||||
if (!bindingsConfig) {
|
||||
return result;
|
||||
// Then perform config based bindings with lower priority
|
||||
const bindings = config
|
||||
.getOptionalConfig('app.routes.bindings')
|
||||
?.get<JsonObject>();
|
||||
if (bindings) {
|
||||
for (const [externalRefId, targetRefId] of Object.entries(bindings)) {
|
||||
if (typeof targetRefId !== 'string' || targetRefId === '') {
|
||||
throw new Error(
|
||||
`Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string`,
|
||||
);
|
||||
}
|
||||
|
||||
const externalRef = routesById.externalRoutes.get(externalRefId);
|
||||
if (!externalRef) {
|
||||
throw new Error(
|
||||
`Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`,
|
||||
);
|
||||
}
|
||||
if (result.has(externalRef)) {
|
||||
continue;
|
||||
}
|
||||
const targetRef = routesById.routes.get(targetRefId);
|
||||
if (!targetRef) {
|
||||
throw new Error(
|
||||
`Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`,
|
||||
);
|
||||
}
|
||||
|
||||
result.set(externalRef, targetRef);
|
||||
}
|
||||
}
|
||||
|
||||
const bindings = bindingsConfig.get<JsonObject>();
|
||||
for (const [externalRefId, targetRefId] of Object.entries(bindings)) {
|
||||
if (typeof targetRefId !== 'string' || targetRefId === '') {
|
||||
throw new Error(
|
||||
`Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string`,
|
||||
);
|
||||
// Finally fall back to attempting to map defaults, at lowest priority
|
||||
for (const externalRef of routesById.externalRoutes.values()) {
|
||||
if (!result.has(externalRef)) {
|
||||
const defaultRefId =
|
||||
toInternalExternalRouteRef(externalRef).getDefaultTarget();
|
||||
if (defaultRefId) {
|
||||
const defaultRef = routesById.routes.get(defaultRefId);
|
||||
if (defaultRef) {
|
||||
result.set(externalRef, defaultRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const externalRef = routesById.externalRoutes.get(externalRefId);
|
||||
if (!externalRef) {
|
||||
throw new Error(
|
||||
`Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`,
|
||||
);
|
||||
}
|
||||
// Route bindings defined in config have lower priority than those defined in code
|
||||
if (result.has(externalRef)) {
|
||||
continue;
|
||||
}
|
||||
const targetRef = routesById.routes.get(targetRefId);
|
||||
if (!targetRef) {
|
||||
throw new Error(
|
||||
`Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`,
|
||||
);
|
||||
}
|
||||
|
||||
result.set(externalRef, targetRef);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user