Files
30-seconds-of-code/node_modules/eslint-plugin-graphql/lib/index.js
2019-08-20 15:52:05 +02:00

355 lines
11 KiB
JavaScript

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.processors = exports.rules = 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 _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _graphql = require('graphql');
var _lodash = require('lodash');
var _graphqlConfig = require('graphql-config');
var _customGraphQLValidationRules = require('./customGraphQLValidationRules');
var customRules = _interopRequireWildcard(_customGraphQLValidationRules);
var _constants = require('./constants');
var _createRule = require('./createRule');
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; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var allGraphQLValidatorNames = _graphql.specifiedRules.map(function (rule) {
return rule.name;
});
// Map of env name to list of rule names.
var envGraphQLValidatorNames = {
apollo: (0, _lodash.without)(allGraphQLValidatorNames, 'KnownFragmentNames', 'NoUnusedFragments'),
lokka: (0, _lodash.without)(allGraphQLValidatorNames, 'KnownFragmentNames', 'NoUnusedFragments'),
fraql: (0, _lodash.without)(allGraphQLValidatorNames, 'KnownFragmentNames', 'NoUnusedFragments'),
relay: (0, _lodash.without)(allGraphQLValidatorNames, 'KnownDirectives', 'KnownFragmentNames', 'NoUndefinedVariables', 'NoUnusedFragments',
// `graphql` < 14
'ProvidedNonNullArguments',
// `graphql`@14
'ProvidedRequiredArguments', 'ScalarLeafs'),
literal: (0, _lodash.without)(allGraphQLValidatorNames, 'KnownFragmentNames', 'NoUnusedFragments')
};
var gqlFiles = ['gql', 'graphql'];
var defaultRuleProperties = {
env: {
enum: ['lokka', 'fraql', 'relay', 'apollo', 'literal']
},
schemaJson: {
type: 'object'
},
schemaJsonFilepath: {
type: 'string'
},
schemaString: {
type: 'string'
},
tagName: {
type: 'string',
pattern: '^[$_a-zA-Z$_][a-zA-Z0-9$_]+(\\.[a-zA-Z0-9$_]+)?$'
},
projectName: {
type: 'string'
}
// schemaJson, schemaJsonFilepath, schemaString and projectName are mutually exclusive:
};var schemaPropsExclusiveness = {
oneOf: [{
required: ['schemaJson'],
not: { required: ['schemaString', 'schemaJsonFilepath', 'projectName'] }
}, {
required: ['schemaJsonFilepath'],
not: { required: ['schemaJson', 'schemaString', 'projectName'] }
}, {
required: ['schemaString'],
not: { required: ['schemaJson', 'schemaJsonFilepath', 'projectName'] }
}, {
not: {
anyOf: [{ required: ['schemaString'] }, { required: ['schemaJson'] }, { required: ['schemaJsonFilepath'] }]
}
}]
};
var rules = exports.rules = {
'template-strings': {
meta: {
schema: {
type: 'array',
items: _extends({
additionalProperties: false,
properties: _extends({}, defaultRuleProperties, {
validators: {
oneOf: [{
type: 'array',
uniqueItems: true,
items: {
enum: allGraphQLValidatorNames
}
}, {
enum: ['all']
}]
}
})
}, schemaPropsExclusiveness)
}
},
create: function create(context) {
return (0, _createRule.createRule)(context, function (optionGroup) {
return parseOptions(optionGroup, context);
});
}
},
'named-operations': {
meta: {
schema: {
type: 'array',
items: _extends({
additionalProperties: false,
properties: _extends({}, defaultRuleProperties)
}, schemaPropsExclusiveness)
}
},
create: function create(context) {
return (0, _createRule.createRule)(context, function (optionGroup) {
return parseOptions(_extends({
validators: ['OperationsMustHaveNames']
}, optionGroup), context);
});
}
},
'required-fields': {
meta: {
schema: {
type: 'array',
minItems: 1,
items: _extends({
additionalProperties: false,
properties: _extends({}, defaultRuleProperties, {
requiredFields: {
type: 'array',
items: {
type: 'string'
}
}
}),
required: ['requiredFields']
}, schemaPropsExclusiveness)
}
},
create: function create(context) {
return (0, _createRule.createRule)(context, function (optionGroup) {
return parseOptions(_extends({
validators: ['RequiredFields'],
options: { requiredFields: optionGroup.requiredFields }
}, optionGroup), context);
});
}
},
'capitalized-type-name': {
meta: {
schema: {
type: 'array',
items: _extends({
additionalProperties: false,
properties: _extends({}, defaultRuleProperties)
}, schemaPropsExclusiveness)
}
},
create: function create(context) {
return (0, _createRule.createRule)(context, function (optionGroup) {
return parseOptions(_extends({
validators: ['typeNamesShouldBeCapitalized']
}, optionGroup), context);
});
}
},
'no-deprecated-fields': {
meta: {
schema: {
type: 'array',
items: _extends({
additionalProperties: false,
properties: _extends({}, defaultRuleProperties)
}, schemaPropsExclusiveness)
}
},
create: function create(context) {
return (0, _createRule.createRule)(context, function (optionGroup) {
return parseOptions(_extends({
validators: ['noDeprecatedFields']
}, optionGroup), context);
});
}
}
};
var schemaCache = {};
var projectCache = {};
function parseOptions(optionGroup, context) {
var schemaJson = optionGroup.schemaJson,
schemaJsonFilepath = optionGroup.schemaJsonFilepath,
schemaString = optionGroup.schemaString,
env = optionGroup.env,
projectName = optionGroup.projectName,
tagNameOption = optionGroup.tagName,
validatorNamesOption = optionGroup.validators;
var cacheHit = schemaCache[JSON.stringify(optionGroup)];
if (cacheHit && env !== 'literal') {
return cacheHit;
}
// Validate and unpack schema
var schema = void 0;
if (schemaJson) {
schema = initSchema(schemaJson);
} else if (schemaJsonFilepath) {
schema = initSchemaFromFile(schemaJsonFilepath);
} else if (schemaString) {
schema = initSchemaFromString(schemaString);
} else {
try {
var config = (0, _graphqlConfig.getGraphQLConfig)(_path2.default.dirname(context.getFilename()));
var projectConfig = void 0;
if (projectName) {
projectConfig = config.getProjects()[projectName];
if (!projectConfig) {
throw new Error('Project with name "' + projectName + '" not found in ' + config.configPath + '.');
}
} else {
projectConfig = config.getConfigForFile(context.getFilename());
}
if (projectConfig) {
var key = config.configPath + '[' + projectConfig.projectName + ']';
schema = projectCache[key];
if (!schema) {
schema = projectConfig.getSchema();
projectCache[key] = schema;
}
}
if (cacheHit) {
return _extends({}, cacheHit, { schema: schema });
}
} catch (e) {
if (e instanceof _graphqlConfig.ConfigNotFoundError) {
throw new Error('Must provide .graphqlconfig file or pass in `schemaJson` option ' + 'with schema object or `schemaJsonFilepath` with absolute path to the json file.');
}
throw e;
}
}
// Validate env
if (env && env !== 'lokka' && env !== 'fraql' && env !== 'relay' && env !== 'apollo' && env !== 'literal') {
throw new Error('Invalid option for env, only `apollo`, `lokka`, `fraql`, `relay`, and `literal` supported.');
}
// Validate tagName and set default
var tagName = void 0;
if (tagNameOption) {
tagName = tagNameOption;
} else if (env === 'relay') {
tagName = 'Relay.QL';
} else if (env === 'literal') {
tagName = _constants.internalTag;
} else {
tagName = 'gql';
}
// The validator list may be:
// The string 'all' to use all rules.
// An array of rule names.
// null/undefined to use the default rule set of the environment, or all rules.
var validatorNames = void 0;
if (validatorNamesOption === 'all') {
validatorNames = allGraphQLValidatorNames;
} else if (validatorNamesOption) {
validatorNames = validatorNamesOption;
} else {
validatorNames = envGraphQLValidatorNames[env] || allGraphQLValidatorNames;
}
var validators = validatorNames.map(function (name) {
if (name in customRules) {
return customRules[name];
} else {
return require('graphql/validation/rules/' + name)[name];
}
});
var results = { schema: schema, env: env, tagName: tagName, validators: validators };
schemaCache[JSON.stringify(optionGroup)] = results;
return results;
}
function initSchema(json) {
var unpackedSchemaJson = json.data ? json.data : json;
if (!unpackedSchemaJson.__schema) {
throw new Error('Please pass a valid GraphQL introspection query result.');
}
return (0, _graphql.buildClientSchema)(unpackedSchemaJson);
}
function initSchemaFromFile(jsonFile) {
return initSchema(JSON.parse(_fs2.default.readFileSync(jsonFile, 'utf8')));
}
function initSchemaFromString(source) {
return (0, _graphql.buildSchema)(source);
}
var gqlProcessor = {
preprocess: function preprocess(text) {
// Wrap the text in backticks and prepend the internal tag. First the text
// must be escaped, because of the three sequences that have special
// meaning in JavaScript template literals, and could change the meaning of
// the text or cause syntax errors.
// https://tc39.github.io/ecma262/#prod-TemplateCharacter
//
// - "`" would end the template literal.
// - "\" would start an escape sequence.
// - "${" would start an interpolation.
var escaped = text.replace(/[`\\]|\$\{/g, '\\$&');
return [_constants.internalTag + '`' + escaped + '`'];
},
postprocess: function postprocess(messages) {
// only report graphql-errors
return (0, _lodash.flatten)(messages).filter(function (message) {
return (0, _lodash.includes)((0, _lodash.keys)(rules).map(function (key) {
return 'graphql/' + key;
}), message.ruleId);
});
}
};
var processors = exports.processors = (0, _lodash.reduce)(gqlFiles, function (result, value) {
return _extends({}, result, _defineProperty({}, '.' + value, gqlProcessor));
}, {});
exports.default = {
rules: rules,
processors: processors
};