Skip to content

Commit 59d825a

Browse files
committed
Added lib
1 parent 3324eee commit 59d825a

File tree

6 files changed

+378
-2
lines changed

6 files changed

+378
-2
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ npm-debug.log
2424
dump.rdb
2525
bundle.js
2626

27-
lib
2827
coverage
2928
.nyc_output
3029
flow-coverage
File renamed without changes.

lib/index.js

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _requestPromise = require('request-promise');
8+
9+
var _requestPromise2 = _interopRequireDefault(_requestPromise);
10+
11+
var _graphql = require('graphql');
12+
13+
var _swagger = require('./swagger');
14+
15+
var _typeMap = require('./typeMap');
16+
17+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18+
19+
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
20+
21+
// @flow
22+
require('babel-polyfill');
23+
24+
25+
var schemaFromEndpoints = function schemaFromEndpoints(endpoints) {
26+
var rootType = new _graphql.GraphQLObjectType({
27+
name: 'Query',
28+
fields: function fields() {
29+
return {
30+
viewer: {
31+
type: new _graphql.GraphQLObjectType({
32+
name: 'viewer',
33+
fields: function fields() {
34+
var queryFields = getQueriesFields(endpoints, false);
35+
if (!Object.keys(queryFields).length) {
36+
throw new Error('Did not find any GET endpoints');
37+
}
38+
return queryFields;
39+
}
40+
}),
41+
resolve: function resolve() {
42+
return 'Without this resolver graphql does not resolve further';
43+
}
44+
}
45+
};
46+
}
47+
});
48+
49+
var graphQLSchema = {
50+
query: rootType
51+
};
52+
53+
var mutationFields = getQueriesFields(endpoints, true);
54+
if (Object.keys(mutationFields).length) {
55+
graphQLSchema.mutation = new _graphql.GraphQLObjectType({
56+
name: 'Mutation',
57+
fields: mutationFields
58+
});
59+
}
60+
61+
return new _graphql.GraphQLSchema(graphQLSchema);
62+
};
63+
64+
var resolver = function resolver(endpoint) {
65+
return function () {
66+
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(_, args, opts) {
67+
var req, res;
68+
return regeneratorRuntime.wrap(function _callee$(_context) {
69+
while (1) {
70+
switch (_context.prev = _context.next) {
71+
case 0:
72+
req = endpoint.request(args, {
73+
baseUrl: opts.GQLProxyBaseUrl
74+
});
75+
76+
if (opts.BearerToken) {
77+
req.headers.Authorization = opts.BearerToken;
78+
}
79+
_context.next = 4;
80+
return (0, _requestPromise2.default)(req);
81+
82+
case 4:
83+
res = _context.sent;
84+
return _context.abrupt('return', JSON.parse(res));
85+
86+
case 6:
87+
case 'end':
88+
return _context.stop();
89+
}
90+
}
91+
}, _callee, undefined);
92+
}));
93+
94+
return function (_x, _x2, _x3) {
95+
return _ref.apply(this, arguments);
96+
};
97+
}();
98+
};
99+
100+
var getQueriesFields = function getQueriesFields(endpoints, isMutation) {
101+
return Object.keys(endpoints).filter(function (typeName) {
102+
return !!endpoints[typeName].mutation === !!isMutation;
103+
}).reduce(function (result, typeName) {
104+
var endpoint = endpoints[typeName];
105+
var type = (0, _typeMap.createGQLObject)(endpoint.response, typeName, endpoint.location);
106+
result[typeName] = {
107+
type: type,
108+
description: endpoint.description,
109+
args: (0, _typeMap.mapParametersToFields)(endpoint.parameters, endpoint.location, typeName),
110+
resolve: resolver(endpoint)
111+
};
112+
return result;
113+
}, {});
114+
};
115+
116+
var build = function () {
117+
var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2(swaggerPath) {
118+
var swaggerSchema, endpoints, schema;
119+
return regeneratorRuntime.wrap(function _callee2$(_context2) {
120+
while (1) {
121+
switch (_context2.prev = _context2.next) {
122+
case 0:
123+
_context2.next = 2;
124+
return (0, _swagger.loadSchema)(swaggerPath);
125+
126+
case 2:
127+
swaggerSchema = _context2.sent;
128+
endpoints = (0, _swagger.getAllEndPoints)(swaggerSchema);
129+
schema = schemaFromEndpoints(endpoints);
130+
return _context2.abrupt('return', schema);
131+
132+
case 6:
133+
case 'end':
134+
return _context2.stop();
135+
}
136+
}
137+
}, _callee2, undefined);
138+
}));
139+
140+
return function build(_x4) {
141+
return _ref2.apply(this, arguments);
142+
};
143+
}();
144+
145+
exports.default = build;
146+
module.exports = exports['default'];

