diff --git a/packages/catalog-model/src/entity/index.ts b/packages/catalog-model/src/entity/index.ts index 12ec19667b..a6e90e6975 100644 --- a/packages/catalog-model/src/entity/index.ts +++ b/packages/catalog-model/src/entity/index.ts @@ -17,8 +17,7 @@ export { entityMetaGeneratedFields } from './Entity'; export type { Entity, EntityMeta } from './Entity'; export * from './policies'; -export { parseEntityName, parseEntityRef, serializeEntityRef } from './ref'; -export type { EntityRefContext } from './ref'; +export { parseEntityName, serializeEntityRef } from './ref'; export { entityHasChanges, generateEntityEtag, diff --git a/packages/catalog-model/src/entity/ref.test.ts b/packages/catalog-model/src/entity/ref.test.ts index 8a8b7d3f86..b76f01f1f9 100644 --- a/packages/catalog-model/src/entity/ref.test.ts +++ b/packages/catalog-model/src/entity/ref.test.ts @@ -68,33 +68,40 @@ describe('ref', () => { expect(() => parseEntityName({ kind: '', namespace: 'b', name: 'c' }), ).toThrow(); + expect(() => parseEntityName({ namespace: 'b', name: 'c' })).toThrow(); expect(() => parseEntityName({ kind: 'a', namespace: '', name: 'c' }), ).toThrow(); + expect(() => parseEntityName({ kind: 'a', name: 'c' })).not.toThrow(); expect(() => parseEntityName({ kind: 'a', namespace: 'b', name: '' }), ).toThrow(); + expect(() => + parseEntityName({ kind: 'a', namespace: 'b' } as any), + ).toThrow(); // two are empty expect(() => parseEntityName({ kind: '', namespace: '', name: 'c' }), ).toThrow(); + expect(() => parseEntityName({ name: 'c' })).toThrow(); expect(() => parseEntityName({ kind: '', namespace: 'b', name: '' }), ).toThrow(); + expect(() => parseEntityName({ namespace: 'b' } as any)).toThrow(); expect(() => parseEntityName({ kind: 'a', namespace: '', name: '' }), ).toThrow(); + expect(() => parseEntityName({ kind: 'a' } as any)).toThrow(); // three are empty expect(() => parseEntityName({ kind: '', namespace: '', name: '' }), ).toThrow(); + expect(() => parseEntityName({} as any)).toThrow(); // one is left out, one empty expect(() => parseEntityName({ namespace: '', name: 'c' })).toThrow(); expect(() => parseEntityName({ namespace: 'b', name: '' })).toThrow(); expect(() => parseEntityName({ kind: '', name: 'c' })).toThrow(); expect(() => parseEntityName({ kind: 'a', name: '' })).toThrow(); - // nothing at all - expect(() => parseEntityName({} as any)).toThrow(); }); it('adds defaults where necessary to strings', () => { diff --git a/packages/catalog-model/src/entity/ref.ts b/packages/catalog-model/src/entity/ref.ts index 1a579eeb7e..b9320a5ac7 100644 --- a/packages/catalog-model/src/entity/ref.ts +++ b/packages/catalog-model/src/entity/ref.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import { CompoundEntityRef, EntityName, EntityRef } from '../types'; +import { EntityName, EntityRef } from '../types'; /** * The context of defaults that entity reference parsing happens within. */ -export type EntityRefContext = { +type EntityRefContext = { /** The default kind, if none is given in the reference */ defaultKind?: string; /** The default namespace, if none is given in the reference */ @@ -53,19 +53,7 @@ export function parseEntityName( ); } - // This is a corner case - when the ref contained a namespace but it was the - // empty string (so the default did not kick in) - if (!namespace) { - throw new Error( - `Entity reference ${kind}:${name} did not contain a namespace`, - ); - } - - return { - kind, - namespace: namespace!, - name, - }; + return { kind, namespace, name }; } /** @@ -79,16 +67,44 @@ export function parseEntityName( * @param context The context of defaults that the parsing happens within * @returns The compound form of the reference */ +export function parseEntityRef( + ref: EntityRef, + context?: { defaultKind: string }, +): { + kind: string; + namespace?: string; + name: string; +}; +export function parseEntityRef( + ref: EntityRef, + context?: { defaultNamespace: string }, +): { + kind?: string; + namespace: string; + name: string; +}; +export function parseEntityRef( + ref: EntityRef, + context?: { defaultKind: string; defaultNamespace: string }, +): { + kind: string; + namespace: string; + name: string; +}; export function parseEntityRef( ref: EntityRef, context: EntityRefContext = {}, -): CompoundEntityRef { +): { + kind?: string; + namespace?: string; + name: string; +} { if (!ref) { throw new Error(`Entity reference must not be empty`); } if (typeof ref === 'string') { - const match = /^(?:([^:/]+):)?(?:([^:/]+)\/)?([^:/]+)$/.exec(ref.trim()); + const match = /^([^:/]+:)?([^:/]+\/)?([^:/]+)$/.exec(ref.trim()); if (!match) { throw new Error( `Entity reference "${ref}" was not on the form [:][/]`, @@ -96,8 +112,8 @@ export function parseEntityRef( } return { - kind: match[1] ?? context.defaultKind, - namespace: match[2] ?? context.defaultNamespace, + kind: match[1]?.slice(0, -1) ?? context.defaultKind, + namespace: match[2]?.slice(0, -1) ?? context.defaultNamespace, name: match[3], }; } @@ -127,9 +143,11 @@ export function parseEntityRef( * @param ref The reference to serialize * @returns The same reference on either string or compound form */ -export function serializeEntityRef( - ref: CompoundEntityRef | EntityName, -): EntityRef { +export function serializeEntityRef(ref: { + kind?: string; + namespace?: string; + name: string; +}): EntityRef { const { kind, namespace, name } = ref; if ( kind?.includes(':') || diff --git a/packages/catalog-model/src/index.ts b/packages/catalog-model/src/index.ts index 16e7e3477b..f93a4001a5 100644 --- a/packages/catalog-model/src/index.ts +++ b/packages/catalog-model/src/index.ts @@ -18,11 +18,5 @@ export * from './entity'; export { EntityPolicies } from './EntityPolicies'; export * from './kinds'; export * from './location'; -export type { - CompoundEntityRef, - EntityName, - EntityPolicy, - EntityRef, - JSONSchema, -} from './types'; +export type { EntityName, EntityPolicy, EntityRef, JSONSchema } from './types'; export * from './validation'; diff --git a/packages/catalog-model/src/types.ts b/packages/catalog-model/src/types.ts index 1e0a778827..3aafdc241a 100644 --- a/packages/catalog-model/src/types.ts +++ b/packages/catalog-model/src/types.ts @@ -45,20 +45,18 @@ export type EntityName = { }; /** - * A reference by name to an entity, where the kind and/or the namespace can be - * left out. + * A reference by name to an entity, either as a compact string representation, + * or as a compound reference structure. + * + * The string representation is on the form [:][/]. * * Left-out parts of the reference need to be handled by the application, * either by rejecting the reference or by falling back to default values. */ -export type CompoundEntityRef = { - kind?: string; - namespace?: string; - name: string; -}; - -/** - * A reference by name to an entity, either as a compact string representation, - * or as a compound reference structure. - */ -export type EntityRef = string | CompoundEntityRef; +export type EntityRef = + | string + | { + kind?: string; + namespace?: string; + name: string; + };