WIP - add extractor, generate snippet_data

This commit is contained in:
Stefan Fejes
2019-08-20 15:52:05 +02:00
parent 88084d3d30
commit cc8f1d8a7a
37396 changed files with 4588842 additions and 133 deletions

6
node_modules/eslint-plugin-graphql/lib/constants.js generated vendored Normal file
View File

@ -0,0 +1,6 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var internalTag = exports.internalTag = 'ESLintPluginGraphQLFile';

245
node_modules/eslint-plugin-graphql/lib/createRule.js generated vendored Normal file
View File

@ -0,0 +1,245 @@
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createRule = createRule;
var _graphql = require('graphql');
var _constants = require('./constants');
function strWithLen(len) {
// from http://stackoverflow.com/questions/14343844/create-a-string-of-variable-length-filled-with-a-repeated-character
return new Array(len + 1).join('x');
}
function replaceExpressions(node, context, env) {
var chunks = [];
node.quasis.forEach(function (element, i) {
var chunk = element.value.cooked;
var value = node.expressions[i];
chunks.push(chunk);
if (!env || env === 'apollo') {
// In Apollo, interpolation is only valid outside top-level structures like `query` or `mutation`.
// We'll check to make sure there's an equivalent set of opening and closing brackets, otherwise
// we're attempting to do an invalid interpolation.
if (chunk.split('{').length - 1 !== chunk.split('}').length - 1) {
context.report({
node: value,
message: 'Invalid interpolation - fragment interpolation must occur outside of the brackets.'
});
throw new Error('Invalid interpolation');
}
}
if (!element.tail) {
// Preserve location of errors by replacing with exactly the same length
var nameLength = value.end - value.start;
if (env === 'relay' && /:\s*$/.test(chunk)) {
// The chunk before this one had a colon at the end, so this
// is a variable
// Add 2 for brackets in the interpolation
var placeholder = strWithLen(nameLength + 2);
chunks.push('$' + placeholder);
} else if (env === 'lokka' && /\.\.\.\s*$/.test(chunk)) {
// This is Lokka-style fragment interpolation where you actually type the '...' yourself
var _placeholder = strWithLen(nameLength + 3);
chunks.push(_placeholder);
} else if (env === 'relay') {
// This is Relay-style fragment interpolation where you don't type '...'
// Ellipsis cancels out extra characters
var _placeholder2 = strWithLen(nameLength);
chunks.push('...' + _placeholder2);
} else if (!env || env === 'apollo') {
// In Apollo, fragment interpolation is only valid outside of brackets
// Since we don't know what we'd interpolate here (that occurs at runtime),
// we're not going to do anything with this interpolation.
} else if (env === 'fraql') {
if (chunk.lastIndexOf('{') > chunk.lastIndexOf('}')) {
chunks.push('__typename');
}
} else {
// Invalid interpolation
context.report({
node: value,
message: 'Invalid interpolation - not a valid fragment or variable.'
});
throw new Error('Invalid interpolation');
}
}
});
return chunks.join('');
}
function locFrom(node, error) {
if (!error.locations || !error.locations.length) {
return;
}
var location = error.locations[0];
var line = void 0;
var column = void 0;
if (location.line === 1 && node.tag.name !== _constants.internalTag) {
line = node.loc.start.line;
column = node.tag.loc.end.column + location.column;
} else {
line = node.loc.start.line + location.line - 1;
column = location.column - 1;
}
return {
line: line,
column: column
};
}
function handleTemplateTag(node, context, schema, env, validators) {
var text = void 0;
try {
text = replaceExpressions(node.quasi, context, env);
} catch (e) {
if (e.message !== 'Invalid interpolation') {
console.log(e); // eslint-disable-line no-console
}
return;
}
// Re-implement syntax sugar for fragment names, which is technically not valid
// graphql
if ((env === 'lokka' || env === 'relay' || env === 'fraql') && /fragment\s+on/.test(text)) {
text = text.replace('fragment', 'fragment _');
}
var ast = void 0;
try {
ast = (0, _graphql.parse)(text);
} catch (error) {
context.report({
node: node,
message: error.message.split('\n')[0],
loc: locFrom(node, error)
});
return;
}
var validationErrors = schema ? (0, _graphql.validate)(schema, ast, validators) : [];
if (validationErrors && validationErrors.length > 0) {
context.report({
node: node,
message: validationErrors[0].message,
loc: locFrom(node, validationErrors[0])
});
return;
}
}
function templateExpressionMatchesTag(tagName, node) {
var tagNameSegments = tagName.split('.').length;
if (tagNameSegments === 1) {
// Check for single identifier, like 'gql'
if (node.tag.type !== 'Identifier' || node.tag.name !== tagName) {
return false;
}
} else if (tagNameSegments === 2) {
// Check for dotted identifier, like 'Relay.QL'
if (node.tag.type !== 'MemberExpression' || node.tag.object.name + '.' + node.tag.property.name !== tagName) {
return false;
}
} else {
// We don't currently support 3 segments so ignore
return false;
}
return true;
}
function createRule(context, optionParser) {
var tagNames = new Set();
var tagRules = [];
var options = context.options.length === 0 ? [{}] : context.options;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
var _loop = function _loop() {
var optionGroup = _step.value;
var _optionParser = optionParser(optionGroup),
schema = _optionParser.schema,
env = _optionParser.env,
tagName = _optionParser.tagName,
validators = _optionParser.validators;
var boundValidators = validators.map(function (v) {
return function (ctx) {
return v(ctx, optionGroup);
};
});
if (tagNames.has(tagName)) {
throw new Error('Multiple options for GraphQL tag ' + tagName);
}
tagNames.add(tagName);
tagRules.push({ schema: schema, env: env, tagName: tagName, validators: boundValidators });
};
for (var _iterator = options[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
_loop();
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
return {
TaggedTemplateExpression: function TaggedTemplateExpression(node) {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = tagRules[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var _ref2 = _step2.value;
var schema = _ref2.schema,
env = _ref2.env,
tagName = _ref2.tagName,
validators = _ref2.validators;
if (templateExpressionMatchesTag(tagName, node)) {
return handleTemplateTag(node, context, schema, env, validators);
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.return) {
_iterator2.return();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}
};
}

View File

@ -0,0 +1,158 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.OperationsMustHaveNames = OperationsMustHaveNames;
exports.RequiredFields = RequiredFields;
exports.typeNamesShouldBeCapitalized = typeNamesShouldBeCapitalized;
exports.noDeprecatedFields = noDeprecatedFields;
var _graphql = require("graphql");
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function OperationsMustHaveNames(context) {
return {
OperationDefinition: function OperationDefinition(node) {
if (!node.name) {
context.reportError(new _graphql.GraphQLError("All operations must be named", [node]));
}
}
};
}
function getFieldWasRequestedOnNode(node, field) {
return node.selectionSet.selections.some(function (n) {
return n.kind === "Field" && n.name.value === field;
});
}
function fieldAvailableOnType(type, field) {
return type && type._fields && type._fields[field] || type.ofType && fieldAvailableOnType(type.ofType, field);
}
function RequiredFields(context, options) {
var requiredFields = options.requiredFields;
return {
FragmentDefinition: function FragmentDefinition(node) {
requiredFields.forEach(function (field) {
var type = context.getType();
if (fieldAvailableOnType(type, field)) {
var fieldWasRequested = getFieldWasRequestedOnNode(node, field);
if (!fieldWasRequested) {
context.reportError(new _graphql.GraphQLError("'" + field + "' field required on 'fragment " + node.name.value + " on " + node.typeCondition.name.value + "'", [node]));
}
}
});
},
// Every inline fragment must have the required field specified inside
// itself or in some parent selection set.
InlineFragment: function InlineFragment(node, key, parent, path, ancestors) {
requiredFields.forEach(function (field) {
var type = context.getType();
if (fieldAvailableOnType(type, field)) {
// First, check the selection set on this inline fragment
if (node.selectionSet && getFieldWasRequestedOnNode(node, field)) {
return true;
}
var ancestorClone = [].concat(_toConsumableArray(ancestors));
var nearestField = void 0;
var nextAncestor = void 0;
// Now, walk up the ancestors, until you see a field.
while (!nearestField) {
nextAncestor = ancestorClone.pop();
if (nextAncestor.selectionSet && getFieldWasRequestedOnNode(nextAncestor, field)) {
return true;
}
if (nextAncestor.kind === "Field") {
nearestField = nextAncestor;
}
}
// If we never found a field, the query is malformed
if (!nearestField) {
throw new Error("Inline fragment found inside document without a parent field.");
}
// We found a field, but we never saw the field we were looking for in
// the intermediate selection sets.
context.reportError(new _graphql.GraphQLError("'" + field + "' field required on '... on " + node.typeCondition.name.value + "'", [node]));
}
});
},
// Every field that can have the field directly on it, should. It's not
// enough to have some child fragment to include the field, since we don't
// know if that fragment covers all of the possible type options.
Field: function Field(node) {
var def = context.getFieldDef();
if (!def) {
return;
}
requiredFields.forEach(function (field) {
if (fieldAvailableOnType(def.type, field)) {
var fieldWasRequested = getFieldWasRequestedOnNode(node, field);
if (!fieldWasRequested) {
context.reportError(new _graphql.GraphQLError("'" + field + "' field required on '" + node.name.value + "'", [node]));
}
}
});
}
};
}
function typeNamesShouldBeCapitalized(context) {
return {
NamedType: function NamedType(node) {
var typeName = node.name.value;
if (typeName[0] == typeName[0].toLowerCase()) {
context.reportError(new _graphql.GraphQLError("All type names should start with a capital letter", [node]));
}
}
};
}
// Mostly taken from https://github.com/graphql/graphql-js/blob/063148de039b02670a760b8d3dfaf2a04a467169/src/utilities/findDeprecatedUsages.js
// See explanation in [#93](https://github.com/apollographql/eslint-plugin-graphql/pull/93)
function noDeprecatedFields(context) {
return {
Field: function Field(node) {
var fieldDef = context.getFieldDef();
if (fieldDef && fieldDef.isDeprecated) {
var parentType = context.getParentType();
if (parentType) {
var reason = fieldDef.deprecationReason;
context.reportError(new _graphql.GraphQLError("The field " + parentType.name + "." + fieldDef.name + " is deprecated." + (reason ? " " + reason : ""), [node]));
}
}
},
EnumValue: function EnumValue(node) {
// context is of type ValidationContext which doesn't export getEnumValue.
// Bypass the public API to grab that information directly from _typeInfo.
var enumVal = context._typeInfo.getEnumValue();
if (enumVal && enumVal.isDeprecated) {
var type = (0, _graphql.getNamedType)(context.getInputType());
if (!type) {
return;
}
var reason = enumVal.deprecationReason;
context.reportError(new _graphql.GraphQLError("The enum value " + type.name + "." + enumVal.name + " is deprecated." + (reason ? " " + reason : ""), [node]));
}
}
};
}

355
node_modules/eslint-plugin-graphql/lib/index.js generated vendored Normal file
View File

@ -0,0 +1,355 @@
'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
};