Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding in allOf functionality #41

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Swagger2GraphQL
# Swagger2graphQL

Swagger2GraphQL converts your existing Swagger schema to GraphQL types where resolvers perform HTTP calls to certain real endpoints.
Swagger2graphQL converts your existing Swagger schema to GraphQL types where resolvers perform HTTP calls to certain real endpoints.
It allows you to move your API to GraphQL with nearly zero afford and maintain both: REST and GraphQL APIs.

<a href="https://medium.com/@raxwunter/moving-existing-api-from-rest-to-graphql-205bab22c184">Why?</a>
Expand All @@ -12,8 +12,9 @@ It allows you to move your API to GraphQL with nearly zero afford and maintain b
```js
const express = require('express');
const app = express();
const graphqlHTTP = require('express-graphql');
const graphQLSchema = require('swagger-to-graphql');
var graphqlHTTP = require('express-graphql');
var graphql = require('graphql');
var graphQLSchema = require('swagger-to-graphql');

graphQLSchema('./petstore.json').then(schema => {
app.use('/graphql', graphqlHTTP(() => {
Expand Down Expand Up @@ -51,4 +52,4 @@ swagger-to-graphql --swagger=/path/to/swagger_schema.json > ./types.graphql
...
```

<a href="https://github.com/yarax/swagger-to-graphql/blob/master/src/types.js#L3"> All context options </a>
<a href="https://github.com/yarax/swagger-to-graphql/blob/master/src/types.js#L3"> All context options </a>
53 changes: 53 additions & 0 deletions lib/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,49 @@ var getSuccessResponse = function getSuccessResponse(responses) {

(0, _keys2.default)(responses).some(function (code) {
resp = responses[code];

return code[0] === '2';
});

// If there is an allOf reference, flatten its properties and the
// additional properties into a single respone.
if (resp.schema && resp.schema.allOf) {
return flattenAllOfProperties(resp.schema);
}

// If it's an array of a definition that uses an allOf, change the items
// to be the flattened definition.
else if (resp.schema && resp.schema.items && resp.schema.items.allOf) {
return {
items: flattenAllOfProperties(resp.schema.items),
type: 'array'
};
}

return resp && resp.schema;
};

var flattenAllOfProperties = function flattenAllOfProperties(schemaDefinition) {
let parentSchema = JSON.parse(JSON.stringify(schemaDefinition.allOf[0]));
let additionalSchema = schemaDefinition.allOf[1] || {};
let finalSchema = parentSchema;
for (const key in additionalSchema) {
// If it's an object, we need to merge in all properties.
if (additionalSchema[key] === Object(additionalSchema[key])) {
for (const propertyKey in additionalSchema[key]) {
finalSchema[key][propertyKey] = additionalSchema[key][propertyKey];
}
}
// If it's not, just add it on. E.g. the 'type' property is a string.
else {
finalSchema[key] = additionalSchema[key];
}
}
// Return this flattened response (instead of the standard one, which would
// contain the allOf elements).
return finalSchema;
}

var loadSchema = exports.loadSchema = function loadSchema(pathToSchema) {
var schema = _jsonSchemaRefParser2.default.dereference(pathToSchema);
__schema = schema;
Expand All @@ -55,6 +92,22 @@ var replaceOddChars = function replaceOddChars(str) {
return str.replace(/[^_a-zA-Z0-9]/g, '_');
};

var censor = function censor(censor) {
var i = 0;

return function(key, value) {
if(i !== 0 && typeof(censor) === 'object' && typeof(value) == 'object' && censor == value)
return '[Circular]';

if(i >= 29) // seems to be a harded maximum of 30 serialized objects?
return '[Unknown]';

++i; // so we know we aren't using the original object anymore

return value;
}
}

/**
* Going throw schema and grab routes
*/
Expand Down
16 changes: 13 additions & 3 deletions lib/typeMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var primitiveTypes = {
};

var isObjectType = function isObjectType(jsonSchema) {
return jsonSchema.properties || jsonSchema.type === 'object' || jsonSchema.type === 'array' || jsonSchema.schema;
return jsonSchema.properties || jsonSchema.type === 'object' || jsonSchema.type === 'array' || jsonSchema.schema || jsonSchema.allOf;
};

var getTypeNameFromRef = function getTypeNameFromRef(ref) {
Expand All @@ -64,6 +64,7 @@ var getRefProp = function getRefProp(jsonSchema) {
};

var createGQLObject = exports.createGQLObject = function createGQLObject(jsonSchema, title, isInputType) {

if (!jsonSchema) {
jsonSchema = { // eslint-disable-line no-param-reassign
type: 'object',
Expand All @@ -74,7 +75,7 @@ var createGQLObject = exports.createGQLObject = function createGQLObject(jsonSch
}

var reference = getRefProp(jsonSchema);

if (reference) {
return getExistingType(reference, isInputType);
}
Expand Down Expand Up @@ -104,7 +105,13 @@ var createGQLObject = exports.createGQLObject = function createGQLObject(jsonSch
};

var getTypeFields = exports.getTypeFields = function getTypeFields(jsonSchema, title, isInputType) {
var fields = _lodash2.default.mapValues(jsonSchema.properties || {}, function (propertySchema, propertyName) {
let properties = {};

if (jsonSchema.properties) {
properties = jsonSchema.properties;
}

var fields = _lodash2.default.mapValues(properties, function (propertySchema, propertyName) {
return {
description: propertySchema.description,
type: jsonSchemaTypeToGraphQL(title, propertySchema, propertyName, isInputType)
Expand All @@ -122,6 +129,9 @@ var getTypeFields = exports.getTypeFields = function getTypeFields(jsonSchema, t

var jsonSchemaTypeToGraphQL = function jsonSchemaTypeToGraphQL(title, jsonSchema, schemaName, isInputType) {
if (isObjectType(jsonSchema)) {
if (title.length > 40) {
throw new Error('got too far');
}
return createGQLObject(jsonSchema, title + '_' + schemaName, isInputType);
} else if (jsonSchema.type) {
return getPrimitiveTypes(jsonSchema);
Expand Down
15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
{
"name": "swagger-to-graphql",
"version": "1.1.7",
"author": "Roman Krivtsov",
"bin": "./bin/swagger2graphql",
"author": {
"name": "Roman Krivtsov"
},
"bin": {
"swagger-to-graphql": "./bin/swagger2graphql"
},
"dependencies": {
"babel-runtime": "^6.25.0",
"graphql": "^0.10.1",
Expand All @@ -15,6 +17,7 @@
"request-promise": "^4.1.1",
"yargs": "^8.0.2"
},
"description": "Swagger2graphQL converts your existing Swagger schema to GraphQL types where resolvers perform HTTP calls to certain real endpoints. It allows you to move your API to GraphQL with nearly zero afford and maintain both: REST and GraphQL APIs.",
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
Expand All @@ -39,11 +42,13 @@
],
"license": "MIT",
"main": "lib/index.js",
"name": "swagger-to-graphql",
"scripts": {
"build": "babel src -d lib",
"lint": "eslint src/",
"prepublish": "npm run build",
"start": "node example/app.js",
"test": "mocha"
}
},
"version": "1.1.7"
}