Skip to content

Commit

Permalink
feat(InputTypeComposer): Method InputTypeComposer.create() can accept…
Browse files Browse the repository at this point in the history
… typeName, input template def,

See test cases in this commit for more details
  • Loading branch information
nodkz committed Oct 10, 2016
1 parent 33b1a78 commit c1577a7
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 22 deletions.
55 changes: 55 additions & 0 deletions src/__tests__/inputTypeComposer-test.js
Expand Up @@ -53,4 +53,59 @@ describe('InputTypeComposer', () => {
expect(tc.getField('input5').type).instanceof(GraphQLNonNull);
expect(tc.getField('input5').type.ofType).to.equal(GraphQLBoolean);
});

describe('static method create()', () => {
it('should create ITC by typeName as a string', () => {
const TC = InputTypeComposer.create('TypeStub');
expect(TC).instanceof(InputTypeComposer);
expect(TC.getType()).instanceof(GraphQLInputObjectType);
expect(TC.getFields()).deep.equal({});
});

it('should create ITC by type template string', () => {
const TC = InputTypeComposer.create(`
input TestTypeTplInput {
f1: String
# Description for some required Int field
f2: Int!
}
`);
expect(TC).instanceof(InputTypeComposer);
expect(TC.getTypeName()).equal('TestTypeTplInput');
expect(TC.getFieldType('f1')).equal(GraphQLString);
expect(TC.getFieldType('f2')).instanceof(GraphQLNonNull);
expect(TC.getFieldType('f2').ofType).equal(GraphQLInt);
});

it('should create ITC by GraphQLObjectTypeConfig', () => {
const TC = InputTypeComposer.create({
name: 'TestTypeInput',
fields: {
f1: {
type: 'String',
},
f2: 'Int!',
},
});
expect(TC).instanceof(InputTypeComposer);
expect(TC.getFieldType('f1')).equal(GraphQLString);
expect(TC.getFieldType('f2')).instanceof(GraphQLNonNull);
expect(TC.getFieldType('f2').ofType).equal(GraphQLInt);
});

it('should create ITC by GraphQLInputObjectType', () => {
const objType = new GraphQLInputObjectType({
name: 'TestTypeObj',
fields: {
f1: {
type: GraphQLString,
},
},
});
const TC = InputTypeComposer.create(objType);
expect(TC).instanceof(InputTypeComposer);
expect(TC.getType()).equal(objType);
expect(TC.getFieldType('f1')).equal(GraphQLString);
});
});
});
78 changes: 56 additions & 22 deletions src/inputTypeComposer.js
Expand Up @@ -23,24 +23,44 @@ import type {
export default class InputTypeComposer {
gqType: GraphQLInputObjectType;

static create(opts: InputObjectConfig | string) {
let objConfig;
static create(opts: InputObjectConfig | string | GraphQLInputObjectType) {
let ITC;

if (isString(opts)) {
objConfig = {
name: opts,
fields: () => ({}),
};
// $FlowFixMe
const typeName: string = opts;
const NAME_RX = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
if (NAME_RX.test(typeName)) {
ITC = new InputTypeComposer(new GraphQLInputObjectType({
name: typeName,
fields: () => ({}),
}));
} else {
const type = TypeMapper.createType(typeName);
if (!(type instanceof GraphQLInputObjectType)) {
throw new Error('You should provide correct GraphQLInputObjectType type definition.');
}
ITC = new InputTypeComposer(type);
}
} else if (opts instanceof GraphQLInputObjectType) {
ITC = new InputTypeComposer(opts);
} else if (isObject(opts)) {
objConfig = opts;
// $FlowFixMe
const type = new GraphQLInputObjectType({
...opts,
fields: () => ({}),
});
ITC = new InputTypeComposer(type);

// $FlowFixMe
if (isObject(opts.fields)) {
ITC.addFields(opts.fields);
}
} else {
throw new Error('You should provide InputObjectConfig or string with type name to InputTypeComposer.create(opts)');
}

// $FlowFixMe
const gqType = new GraphQLInputObjectType(objConfig);

return new InputTypeComposer(gqType);
return ITC;
}

constructor(gqType: GraphQLInputObjectType) {
Expand Down Expand Up @@ -75,23 +95,37 @@ export default class InputTypeComposer {
return !!fields[fieldName];
}

convertFieldStringTypes(
fieldConfig: InputObjectFieldConfig,
fieldName: string
): InputObjectFieldConfig {
if (typeof fieldConfig === 'string') {
fieldConfig = { // eslint-disable-line no-param-reassign
type: fieldConfig,
};
}

if (typeof fieldConfig.type === 'string') {
const typeName: string = fieldConfig.type;
const type = TypeMapper.getWrapped(typeName);
if (isInputType(type)) {
// $FlowFixMe
fieldConfig.type = type; // eslint-disable-line
} else {
throw new Error(`${this.getTypeName()}.${fieldName} provided incorrect output type '${typeName}'`);
}
}

return fieldConfig;
}

/**
* Completely replace all fields in GraphQL type
* WARNING: this method rewrite an internal GraphQL instance variable.
*/
setFields(fields: InputObjectConfigFieldMap): void {
Object.keys(fields).forEach((name) => {
const fieldConfig = fields[name];
if (typeof fieldConfig.type === 'string') {
const typeName: string = fieldConfig.type;
const type = TypeMapper.getWrapped(typeName);
if (isInputType(type)) {
// $FlowFixMe
fieldConfig.type = type; // eslint-disable-line
} else {
throw new Error(`${this.getTypeName()}.${name} provided incorrect output type '${typeName}'`);
}
}
fields[name] = this.convertFieldStringTypes(fields[name], name); // eslint-disable-line
});

this.gqType._typeConfig.fields = () => fields;
Expand Down

0 comments on commit c1577a7

Please sign in to comment.