diff --git a/.changeset/poor-coats-boil.md b/.changeset/poor-coats-boil.md index b81843806b..a9720614a5 100644 --- a/.changeset/poor-coats-boil.md +++ b/.changeset/poor-coats-boil.md @@ -3,4 +3,4 @@ '@backstage/plugin-notifications': minor --- -notifications-backend URL query parameters changed from sort/sortOrder to orderField and created_after to createdAfter to unify with other plugins +Notifications-backend URL query parameters changed from `sort/sortOrder` to `orderField` and `created_after` to `createdAfter` to unify with other plugins. diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index d8e7c75d17..68c7b9b22b 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -37,7 +37,6 @@ "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", - "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-notifications-common": "workspace:^", "@backstage/plugin-notifications-node": "workspace:^", diff --git a/plugins/notifications-backend/src/service/parseEntityOrderFieldParams.test.ts b/plugins/notifications-backend/src/service/parseEntityOrderFieldParams.test.ts new file mode 100644 index 0000000000..1d494df0ca --- /dev/null +++ b/plugins/notifications-backend/src/service/parseEntityOrderFieldParams.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams'; + +describe('parseEntityOrderFieldParams', () => { + it('supports no order fields', () => { + const result = parseEntityOrderFieldParams({}); + expect(result).toEqual(undefined); + }); + + it('supports single orderField', () => { + const result = parseEntityOrderFieldParams({ + orderField: ['metadata.name,desc'], + })!; + expect(result).toEqual([{ field: 'metadata.name', order: 'desc' }]); + }); + + it('supports single orderField without order', () => { + const result = parseEntityOrderFieldParams({ + orderField: ['metadata.name'], + })!; + expect(result).toEqual([{ field: 'metadata.name' }]); + }); + + it('supports multiple order fields', () => { + const result = parseEntityOrderFieldParams({ + orderField: ['metadata.name,desc', 'metadata.uid,asc'], + }); + + expect(result).toEqual([ + { field: 'metadata.name', order: 'desc' }, + { field: 'metadata.uid', order: 'asc' }, + ]); + }); + + it('throws if orderField order is not valid', () => { + expect(() => + parseEntityOrderFieldParams({ + orderField: ['metadata.name,desc', 'metadata.uid,invalid'], + }), + ).toThrow(/Invalid order field order/); + }); +}); diff --git a/plugins/notifications-backend/src/service/parseEntityOrderFieldParams.ts b/plugins/notifications-backend/src/service/parseEntityOrderFieldParams.ts new file mode 100644 index 0000000000..913e04993c --- /dev/null +++ b/plugins/notifications-backend/src/service/parseEntityOrderFieldParams.ts @@ -0,0 +1,62 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This file is based on the plugins/catalog-backend + +import { InputError } from '@backstage/errors'; +import { EntityOrder } from '../database'; + +/** + * Takes a single unknown parameter and makes sure that it's a single string or + * an array of strings, and returns as an array. + */ +export function parseStringsParam( + param: unknown, + ctx: string, +): string[] | undefined { + if (param === undefined) { + return undefined; + } + + const array = [param].flat(); + if (array.some(p => typeof p !== 'string')) { + throw new InputError(`Invalid ${ctx}, not a string`); + } + + return array as string[]; +} + +export function parseEntityOrderFieldParams( + params: Record, +): EntityOrder[] | undefined { + const orderFieldStrings = parseStringsParam(params.orderField, 'orderField'); + if (!orderFieldStrings) { + return undefined; + } + + return orderFieldStrings.map(orderFieldString => { + const [field, order] = orderFieldString.split(','); + + if (order !== undefined && !isOrder(order)) { + throw new InputError('Invalid order field order, must be asc or desc'); + } + return { field, order }; + }); +} + +export function isOrder(order: string): order is 'asc' | 'desc' { + return ['asc', 'desc'].includes(order); +} diff --git a/plugins/notifications-backend/src/service/router.ts b/plugins/notifications-backend/src/service/router.ts index e72775f06f..f6b7e318f1 100644 --- a/plugins/notifications-backend/src/service/router.ts +++ b/plugins/notifications-backend/src/service/router.ts @@ -45,7 +45,7 @@ import { Notification, NotificationReadSignal, } from '@backstage/plugin-notifications-common'; -import { parseEntityOrderFieldParams } from '@backstage/plugin-catalog-backend'; +import { parseEntityOrderFieldParams } from './parseEntityOrderFieldParams'; /** @internal */ export interface RouterOptions {