Comparing version 0.0.0-main-8de1c8ac to 0.0.0-main-99a0ac85
@@ -12,2 +12,3 @@ /** | ||
export declare function fieldTagOnWrongNode(): string; | ||
export declare function implementsTagOnWrongNode(): string; | ||
export declare function killsParentOnExceptionOnWrongNode(): string; | ||
@@ -71,1 +72,4 @@ export declare function wrongCasingForGratsTag(actual: string, expected: string): string; | ||
export declare function mergedInterfaces(interfaceName: string): string; | ||
export declare function implementsTagMissingValue(): string; | ||
export declare function duplicateTag(tagName: string): string; | ||
export declare function duplicateInterfaceTag(): string; |
"use strict"; | ||
exports.__esModule = true; | ||
exports.defaultArgPropertyMissingName = exports.defaultArgElementIsNotAssignment = exports.defaultValueIsNotLiteral = exports.ambiguousNumberType = exports.expectedOneNonNullishType = exports.propertyFieldMissingType = exports.cannotResolveSymbolForDescription = exports.promiseMissingTypeArg = exports.methodMissingType = exports.gqlEntityMissingName = exports.enumVariantMissingInitializer = exports.enumVariantNotStringLiteral = exports.enumTagOnInvalidNode = exports.argNotTyped = exports.argNameNotLiteral = exports.argIsNotProperty = exports.argumentParamIsNotObject = exports.argumentParamIsMissingType = exports.typeNameDoesNotMatchExpected = exports.typeNameTypeNotStringLiteral = exports.typeNameMissingTypeAnnotation = exports.typeNameInitializerWrong = exports.typeNameInitializeNotString = exports.typeNameMissingInitializer = exports.typeNameNotDeclaration = exports.typeTagOnAliasOfNonObject = exports.typeTagOnUnamedClass = exports.inputFieldUntyped = exports.inputTypeFieldNotProperty = exports.inputTypeNotLiteral = exports.functionFieldNotNamedExport = exports.functionFieldDefaultExport = exports.functionFieldNotNamed = exports.functionFieldParentTypeNotValid = exports.functionFieldParentTypeMissing = exports.functionFieldNotTopLevel = exports.invalidReturnTypeForFunctionField = exports.invalidParentArgForFunctionField = exports.expectedUnionTypeReference = exports.expectedUnionTypeNode = exports.invalidUnionTagUsage = exports.invalidInputTagUsage = exports.invalidEnumTagUsage = exports.invalidInterfaceTagUsage = exports.invalidScalarTagUsage = exports.invalidTypeTagUsage = exports.invalidGratsTag = exports.wrongCasingForGratsTag = exports.killsParentOnExceptionOnWrongNode = exports.fieldTagOnWrongNode = void 0; | ||
exports.mergedInterfaces = exports.nonNullTypeCannotBeOptional = exports.killsParentOnExceptionOnNullable = exports.killsParentOnExceptionWithWrongConfig = exports.expectedIdentifer = exports.pluralTypeMissingParameter = exports.unknownGraphQLType = exports.unsupportedTypeLiteral = exports.defaultArgPropertyMissingInitializer = void 0; | ||
exports.defaultArgElementIsNotAssignment = exports.defaultValueIsNotLiteral = exports.ambiguousNumberType = exports.expectedOneNonNullishType = exports.propertyFieldMissingType = exports.cannotResolveSymbolForDescription = exports.promiseMissingTypeArg = exports.methodMissingType = exports.gqlEntityMissingName = exports.enumVariantMissingInitializer = exports.enumVariantNotStringLiteral = exports.enumTagOnInvalidNode = exports.argNotTyped = exports.argNameNotLiteral = exports.argIsNotProperty = exports.argumentParamIsNotObject = exports.argumentParamIsMissingType = exports.typeNameDoesNotMatchExpected = exports.typeNameTypeNotStringLiteral = exports.typeNameMissingTypeAnnotation = exports.typeNameInitializerWrong = exports.typeNameInitializeNotString = exports.typeNameMissingInitializer = exports.typeNameNotDeclaration = exports.typeTagOnAliasOfNonObject = exports.typeTagOnUnamedClass = exports.inputFieldUntyped = exports.inputTypeFieldNotProperty = exports.inputTypeNotLiteral = exports.functionFieldNotNamedExport = exports.functionFieldDefaultExport = exports.functionFieldNotNamed = exports.functionFieldParentTypeNotValid = exports.functionFieldParentTypeMissing = exports.functionFieldNotTopLevel = exports.invalidReturnTypeForFunctionField = exports.invalidParentArgForFunctionField = exports.expectedUnionTypeReference = exports.expectedUnionTypeNode = exports.invalidUnionTagUsage = exports.invalidInputTagUsage = exports.invalidEnumTagUsage = exports.invalidInterfaceTagUsage = exports.invalidScalarTagUsage = exports.invalidTypeTagUsage = exports.invalidGratsTag = exports.wrongCasingForGratsTag = exports.killsParentOnExceptionOnWrongNode = exports.implementsTagOnWrongNode = exports.fieldTagOnWrongNode = void 0; | ||
exports.duplicateInterfaceTag = exports.duplicateTag = exports.implementsTagMissingValue = exports.mergedInterfaces = exports.nonNullTypeCannotBeOptional = exports.killsParentOnExceptionOnNullable = exports.killsParentOnExceptionWithWrongConfig = exports.expectedIdentifer = exports.pluralTypeMissingParameter = exports.unknownGraphQLType = exports.unsupportedTypeLiteral = exports.defaultArgPropertyMissingInitializer = exports.defaultArgPropertyMissingName = void 0; | ||
var Extractor_1 = require("./Extractor"); | ||
@@ -24,2 +24,6 @@ // TODO: Move these to short URLS that are easier to keep from breaking. | ||
exports.fieldTagOnWrongNode = fieldTagOnWrongNode; | ||
function implementsTagOnWrongNode() { | ||
return "`@".concat(Extractor_1.IMPLEMENTS_TAG, "` can only be used on Grats type or interface declarations. Did you mean to include the `@").concat(Extractor_1.TYPE_TAG, "` or `@").concat(Extractor_1.INTERFACE_TAG, "` tag in this docblock?"); | ||
} | ||
exports.implementsTagOnWrongNode = implementsTagOnWrongNode; | ||
function killsParentOnExceptionOnWrongNode() { | ||
@@ -264,1 +268,13 @@ return "Unexpected `@".concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "`. `@").concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` can only be used in field annotation docblocks. Perhaps you are missing a `@").concat(Extractor_1.FIELD_TAG, "` tag?"); | ||
exports.mergedInterfaces = mergedInterfaces; | ||
function implementsTagMissingValue() { | ||
return "Expected `@".concat(Extractor_1.IMPLEMENTS_TAG, "` to be followed by one or more interface names."); | ||
} | ||
exports.implementsTagMissingValue = implementsTagMissingValue; | ||
function duplicateTag(tagName) { | ||
return "Unexpected duplicate `@".concat(tagName, "` tag. Grats does not accept multiple instances of the same tag."); | ||
} | ||
exports.duplicateTag = duplicateTag; | ||
function duplicateInterfaceTag() { | ||
return "Unexpected duplicate `@".concat(Extractor_1.IMPLEMENTS_TAG, "` tag. To declare that a type or interface implements multiple interfaces list them as comma separated values: `@").concat(Extractor_1.IMPLEMENTS_TAG, " interfaceA, interfaceB`."); | ||
} | ||
exports.duplicateInterfaceTag = duplicateInterfaceTag; |
@@ -16,2 +16,3 @@ import { DefinitionNode, FieldDefinitionNode, InputValueDefinitionNode, ListTypeNode, NamedTypeNode, Location as GraphQLLocation, NameNode, Token, TypeNode, NonNullTypeNode, StringValueNode, ConstValueNode, ConstDirectiveNode, ConstArgumentNode, EnumValueDefinitionNode, ConstObjectFieldNode, ConstObjectValueNode, ConstListValueNode } from "graphql"; | ||
export declare const INPUT_TAG = "gqlInput"; | ||
export declare const IMPLEMENTS_TAG = "gqlImplements"; | ||
export declare const KILLS_PARENT_ON_EXCEPTION_TAG = "killsParentOnException"; | ||
@@ -72,3 +73,5 @@ export declare const ALL_TAGS: string[]; | ||
isValidTypenamePropertyType(node: ts.TypeNode, expectedName: string): boolean; | ||
collectInterfaces(node: ts.ClassDeclaration | ts.InterfaceDeclaration): Array<NamedTypeNode> | null; | ||
collectInterfaces(node: ts.ClassDeclaration | ts.InterfaceDeclaration | ts.TypeAliasDeclaration): Array<NamedTypeNode> | null; | ||
collectTagInterfaces(node: ts.ClassDeclaration | ts.InterfaceDeclaration | ts.TypeAliasDeclaration): Array<NamedTypeNode> | null; | ||
collectHeritageInterfaces(node: ts.ClassDeclaration): Array<NamedTypeNode> | null; | ||
interfaceInterfaceDeclaration(node: ts.InterfaceDeclaration, tag: ts.JSDocTag): null | undefined; | ||
@@ -75,0 +78,0 @@ collectFields(node: ts.ClassDeclaration | ts.InterfaceDeclaration | ts.TypeLiteralNode): Array<FieldDefinitionNode>; |
@@ -30,3 +30,3 @@ "use strict"; | ||
exports.__esModule = true; | ||
exports.Extractor = exports.ALL_TAGS = exports.KILLS_PARENT_ON_EXCEPTION_TAG = exports.INPUT_TAG = exports.UNION_TAG = exports.ENUM_TAG = exports.INTERFACE_TAG = exports.SCALAR_TAG = exports.FIELD_TAG = exports.TYPE_TAG = exports.ISSUE_URL = exports.LIBRARY_NAME = exports.LIBRARY_IMPORT_NAME = void 0; | ||
exports.Extractor = exports.ALL_TAGS = exports.KILLS_PARENT_ON_EXCEPTION_TAG = exports.IMPLEMENTS_TAG = exports.INPUT_TAG = exports.UNION_TAG = exports.ENUM_TAG = exports.INTERFACE_TAG = exports.SCALAR_TAG = exports.FIELD_TAG = exports.TYPE_TAG = exports.ISSUE_URL = exports.LIBRARY_NAME = exports.LIBRARY_IMPORT_NAME = void 0; | ||
var graphql_1 = require("graphql"); | ||
@@ -39,2 +39,3 @@ var DiagnosticError_1 = require("./utils/DiagnosticError"); | ||
var JSDoc_1 = require("./utils/JSDoc"); | ||
var helpers_1 = require("./utils/helpers"); | ||
exports.LIBRARY_IMPORT_NAME = "grats"; | ||
@@ -50,3 +51,5 @@ exports.LIBRARY_NAME = "Grats"; | ||
exports.INPUT_TAG = "gqlInput"; | ||
exports.IMPLEMENTS_TAG = "gqlImplements"; | ||
exports.KILLS_PARENT_ON_EXCEPTION_TAG = "killsParentOnException"; | ||
// All the tags that start with gql | ||
exports.ALL_TAGS = [ | ||
@@ -60,2 +63,3 @@ exports.TYPE_TAG, | ||
exports.INPUT_TAG, | ||
exports.IMPLEMENTS_TAG, | ||
]; | ||
@@ -121,2 +125,11 @@ var DEPRECATED_TAG = "deprecated"; | ||
break; | ||
case exports.IMPLEMENTS_TAG: { | ||
var hasTypeOrInterfaceTag = ts.getJSDocTags(node).some(function (t) { | ||
return (t.tagName.text === exports.TYPE_TAG || t.tagName.text === exports.INTERFACE_TAG); | ||
}); | ||
if (!hasTypeOrInterfaceTag) { | ||
_this.report(tag.tagName, E.implementsTagOnWrongNode()); | ||
} | ||
break; | ||
} | ||
case exports.KILLS_PARENT_ON_EXCEPTION_TAG: { | ||
@@ -528,2 +541,3 @@ var hasFieldTag = ts.getJSDocTags(node).some(function (t) { | ||
var fields = this.collectFields(node.type); | ||
var interfaces = this.collectInterfaces(node); | ||
this.ctx.recordTypeName(node.name, name.value); | ||
@@ -538,5 +552,3 @@ this.checkForTypenameProperty(node.type, name.value); | ||
fields: fields, | ||
// I don't believe there is a reasonable way to specify that a type | ||
// implements an interface. | ||
interfaces: undefined | ||
interfaces: interfaces !== null && interfaces !== void 0 ? interfaces : undefined | ||
}); | ||
@@ -609,3 +621,26 @@ }; | ||
Extractor.prototype.collectInterfaces = function (node) { | ||
var heritageInterfaces = ts.isClassDeclaration(node) | ||
? this.collectHeritageInterfaces(node) | ||
: null; | ||
return (0, helpers_1.concatMaybeArrays)(heritageInterfaces, this.collectTagInterfaces(node)); | ||
}; | ||
Extractor.prototype.collectTagInterfaces = function (node) { | ||
var _this = this; | ||
var tag = this.findTag(node, exports.IMPLEMENTS_TAG); | ||
if (tag == null) | ||
return null; | ||
var commentName = ts.getTextOfJSDocComment(tag.comment); | ||
if (commentName == null) { | ||
return this.report(tag, E.implementsTagMissingValue()); | ||
} | ||
return commentName.split(",").map(function (name) { | ||
// FIXME: Use more targeted location information. | ||
// Will require rewriting everything that expects a node for location | ||
// purposes to transform the node into a location eagerly. Then we can have | ||
// a richer set of tools to construct custom locations. | ||
return _this.gqlNamedType(tag, name.trim()); | ||
}); | ||
}; | ||
Extractor.prototype.collectHeritageInterfaces = function (node) { | ||
var _this = this; | ||
if (node.heritageClauses == null) | ||
@@ -645,3 +680,3 @@ return null; | ||
var otherLocations = symbol.declarations | ||
.filter(function (d) { return d !== node; }) | ||
.filter(function (d) { return d !== node && ts.isInterfaceDeclaration(d); }) | ||
.map(function (d) { | ||
@@ -652,11 +687,10 @@ var _a; | ||
}); | ||
return this.report(node.name, E.mergedInterfaces(name.value), otherLocations); | ||
if (otherLocations.length > 0) { | ||
return this.report(node.name, E.mergedInterfaces(name.value), otherLocations); | ||
} | ||
} | ||
var description = this.collectDescription(node.name); | ||
var interfaces = this.collectInterfaces(node); | ||
var fields = this.collectFields(node); | ||
this.ctx.recordTypeName(node.name, name.value); | ||
// While GraphQL supports interfaces that extend other interfaces, | ||
// TypeScript does not. So we can't support that here either. | ||
// In the future we could support classes that act as interfaces through | ||
// inheritance. | ||
this.definitions.push({ | ||
@@ -667,3 +701,4 @@ kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION, | ||
name: name, | ||
fields: fields | ||
fields: fields, | ||
interfaces: interfaces || undefined | ||
}); | ||
@@ -1308,6 +1343,19 @@ }; | ||
Extractor.prototype.findTag = function (node, tagName) { | ||
var _a; | ||
return ((_a = ts | ||
var _this = this; | ||
var tags = ts | ||
.getJSDocTags(node) | ||
.find(function (tag) { return tag.tagName.escapedText === tagName; })) !== null && _a !== void 0 ? _a : null); | ||
.filter(function (tag) { return tag.tagName.escapedText === tagName; }); | ||
if (tags.length === 0) { | ||
return null; | ||
} | ||
if (tags.length > 1) { | ||
var additionalTags = tags.slice(1).map(function (tag) { | ||
return _this.related(tag, "Additional tag"); | ||
}); | ||
var message = tagName === exports.IMPLEMENTS_TAG | ||
? E.duplicateInterfaceTag() | ||
: E.duplicateTag(tagName); | ||
return this.report(tags[0], message, additionalTags); | ||
} | ||
return tags[0]; | ||
}; | ||
@@ -1314,0 +1362,0 @@ // It is a GraphQL best practice to model all fields as nullable. This allows |
{ | ||
"name": "grats", | ||
"version": "0.0.0-main-8de1c8ac", | ||
"version": "0.0.0-main-99a0ac85", | ||
"main": "dist/src/index.js", | ||
@@ -5,0 +5,0 @@ "bin": "dist/src/cli.js", |
163803
37
3437