Changing how negation key word is processed
Signed-off-by: Jordan Snow <jordans@spotify.com>
This commit is contained in:
@@ -16,7 +16,6 @@
|
||||
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { EntityMatcherFn } from './types';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
const allowedMatchers: Record<string, EntityMatcherFn> = {
|
||||
labels: entity => {
|
||||
@@ -33,7 +32,6 @@ const allowedMatchers: Record<string, EntityMatcherFn> = {
|
||||
export function createHasMatcher(
|
||||
parameters: string[],
|
||||
onParseError: (error: Error) => void,
|
||||
negation?: boolean,
|
||||
): EntityMatcherFn {
|
||||
const matchers = parameters.flatMap(parameter => {
|
||||
const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')];
|
||||
@@ -49,7 +47,6 @@ export function createHasMatcher(
|
||||
return [matcher];
|
||||
});
|
||||
|
||||
const isMatch = (entity: Entity) =>
|
||||
return entity =>
|
||||
matchers.length ? matchers.some(matcher => matcher(entity)) : true;
|
||||
return negation ? entity => !isMatch(entity) : isMatch;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ const allowedMatchers: Record<string, EntityMatcherFn> = {
|
||||
export function createIsMatcher(
|
||||
parameters: string[],
|
||||
onParseError: (error: Error) => void,
|
||||
negation?: boolean,
|
||||
): EntityMatcherFn {
|
||||
const matchers = parameters.flatMap(parameter => {
|
||||
const matcher = allowedMatchers[parameter.toLocaleLowerCase('en-US')];
|
||||
@@ -44,7 +43,6 @@ export function createIsMatcher(
|
||||
return [matcher];
|
||||
});
|
||||
|
||||
const isMatch = (entity: any) =>
|
||||
return entity =>
|
||||
matchers.length ? matchers.some(matcher => matcher(entity)) : true;
|
||||
return negation ? entity => !isMatch(entity) : isMatch;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,7 @@ import { EntityMatcherFn } from './types';
|
||||
export function createKindMatcher(
|
||||
parameters: string[],
|
||||
_onParseError: (error: Error) => void,
|
||||
negation?: boolean,
|
||||
): EntityMatcherFn {
|
||||
const items = parameters.map(p => p.toLocaleLowerCase('en-US'));
|
||||
const isMatch = (entity: any) =>
|
||||
items.includes(entity.kind.toLocaleLowerCase('en-US'));
|
||||
return negation ? entity => !isMatch(entity) : isMatch;
|
||||
return entity => items.includes(entity.kind.toLocaleLowerCase('en-US'));
|
||||
}
|
||||
|
||||
@@ -22,14 +22,13 @@ import { EntityMatcherFn } from './types';
|
||||
export function createTypeMatcher(
|
||||
parameters: string[],
|
||||
_onParseError: (error: Error) => void,
|
||||
negation?: boolean,
|
||||
): EntityMatcherFn {
|
||||
const items = parameters.map(p => p.toLocaleLowerCase('en-US'));
|
||||
return entity => {
|
||||
const value = entity.spec?.type;
|
||||
const isMatch =
|
||||
return (
|
||||
typeof value === 'string' &&
|
||||
items.includes(value.toLocaleLowerCase('en-US'));
|
||||
return negation ? !isMatch : isMatch;
|
||||
items.includes(value.toLocaleLowerCase('en-US'))
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -137,17 +137,21 @@ describe('splitFilterExpression', () => {
|
||||
expect(run('')).toEqual([]);
|
||||
expect(run(' ')).toEqual([]);
|
||||
expect(run('kind:component')).toEqual([
|
||||
{ key: 'kind', parameters: ['component'] },
|
||||
{ key: 'kind', parameters: ['component'], negation: false },
|
||||
]);
|
||||
expect(run('kind:component,user')).toEqual([
|
||||
{ key: 'kind', parameters: ['component', 'user'] },
|
||||
{ key: 'kind', parameters: ['component', 'user'], negation: false },
|
||||
]);
|
||||
expect(run('kind:component,user not:type:foo')).toEqual([
|
||||
{ key: 'kind', parameters: ['component', 'user'], negation: false },
|
||||
{ key: 'type', parameters: ['foo'], negation: true },
|
||||
]);
|
||||
expect(run('kind:component,user type:foo')).toEqual([
|
||||
{ key: 'kind', parameters: ['component', 'user'] },
|
||||
{ key: 'type', parameters: ['foo'] },
|
||||
{ key: 'kind', parameters: ['component', 'user'], negation: false },
|
||||
{ key: 'type', parameters: ['foo'], negation: false },
|
||||
]);
|
||||
expect(run('with:multiple:colons')).toEqual([
|
||||
{ key: 'with', parameters: ['multiple:colons'] },
|
||||
{ key: 'with', parameters: ['multiple:colons'], negation: false },
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -61,14 +61,10 @@ export function parseFilterExpression(expression: string): {
|
||||
const parts = splitFilterExpression(expression, e =>
|
||||
expressionParseErrors.push(e),
|
||||
);
|
||||
let negation = false;
|
||||
const matchers = parts.flatMap(part => {
|
||||
const factory = rootMatcherFactories[part.key];
|
||||
const negation = part.negation;
|
||||
if (!factory) {
|
||||
if (isNegation(part.key)) {
|
||||
negation = true;
|
||||
return [];
|
||||
}
|
||||
const known = Object.keys(rootMatcherFactories).map(m => `'${m}'`);
|
||||
expressionParseErrors.push(
|
||||
new InputError(
|
||||
@@ -78,13 +74,11 @@ export function parseFilterExpression(expression: string): {
|
||||
return [];
|
||||
}
|
||||
|
||||
const matcher = factory(
|
||||
part.parameters,
|
||||
e => expressionParseErrors.push(e),
|
||||
negation,
|
||||
const matcher = factory(part.parameters, e =>
|
||||
expressionParseErrors.push(e),
|
||||
);
|
||||
negation = false;
|
||||
return [matcher];
|
||||
|
||||
return [negation ? (entity: Entity) => !matcher(entity) : matcher];
|
||||
});
|
||||
|
||||
const filterFn = (entity: Entity) =>
|
||||
@@ -105,20 +99,20 @@ export function parseFilterExpression(expression: string): {
|
||||
export function splitFilterExpression(
|
||||
expression: string,
|
||||
onParseError: (error: Error) => void,
|
||||
): Array<{ key: string; parameters: string[] }> {
|
||||
): Array<{ key: string; parameters: string[]; negation: boolean }> {
|
||||
const words = expression
|
||||
.split(' ')
|
||||
.map(w => w.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
const result = new Array<{ key: string; parameters: string[] }>();
|
||||
const result = new Array<{
|
||||
key: string;
|
||||
parameters: string[];
|
||||
negation: boolean;
|
||||
}>();
|
||||
|
||||
for (const word of words) {
|
||||
let match = word.match(/^([^:]+):(.+)$/);
|
||||
if (match && isNegation(match[1])) {
|
||||
result.push({ key: 'not', parameters: [] });
|
||||
match = match[2].match(/^([^:]+):(.+)$/) || null;
|
||||
}
|
||||
const match = word.match(/^(not:)?([^:]+):(.+)$/);
|
||||
if (!match) {
|
||||
onParseError(
|
||||
new InputError(
|
||||
@@ -127,19 +121,14 @@ export function splitFilterExpression(
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const key = match[1];
|
||||
const parameters = match[2].split(',').filter(Boolean); // silently ignore double commas
|
||||
|
||||
result.push({ key, parameters });
|
||||
const key = match[2];
|
||||
const parameters = match[3].split(',').filter(Boolean); // silently ignore double commas
|
||||
if (match[1]) {
|
||||
result.push({ key, parameters, negation: true });
|
||||
} else {
|
||||
result.push({ key, parameters, negation: false });
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function isNegation(parameter: string): boolean {
|
||||
if (parameter.toLocaleLowerCase('en-US') === 'not') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user