Skip to content

Commit 2706ca1

Browse files
Glavin001mickhansen
authored andcommitted
Fixes #223. Add cache argument to attributeFields (#272)
* See #223. Add failing unit test for multiple enum types with same name * Fixes #223. Add cache argument to attributeFields * Clean up commenting of attributeFields * See #223. Document attributeFields 'cache' option * See #229. Document attributeFields commentToDescription option
1 parent 0388755 commit 2706ca1

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,16 @@ var Model = sequelize.define('User', {
157157

158158
import {attributeFields} from 'graphql-sequelize';
159159

160+
var cache = {}; // Reusable cache of enum types
160161
attributeFields(Model, {
161162
// ... options
162163
exclude: [], // array of model attributes to ignore - default: []
163164
only: [], // only generate definitions for these model attributes - default: null
164165
globalId: true, // return an relay global id field - default: false
165166
map: {}, // rename fields - default: {}
166167
allowNull: false, // disable wrapping mandatory fields in `GraphQLNonNull` - default: false
168+
commentToDescription: false, // convert model comment to GraphQL description - default: false
169+
cache: cache, // Cache enum types to prevent duplicate type name error - default: {}
167170
});
168171

169172
/*

src/attributeFields.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { GraphQLNonNull, GraphQLEnumType } from 'graphql';
33
import { globalIdField } from 'graphql-relay';
44

55
module.exports = function (Model, options = {}) {
6+
var cache = options.cache || {};
67
var result = Object.keys(Model.rawAttributes).reduce(function (memo, key) {
78
if (options.exclude && ~options.exclude.indexOf(key)) return memo;
89
if (options.only && !~options.only.indexOf(key)) return memo;
@@ -24,7 +25,18 @@ module.exports = function (Model, options = {}) {
2425
};
2526

2627
if (memo[key].type instanceof GraphQLEnumType ) {
27-
memo[key].type.name = `${Model.name}${key}EnumType`;
28+
var typeName = `${Model.name}${key}EnumType`;
29+
/*
30+
Cache enum types to prevent duplicate type name error
31+
when calling attributeFields multiple times on the same model
32+
*/
33+
if (cache[typeName]) {
34+
memo[key].type = cache[typeName];
35+
} else {
36+
memo[key].type.name = typeName;
37+
cache[typeName] = memo[key].type;
38+
}
39+
2840
}
2941

3042
if (!options.allowNull) {

test/unit/attributeFields.test.js

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import {
1414
GraphQLNonNull,
1515
GraphQLBoolean,
1616
GraphQLEnumType,
17-
GraphQLList
17+
GraphQLList,
18+
GraphQLObjectType,
19+
GraphQLSchema
1820
} from 'graphql';
1921

2022
import {
@@ -197,6 +199,56 @@ describe('attributeFields', function () {
197199
expect(fields.enumTwo.type.getValues()[0].value).to.equal('foo_bar');
198200
});
199201

202+
it('should not create multiple enum types with same name when using cache', function () {
203+
204+
// Create Schema
205+
var schemaFn = function (fields1, fields2) {
206+
return function () {
207+
var object1 = new GraphQLObjectType({
208+
name: 'Object1',
209+
fields: fields1
210+
});
211+
var object2 = new GraphQLObjectType({
212+
name: 'Object2',
213+
fields: fields2
214+
});
215+
return new GraphQLSchema({
216+
query: new GraphQLObjectType({
217+
name: 'RootQueryType',
218+
fields: {
219+
object1: {
220+
type: object1,
221+
resolve: function () {
222+
return {};
223+
}
224+
},
225+
object2: {
226+
type: object2,
227+
resolve: function () {
228+
return {};
229+
}
230+
}
231+
}
232+
})
233+
});
234+
}
235+
};
236+
237+
// Bad: Will create multiple/duplicate types with same name
238+
var fields1a = attributeFields(Model);
239+
var fields2a = attributeFields(Model);
240+
241+
expect(schemaFn(fields1a, fields2a)).to.throw(Error);
242+
243+
// Good: Will use cache and not create mutliple/duplicate types with same name
244+
var cache = {};
245+
var fields1b = attributeFields(Model, {cache: cache});
246+
var fields2b = attributeFields(Model, {cache: cache});
247+
248+
expect(schemaFn(fields1b, fields2b)).to.not.throw(Error);
249+
250+
});
251+
200252
describe('with non-default primary key', function () {
201253
var ModelWithoutId;
202254
var modelName = Math.random().toString();

0 commit comments

Comments
 (0)