Skip to content

Commit 2a399aa

Browse files
committed
feat: add RegExpAsString GraphQL custom scalar type for filtration by RegExp
1 parent a3001d0 commit 2a399aa

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

src/types/RegExpAsString.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { GraphQLScalarType, Kind } from 'graphql-compose/lib/graphql';
2+
3+
function parseStringWithRegExp(str: string): RegExp {
4+
if (str.startsWith('/')) {
5+
const m = str.match(/^\/(.+)\/([gimsuy]*)$/);
6+
if (m) {
7+
return new RegExp(m[1], m[2]);
8+
}
9+
throw new TypeError('Field error: cannot parse provided string as RegExp object');
10+
} else {
11+
// simple regexp without expression flags
12+
return new RegExp(str);
13+
}
14+
}
15+
16+
const GraphQLRegExpAsString = new GraphQLScalarType({
17+
name: 'RegExpAsString',
18+
specifiedByUrl: 'http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf',
19+
description:
20+
'The string representation of JavaScript regexp. You may provide it with flags "/^abc.*/i" or without flags like "^abc.*". More info about RegExp characters and flags: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions',
21+
serialize: String,
22+
parseValue(value: any) {
23+
if (typeof value !== 'string') {
24+
throw new TypeError(
25+
'Field error: GraphQL RegExpAsString value should be provided as a string'
26+
);
27+
}
28+
return parseStringWithRegExp(value);
29+
},
30+
parseLiteral(ast) {
31+
if (ast.kind !== Kind.STRING) {
32+
throw new TypeError(
33+
'Field error: GraphQL RegExpAsString value should be provided as a string'
34+
);
35+
}
36+
return parseStringWithRegExp(ast.value);
37+
},
38+
});
39+
40+
export default GraphQLRegExpAsString;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { Kind } from 'graphql-compose/lib/graphql';
2+
import GraphQLRegExpAsString from '../RegExpAsString';
3+
4+
describe('GraphQLRegExpAsString', () => {
5+
describe('serialize', () => {
6+
it('pass RegExp without flags', () => {
7+
expect(GraphQLRegExpAsString.serialize(new RegExp('^Abc$'))).toBe('/^Abc$/');
8+
expect(GraphQLRegExpAsString.serialize(new RegExp(/^Abc$/))).toBe('/^Abc$/');
9+
});
10+
11+
it('pass RegExp with flags', () => {
12+
expect(GraphQLRegExpAsString.serialize(new RegExp('^Abc$', 'gm'))).toBe('/^Abc$/gm');
13+
});
14+
15+
it('pass as String', () => {
16+
expect(GraphQLRegExpAsString.serialize('abc')).toBe('abc');
17+
});
18+
});
19+
20+
describe('parseValue', () => {
21+
it('pass as string', () => {
22+
expect(GraphQLRegExpAsString.parseValue('^Abc$')).toEqual(/^Abc$/);
23+
expect(GraphQLRegExpAsString.parseValue('/^Abc$/')).toEqual(/^Abc$/);
24+
expect(GraphQLRegExpAsString.parseValue('/^Abc$/gm')).toEqual(/^Abc$/gm);
25+
expect(GraphQLRegExpAsString.parseValue('so/me')).toEqual(/so\/me/);
26+
});
27+
28+
it('pass as wrong type', () => {
29+
expect(() => GraphQLRegExpAsString.parseValue(123)).toThrow(
30+
'value should be provided as a string'
31+
);
32+
});
33+
});
34+
35+
describe('parseLiteral', () => {
36+
it('parse a ast STRING literal', async () => {
37+
const ast = {
38+
kind: Kind.STRING,
39+
value: '^Abc$',
40+
};
41+
expect(GraphQLRegExpAsString.parseLiteral(ast, {})).toEqual(/^Abc$/);
42+
43+
const ast2 = {
44+
kind: Kind.STRING,
45+
value: '/^Abc$/gm',
46+
};
47+
expect(GraphQLRegExpAsString.parseLiteral(ast2, {})).toEqual(/^Abc$/gm);
48+
});
49+
50+
it('parse wrong ast literal', async () => {
51+
const ast: any = {
52+
kind: Kind.INT,
53+
value: 123,
54+
};
55+
expect(() => GraphQLRegExpAsString.parseLiteral(ast, {})).toThrow(
56+
'value should be provided as a string'
57+
);
58+
});
59+
});
60+
});

0 commit comments

Comments
 (0)