lib/swagger.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.getAllEndPoints = exports.loadSchema = exports.getSchema = undefined;
7+
8+
var _jsonSchemaRefParser = require('json-schema-ref-parser');
9+
10+
var _jsonSchemaRefParser2 = _interopRequireDefault(_jsonSchemaRefParser);
11+
12+
var _nodeRequestBySwagger = require('node-request-by-swagger');
13+
14+
var _nodeRequestBySwagger2 = _interopRequireDefault(_nodeRequestBySwagger);
15+
16+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17+
18+
// @flow
19+
20+
var __schema = void 0;
21+
22+
var getSchema = exports.getSchema = function getSchema() {
23+
if (!__schema || !Object.keys(__schema).length) {
24+
throw new Error('Schema was not loaded');
25+
}
26+
return __schema;
27+
};
28+
29+
var getGQLTypeNameFromURL = function getGQLTypeNameFromURL(method, url) {
30+
var fromUrl = url.replace(/[\{\}]+/g, '').replace(/[^a-zA-Z0-9_]+/g, '_');
31+
return '' + method + fromUrl;
32+
};
33+
34+
var getSuccessResponse = function getSuccessResponse(responses) {
35+
var resp = void 0;
36+
37+
if (!responses) return null;
38+
39+
Object.keys(responses).some(function (code) {
40+
resp = responses[code];
41+
return code[0] === '2';
42+
});
43+
44+
return resp && resp.schema;
45+
};
46+
47+
var loadSchema = exports.loadSchema = function loadSchema(pathToSchema) {
48+
var schema = _jsonSchemaRefParser2.default.dereference(pathToSchema);
49+
__schema = schema;
50+
return schema;
51+
};
52+
53+
var replaceOddChars = function replaceOddChars(str) {
54+
return str.replace(/[^_a-zA-Z0-9]/g, '_');
55+
};
56+
57+
/**
58+
* Going throw schema and grab routes
59+
* @returns Promise<T>
60+
*/
61+
var getAllEndPoints = exports.getAllEndPoints = function getAllEndPoints(schema) {
62+
var allTypes = {};
63+
Object.keys(schema.paths).forEach(function (path) {
64+
var route = schema.paths[path];
65+
Object.keys(route).forEach(function (method) {
66+
var obj = route[method];
67+
var isMutation = ['post', 'put', 'patch', 'delete'].indexOf(method) !== -1;
68+
var typeName = obj.operationId || getGQLTypeNameFromURL(method, path);
69+
var parameters = obj.parameters ? obj.parameters.map(function (param) {
70+
var type = param.type;
71+
return { name: replaceOddChars(param.name), type: type, jsonSchema: param };
72+
}) : [];
73+
allTypes[typeName] = {
74+
parameters: parameters,
75+
description: obj.description,
76+
response: getSuccessResponse(obj.responses),
77+
request: function request(args, server) {
78+
var url = '' + server.baseUrl + path;
79+
return (0, _nodeRequestBySwagger2.default)(obj, {
80+
request: args,
81+
url: url,
82+
method: method
83+
}, '');
84+
},
85+
mutation: isMutation
86+
};
87+
});
88+
});
89+
return allTypes;
90+
};

