Skip to content

Commit 1765cbc

Browse files
authored
feat: added array support (#83)
1 parent 49cde70 commit 1765cbc

File tree

2 files changed

+370
-37
lines changed

2 files changed

+370
-37
lines changed

index.js

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,128 @@
1-
const { GraphQLFloat, GraphQLInt, GraphQLString, GraphQLNonNull, isNonNullType, isScalarType } = require('graphql')
1+
const {
2+
GraphQLFloat,
3+
GraphQLInt,
4+
GraphQLString,
5+
GraphQLNonNull,
6+
isNonNullType,
7+
isScalarType,
8+
GraphQLList,
9+
isListType
10+
} = require('graphql')
211
const { getDirectives, mapSchema, MapperKind } = require('@graphql-tools/utils')
312
const ConstraintStringType = require('./scalars/string')
413
const ConstraintNumberType = require('./scalars/number')
514

615
function constraintDirective () {
716
const constraintTypes = {}
817

9-
function getConstraintType (fieldName, type, notNull, directiveArgumentMap) {
18+
function getConstraintType (fieldName, type, notNull, directiveArgumentMap, list, listNotNull) {
1019
// Names must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ as per graphql-js
1120
let uniqueTypeName
1221
if (directiveArgumentMap.uniqueTypeName) {
1322
uniqueTypeName = directiveArgumentMap.uniqueTypeName.replace(/\W/g, '')
1423
} else {
15-
uniqueTypeName = `${fieldName}_${type.name}_${notNull ? 'NotNull_' : ''}` + Object.entries(directiveArgumentMap)
16-
.map(([key, value]) => {
17-
if (key === 'min' || key === 'max' || key === 'exclusiveMin' || key === 'exclusiveMax' || key === 'multipleOf') {
18-
return `${key}_${value.toString().replace(/\W/g, 'dot')}`
19-
}
20-
return `${key}_${value.toString().replace(/\W/g, '')}`
21-
})
22-
.join('_')
24+
uniqueTypeName =
25+
`${fieldName}_${list ? 'List_' : ''}${listNotNull ? 'ListNotNull_' : ''}${
26+
type.name
27+
}_${notNull ? 'NotNull_' : ''}` +
28+
Object.entries(directiveArgumentMap)
29+
.map(([key, value]) => {
30+
if (
31+
key === 'min' ||
32+
key === 'max' ||
33+
key === 'exclusiveMin' ||
34+
key === 'exclusiveMax' ||
35+
key === 'multipleOf'
36+
) {
37+
return `${key}_${value.toString().replace(/\W/g, 'dot')}`
38+
}
39+
return `${key}_${value.toString().replace(/\W/g, '')}`
40+
})
41+
.join('_')
2342
}
2443
const key = Symbol.for(uniqueTypeName)
2544
let constraintType = constraintTypes[key]
26-
2745
if (constraintType) return constraintType
28-
2946
if (type === GraphQLString) {
3047
if (notNull) {
31-
constraintType = new GraphQLNonNull(new ConstraintStringType(fieldName, uniqueTypeName, type, directiveArgumentMap))
48+
constraintType = new GraphQLNonNull(
49+
new ConstraintStringType(fieldName, uniqueTypeName, type, directiveArgumentMap)
50+
)
3251
} else {
33-
constraintType = new ConstraintStringType(fieldName, uniqueTypeName, type, directiveArgumentMap)
52+
constraintType = new ConstraintStringType(
53+
fieldName,
54+
uniqueTypeName,
55+
type,
56+
directiveArgumentMap
57+
)
3458
}
3559
} else if (type === GraphQLFloat || type === GraphQLInt) {
3660
if (notNull) {
37-
constraintType = new GraphQLNonNull(new ConstraintNumberType(fieldName, uniqueTypeName, type, directiveArgumentMap))
61+
constraintType = new GraphQLNonNull(
62+
new ConstraintNumberType(fieldName, uniqueTypeName, type, directiveArgumentMap)
63+
)
3864
} else {
39-
constraintType = new ConstraintNumberType(fieldName, uniqueTypeName, type, directiveArgumentMap)
65+
constraintType = new ConstraintNumberType(
66+
fieldName,
67+
uniqueTypeName,
68+
type,
69+
directiveArgumentMap
70+
)
4071
}
4172
} else {
4273
throw new Error(`Not a valid scalar type: ${type.toString()}`)
4374
}
44-
75+
if (list) {
76+
constraintType = new GraphQLList(constraintType)
77+
if (listNotNull) {
78+
constraintType = new GraphQLNonNull(constraintType)
79+
}
80+
}
4581
constraintTypes[key] = constraintType
4682

4783
return constraintType
4884
}
4985

50-
function wrapType (fieldConfig, directiveArgumentMap) {
51-
let originalType, notNull
52-
53-
if (isNonNullType(fieldConfig.type)) {
54-
originalType = fieldConfig.type.ofType
55-
notNull = true
56-
} else if (isScalarType(fieldConfig.type)) {
57-
originalType = fieldConfig.type
86+
function getScalarType (fieldConfig) {
87+
if (isScalarType(fieldConfig)) {
88+
return { scalarType: fieldConfig }
89+
} else if (isListType(fieldConfig)) {
90+
return { ...getScalarType(fieldConfig.ofType), list: true }
91+
} else if (isNonNullType(fieldConfig) && isScalarType(fieldConfig.ofType)) {
92+
return { scalarType: fieldConfig.ofType, scalarNotNull: true }
93+
} else if (isNonNullType(fieldConfig)) {
94+
return { ...getScalarType(fieldConfig.ofType.ofType), list: true, listNotNull: true }
5895
} else {
59-
throw new Error(`Not a scalar type: ${fieldConfig.type.toString()}`)
96+
throw new Error(`Not a valid scalar type: ${fieldConfig.toString()}`)
6097
}
98+
}
6199

100+
function wrapType (fieldConfig, directiveArgumentMap) {
101+
const result = getScalarType(fieldConfig.type)
62102
const fieldName = fieldConfig.astNode.name.value
63-
64-
fieldConfig.type = getConstraintType(fieldName, originalType, notNull, directiveArgumentMap)
103+
fieldConfig.type = getConstraintType(
104+
fieldName,
105+
result.scalarType,
106+
result.scalarNotNull,
107+
directiveArgumentMap,
108+
result.list,
109+
result.listNotNull
110+
)
65111
}
66112

67-
return schema => mapSchema(schema, {
68-
[MapperKind.FIELD]: (fieldConfig) => {
69-
const directives = getDirectives(schema, fieldConfig)
70-
const directiveArgumentMap = directives.constraint
113+
return (schema) =>
114+
mapSchema(schema, {
115+
[MapperKind.FIELD]: (fieldConfig) => {
116+
const directives = getDirectives(schema, fieldConfig)
117+
const directiveArgumentMap = directives.constraint
71118

72-
if (directiveArgumentMap) {
73-
wrapType(fieldConfig, directiveArgumentMap)
119+
if (directiveArgumentMap) {
120+
wrapType(fieldConfig, directiveArgumentMap)
74121

75-
return fieldConfig
122+
return fieldConfig
123+
}
76124
}
77-
}
78-
})
125+
})
79126
}
80127

81128
const constraintDirectiveTypeDefs = `

0 commit comments

Comments
 (0)