UNPKG

@vanta-inc/eslint-plugin-vanta

Version:
93 lines (92 loc) 4.14 kB
"use strict"; /** * @fileoverview Lint rule to ensure that all types reachable from fields marked as @public are themselves marked as @public. */ var _a; Object.defineProperty(exports, "__esModule", { value: true }); var eslint_plugin_1 = require("@graphql-eslint/eslint-plugin"); var graphql_1 = require("graphql"); var graphqlutils_1 = require("../utils/graphqlutils"); var PUBLIC_DIRECTIVE = "public"; var RULE_ID = "public-descendants-public"; var rule = { meta: { type: "problem", docs: { category: "Schema", // @ts-ignore description: "Ensures that all types reachable from fields marked as @public are themselves marked as @public.", url: "https://github.com/VantaInc/eslint-plugin-vanta/blob/main/docs/rules/public-descendants-public.md", requiresSchema: true, }, messages: (_a = {}, _a[RULE_ID] = "All types reachable from fields marked as @public must be also marked as @public", _a), }, create: function (context) { var schema = eslint_plugin_1.requireGraphQLSchemaFromContext(RULE_ID, context); var hasPublicDirective = function (directives) { return Boolean(directives === null || directives === void 0 ? void 0 : directives.find(function (x) { return x.name.value === PUBLIC_DIRECTIVE; })); }; var fieldPointsToPublicTypeOrScalar = function (node) { var _a; var typeName = graphqlutils_1.extractNamedType(node.type).name.value; var type = schema.getType(typeName); if (!type) { return true; // type not found; assume OK } // need to check a whitelist since the version of graphql we're using // seems to not work with the instanceOf checks. Hoping we can get rid of // this in the future. var builtinScalars = ["Int", "Float", "String", "Boolean", "ID"]; var customScalarsAndEnums = [ "DateTime", "reportStandard", "testOutcome", ]; var typeIsScalar = type instanceof graphql_1.GraphQLScalarType || type instanceof graphql_1.GraphQLEnumType || builtinScalars.includes(typeName) || customScalarsAndEnums.includes(typeName); return hasPublicDirective((_a = type.astNode) === null || _a === void 0 ? void 0 : _a.directives) || typeIsScalar; }; return { FieldDefinition: function (node) { if (!hasPublicDirective(node.directives)) { return; } if (!fieldPointsToPublicTypeOrScalar(node.rawNode())) { context.report({ node: node, message: "Types accessible by @" + PUBLIC_DIRECTIVE + " fields must be marked @" + PUBLIC_DIRECTIVE + ".", }); } }, ObjectTypeDefinition: function (node) { var _a; if (!hasPublicDirective(node.directives)) { return; } (_a = node.rawNode().fields) === null || _a === void 0 ? void 0 : _a.forEach(function (field) { if (!fieldPointsToPublicTypeOrScalar(field)) { context.report({ node: node, message: "Types accessible from @" + PUBLIC_DIRECTIVE + " types must themselves be marked @" + PUBLIC_DIRECTIVE + ". Unmarked field: " + field.name.value, }); } }); }, ObjectTypeExtension: function (node) { if (!hasPublicDirective(node.directives)) { return; } context.report({ node: node, message: "@" + PUBLIC_DIRECTIVE + " directive not supported on type extensions", }); }, }; }, }; module.exports = rule; exports.default = rule;