Skip to content

Commit

Permalink
Merge pull request #76 from 0xR/required-fields
Browse files Browse the repository at this point in the history
Preserve required fields in GraphQL schema
  • Loading branch information
raxpost authored May 28, 2018
2 parents fe2ad4e + cb9bad1 commit e77699a
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 44 deletions.
4 changes: 2 additions & 2 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ var schemaFromEndpoints = function schemaFromEndpoints(endpoints, proxyUrl, head
var resolver = function resolver(endpoint, proxyUrl) {
var customHeaders = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
return function () {
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(_, args, opts) {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(_, args, opts) {
var proxy, req, res;
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
Expand Down Expand Up @@ -113,7 +113,7 @@ var getFields = function getFields(endpoints, isMutation, gqlTypes, proxyUrl, he
};

var build = function () {
var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(swaggerPath) {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(swaggerPath) {
var proxyUrl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
var headers = arguments[2];
var swaggerSchema, refs, endpoints, schema;
Expand Down
4 changes: 2 additions & 2 deletions lib/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ var getSuccessResponse = function getSuccessResponse(responses) {
};

var loadSchema = exports.loadSchema = function () {
var _ref = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee(pathToSchema) {
var _ref = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee(pathToSchema) {
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
Expand All @@ -84,7 +84,7 @@ var loadSchema = exports.loadSchema = function () {
}();

var loadRefs = exports.loadRefs = function () {
var _ref2 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee2(pathToSchema) {
var _ref2 = (0, _asyncToGenerator3.default)( /*#__PURE__*/_regenerator2.default.mark(function _callee2(pathToSchema) {
return _regenerator2.default.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
Expand Down
23 changes: 14 additions & 9 deletions lib/typeMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,23 +135,28 @@ var getTypeFields = exports.getTypeFields = function getTypeFields(jsonSchema, t
}
return function () {
return _lodash2.default.mapValues(jsonSchema.properties || {}, function (propertySchema, propertyName) {
var baseType = jsonSchemaTypeToGraphQL(title, propertySchema, propertyName, isInputType, gqlTypes);
var type = jsonSchema.required && jsonSchema.required.includes(propertyName) ? graphql.GraphQLNonNull(baseType) : baseType;
return {
description: propertySchema.description,
type: jsonSchemaTypeToGraphQL(title, propertySchema, propertyName, isInputType, gqlTypes)
type: type
};
});
};
};

var jsonSchemaTypeToGraphQL = function jsonSchemaTypeToGraphQL(title, jsonSchema, schemaName, isInputType, gqlTypes) {
if (jsonSchema.$ref) {
return getExistingType(jsonSchema.$ref, isInputType, gqlTypes);
} else if (isObjectType(jsonSchema)) {
return createGQLObject(jsonSchema, title + '_' + schemaName, isInputType, gqlTypes);
} else if (jsonSchema.type) {
return getPrimitiveTypes(jsonSchema);
}
throw new Error("Don't know how to handle schema " + (0, _stringify2.default)(jsonSchema) + ' without type and schema');
var baseType = function () {
if (jsonSchema.$ref) {
return getExistingType(jsonSchema.$ref, isInputType, gqlTypes);
} else if (isObjectType(jsonSchema)) {
return createGQLObject(jsonSchema, title + '_' + schemaName, isInputType, gqlTypes);
} else if (jsonSchema.type) {
return getPrimitiveTypes(jsonSchema);
}
throw new Error("Don't know how to handle schema " + (0, _stringify2.default)(jsonSchema) + ' without type and schema');
}();
return jsonSchema.required ? graphql.GraphQLNonNull(baseType) : baseType;
};

var getPrimitiveTypes = function getPrimitiveTypes(jsonSchema) {
Expand Down
23 changes: 14 additions & 9 deletions src/typeMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,27 @@ export const getTypeFields = (jsonSchema: JSONSchemaType, title: string, isInput
}
return () =>
_.mapValues(jsonSchema.properties || {}, (propertySchema, propertyName) => {
const baseType = jsonSchemaTypeToGraphQL(title, propertySchema, propertyName, isInputType, gqlTypes);
const type = jsonSchema.required && jsonSchema.required.includes(propertyName) ? graphql.GraphQLNonNull(baseType) : baseType;
return {
description: propertySchema.description,
type: jsonSchemaTypeToGraphQL(title, propertySchema, propertyName, isInputType, gqlTypes)
type
};
});
};

const jsonSchemaTypeToGraphQL = (title: string, jsonSchema: JSONSchemaType, schemaName: string, isInputType: boolean, gqlTypes: GraphQLTypeMap) => {
if (jsonSchema.$ref) {
return getExistingType(jsonSchema.$ref, isInputType, gqlTypes);
} else if (isObjectType(jsonSchema)) {
return createGQLObject(jsonSchema, title + '_' + schemaName, isInputType, gqlTypes);
} else if (jsonSchema.type) {
return getPrimitiveTypes(jsonSchema);
}
throw new Error("Don't know how to handle schema " + JSON.stringify(jsonSchema) + ' without type and schema');
const baseType = (() => {
if (jsonSchema.$ref) {
return getExistingType(jsonSchema.$ref, isInputType, gqlTypes);
} else if (isObjectType(jsonSchema)) {
return createGQLObject(jsonSchema, title + '_' + schemaName, isInputType, gqlTypes);
} else if (jsonSchema.type) {
return getPrimitiveTypes(jsonSchema);
}
throw new Error("Don't know how to handle schema " + JSON.stringify(jsonSchema) + ' without type and schema');
})();
return jsonSchema.required ? graphql.GraphQLNonNull(baseType) : baseType;
};

const getPrimitiveTypes = (jsonSchema: JSONSchemaType): GraphQLScalarType => {
Expand Down
3 changes: 2 additions & 1 deletion src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export type JSONSchemaType = {
type?: string,
properties?: Array<string>,
title?: string,
description?: string
description?: string,
required?: boolean | Array<string>
}

export type SwaggerSchema = {
Expand Down
42 changes: 21 additions & 21 deletions test/fixtures/petstore.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,27 @@ type logoutUser {
}

type Mutation {
addPet(body: PetInput): addPet
updatePet(body: PetInput): updatePet
updatePetWithForm(petId: String, name: String, status: String): updatePetWithForm
deletePet(api_key: String, petId: String): deletePet
placeOrder(body: OrderInput): Order
addPet(body: PetInput!): addPet
updatePet(body: PetInput!): updatePet
updatePetWithForm(petId: String!, name: String, status: String): updatePetWithForm
deletePet(api_key: String, petId: String!): deletePet
placeOrder(body: OrderInput!): Order

"""
For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors
"""
deleteOrder(orderId: String): deleteOrder
deleteOrder(orderId: String!): deleteOrder

"""This can only be done by the logged in user."""
createUser(body: UserInput): createUser
createUsersWithArrayInput(body: param_createUsersWithArrayInput_bodyInput): createUsersWithArrayInput
createUsersWithListInput(body: param_createUsersWithListInput_bodyInput): createUsersWithListInput
createUser(body: UserInput!): createUser
createUsersWithArrayInput(body: param_createUsersWithArrayInput_bodyInput!): createUsersWithArrayInput
createUsersWithListInput(body: param_createUsersWithListInput_bodyInput!): createUsersWithListInput

"""This can only be done by the logged in user."""
updateUser(username: String, body: UserInput): updateUser
updateUser(username: String!, body: UserInput!): updateUser

"""This can only be done by the logged in user."""
deleteUser(username: String): deleteUser
deleteUser(username: String!): deleteUser
}

type Order {
Expand Down Expand Up @@ -119,8 +119,8 @@ input param_createUsersWithListInput_bodyInput {
type Pet {
id: String
category: Category
name: String
photoUrls: [String]
name: String!
photoUrls: [String]!
tags: [Tag]

"""pet status in the store"""
Expand All @@ -130,8 +130,8 @@ type Pet {
input PetInput {
id: String
category: CategoryInput
name: String
photoUrls: [String]
name: String!
photoUrls: [String]!
tags: [TagInput]

"""pet status in the store"""
Expand All @@ -140,26 +140,26 @@ input PetInput {

type Query {
"""Multiple status values can be provided with comma separated strings"""
findPetsByStatus(status: [String]): [Pet]
findPetsByStatus(status: [String]!): [Pet]

"""
Muliple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
"""
findPetsByTags(tags: [String]): [Pet]
findPetsByTags(tags: [String]!): [Pet]

"""Returns a single pet"""
getPetById(petId: String): Pet
getPetById(petId: String!): Pet

"""Returns a map of status codes to quantities"""
getInventory: getInventory

"""
For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions
"""
getOrderById(orderId: String): Order
loginUser(username: String, password: String): loginUser
getOrderById(orderId: String!): Order
loginUser(username: String!, password: String!): loginUser
logoutUser: logoutUser
getUserByName(username: String): User
getUserByName(username: String!): User
}

type Tag {
Expand Down

0 comments on commit e77699a

Please sign in to comment.