lib/typeMap.js

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
exports.mapParametersToFields = exports.getTypeFields = exports.createGQLObject = undefined;
7+
8+
var _lodash = require('lodash');
9+
10+
var _lodash2 = _interopRequireDefault(_lodash);
11+
12+
var _graphql = require('graphql');
13+
14+
var graphql = _interopRequireWildcard(_graphql);
15+
16+
var _swagger = require('./swagger');
17+
18+
var _swagger2 = _interopRequireDefault(_swagger);
19+
20+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
21+
22+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23+
24+
var __allTypes = {}; // @flow
25+
26+
var primitiveTypes = {
27+
string: graphql.GraphQLString,
28+
date: graphql.GraphQLString,
29+
integer: graphql.GraphQLInt,
30+
number: graphql.GraphQLInt,
31+
boolean: graphql.GraphQLBoolean
32+
};
33+
34+
var isObjectType = function isObjectType(jsonSchema) {
35+
return jsonSchema.properties || jsonSchema.type === 'object' || jsonSchema.type === "array" || jsonSchema.schema;
36+
};
37+
38+
var getTypeNameFromRef = function getTypeNameFromRef(ref) {
39+
var cutRef = ref.replace('#/definitions/', '');
40+
return cutRef.replace(/\//, '_');
41+
};
42+
43+
var getExistingType = function getExistingType(ref, isInputType) {
44+
var typeName = getTypeNameFromRef(ref);
45+
var allSchema = _swagger2.default.getSchema();
46+
if (!__allTypes[typeName]) {
47+
var schema = allSchema.definitions[typeName];
48+
if (!schema) {
49+
throw new Error('Definition ' + typeName + ' was not found in schema');
50+
}
51+
__allTypes[typeName] = createGQLObject(schema, typeName, ref, isInputType);
52+
}
53+
return __allTypes[typeName];
54+
};
55+
56+
var getRefProp = function getRefProp(jsonSchema) {
57+
return jsonSchema.$ref || jsonSchema.schema && jsonSchema.schema.$ref;
58+
};
59+
60+
var createGQLObject = exports.createGQLObject = function createGQLObject(jsonSchema, title, isInputType) {
61+
if (!jsonSchema) {
62+
jsonSchema = {
63+
type: 'object',
64+
properties: {}
65+
};
66+
}
67+
68+
var reference = getRefProp(jsonSchema);
69+
70+
if (reference) {
71+
return getExistingType(reference, isInputType);
72+
}
73+
74+
if (jsonSchema.type === 'array') {
75+
if (isObjectType(jsonSchema.items)) {
76+
return new graphql.GraphQLList(createGQLObject(jsonSchema.items, title + '_items', isInputType));
77+
} else {
78+
return new graphql.GraphQLList(getPrimitiveTypes(jsonSchema.items));
79+
}
80+
}
81+
82+
title = title || jsonSchema.title;
83+
84+
var objectType = isInputType ? 'GraphQLInputObjectType' : 'GraphQLObjectType';
85+
86+
return new graphql[objectType]({
87+
name: title,
88+
description: jsonSchema.description,
89+
fields: getTypeFields(jsonSchema, title, isInputType)
90+
});
91+
};
92+
93+
var getTypeFields = exports.getTypeFields = function getTypeFields(jsonSchema, title, isInputType) {
94+
var fields = _lodash2.default.mapValues(jsonSchema.properties || {}, function (propertySchema, propertyName) {
95+
return {
96+
description: propertySchema.description,
97+
type: jsonSchemaTypeToGraphQL(title, propertySchema, propertyName, isInputType)
98+
};
99+
});
100+
101+
if (!Object.keys(fields).length) {
102+
fields.empty = {
103+
description: 'default field',
104+
type: graphql.GraphQLString
105+
};
106+
}
107+
return fields;
108+
};
109+
110+
var jsonSchemaTypeToGraphQL = function jsonSchemaTypeToGraphQL(title, jsonSchema, schemaName, isInputType) {
111+
if (isObjectType(jsonSchema)) {
112+
return createGQLObject(jsonSchema, title + '_' + schemaName, isInputType);
113+
} else if (jsonSchema.type) {
114+
return getPrimitiveTypes(jsonSchema);
115+
} else {
116+
throw new Error("Don't know how to handle schema " + JSON.stringify(jsonSchema) + " without type and schema");
117+
}
118+
};
119+
120+
var getPrimitiveTypes = function getPrimitiveTypes(jsonSchema) {
121+
var jsonType = jsonSchema.type;
122+
var format = jsonSchema.format;
123+
if (format === 'int64') {
124+
jsonType = 'string';
125+
}
126+
var type = primitiveTypes[jsonType];
127+
if (!type) {
128+
throw new Error('Cannot build primitive type "' + jsonType + '"');
129+
}
130+
return type;
131+
};
132+
133+
var mapParametersToFields = exports.mapParametersToFields = function mapParametersToFields(parameters, endpointLocation, typeName) {
134+
return parameters.reduce(function (res, param) {
135+
var type = jsonSchemaTypeToGraphQL('param_' + typeName, param.jsonSchema, param.name, true);
136+
res[param.name] = {
137+
type: type
138+
};
139+
return res;
140+
}, {});
141+
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "swagger-to-graphql",
3-
"version": "1.1.0",
3+
"version": "1.1.1",
44
"author": "Roman Krivtsov",
55
"bin": "./bin/swagger2graphql",
66
"dependencies": {

0 commit comments

Comments
 (0)