-
Notifications
You must be signed in to change notification settings - Fork 22
/
scalars.js
137 lines (113 loc) · 5.27 KB
/
scalars.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { GraphQLError } from 'graphql/error';
import { Kind } from 'graphql/language';
import { Factory } from './factory';
import { GraphQLCustomScalarType } from './types';
const factory = new Factory();
export const GraphQLEmail = factory.getRegexScalar({
name: 'Email',
regex: /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i,
description: 'The Email scalar type represents E-Mail addresses compliant to RFC 822.',
error: 'Query error: Not a valid Email address'
});
export const GraphQLURL = factory.getRegexScalar({
name: 'URL',
// RegExp taken from https://gist.github.com/dperini/729294
regex: new RegExp('^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))\\.?)(?::\\d{2,5})?(?:[/?#]\\S*)?$', 'i'),
description: 'The URL scalar type represents URL addresses.',
error: 'Query error: Not a valid URL'
});
export const GraphQLUUID = factory.getRegexScalar({
name: 'UUID',
// https://github.com/chriso/validator.js/blob/master/src/lib/isUUID.js#L7
regex: new RegExp('^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$', 'i'),
description: 'The UUID scalar type represents a UUID.',
error: 'Query error: Not a valid UUID'
});
const stringValidator = function(ast) {
if (ast.kind !== Kind.STRING) {
throw new GraphQLError('Query error: Can only parse strings got a: ' + ast.kind, [ast]);
}
};
const lengthValidator = function(ast, min, max) {
if(ast.value.length < min) {
throw new GraphQLError('Query error: String not long enough', [ast]);
}
if(max && ast.value.length > max) {
throw new GraphQLError('Query error: String too long', [ast]);
}
};
const alphabetValidator = function(ast, alphabet) {
for(var char of ast.value) {
if(alphabet.indexOf(char) < 0) {
throw new GraphQLError('Query error: Invalid character found', [ast]);
}
}
};
const complexityValidator = function(ast, options) {
const complexity = options || {};
const alhpaNumericRe = /^(?=.*[0-9])(?=.*[a-zA-Z])(.+)$/;
const mixedCaseRe = /^(?=.*[a-z])(?=.*[A-Z])(.+)$/;
const specialCharsRe = /^(?=.*[^a-zA-Z0-9])(.+)$/;
if(complexity.alphaNumeric && !alhpaNumericRe.test(ast.value)) {
throw new GraphQLError('Query error: String must contain at least one number and one letter', [ast]);
}
if(complexity.mixedCase && !mixedCaseRe.test(ast.value)) {
throw new GraphQLError('Query error: String must contain at least one uper and one lower case letter', [ast]);
}
if(complexity.specialChars && !specialCharsRe.test(ast.value)) {
throw new GraphQLError('Query error: String must contain at least one special character', [ast]);
}
};
var limitedStringCounter = 0;
export class GraphQLLimitedString extends GraphQLCustomScalarType {
constructor(min = 1, max, alphabet) {
const suffix = (limitedStringCounter++ > 0) ? limitedStringCounter : '';
const name = 'LimitedString' + suffix;
var description = 'A limited string.';
if(max) description += ' Has to be between ' + min + ' and ' + max + ' characters long.';
else description += ' Has to be at least ' + min + ' characters long.';
if(alphabet) description += ' May only contain the following characters: ' + alphabet;
const validator = function(ast) {
stringValidator(ast);
lengthValidator(ast, min, max);
if(alphabet) alphabetValidator(ast, alphabet);
return ast.value;
}
super(name, description, validator);
}
};
var passwordCounter = 0;
export class GraphQLPassword extends GraphQLCustomScalarType {
constructor(min = 1, max, alphabet, complexity) {
const suffix = (passwordCounter++ > 0) ? passwordCounter : '';
const name = 'Password' + suffix;
var description = 'A password string.';
if(max) description += ' Has to be between ' + min + ' and ' + max + ' characters long.';
else description += ' Has to be at least ' + min + ' characters long.';
if(alphabet) description += ' May only contain the following characters: ' + alphabet;
if(complexity) {
if(complexity.alphaNumeric) description += ' Has to be alpha numeric.';
if(complexity.mixedCase) description += ' Has to be mixed case.';
if(complexity.specialChars) description += ' Has to contain special characters.';
}
const validator = function(ast) {
stringValidator(ast);
lengthValidator(ast, min, max);
if(alphabet) alphabetValidator(ast, alphabet);
if(complexity) complexityValidator(ast, complexity);
return ast.value;
}
super(name, description, validator);
}
};
export const GraphQLDateTime = factory.getCustomScalar(
'DateTime',
'The DateTime scalar type represents date time strings complying to ISO-8601.',
function(ast) {
stringValidator(ast);
if(!Date.parse(ast.value)) {
throw new GraphQLError('Query error: String is not a valid date time string', [ast]);
}
return ast.value;
}
);