chore: implement parseEntityOrderFieldParams

Based on the implemntation in plugins/catalog-backend.

Signed-off-by: Marek Libra <marek.libra@gmail.com>
This commit is contained in:
Marek Libra
2024-03-14 13:21:16 +01:00
parent cd96173afb
commit 5983bcd705
5 changed files with 121 additions and 3 deletions
@@ -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:^",
@@ -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/);
});
});
@@ -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<string, unknown>,
): 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);
}
@@ -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 {