graphql-tools
Advanced tools
Comparing version 0.6.6 to 0.7.0
@@ -5,3 +5,22 @@ # Changelog | ||
### v0.7.0 | ||
* Various Bugfixes ([@DxCx](https://github.com/DxCx) in [#129](https://github.com/apollostack/graphql-tools/pull/129)) | ||
- Istanbul coverage was not working well due to Istanbul bug [#549](https://github.com/gotwarlost/istanbul/issues/549) | ||
- Bluebird promise was not converted well on tests | ||
- "console.warn" got overwritten on tests | ||
* Migrated code from Javascript to Typescript ([@DxCx](https://github.com/DxCx) in [#129](https://github.com/apollostack/graphql-tools/pull/129)) | ||
* Deprecated addConnectorsToContext ([@DxCx](https://github.com/DxCx) in [#129](https://github.com/apollostack/graphql-tools/pull/129)) | ||
* Removed deprecated aplloServer ([@DxCx](https://github.com/DxCx) in [#129](https://github.com/apollostack/graphql-tools/pull/129)) | ||
* Removed testing on Node 5 ([@DxCx](https://github.com/DxCx) in [#129](https://github.com/apollostack/graphql-tools/pull/129)) | ||
* Changed GraphQL typings requirment from peer to standard ([@DxCx](https://github.com/DxCx) in [#129](https://github.com/apollostack/graphql-tools/pull/129)) | ||
* Change the missing resolve function validator to show a warning instead of an error ([@nicolaslopezj](https://github.com/nicolaslopezj) in [#134](https://github.com/apollostack/graphql-tools/pull/134)) | ||
* Add missing type annotations to avoid typescript compiler errors when 'noImplicitAny' is enabled ([@almilo](https://github.com/almilo) in [#133](https://github.com/apollostack/graphql-tools/pull/133)) | ||
### v0.6.6 | ||
@@ -8,0 +27,0 @@ * Added embedded Typescript definitions ([@DxCx](https://github.com/DxCx) in [#120](https://github.com/apollostack/graphql-tools/pull/120)) |
@@ -1,104 +0,7 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _schemaGenerator = require('./schemaGenerator'); | ||
Object.defineProperty(exports, 'generateSchema', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.generateSchema; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'makeExecutableSchema', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.makeExecutableSchema; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'buildSchemaFromTypeDefinitions', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.buildSchemaFromTypeDefinitions; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'forEachField', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.forEachField; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'SchemaError', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.SchemaError; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'addErrorLoggingToSchema', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.addErrorLoggingToSchema; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'addResolveFunctionsToSchema', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.addResolveFunctionsToSchema; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'addCatchUndefinedToSchema', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.addCatchUndefinedToSchema; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'addSchemaLevelResolveFunction', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.addSchemaLevelResolveFunction; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'assertResolveFunctionsPresent', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.assertResolveFunctionsPresent; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'attachConnectorsToContext', { | ||
enumerable: true, | ||
get: function get() { | ||
return _schemaGenerator.attachConnectorsToContext; | ||
} | ||
}); | ||
var _mock = require('./mock'); | ||
Object.defineProperty(exports, 'addMockFunctionsToSchema', { | ||
enumerable: true, | ||
get: function get() { | ||
return _mock.addMockFunctionsToSchema; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'MockList', { | ||
enumerable: true, | ||
get: function get() { | ||
return _mock.MockList; | ||
} | ||
}); | ||
Object.defineProperty(exports, 'mockServer', { | ||
enumerable: true, | ||
get: function get() { | ||
return _mock.mockServer; | ||
} | ||
}); | ||
var _apolloServer = require('./apolloServer'); | ||
Object.defineProperty(exports, 'apolloServer', { | ||
enumerable: true, | ||
get: function get() { | ||
return _apolloServer.apolloServer; | ||
} | ||
}); | ||
"use strict"; | ||
function __export(m) { | ||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; | ||
} | ||
__export(require('./schemaGenerator')); | ||
__export(require('./mock')); | ||
//# sourceMappingURL=index.js.map |
@@ -1,52 +0,26 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
/* | ||
* A very simple class for logging errors | ||
*/ | ||
var Logger = function () { | ||
function Logger(name, callback) { | ||
_classCallCheck(this, Logger); | ||
this.name = name; | ||
this.errors = []; | ||
this.callback = callback; | ||
// TODO: should assert that callback is a function | ||
} | ||
_createClass(Logger, [{ | ||
key: 'log', | ||
value: function log(err) { | ||
this.errors.push(err); | ||
if (typeof this.callback === 'function') { | ||
this.callback(err); | ||
} | ||
"use strict"; | ||
class Logger { | ||
constructor(name, callback) { | ||
this.name = name; | ||
this.errors = []; | ||
this.callback = callback; | ||
// TODO: should assert that callback is a function | ||
} | ||
}, { | ||
key: 'printOneError', | ||
value: function printOneError(e) { | ||
return e.stack; | ||
log(err) { | ||
this.errors.push(err); | ||
if (typeof this.callback === 'function') { | ||
this.callback(err); | ||
} | ||
} | ||
}, { | ||
key: 'printAllErrors', | ||
value: function printAllErrors() { | ||
var _this = this; | ||
return this.errors.reduce(function (agg, e) { | ||
return agg + '\n' + _this.printOneError(e); | ||
}, ''); | ||
printOneError(e) { | ||
return e.stack; | ||
} | ||
}]); | ||
return Logger; | ||
}(); | ||
exports.Logger = Logger; | ||
printAllErrors() { | ||
return this.errors.reduce((agg, e) => `${agg}\n${this.printOneError(e)}`, ''); | ||
} | ||
} | ||
exports.Logger = Logger; | ||
//# sourceMappingURL=Logger.js.map |
588
dist/mock.js
@@ -1,362 +0,272 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.mockServer = exports.MockList = exports.addMockFunctionsToSchema = undefined; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _type = require('graphql/type'); | ||
var _graphql = require('graphql'); | ||
var _nodeUuid = require('node-uuid'); | ||
var _nodeUuid2 = _interopRequireDefault(_nodeUuid); | ||
var _schemaGenerator = require('./schemaGenerator'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
"use strict"; | ||
const graphql_1 = require('graphql'); | ||
const graphql_2 = require('graphql'); | ||
const uuid = require('node-uuid'); | ||
const schemaGenerator_1 = require('./schemaGenerator'); | ||
// This function wraps addMockFunctionsToSchema for more convenience | ||
function mockServer(schema) { | ||
var mocks = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var preserveResolvers = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2]; | ||
var mySchema = schema; | ||
if (!(schema instanceof _type.GraphQLSchema)) { | ||
// TODO: provide useful error messages here if this fails | ||
mySchema = (0, _schemaGenerator.buildSchemaFromTypeDefinitions)(schema); | ||
} | ||
addMockFunctionsToSchema({ schema: mySchema, mocks: mocks, preserveResolvers: preserveResolvers }); | ||
return { query: function query(_query, vars) { | ||
return (0, _graphql.graphql)(mySchema, _query, {}, {}, vars); | ||
} }; | ||
function mockServer(schema, mocks, preserveResolvers = false) { | ||
let mySchema; | ||
if (!(schema instanceof graphql_1.GraphQLSchema)) { | ||
// TODO: provide useful error messages here if this fails | ||
mySchema = schemaGenerator_1.buildSchemaFromTypeDefinitions(schema); | ||
} | ||
else { | ||
mySchema = schema; | ||
} | ||
addMockFunctionsToSchema({ schema: mySchema, mocks, preserveResolvers }); | ||
return { query: (query, vars) => graphql_2.graphql(mySchema, query, {}, {}, vars) }; | ||
} | ||
exports.mockServer = mockServer; | ||
// TODO allow providing a seed such that lengths of list could be deterministic | ||
// this could be done by using casual to get a random list length if the casual | ||
// object is global. | ||
function addMockFunctionsToSchema() { | ||
var _ref = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0]; | ||
var schema = _ref.schema; | ||
var _ref$mocks = _ref.mocks; | ||
var mocks = _ref$mocks === undefined ? {} : _ref$mocks; | ||
var _ref$preserveResolver = _ref.preserveResolvers; | ||
var preserveResolvers = _ref$preserveResolver === undefined ? false : _ref$preserveResolver; | ||
function isObject(thing) { | ||
return thing === Object(thing) && !Array.isArray(thing); | ||
} | ||
if (!schema) { | ||
// XXX should we check that schema is an instance of GraphQLSchema? | ||
throw new Error('Must provide schema to mock'); | ||
} | ||
if (!isObject(mocks)) { | ||
throw new Error('mocks must be of type Object'); | ||
} | ||
// use Map internally, because that API is nicer. | ||
var mockFunctionMap = new Map(); | ||
Object.keys(mocks).forEach(function (typeName) { | ||
mockFunctionMap.set(typeName, mocks[typeName]); | ||
}); | ||
mockFunctionMap.forEach(function (mockFunction, mockTypeName) { | ||
if (typeof mockFunction !== 'function') { | ||
throw new Error('mockFunctionMap[' + mockTypeName + '] must be a function'); | ||
function addMockFunctionsToSchema({ schema, mocks = {}, preserveResolvers = false }) { | ||
function isObject(thing) { | ||
return thing === Object(thing) && !Array.isArray(thing); | ||
} | ||
}); | ||
var defaultMockMap = new Map(); | ||
defaultMockMap.set('Int', function () { | ||
return Math.round(Math.random() * 200) - 100; | ||
}); | ||
defaultMockMap.set('Float', function () { | ||
return Math.random() * 200 - 100; | ||
}); | ||
defaultMockMap.set('String', function () { | ||
return 'Hello World'; | ||
}); | ||
defaultMockMap.set('Boolean', function () { | ||
return Math.random() > 0.5; | ||
}); | ||
defaultMockMap.set('ID', function () { | ||
return _nodeUuid2.default.v4(); | ||
}); | ||
function mergeObjects(a, b) { | ||
return Object.assign(a, b); | ||
} | ||
function copyOwnPropsIfNotPresent(target, source) { | ||
Object.getOwnPropertyNames(source).forEach(function (prop) { | ||
if (!Object.getOwnPropertyDescriptor(target, prop)) { | ||
Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop)); | ||
} | ||
}); | ||
} | ||
function copyOwnProps(target) { | ||
for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { | ||
sources[_key - 1] = arguments[_key]; | ||
if (!schema) { | ||
// XXX should we check that schema is an instance of GraphQLSchema? | ||
throw new Error('Must provide schema to mock'); | ||
} | ||
sources.forEach(function (source) { | ||
var chain = source; | ||
while (chain) { | ||
copyOwnPropsIfNotPresent(target, chain); | ||
chain = Object.getPrototypeOf(chain); | ||
} | ||
if (!isObject(mocks)) { | ||
throw new Error('mocks must be of type Object'); | ||
} | ||
// use Map internally, because that API is nicer. | ||
const mockFunctionMap = new Map(); | ||
Object.keys(mocks).forEach((typeName) => { | ||
mockFunctionMap.set(typeName, mocks[typeName]); | ||
}); | ||
return target; | ||
} | ||
// returns a random element from that ary | ||
function getRandomElement(ary) { | ||
var sample = Math.floor(Math.random() * ary.length); | ||
return ary[sample]; | ||
} | ||
// takes either an object or a (possibly nested) array | ||
// and completes the customMock object with any fields | ||
// defined on genericMock | ||
// only merges objects or arrays. Scalars are returned as is | ||
function mergeMocks(genericMockFunction, customMock) { | ||
if (Array.isArray(customMock)) { | ||
return customMock.map(function (el) { | ||
return mergeMocks(genericMockFunction, el); | ||
}); | ||
mockFunctionMap.forEach((mockFunction, mockTypeName) => { | ||
if (typeof mockFunction !== 'function') { | ||
throw new Error(`mockFunctionMap[${mockTypeName}] must be a function`); | ||
} | ||
}); | ||
const defaultMockMap = new Map(); | ||
defaultMockMap.set('Int', () => Math.round(Math.random() * 200) - 100); | ||
defaultMockMap.set('Float', () => (Math.random() * 200) - 100); | ||
defaultMockMap.set('String', () => 'Hello World'); | ||
defaultMockMap.set('Boolean', () => Math.random() > 0.5); | ||
defaultMockMap.set('ID', () => uuid.v4()); | ||
function mergeObjects(a, b) { | ||
return Object.assign(a, b); | ||
} | ||
if (isObject(customMock)) { | ||
return mergeObjects(genericMockFunction(), customMock); | ||
function copyOwnPropsIfNotPresent(target, source) { | ||
Object.getOwnPropertyNames(source).forEach(prop => { | ||
if (!Object.getOwnPropertyDescriptor(target, prop)) { | ||
Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop)); | ||
} | ||
}); | ||
} | ||
return customMock; | ||
} | ||
function assignResolveType(type) { | ||
var fieldType = (0, _type.getNullableType)(type); | ||
var namedFieldType = (0, _type.getNamedType)(fieldType); | ||
var oldResolveType = namedFieldType.resolveType; | ||
if (preserveResolvers && oldResolveType && oldResolveType.length) { | ||
return; | ||
function copyOwnProps(target, ...sources) { | ||
sources.forEach(source => { | ||
let chain = source; | ||
while (chain) { | ||
copyOwnPropsIfNotPresent(target, chain); | ||
chain = Object.getPrototypeOf(chain); | ||
} | ||
}); | ||
return target; | ||
} | ||
if (namedFieldType instanceof _type.GraphQLUnionType || namedFieldType instanceof _type.GraphQLInterfaceType) { | ||
// the default `resolveType` always returns null. We add a fallback | ||
// resolution that works with how unions and interface are mocked | ||
namedFieldType.resolveType = function (data, context, info) { | ||
return info.schema.getType(data.typename); | ||
}; | ||
// returns a random element from that ary | ||
function getRandomElement(ary) { | ||
const sample = Math.floor(Math.random() * ary.length); | ||
return ary[sample]; | ||
} | ||
} | ||
var mockType = function mockType(type, typeName, fieldName) { | ||
// order of precendence for mocking: | ||
// 1. if the object passed in already has fieldName, just use that | ||
// --> if it's a function, that becomes your resolver | ||
// --> if it's a value, the mock resolver will return that | ||
// 2. if the nullableType is a list, recurse | ||
// 2. if there's a mock defined for this typeName, that will be used | ||
// 3. if there's no mock defined, use the default mocks for this type | ||
return function () { | ||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
var root = args[0]; | ||
var queryArgs = args[1]; | ||
var context = args[2]; | ||
var info = args[3]; | ||
// nullability doesn't matter for the purpose of mocking. | ||
var fieldType = (0, _type.getNullableType)(type); | ||
var namedFieldType = (0, _type.getNamedType)(fieldType); | ||
if (root && typeof root[fieldName] !== 'undefined') { | ||
var result = void 0; | ||
// if we're here, the field is already defined | ||
if (typeof root[fieldName] === 'function') { | ||
result = root[fieldName].apply(root, args); | ||
if (result instanceof MockList) { | ||
var _result; | ||
result = (_result = result).mock.apply(_result, args.concat([fieldType, mockType])); | ||
} | ||
} else { | ||
result = root[fieldName]; | ||
// takes either an object or a (possibly nested) array | ||
// and completes the customMock object with any fields | ||
// defined on genericMock | ||
// only merges objects or arrays. Scalars are returned as is | ||
function mergeMocks(genericMockFunction, customMock) { | ||
if (Array.isArray(customMock)) { | ||
return customMock.map((el) => mergeMocks(genericMockFunction, el)); | ||
} | ||
// Now we merge the result with the default mock for this type. | ||
// This allows overriding defaults while writing very little code. | ||
if (mockFunctionMap.has(namedFieldType.name)) { | ||
var _mockFunctionMap$get; | ||
result = mergeMocks((_mockFunctionMap$get = mockFunctionMap.get(namedFieldType.name)).bind.apply(_mockFunctionMap$get, [null].concat(args)), result); | ||
if (isObject(customMock)) { | ||
return mergeObjects(genericMockFunction(), customMock); | ||
} | ||
return result; | ||
} | ||
if (fieldType instanceof _type.GraphQLList) { | ||
return [mockType(fieldType.ofType).apply(undefined, args), mockType(fieldType.ofType).apply(undefined, args)]; | ||
} | ||
if (mockFunctionMap.has(fieldType.name)) { | ||
// the object passed doesn't have this field, so we apply the default mock | ||
return mockFunctionMap.get(fieldType.name).apply(undefined, args); | ||
} | ||
if (fieldType instanceof _type.GraphQLObjectType) { | ||
// objects don't return actual data, we only need to mock scalars! | ||
return {}; | ||
} | ||
// TODO mocking Interface and Union types will require determining the | ||
// resolve type before passing it on. | ||
// XXX we recommend a generic way for resolve type here, which is defining | ||
// typename on the object. | ||
if (fieldType instanceof _type.GraphQLUnionType) { | ||
var randomType = getRandomElement(fieldType.getTypes()); | ||
return _extends({ | ||
typename: randomType | ||
}, mockType(randomType).apply(undefined, args)); | ||
} | ||
if (fieldType instanceof _type.GraphQLInterfaceType) { | ||
var possibleTypes = schema.getPossibleTypes(fieldType); | ||
var _randomType = getRandomElement(possibleTypes); | ||
return _extends({ | ||
typename: _randomType | ||
}, mockType(_randomType).apply(undefined, args)); | ||
} | ||
if (fieldType instanceof _type.GraphQLEnumType) { | ||
return getRandomElement(fieldType.getValues()).value; | ||
} | ||
if (defaultMockMap.has(fieldType.name)) { | ||
return defaultMockMap.get(fieldType.name).apply(undefined, args); | ||
} | ||
// if we get to here, we don't have a value, and we don't have a mock for this type, | ||
// we could return undefined, but that would be hard to debug, so we throw instead. | ||
throw new Error('No mock defined for type "' + fieldType.name + '"'); | ||
}; | ||
}; | ||
(0, _schemaGenerator.forEachField)(schema, function (field, typeName, fieldName) { | ||
assignResolveType(field.type); | ||
var mockResolver = void 0; | ||
// we have to handle the root mutation and root query types differently, | ||
// because no resolver is called at the root. | ||
var isOnQueryType = typeName === (schema.getQueryType() || {}).name; | ||
var isOnMutationType = typeName === (schema.getMutationType() || {}).name; | ||
if (isOnQueryType || isOnMutationType) { | ||
if (mockFunctionMap.has(typeName)) { | ||
(function () { | ||
var rootMock = mockFunctionMap.get(typeName); | ||
if (rootMock()[fieldName]) { | ||
// TODO: assert that it's a function | ||
// eslint-disable-next-line no-param-reassign | ||
mockResolver = function mockResolver(root) { | ||
for (var _len3 = arguments.length, rest = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { | ||
rest[_key3 - 1] = arguments[_key3]; | ||
} | ||
var updatedRoot = root || {}; // TODO: should we clone instead? | ||
updatedRoot[fieldName] = rootMock()[fieldName]; | ||
// XXX this is a bit of a hack to still use mockType, which | ||
// lets you mock lists etc. as well | ||
// otherwise we could just set field.resolve to rootMock()[fieldName] | ||
// it's like pretending there was a resolve function that ran before | ||
// the root resolve function. | ||
return mockType(field.type, typeName, fieldName).apply(undefined, [updatedRoot].concat(rest)); | ||
return customMock; | ||
} | ||
function getResolveType(namedFieldType) { | ||
if ((namedFieldType instanceof graphql_1.GraphQLInterfaceType) || | ||
(namedFieldType instanceof graphql_1.GraphQLUnionType)) { | ||
return namedFieldType.resolveType; | ||
} | ||
else { | ||
return undefined; | ||
} | ||
} | ||
function assignResolveType(type) { | ||
const fieldType = graphql_1.getNullableType(type); | ||
const namedFieldType = graphql_1.getNamedType(fieldType); | ||
const oldResolveType = getResolveType(namedFieldType); | ||
if (preserveResolvers && oldResolveType && oldResolveType.length) { | ||
return; | ||
} | ||
if (namedFieldType instanceof graphql_1.GraphQLUnionType || | ||
namedFieldType instanceof graphql_1.GraphQLInterfaceType) { | ||
// the default `resolveType` always returns null. We add a fallback | ||
// resolution that works with how unions and interface are mocked | ||
namedFieldType.resolveType = (data, context, info) => { | ||
return info.schema.getType(data.typename); | ||
}; | ||
} | ||
})(); | ||
} | ||
} | ||
} | ||
if (!mockResolver) { | ||
mockResolver = mockType(field.type, typeName, fieldName); | ||
} | ||
if (!preserveResolvers || !field.resolve) { | ||
// eslint-disable-next-line no-param-reassign | ||
field.resolve = mockResolver; | ||
} else { | ||
(function () { | ||
var oldResolver = field.resolve; | ||
// eslint-disable-next-line no-param-reassign | ||
field.resolve = function () { | ||
return Promise.all([mockResolver.apply(undefined, arguments), oldResolver.apply(undefined, arguments)]).then(function (values) { | ||
var _values = _slicedToArray(values, 2); | ||
var mockedValue = _values[0]; | ||
var resolvedValue = _values[1]; | ||
if (isObject(mockedValue) && isObject(resolvedValue)) { | ||
// Object.assign() won't do here, as we need to all properties, including | ||
// the non-enumerable ones and defined using Object.defineProperty | ||
return copyOwnProps({}, resolvedValue, mockedValue); | ||
const mockType = function mockType(type, typeName, fieldName) { | ||
// order of precendence for mocking: | ||
// 1. if the object passed in already has fieldName, just use that | ||
// --> if it's a function, that becomes your resolver | ||
// --> if it's a value, the mock resolver will return that | ||
// 2. if the nullableType is a list, recurse | ||
// 2. if there's a mock defined for this typeName, that will be used | ||
// 3. if there's no mock defined, use the default mocks for this type | ||
return (root, args, context, info) => { | ||
// nullability doesn't matter for the purpose of mocking. | ||
const fieldType = graphql_1.getNullableType(type); | ||
const namedFieldType = graphql_1.getNamedType(fieldType); | ||
if (root && typeof root[fieldName] !== 'undefined') { | ||
let result; | ||
// if we're here, the field is already defined | ||
if (typeof root[fieldName] === 'function') { | ||
result = root[fieldName](root, args, context, info); | ||
if (result instanceof MockList) { | ||
result = result.mock(root, args, context, info, fieldType, mockType); | ||
} | ||
} | ||
else { | ||
result = root[fieldName]; | ||
} | ||
// Now we merge the result with the default mock for this type. | ||
// This allows overriding defaults while writing very little code. | ||
if (mockFunctionMap.has(namedFieldType.name)) { | ||
result = mergeMocks(mockFunctionMap.get(namedFieldType.name).bind(null, root, args, context, info), result); | ||
} | ||
return result; | ||
} | ||
return undefined !== resolvedValue ? resolvedValue : mockedValue; | ||
}); | ||
if (fieldType instanceof graphql_1.GraphQLList) { | ||
return [mockType(fieldType.ofType)(root, args, context, info), | ||
mockType(fieldType.ofType)(root, args, context, info)]; | ||
} | ||
if (mockFunctionMap.has(fieldType.name)) { | ||
// the object passed doesn't have this field, so we apply the default mock | ||
return mockFunctionMap.get(fieldType.name)(root, args, context, info); | ||
} | ||
if (fieldType instanceof graphql_1.GraphQLObjectType) { | ||
// objects don't return actual data, we only need to mock scalars! | ||
return {}; | ||
} | ||
// TODO mocking Interface and Union types will require determining the | ||
// resolve type before passing it on. | ||
// XXX we recommend a generic way for resolve type here, which is defining | ||
// typename on the object. | ||
if (fieldType instanceof graphql_1.GraphQLUnionType) { | ||
const randomType = getRandomElement(fieldType.getTypes()); | ||
return Object.assign({ typename: randomType }, mockType(randomType)(root, args, context, info)); | ||
} | ||
if (fieldType instanceof graphql_1.GraphQLInterfaceType) { | ||
const possibleTypes = schema.getPossibleTypes(fieldType); | ||
const randomType = getRandomElement(possibleTypes); | ||
return Object.assign({ typename: randomType }, mockType(randomType)(root, args, context, info)); | ||
} | ||
if (fieldType instanceof graphql_1.GraphQLEnumType) { | ||
return getRandomElement(fieldType.getValues()).value; | ||
} | ||
if (defaultMockMap.has(fieldType.name)) { | ||
return defaultMockMap.get(fieldType.name)(root, args, context, info); | ||
} | ||
// if we get to here, we don't have a value, and we don't have a mock for this type, | ||
// we could return undefined, but that would be hard to debug, so we throw instead. | ||
throw new Error(`No mock defined for type "${fieldType.name}"`); | ||
}; | ||
})(); | ||
} | ||
}); | ||
}; | ||
schemaGenerator_1.forEachField(schema, (field, typeName, fieldName) => { | ||
assignResolveType(field.type); | ||
let mockResolver; | ||
// we have to handle the root mutation and root query types differently, | ||
// because no resolver is called at the root. | ||
/* istanbul ignore next: Must provide schema definition with query type or a type named Query. */ | ||
const isOnQueryType = schema.getQueryType() ? (schema.getQueryType().name === typeName) : false; | ||
const isOnMutationType = schema.getMutationType() ? (schema.getMutationType().name === typeName) : false; | ||
if (isOnQueryType || isOnMutationType) { | ||
if (mockFunctionMap.has(typeName)) { | ||
const rootMock = mockFunctionMap.get(typeName); | ||
// XXX: BUG in here, need to provide proper signature for rootMock. | ||
if (rootMock(undefined, {}, {}, {})[fieldName]) { | ||
// TODO: assert that it's a function | ||
mockResolver = (root, args, context, info) => { | ||
const updatedRoot = root || {}; // TODO: should we clone instead? | ||
updatedRoot[fieldName] = rootMock(root, args, context, info)[fieldName]; | ||
// XXX this is a bit of a hack to still use mockType, which | ||
// lets you mock lists etc. as well | ||
// otherwise we could just set field.resolve to rootMock()[fieldName] | ||
// it's like pretending there was a resolve function that ran before | ||
// the root resolve function. | ||
return mockType(field.type, typeName, fieldName)(updatedRoot, args, context, info); | ||
}; | ||
} | ||
} | ||
} | ||
if (!mockResolver) { | ||
mockResolver = mockType(field.type, typeName, fieldName); | ||
} | ||
if (!preserveResolvers || !field.resolve) { | ||
field.resolve = mockResolver; | ||
} | ||
else { | ||
const oldResolver = field.resolve; | ||
field.resolve = (rootObject, args, context, info) => Promise.all([ | ||
mockResolver(rootObject, args, context, info), | ||
oldResolver(rootObject, args, context, info), | ||
]).then(values => { | ||
const [mockedValue, resolvedValue] = values; | ||
if (isObject(mockedValue) && isObject(resolvedValue)) { | ||
// Object.assign() won't do here, as we need to all properties, including | ||
// the non-enumerable ones and defined using Object.defineProperty | ||
return copyOwnProps({}, resolvedValue, mockedValue); | ||
} | ||
return (undefined !== resolvedValue) ? resolvedValue : mockedValue; | ||
}); | ||
} | ||
}); | ||
} | ||
var MockList = function () { | ||
// wrappedFunction can return another MockList or a value | ||
function MockList(len, wrappedFunction) { | ||
_classCallCheck(this, MockList); | ||
this.len = len; | ||
if (typeof wrappedFunction !== 'undefined') { | ||
if (typeof wrappedFunction !== 'function') { | ||
throw new Error('Second argument to MockList must be a function or undefined'); | ||
} | ||
this.wrappedFunction = wrappedFunction; | ||
exports.addMockFunctionsToSchema = addMockFunctionsToSchema; | ||
class MockList { | ||
// wrappedFunction can return another MockList or a value | ||
constructor(len, wrappedFunction) { | ||
this.len = len; | ||
if (typeof wrappedFunction !== 'undefined') { | ||
if (typeof wrappedFunction !== 'function') { | ||
throw new Error('Second argument to MockList must be a function or undefined'); | ||
} | ||
this.wrappedFunction = wrappedFunction; | ||
} | ||
} | ||
} | ||
_createClass(MockList, [{ | ||
key: 'mock', | ||
value: function mock(root, args, context, info, fieldType, mockTypeFunc) { | ||
function randint(low, high) { | ||
return Math.floor(Math.random() * (high - low + 1) + low); | ||
} | ||
var arr = void 0; | ||
if (Array.isArray(this.len)) { | ||
arr = new Array(randint(this.len[0], this.len[1])); | ||
} else { | ||
arr = new Array(this.len); | ||
} | ||
for (var i = 0; i < arr.length; i++) { | ||
if (typeof this.wrappedFunction === 'function') { | ||
var res = this.wrappedFunction(root, args, context, info); | ||
if (res instanceof MockList) { | ||
var nullableType = (0, _type.getNullableType)(fieldType.ofType); | ||
arr[i] = res.mock(root, args, context, info, nullableType, mockTypeFunc); | ||
} else { | ||
arr[i] = res; | ||
} | ||
} else { | ||
arr[i] = mockTypeFunc(fieldType.ofType)(root, args, context, info); | ||
mock(root, args, context, info, fieldType, mockTypeFunc) { | ||
let arr; | ||
if (Array.isArray(this.len)) { | ||
arr = new Array(this.randint(this.len[0], this.len[1])); | ||
} | ||
} | ||
return arr; | ||
else { | ||
arr = new Array(this.len); | ||
} | ||
for (let i = 0; i < arr.length; i++) { | ||
if (typeof this.wrappedFunction === 'function') { | ||
const res = this.wrappedFunction(root, args, context, info); | ||
if (res instanceof MockList) { | ||
const nullableType = graphql_1.getNullableType(fieldType.ofType); | ||
arr[i] = res.mock(root, args, context, info, nullableType, mockTypeFunc); | ||
} | ||
else { | ||
arr[i] = res; | ||
} | ||
} | ||
else { | ||
arr[i] = mockTypeFunc(fieldType.ofType)(root, args, context, info); | ||
} | ||
} | ||
return arr; | ||
} | ||
}]); | ||
return MockList; | ||
}(); | ||
exports.addMockFunctionsToSchema = addMockFunctionsToSchema; | ||
randint(low, high) { | ||
return Math.floor((Math.random() * ((high - low) + 1)) + low); | ||
} | ||
} | ||
exports.MockList = MockList; | ||
exports.mockServer = mockServer; | ||
//# sourceMappingURL=mock.js.map |
@@ -1,172 +0,118 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.attachConnectorsToContext = exports.addSchemaLevelResolveFunction = exports.buildSchemaFromTypeDefinitions = exports.assertResolveFunctionsPresent = exports.addCatchUndefinedToSchema = exports.addResolveFunctionsToSchema = exports.addErrorLoggingToSchema = exports.forEachField = exports.SchemaError = exports.makeExecutableSchema = exports.generateSchema = undefined; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; // Generates a schema for graphql-js given a shorthand schema | ||
// Generates a schema for graphql-js given a shorthand schema | ||
"use strict"; | ||
// TODO: document each function clearly in the code: what arguments it accepts | ||
// and what it outputs. | ||
var _language = require('graphql/language'); | ||
var _lodash = require('lodash.uniq'); | ||
var _lodash2 = _interopRequireDefault(_lodash); | ||
var _utilities = require('graphql/utilities'); | ||
var _type = require('graphql/type'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const graphql_1 = require('graphql'); | ||
const lodash_1 = require('lodash'); | ||
const graphql_2 = require('graphql'); | ||
const graphql_3 = require('graphql'); | ||
const deprecated_decorator_1 = require("deprecated-decorator"); | ||
// @schemaDefinition: A GraphQL type schema in shorthand | ||
// @resolvers: Definitions for resolvers to be merged with schema | ||
function SchemaError(message) { | ||
Error.captureStackTrace(this, this.constructor); | ||
this.message = message; | ||
class SchemaError extends Error { | ||
constructor(message) { | ||
super(message); | ||
Error.captureStackTrace(this, this.constructor); | ||
} | ||
} | ||
// eslint-disable-next-line new-parens | ||
SchemaError.prototype = new Error(); | ||
function generateSchema() { | ||
console.error('generateSchema is deprecated, use makeExecutableSchema instead'); | ||
return _generateSchema.apply(undefined, arguments); | ||
} | ||
exports.SchemaError = SchemaError; | ||
// type definitions can be a string or an array of strings. | ||
function _generateSchema(typeDefinitions, resolveFunctions, logger) { | ||
var allowUndefinedInResolve = arguments.length <= 3 || arguments[3] === undefined ? true : arguments[3]; | ||
var resolverValidationOptions = arguments.length <= 4 || arguments[4] === undefined ? {} : arguments[4]; | ||
if ((typeof resolverValidationOptions === 'undefined' ? 'undefined' : _typeof(resolverValidationOptions)) !== 'object') { | ||
throw new SchemaError('Expected `resolverValidationOptions` to be an object'); | ||
} | ||
if (!typeDefinitions) { | ||
throw new SchemaError('Must provide typeDefs'); | ||
} | ||
if (!resolveFunctions) { | ||
throw new SchemaError('Must provide resolvers'); | ||
} | ||
// TODO: check that typeDefinitions is either string or array of strings | ||
var schema = buildSchemaFromTypeDefinitions(typeDefinitions); | ||
addResolveFunctionsToSchema(schema, resolveFunctions); | ||
assertResolveFunctionsPresent(schema, resolverValidationOptions); | ||
if (!allowUndefinedInResolve) { | ||
addCatchUndefinedToSchema(schema); | ||
} | ||
if (logger) { | ||
addErrorLoggingToSchema(schema, logger); | ||
} | ||
return schema; | ||
function _generateSchema(typeDefinitions, resolveFunctions, logger, | ||
// TODO: rename to allowUndefinedInResolve to be consistent | ||
allowUndefinedInResolve = true, resolverValidationOptions = {}) { | ||
if (typeof resolverValidationOptions !== 'object') { | ||
throw new SchemaError('Expected `resolverValidationOptions` to be an object'); | ||
} | ||
if (!typeDefinitions) { | ||
throw new SchemaError('Must provide typeDefs'); | ||
} | ||
if (!resolveFunctions) { | ||
throw new SchemaError('Must provide resolvers'); | ||
} | ||
// TODO: check that typeDefinitions is either string or array of strings | ||
const schema = buildSchemaFromTypeDefinitions(typeDefinitions); | ||
addResolveFunctionsToSchema(schema, resolveFunctions); | ||
assertResolveFunctionsPresent(schema, resolverValidationOptions); | ||
if (!allowUndefinedInResolve) { | ||
addCatchUndefinedToSchema(schema); | ||
} | ||
if (logger) { | ||
addErrorLoggingToSchema(schema, logger); | ||
} | ||
return schema; | ||
} | ||
function makeExecutableSchema(_ref) { | ||
var typeDefs = _ref.typeDefs; | ||
var resolvers = _ref.resolvers; | ||
var connectors = _ref.connectors; | ||
var logger = _ref.logger; | ||
var _ref$allowUndefinedIn = _ref.allowUndefinedInResolve; | ||
var allowUndefinedInResolve = _ref$allowUndefinedIn === undefined ? true : _ref$allowUndefinedIn; | ||
var _ref$resolverValidati = _ref.resolverValidationOptions; | ||
var resolverValidationOptions = _ref$resolverValidati === undefined ? {} : _ref$resolverValidati; | ||
var jsSchema = _generateSchema(typeDefs, resolvers, logger, allowUndefinedInResolve, resolverValidationOptions); | ||
if (typeof resolvers.__schema === 'function') { | ||
// TODO a bit of a hack now, better rewrite generateSchema to attach it there. | ||
// not doing that now, because I'd have to rewrite a lot of tests. | ||
addSchemaLevelResolveFunction(jsSchema, resolvers.__schema); | ||
} | ||
if (connectors) { | ||
// connectors are optional, at least for now. That means you can just import them in the resolve | ||
// function if you want. | ||
attachConnectorsToContext(jsSchema, connectors); | ||
} | ||
return jsSchema; | ||
} | ||
function concatenateTypeDefs(typeDefinitionsAry) { | ||
var functionsCalled = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var resolvedTypeDefinitions = []; | ||
typeDefinitionsAry.forEach(function (typeDef) { | ||
if (typeof typeDef === 'function') { | ||
if (!(typeDef in functionsCalled)) { | ||
// eslint-disable-next-line no-param-reassign | ||
functionsCalled[typeDef] = 1; | ||
resolvedTypeDefinitions = resolvedTypeDefinitions.concat(concatenateTypeDefs(typeDef(), functionsCalled)); | ||
} | ||
} else if (typeof typeDef === 'string') { | ||
resolvedTypeDefinitions.push(typeDef.trim()); | ||
} else { | ||
var type = typeof typeDef === 'undefined' ? 'undefined' : _typeof(typeDef); | ||
throw new SchemaError('typeDef array must contain only strings and functions, got ' + type); | ||
function makeExecutableSchema({ typeDefs, resolvers, connectors, logger, allowUndefinedInResolve = true, resolverValidationOptions = {}, }) { | ||
const jsSchema = _generateSchema(typeDefs, resolvers, logger, allowUndefinedInResolve, resolverValidationOptions); | ||
if (typeof resolvers['__schema'] === 'function') { | ||
// TODO a bit of a hack now, better rewrite generateSchema to attach it there. | ||
// not doing that now, because I'd have to rewrite a lot of tests. | ||
addSchemaLevelResolveFunction(jsSchema, resolvers['__schema']); | ||
} | ||
}); | ||
return (0, _lodash2.default)(resolvedTypeDefinitions.map(function (x) { | ||
return x.trim(); | ||
})).join('\n'); | ||
if (connectors) { | ||
// connectors are optional, at least for now. That means you can just import them in the resolve | ||
// function if you want. | ||
attachConnectorsToContext(jsSchema, connectors); | ||
} | ||
return jsSchema; | ||
} | ||
exports.makeExecutableSchema = makeExecutableSchema; | ||
function concatenateTypeDefs(typeDefinitionsAry, functionsCalled = {}) { | ||
let resolvedTypeDefinitions = []; | ||
typeDefinitionsAry.forEach((typeDef) => { | ||
if (typeof typeDef === 'function') { | ||
if (!(typeDef in functionsCalled)) { | ||
functionsCalled[typeDef] = 1; | ||
resolvedTypeDefinitions = resolvedTypeDefinitions.concat(concatenateTypeDefs(typeDef(), functionsCalled)); | ||
} | ||
} | ||
else if (typeof typeDef === 'string') { | ||
resolvedTypeDefinitions.push(typeDef.trim()); | ||
} | ||
else { | ||
const type = typeof typeDef; | ||
throw new SchemaError(`typeDef array must contain only strings and functions, got ${type}`); | ||
} | ||
}); | ||
return lodash_1.uniq(resolvedTypeDefinitions.map((x) => x.trim())).join('\n'); | ||
} | ||
function buildSchemaFromTypeDefinitions(typeDefinitions) { | ||
// TODO: accept only array here, otherwise interfaces get confusing. | ||
var myDefinitions = typeDefinitions; | ||
if (typeof myDefinitions !== 'string') { | ||
if (!Array.isArray(myDefinitions)) { | ||
// TODO improve error message and say what type was actually found | ||
throw new SchemaError('`typeDefs` must be a string or array'); | ||
// TODO: accept only array here, otherwise interfaces get confusing. | ||
let myDefinitions = typeDefinitions; | ||
if (typeof myDefinitions !== 'string') { | ||
if (!Array.isArray(myDefinitions)) { | ||
// TODO improve error message and say what type was actually found | ||
throw new SchemaError('`typeDefs` must be a string or array'); | ||
} | ||
myDefinitions = concatenateTypeDefs(myDefinitions); | ||
} | ||
myDefinitions = concatenateTypeDefs(myDefinitions); | ||
} | ||
var astDocument = (0, _language.parse)(myDefinitions); | ||
var schema = (0, _utilities.buildASTSchema)(astDocument); | ||
var extensionsAst = extractExtensionDefinitions(astDocument); | ||
if (extensionsAst.definitions.length > 0) { | ||
schema = (0, _utilities.extendSchema)(schema, extensionsAst); | ||
} | ||
return schema; | ||
const astDocument = graphql_1.parse(myDefinitions); | ||
let schema = graphql_2.buildASTSchema(astDocument); | ||
const extensionsAst = extractExtensionDefinitions(astDocument); | ||
if (extensionsAst.definitions.length > 0) { | ||
schema = graphql_2.extendSchema(schema, extensionsAst); | ||
} | ||
return schema; | ||
} | ||
exports.buildSchemaFromTypeDefinitions = buildSchemaFromTypeDefinitions; | ||
function extractExtensionDefinitions(ast) { | ||
var extensionDefs = ast.definitions.filter(function (def) { | ||
return def.kind === _language.Kind.TYPE_EXTENSION_DEFINITION; | ||
}); | ||
return _extends({}, ast, { | ||
definitions: extensionDefs | ||
}); | ||
const extensionDefs = ast.definitions.filter((def) => def.kind === graphql_1.Kind.TYPE_EXTENSION_DEFINITION); | ||
return Object.assign({}, ast, { | ||
definitions: extensionDefs, | ||
}); | ||
} | ||
function forEachField(schema, fn) { | ||
var typeMap = schema.getTypeMap(); | ||
Object.keys(typeMap).forEach(function (typeName) { | ||
var type = typeMap[typeName]; | ||
// TODO: maybe have an option to include these? | ||
if (!(0, _type.getNamedType)(type).name.startsWith('__') && type instanceof _type.GraphQLObjectType) { | ||
(function () { | ||
var fields = type.getFields(); | ||
Object.keys(fields).forEach(function (fieldName) { | ||
var field = fields[fieldName]; | ||
fn(field, typeName, fieldName); | ||
}); | ||
})(); | ||
} | ||
}); | ||
const typeMap = schema.getTypeMap(); | ||
Object.keys(typeMap).forEach((typeName) => { | ||
const type = typeMap[typeName]; | ||
// TODO: maybe have an option to include these? | ||
if (!graphql_3.getNamedType(type).name.startsWith('__') && type instanceof graphql_3.GraphQLObjectType) { | ||
const fields = type.getFields(); | ||
Object.keys(fields).forEach((fieldName) => { | ||
const field = fields[fieldName]; | ||
fn(field, typeName, fieldName); | ||
}); | ||
} | ||
}); | ||
} | ||
exports.forEachField = forEachField; | ||
// takes a GraphQL-JS schema and an object of connectors, then attaches | ||
@@ -176,163 +122,172 @@ // the connectors to the context by wrapping each query or mutation resolve | ||
// attaches connectors only once to make sure they are singletons | ||
function attachConnectorsToContext(schema, connectors) { | ||
if (!schema || !(schema instanceof _type.GraphQLSchema)) { | ||
throw new Error('schema must be an instance of GraphQLSchema. ' + 'This error could be caused by installing more than one version of GraphQL-JS'); | ||
} | ||
if ((typeof connectors === 'undefined' ? 'undefined' : _typeof(connectors)) !== 'object') { | ||
var connectorType = typeof connectors === 'undefined' ? 'undefined' : _typeof(connectors); | ||
throw new Error('Expected connectors to be of type object, got ' + connectorType); | ||
} | ||
if (Object.keys(connectors).length === 0) { | ||
throw new Error('Expected connectors to not be an empty object'); | ||
} | ||
if (Array.isArray(connectors)) { | ||
throw new Error('Expected connectors to be of type object, got Array'); | ||
} | ||
if (schema._apolloConnectorsAttached) { | ||
throw new Error('Connectors already attached to context, cannot attach more than once'); | ||
} | ||
// eslint-disable-next-line no-param-reassign | ||
schema._apolloConnectorsAttached = true; | ||
var attachconnectorFn = function attachconnectorFn(root, args, ctx) { | ||
if ((typeof ctx === 'undefined' ? 'undefined' : _typeof(ctx)) !== 'object') { | ||
// if in any way possible, we should throw an error when the attachconnectors | ||
// function is called, not when a query is executed. | ||
var contextType = typeof ctx === 'undefined' ? 'undefined' : _typeof(ctx); | ||
throw new Error('Cannot attach connector because context is not an object: ' + contextType); | ||
const attachConnectorsToContext = deprecated_decorator_1.deprecated({ | ||
version: '0.7.0', | ||
url: 'https://github.com/apollostack/graphql-tools/issues/140', | ||
}, function attachConnectorsToContext(schema, connectors) { | ||
if (!schema || !(schema instanceof graphql_3.GraphQLSchema)) { | ||
throw new Error('schema must be an instance of GraphQLSchema. ' + | ||
'This error could be caused by installing more than one version of GraphQL-JS'); | ||
} | ||
if (typeof ctx.connectors === 'undefined') { | ||
// eslint-disable-next-line no-param-reassign | ||
ctx.connectors = {}; | ||
if (typeof connectors !== 'object') { | ||
const connectorType = typeof connectors; | ||
throw new Error(`Expected connectors to be of type object, got ${connectorType}`); | ||
} | ||
Object.keys(connectors).forEach(function (connectorName) { | ||
// eslint-disable-next-line no-param-reassign | ||
ctx.connectors[connectorName] = new connectors[connectorName](ctx); | ||
}); | ||
return root; | ||
}; | ||
addSchemaLevelResolveFunction(schema, attachconnectorFn); | ||
} | ||
if (Object.keys(connectors).length === 0) { | ||
throw new Error('Expected connectors to not be an empty object'); | ||
} | ||
if (Array.isArray(connectors)) { | ||
throw new Error('Expected connectors to be of type object, got Array'); | ||
} | ||
if (schema['_apolloConnectorsAttached']) { | ||
throw new Error('Connectors already attached to context, cannot attach more than once'); | ||
} | ||
schema['_apolloConnectorsAttached'] = true; | ||
const attachconnectorFn = (root, args, ctx) => { | ||
if (typeof ctx !== 'object') { | ||
// if in any way possible, we should throw an error when the attachconnectors | ||
// function is called, not when a query is executed. | ||
const contextType = typeof ctx; | ||
throw new Error(`Cannot attach connector because context is not an object: ${contextType}`); | ||
} | ||
if (typeof ctx.connectors === 'undefined') { | ||
ctx.connectors = {}; | ||
} | ||
Object.keys(connectors).forEach((connectorName) => { | ||
let connector = connectors[connectorName]; | ||
if (!!connector.prototype) { | ||
ctx.connectors[connectorName] = new connector(ctx); | ||
} | ||
else { | ||
throw new Error(`Connector must be a function or an class`); | ||
} | ||
}); | ||
return root; | ||
}; | ||
addSchemaLevelResolveFunction(schema, attachconnectorFn); | ||
}); | ||
exports.attachConnectorsToContext = attachConnectorsToContext; | ||
// wraps all resolve functions of query, mutation or subscription fields | ||
// with the provided function to simulate a root schema level resolve funciton | ||
function addSchemaLevelResolveFunction(schema, fn) { | ||
// TODO test that schema is a schema, fn is a function | ||
var rootTypes = [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()].filter(function (x) { | ||
return !!x; | ||
}); | ||
// XXX this should run at most once per request to simulate a true root resolver | ||
// for graphql-js this is an approximation that works with queries but not mutations | ||
var rootResolveFn = runAtMostOncePerRequest(fn); | ||
rootTypes.forEach(function (type) { | ||
var fields = type.getFields(); | ||
Object.keys(fields).forEach(function (fieldName) { | ||
fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, rootResolveFn); | ||
// TODO test that schema is a schema, fn is a function | ||
const rootTypes = ([ | ||
schema.getQueryType(), | ||
schema.getMutationType(), | ||
schema.getSubscriptionType(), | ||
]).filter(x => !!x); | ||
// XXX this should run at most once per request to simulate a true root resolver | ||
// for graphql-js this is an approximation that works with queries but not mutations | ||
const rootResolveFn = runAtMostOncePerRequest(fn); | ||
rootTypes.forEach((type) => { | ||
const fields = type.getFields(); | ||
Object.keys(fields).forEach((fieldName) => { | ||
fields[fieldName].resolve = wrapResolver(fields[fieldName].resolve, rootResolveFn); | ||
}); | ||
}); | ||
}); | ||
} | ||
exports.addSchemaLevelResolveFunction = addSchemaLevelResolveFunction; | ||
function getFieldsForType(type) { | ||
if ((type instanceof graphql_3.GraphQLObjectType) || | ||
(type instanceof graphql_3.GraphQLInterfaceType)) { | ||
return type.getFields(); | ||
} | ||
else { | ||
return undefined; | ||
} | ||
} | ||
function addResolveFunctionsToSchema(schema, resolveFunctions) { | ||
Object.keys(resolveFunctions).forEach(function (typeName) { | ||
var type = schema.getType(typeName); | ||
if (!type && typeName !== '__schema') { | ||
throw new SchemaError('"' + typeName + '" defined in resolvers, but not in schema'); | ||
} | ||
Object.keys(resolveFunctions[typeName]).forEach(function (fieldName) { | ||
if (fieldName.startsWith('__')) { | ||
// this is for isTypeOf and resolveType and all the other stuff. | ||
// TODO require resolveType for unions and interfaces. | ||
type[fieldName.substring(2)] = resolveFunctions[typeName][fieldName]; | ||
return; | ||
} | ||
if (!type.getFields()[fieldName]) { | ||
throw new SchemaError(typeName + '.' + fieldName + ' defined in resolvers, but not in schema'); | ||
} | ||
var field = type.getFields()[fieldName]; | ||
var fieldResolve = resolveFunctions[typeName][fieldName]; | ||
if (typeof fieldResolve === 'function') { | ||
// for convenience. Allows shorter syntax in resolver definition file | ||
setFieldProperties(field, { resolve: fieldResolve }); | ||
} else { | ||
if ((typeof fieldResolve === 'undefined' ? 'undefined' : _typeof(fieldResolve)) !== 'object') { | ||
throw new SchemaError('Resolver ' + typeName + '.' + fieldName + ' must be object or function'); | ||
Object.keys(resolveFunctions).forEach((typeName) => { | ||
const type = schema.getType(typeName); | ||
if (!type && typeName !== '__schema') { | ||
throw new SchemaError(`"${typeName}" defined in resolvers, but not in schema`); | ||
} | ||
setFieldProperties(field, fieldResolve); | ||
} | ||
Object.keys(resolveFunctions[typeName]).forEach((fieldName) => { | ||
if (fieldName.startsWith('__')) { | ||
// this is for isTypeOf and resolveType and all the other stuff. | ||
// TODO require resolveType for unions and interfaces. | ||
type[fieldName.substring(2)] = resolveFunctions[typeName][fieldName]; | ||
return; | ||
} | ||
const fields = getFieldsForType(type); | ||
if (!fields) { | ||
throw new SchemaError(`${typeName} was defined in resolvers, but it's not an object`); | ||
} | ||
if (!fields[fieldName]) { | ||
throw new SchemaError(`${typeName}.${fieldName} defined in resolvers, but not in schema`); | ||
} | ||
const field = fields[fieldName]; | ||
const fieldResolve = resolveFunctions[typeName][fieldName]; | ||
if (typeof fieldResolve === 'function') { | ||
// for convenience. Allows shorter syntax in resolver definition file | ||
setFieldProperties(field, { resolve: fieldResolve }); | ||
} | ||
else { | ||
if (typeof fieldResolve !== 'object') { | ||
throw new SchemaError(`Resolver ${typeName}.${fieldName} must be object or function`); | ||
} | ||
setFieldProperties(field, fieldResolve); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
exports.addResolveFunctionsToSchema = addResolveFunctionsToSchema; | ||
function setFieldProperties(field, propertiesObj) { | ||
Object.keys(propertiesObj).forEach(function (propertyName) { | ||
// eslint-disable-next-line no-param-reassign | ||
field[propertyName] = propertiesObj[propertyName]; | ||
}); | ||
Object.keys(propertiesObj).forEach((propertyName) => { | ||
field[propertyName] = propertiesObj[propertyName]; | ||
}); | ||
} | ||
function assertResolveFunctionsPresent(schema) { | ||
var resolverValidationOptions = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; | ||
var _resolverValidationOp = resolverValidationOptions.requireResolversForArgs; | ||
var requireResolversForArgs = _resolverValidationOp === undefined ? true : _resolverValidationOp; | ||
var _resolverValidationOp2 = resolverValidationOptions.requireResolversForNonScalar; | ||
var requireResolversForNonScalar = _resolverValidationOp2 === undefined ? true : _resolverValidationOp2; | ||
var _resolverValidationOp3 = resolverValidationOptions.requireResolversForAllFields; | ||
var requireResolversForAllFields = _resolverValidationOp3 === undefined ? false : _resolverValidationOp3; | ||
if (requireResolversForAllFields && (!requireResolversForArgs || !requireResolversForNonScalar)) { | ||
throw new TypeError('requireResolversForAllFields takes precedence over the more specific assertions. ' + 'Please configure either requireResolversForAllFields or requireResolversForArgs / ' + 'requireResolversForNonScalar, but not a combination of them.'); | ||
} | ||
forEachField(schema, function (field, typeName, fieldName) { | ||
// requires a resolve function for *every* field. | ||
if (requireResolversForAllFields) { | ||
expectResolveFunction(field, typeName, fieldName); | ||
function assertResolveFunctionsPresent(schema, resolverValidationOptions = {}) { | ||
const { requireResolversForArgs = true, requireResolversForNonScalar = true, requireResolversForAllFields = false, } = resolverValidationOptions; | ||
if (requireResolversForAllFields && (!requireResolversForArgs || !requireResolversForNonScalar)) { | ||
throw new TypeError('requireResolversForAllFields takes precedence over the more specific assertions. ' + | ||
'Please configure either requireResolversForAllFields or requireResolversForArgs / ' + | ||
'requireResolversForNonScalar, but not a combination of them.'); | ||
} | ||
// requires a resolve function on every field that has arguments | ||
if (requireResolversForArgs && field.args.length > 0) { | ||
expectResolveFunction(field, typeName, fieldName); | ||
forEachField(schema, (field, typeName, fieldName) => { | ||
// requires a resolve function for *every* field. | ||
if (requireResolversForAllFields) { | ||
expectResolveFunction(field, typeName, fieldName); | ||
} | ||
// requires a resolve function on every field that has arguments | ||
if (requireResolversForArgs && field.args.length > 0) { | ||
expectResolveFunction(field, typeName, fieldName); | ||
} | ||
// requires a resolve function on every field that returns a non-scalar type | ||
if (requireResolversForNonScalar && !(graphql_3.getNamedType(field.type) instanceof graphql_3.GraphQLScalarType)) { | ||
expectResolveFunction(field, typeName, fieldName); | ||
} | ||
}); | ||
} | ||
exports.assertResolveFunctionsPresent = assertResolveFunctionsPresent; | ||
function expectResolveFunction(field, typeName, fieldName) { | ||
if (!field.resolve) { | ||
// tslint:disable-next-line: max-line-length | ||
console.warn(`Resolve function missing for "${typeName}.${fieldName}". To disable this warning check https://github.com/apollostack/graphql-tools/issues/131`); | ||
return; | ||
} | ||
// requires a resolve function on every field that returns a non-scalar type | ||
if (requireResolversForNonScalar && !((0, _type.getNamedType)(field.type) instanceof _type.GraphQLScalarType)) { | ||
expectResolveFunction(field, typeName, fieldName); | ||
if (typeof field.resolve !== 'function') { | ||
throw new SchemaError(`Resolver "${typeName}.${fieldName}" must be a function`); | ||
} | ||
}); | ||
} | ||
function expectResolveFunction(field, typeName, fieldName) { | ||
if (!field.resolve) { | ||
throw new SchemaError('Resolve function missing for "' + typeName + '.' + fieldName + '"'); | ||
} | ||
if (typeof field.resolve !== 'function') { | ||
throw new SchemaError('Resolver "' + typeName + '.' + fieldName + '" must be a function'); | ||
} | ||
} | ||
function addErrorLoggingToSchema(schema, logger) { | ||
if (!logger) { | ||
throw new Error('Must provide a logger'); | ||
} | ||
if (typeof logger.log !== 'function') { | ||
throw new Error('Logger.log must be a function'); | ||
} | ||
forEachField(schema, function (field, typeName, fieldName) { | ||
var errorHint = typeName + '.' + fieldName; | ||
// eslint-disable-next-line no-param-reassign | ||
field.resolve = decorateWithLogger(field.resolve, logger, errorHint); | ||
}); | ||
if (!logger) { | ||
throw new Error('Must provide a logger'); | ||
} | ||
if (typeof logger.log !== 'function') { | ||
throw new Error('Logger.log must be a function'); | ||
} | ||
forEachField(schema, (field, typeName, fieldName) => { | ||
const errorHint = `${typeName}.${fieldName}`; | ||
field.resolve = decorateWithLogger(field.resolve, logger, errorHint); | ||
}); | ||
} | ||
exports.addErrorLoggingToSchema = addErrorLoggingToSchema; | ||
function wrapResolver(innerResolver, outerResolver) { | ||
return function (obj, args, ctx, info) { | ||
var root = outerResolver(obj, args, ctx, info); | ||
if (innerResolver) { | ||
return innerResolver(root, args, ctx, info); | ||
} | ||
return defaultResolveFn(root, args, ctx, info); | ||
}; | ||
return (obj, args, ctx, info) => { | ||
const root = outerResolver(obj, args, ctx, info); | ||
if (innerResolver) { | ||
return innerResolver(root, args, ctx, info); | ||
} | ||
return defaultResolveFn(root, args, ctx, info); | ||
}; | ||
} | ||
@@ -344,49 +299,44 @@ /* | ||
*/ | ||
function decorateWithLogger(fn, logger) { | ||
var hint = arguments.length <= 2 || arguments[2] === undefined ? '' : arguments[2]; | ||
if (typeof fn === 'undefined') { | ||
// eslint-disable-next-line no-param-reassign | ||
fn = defaultResolveFn; | ||
} | ||
return function () { | ||
try { | ||
return fn.apply(undefined, arguments); | ||
} catch (e) { | ||
// TODO: clone the error properly | ||
var newE = new Error(); | ||
newE.stack = e.stack; | ||
if (hint) { | ||
newE.originalMessage = e.message; | ||
newE.message = 'Error in resolver ' + hint + '\n' + e.message; | ||
} | ||
logger.log(newE); | ||
// we want to pass on the error, just in case. | ||
throw e; | ||
function decorateWithLogger(fn, logger, hint = '') { | ||
if (typeof fn === 'undefined') { | ||
fn = defaultResolveFn; | ||
} | ||
}; | ||
return (root, args, ctx, info) => { | ||
try { | ||
return fn(root, args, ctx, info); | ||
} | ||
catch (e) { | ||
// TODO: clone the error properly | ||
const newE = new Error(); | ||
newE.stack = e.stack; | ||
/* istanbul ignore else: always get the hint from addErrorLoggingToSchema */ | ||
if (hint) { | ||
newE['originalMessage'] = e.message; | ||
newE['message'] = `Error in resolver ${hint}\n${e.message}`; | ||
} | ||
logger.log(newE); | ||
// we want to pass on the error, just in case. | ||
throw e; | ||
} | ||
}; | ||
} | ||
function addCatchUndefinedToSchema(schema) { | ||
forEachField(schema, function (field, typeName, fieldName) { | ||
var errorHint = typeName + '.' + fieldName; | ||
// eslint-disable-next-line no-param-reassign | ||
field.resolve = decorateToCatchUndefined(field.resolve, errorHint); | ||
}); | ||
forEachField(schema, (field, typeName, fieldName) => { | ||
const errorHint = `${typeName}.${fieldName}`; | ||
field.resolve = decorateToCatchUndefined(field.resolve, errorHint); | ||
}); | ||
} | ||
exports.addCatchUndefinedToSchema = addCatchUndefinedToSchema; | ||
function decorateToCatchUndefined(fn, hint) { | ||
if (typeof fn === 'undefined') { | ||
// eslint-disable-next-line no-param-reassign | ||
fn = defaultResolveFn; | ||
} | ||
return function () { | ||
var result = fn.apply(undefined, arguments); | ||
if (typeof result === 'undefined') { | ||
throw new Error('Resolve function for "' + hint + '" returned undefined'); | ||
if (typeof fn === 'undefined') { | ||
fn = defaultResolveFn; | ||
} | ||
return result; | ||
}; | ||
return (root, args, ctx, info) => { | ||
const result = fn(root, args, ctx, info); | ||
if (typeof result === 'undefined') { | ||
throw new Error(`Resolve function for "${hint}" returned undefined`); | ||
} | ||
return result; | ||
}; | ||
} | ||
// XXX this function only works for resolvers | ||
@@ -399,18 +349,15 @@ // XXX very hacky way to remember if the function | ||
function runAtMostOncePerRequest(fn) { | ||
var value = void 0; | ||
var randomNumber = Math.random(); | ||
return function (root, args, ctx, info) { | ||
if (!info.operation.__runAtMostOnce) { | ||
// eslint-disable-next-line no-param-reassign | ||
info.operation.__runAtMostOnce = {}; | ||
} | ||
if (!info.operation.__runAtMostOnce[randomNumber]) { | ||
// eslint-disable-next-line no-param-reassign | ||
info.operation.__runAtMostOnce[randomNumber] = true; | ||
value = fn(root, args, ctx, info); | ||
} | ||
return value; | ||
}; | ||
let value; | ||
const randomNumber = Math.random(); | ||
return (root, args, ctx, info) => { | ||
if (!info.operation['__runAtMostOnce']) { | ||
info.operation['__runAtMostOnce'] = {}; | ||
} | ||
if (!info.operation['__runAtMostOnce'][randomNumber]) { | ||
info.operation['__runAtMostOnce'][randomNumber] = true; | ||
value = fn(root, args, ctx, info); | ||
} | ||
return value; | ||
}; | ||
} | ||
/** | ||
@@ -425,24 +372,10 @@ * XXX taken from graphql-js: src/execution/execute.js, because that function | ||
*/ | ||
function defaultResolveFn(source, args, context, _ref2) { | ||
var fieldName = _ref2.fieldName; | ||
// ensure source is a value for which property access is acceptable. | ||
if ((typeof source === 'undefined' ? 'undefined' : _typeof(source)) === 'object' || typeof source === 'function') { | ||
var property = source[fieldName]; | ||
return typeof property === 'function' ? source[fieldName]() : property; | ||
} | ||
return undefined; | ||
function defaultResolveFn(source, args, context, { fieldName }) { | ||
// ensure source is a value for which property access is acceptable. | ||
if (typeof source === 'object' || typeof source === 'function') { | ||
const property = source[fieldName]; | ||
return typeof property === 'function' ? source[fieldName]() : property; | ||
} | ||
return undefined; | ||
} | ||
exports.generateSchema = generateSchema; | ||
exports. // TODO deprecated, remove for v 0.4.x | ||
makeExecutableSchema = makeExecutableSchema; | ||
exports.SchemaError = SchemaError; | ||
exports.forEachField = forEachField; | ||
exports.addErrorLoggingToSchema = addErrorLoggingToSchema; | ||
exports.addResolveFunctionsToSchema = addResolveFunctionsToSchema; | ||
exports.addCatchUndefinedToSchema = addCatchUndefinedToSchema; | ||
exports.assertResolveFunctionsPresent = assertResolveFunctionsPresent; | ||
exports.buildSchemaFromTypeDefinitions = buildSchemaFromTypeDefinitions; | ||
exports.addSchemaLevelResolveFunction = addSchemaLevelResolveFunction; | ||
exports.attachConnectorsToContext = attachConnectorsToContext; | ||
//# sourceMappingURL=schemaGenerator.js.map |
{ | ||
"name": "graphql-tools", | ||
"version": "0.6.6", | ||
"version": "0.7.0", | ||
"description": "A set of useful GraphQL tools", | ||
"main": "dist/index.js", | ||
"typings": "index.d.ts", | ||
"typings": "dist/index.d.ts", | ||
"typescript": { | ||
"definition": "dist/index.d.ts" | ||
}, | ||
"directories": { | ||
@@ -11,6 +14,13 @@ "test": "test" | ||
"scripts": { | ||
"test": "istanbul cover ./node_modules/mocha/bin/_mocha -- --reporter spec --full-trace test/index.js && npm run lint", | ||
"lint": "eslint .", | ||
"testonly": "mocha test/index.js", | ||
"prepublish": "rm -rf ./dist && babel ./src --ignore test --out-dir ./dist" | ||
"compile": "tsc", | ||
"typings": "typings install", | ||
"pretest": "npm run compile", | ||
"test": "npm run testonly --", | ||
"posttest": "npm run lint", | ||
"lint": "tslint ./src/**/*.ts", | ||
"watch": "tsc -w", | ||
"testonly": "mocha --reporter spec --full-trace ./dist/test/tests.js", | ||
"coverage": "babel-node ./node_modules/istanbul/lib/cli.js cover _mocha -- --reporter dot --full-trace ./dist/test/tests.js", | ||
"postcoverage": "remap-istanbul --input coverage/coverage.json --type lcovonly --output coverage/lcov.info", | ||
"prepublish": "npm run compile" | ||
}, | ||
@@ -36,25 +46,28 @@ "repository": { | ||
"dependencies": { | ||
"deprecated-decorator": "^0.1.6", | ||
"lodash.uniq": "^4.3.0", | ||
"node-uuid": "^1.4.7" | ||
"node-uuid": "^1.4.7", | ||
"typed-graphql": "git://github.com/DxCx/typed-graphql.git#resolve-funcs-fix" | ||
}, | ||
"peerDependencies": { | ||
"graphql": "^0.5.0 || ^0.6.0 || ^0.7.0", | ||
"graphql-typings": "^0.0.1-beta-2" | ||
"graphql": "^0.5.0 || ^0.6.0 || ^0.7.0" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.6.5", | ||
"babel-core": "^6.9.1", | ||
"babel-eslint": "^6.0.0-beta.6", | ||
"babel-loader": "6.2.5", | ||
"babel-polyfill": "^6.5.0", | ||
"babel-preset-es2015": "^6.5.0", | ||
"babel-preset-stage-0": "^6.5.0", | ||
"@types/bluebird": "^3.0.32", | ||
"@types/chai": "^3.4.32", | ||
"@types/lodash": "^4.14.34", | ||
"@types/mocha": "^2.2.31", | ||
"@types/node": "^6.0.38", | ||
"@types/node-uuid": "0.0.27", | ||
"@types/request": "0.0.30", | ||
"@types/request-promise": "^3.0.30", | ||
"babel-cli": "^6.14.0", | ||
"babel-core": "^6.14.0", | ||
"babel-polyfill": "^6.13.0", | ||
"babel-preset-es2015": "^6.14.0", | ||
"body-parser": "^1.15.0", | ||
"chai": "^3.5.0", | ||
"dataloader": "^1.1.0", | ||
"eslint": "^3.2.2", | ||
"eslint-config-airbnb": "^10.0.0", | ||
"eslint-plugin-import": "^1.1.0", | ||
"eslint-plugin-jsx-a11y": "^2.0.1", | ||
"eslint-plugin-react": "^6.0.0", | ||
"dataloader": "git://github.com/DxCx/dataloader.git#typings-tmp-pkg", | ||
"delete-empty": "^0.1.3", | ||
"dts-bundle": "^0.5.0", | ||
"express": "^4.13.4", | ||
@@ -64,4 +77,3 @@ "express3": "0.0.0", | ||
"graphql": "^0.7.0", | ||
"graphql-typings": "^0.0.1-beta-2", | ||
"istanbul": "1.0.0-alpha.2", | ||
"istanbul": "^0.4.5", | ||
"lodash": "^4.10.0", | ||
@@ -71,8 +83,12 @@ "mocha": "^3.0.1", | ||
"nodemon": "^1.9.1", | ||
"remap-istanbul": "^0.6.4", | ||
"request": "^2.72.0", | ||
"request-promise": "^4.1.0", | ||
"source-map-support": "^0.4.2", | ||
"supertest": "^2.0.0", | ||
"supertest-as-promised": "^4.0.0", | ||
"webpack": "^1.13.1" | ||
"tslint": "^3.15.1", | ||
"tslint-loader": "^2.1.5", | ||
"typescript": "2.0.0" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
155588
22
5
35
788
1
1
+ Addeddeprecated-decorator@^0.1.6
+ Addedtyped-graphql@git://github.com/DxCx/typed-graphql.git#resolve-funcs-fix
+ Addeddeprecated-decorator@0.1.6(transitive)
- Removedgraphql-typings@0.0.1-beta-2(transitive)