Simplified the parseEntityRef function

Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
Fredrik Adelöw
2022-02-23 13:28:54 +01:00
parent 0ba3149bee
commit 68f0871b76
6 changed files with 41 additions and 114 deletions
+8
View File
@@ -0,0 +1,8 @@
---
'@backstage/catalog-model': minor
---
**BREAKING**: Simplified the `parseEntityRef` function to _always_ either return
a complete `EntityName`, complete with both kind, namespace and name, or throw
an error if it for some reason did not have enough information to form that
result. This makes its usage and its type declaration vastly simpler.
+2 -38
View File
@@ -417,47 +417,11 @@ export function parseEntityRef(
name: string;
},
context?: {
defaultKind: string;
defaultNamespace: string;
defaultKind?: string;
defaultNamespace?: string;
},
): EntityName;
// @public
export function parseEntityRef(
ref:
| string
| {
kind?: string;
namespace?: string;
name: string;
},
context?: {
defaultKind: string;
},
): {
kind: string;
namespace?: string;
name: string;
};
// @public
export function parseEntityRef(
ref:
| string
| {
kind?: string;
namespace?: string;
name: string;
},
context?: {
defaultNamespace: string;
},
): {
kind?: string;
namespace: string;
name: string;
};
// @public
export function parseLocationRef(ref: string): {
type: string;
@@ -187,21 +187,11 @@ describe('ref', () => {
namespace: 'b',
name: 'c',
});
expect(parseEntityRef('b/c')).toEqual({
kind: undefined,
namespace: 'b',
name: 'c',
});
expect(parseEntityRef('a:c')).toEqual({
kind: 'a',
namespace: 'default',
name: 'c',
});
expect(parseEntityRef('c')).toEqual({
kind: undefined,
namespace: 'default',
name: 'c',
});
});
it('rejects bad inputs', () => {
+29 -59
View File
@@ -121,81 +121,51 @@ export function parseEntityName(
*/
export function parseEntityRef(
ref: string | { kind?: string; namespace?: string; name: string },
context?: { defaultKind: string; defaultNamespace: string },
): EntityName;
/**
* parseEntityRef with optional Kind.
*
* @public
*/
export function parseEntityRef(
ref: string | { kind?: string; namespace?: string; name: string },
context?: { defaultKind: string },
): {
kind: string;
namespace?: string;
name: string;
};
/**
* parseEntityRef with optional Namespace.
*
* @public
*/
export function parseEntityRef(
ref: string | { kind?: string; namespace?: string; name: string },
context?: { defaultNamespace: string },
): {
kind?: string;
namespace: string;
name: string;
};
/**
* parseEntityRef with optional Kind and Namespace.
*
* @public
*/
export function parseEntityRef(
ref: string | { kind?: string; namespace?: string; name: string },
context: {
context?: {
/** The default kind, if none is given in the reference */
defaultKind?: string;
/** The default namespace, if none is given in the reference */
defaultNamespace?: string;
} = {},
): {
kind?: string;
namespace?: string;
name: string;
} {
},
): EntityName {
if (!ref) {
throw new Error(`Entity reference must not be empty`);
}
const defaultNamespace = context.defaultNamespace || DEFAULT_NAMESPACE;
const defaultKind = context?.defaultKind;
const defaultNamespace = context?.defaultNamespace || DEFAULT_NAMESPACE;
let kind: string | undefined;
let namespace: string | undefined;
let name: string | undefined;
if (typeof ref === 'string') {
const parsed = parseRefString(ref);
return {
kind: parsed.kind ?? context.defaultKind,
namespace: parsed.namespace ?? defaultNamespace,
name: parsed.name,
};
kind = parsed.kind ?? defaultKind;
namespace = parsed.namespace ?? defaultNamespace;
name = parsed.name;
} else {
kind = ref.kind ?? defaultKind;
namespace = ref.namespace ?? defaultNamespace;
name = ref.name;
}
const { kind, namespace, name } = ref;
if (kind === '') {
throw new Error('Entity reference kinds must not be empty');
} else if (namespace === '') {
throw new Error('Entity reference namespaces must not be empty');
if (!kind) {
const textual = JSON.stringify(ref);
throw new Error(
`Entity reference ${textual} had missing or empty kind (e.g. did not start with "component:" or similar)`,
);
} else if (!namespace) {
const textual = JSON.stringify(ref);
throw new Error(
`Entity reference ${textual} had missing or empty namespace`,
);
} else if (!name) {
throw new Error('Entity references must contain a name');
const textual = JSON.stringify(ref);
throw new Error(`Entity reference ${textual} had missing or empty name`);
}
return {
kind: kind ?? context.defaultKind,
namespace: namespace ?? defaultNamespace,
name,
};
return { kind, namespace, name };
}
/**
@@ -187,7 +187,7 @@ describe('BuiltinKindsEntityProcessor', () => {
await expect(
processor.postProcessEntity(entity, location, emit),
).rejects.toThrowError(
'Entity reference "r" did not specify a kind (e.g. starting with "Component:"), and has no default',
'Entity reference "r" had missing or empty kind (e.g. did not start with "component:" or similar)',
);
});
@@ -360,7 +360,7 @@ describe('BuiltinKindsEntityProcessor', () => {
await expect(
processor.postProcessEntity(entity, location, emit),
).rejects.toThrowError(
'Entity reference "c" did not specify a kind (e.g. starting with "Component:"), and has no default',
'Entity reference "c" had missing or empty kind (e.g. did not start with "component:" or similar)',
);
});
@@ -106,11 +106,6 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor {
}
for (const target of [targets].flat()) {
const targetRef = parseEntityRef(target, context);
if (targetRef.kind === undefined) {
throw new Error(
`Entity reference "${target}" did not specify a kind (e.g. starting with "Component:"), and has no default`,
);
}
emit(
result.relation({
source: selfRef,