New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

grats

Package Overview
Dependencies
Maintainers
1
Versions
240
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grats - npm Package Compare versions

Comparing version 0.0.0-main-6626f659 to 0.0.0-main-663d2ac4

dist/src/codegen.d.ts

12

dist/package.json
{
"name": "grats",
"version": "0.0.5",
"version": "0.0.10",
"main": "dist/src/index.js",

@@ -15,11 +15,12 @@ "bin": "dist/src/cli.js",

"build": "tsc --build",
"lint": "eslint src/**/*.ts"
"format": "prettier . --write",
"lint": "eslint src/**/*.ts && prettier . --check"
},
"dependencies": {
"@graphql-tools/utils": "^9.2.1",
"commander": "^10.0.0",
"graphql": "^16.6.0",
"typescript": "^4.9.5"
"typescript": "^5.0.2"
},
"devDependencies": {
"@graphql-tools/utils": "^9.2.1",
"@types/node": "^18.14.6",

@@ -32,2 +33,3 @@ "@typescript-eslint/eslint-plugin": "^5.55.0",

"path-browserify": "^1.0.1",
"prettier": "^2.8.7",
"process": "^0.11.10",

@@ -39,3 +41,3 @@ "ts-node": "^10.9.1"

},
"packageManager": "pnpm@8.1.1",
"packageManager": "pnpm@8.12.0",
"engines": {

@@ -42,0 +44,0 @@ "node": ">=16 <=21",

@@ -39,3 +39,3 @@ #!/usr/bin/env node

};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatLoc = void 0;

@@ -45,3 +45,2 @@ var graphql_1 = require("graphql");

var lib_1 = require("./lib");
var utils_1 = require("@graphql-tools/utils");
var commander_1 = require("commander");

@@ -52,2 +51,4 @@ var fs_1 = require("fs");

var Locate_1 = require("./Locate");
var printSchema_1 = require("./printSchema");
var ts = require("typescript");
var program = new commander_1.Command();

@@ -58,9 +59,8 @@ program

.version(package_json_1.version)
.option("-o, --output <SCHEMA_FILE>", "Where to write the schema file. Defaults to stdout")
.option("--tsconfig <TSCONFIG>", "Path to tsconfig.json. Defaults to auto-detecting based on the current working directory")
.action(function (_a) {
var output = _a.output, tsconfig = _a.tsconfig;
var tsconfig = _a.tsconfig;
return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_b) {
build(output, tsconfig);
build(tsconfig);
return [2 /*return*/];

@@ -76,3 +76,4 @@ });

var tsconfig = _a.tsconfig;
var schema = buildSchema(tsconfig);
var config = getTsConfig(tsconfig).config;
var schema = buildSchema(config);
var loc = (0, Locate_1.locate)(schema, entity);

@@ -86,26 +87,31 @@ if (loc.kind === "ERROR") {

program.parse();
function build(output, tsconfig) {
var schema = buildSchema(tsconfig);
function build(tsconfig) {
var _a = getTsConfig(tsconfig), config = _a.config, configPath = _a.configPath;
var schema = buildSchema(config);
var sortedSchema = (0, graphql_1.lexicographicSortSchema)(schema);
var schemaStr = (0, utils_1.printSchemaWithDirectives)(sortedSchema, {
assumeValid: true
});
if (output) {
var absOutput = (0, path_1.resolve)(process.cwd(), output);
(0, fs_1.writeFileSync)(absOutput, schemaStr);
console.error("Grats: Wrote schema to `".concat(absOutput, "`."));
var gratsOptions = config.raw.grats;
var dest = (0, path_1.resolve)((0, path_1.dirname)(configPath), gratsOptions.tsSchema);
var code = (0, printSchema_1.printExecutableSchema)(sortedSchema, gratsOptions, dest);
(0, fs_1.writeFileSync)(dest, code);
console.error("Grats: Wrote TypeScript schema to `".concat(dest, "`."));
var schemaStr = (0, printSchema_1.printGratsSDL)(sortedSchema, gratsOptions);
var absOutput = (0, path_1.resolve)((0, path_1.dirname)(configPath), gratsOptions.graphqlSchema);
(0, fs_1.writeFileSync)(absOutput, schemaStr);
console.error("Grats: Wrote schema to `".concat(absOutput, "`."));
}
// Locate and read the tsconfig.json file
function getTsConfig(tsconfig) {
var configPath = tsconfig || ts.findConfigFile(process.cwd(), ts.sys.fileExists);
if (configPath == null) {
throw new Error("Grats: Could not find tsconfig.json");
}
else {
console.log(schemaStr);
var optionsResult = (0, _1.getParsedTsConfig)(configPath);
if (optionsResult.kind === "ERROR") {
console.error(optionsResult.err.formatDiagnosticsWithColorAndContext());
process.exit(1);
}
return { configPath: configPath, config: optionsResult.value };
}
function buildSchema(tsconfig) {
if (tsconfig && !(0, fs_1.existsSync)(tsconfig)) {
console.error("Grats: Could not find tsconfig.json at `".concat(tsconfig, "`."));
process.exit(1);
}
var parsed = (0, _1.getParsedTsConfig)(tsconfig);
// FIXME: Validate config!
// https://github.com/tsconfig/bases
var schemaResult = (0, lib_1.buildSchemaResult)(parsed);
function buildSchema(options) {
var schemaResult = (0, lib_1.buildSchemaResult)(options);
if (schemaResult.kind === "ERROR") {

@@ -112,0 +118,0 @@ console.error(schemaResult.err.formatDiagnosticsWithColorAndContext());

@@ -69,3 +69,3 @@ /**

export declare function nonNullTypeCannotBeOptional(): string;
export declare function mergedInterfaces(interfaceName: string): string;
export declare function mergedInterfaces(): string;
export declare function implementsTagMissingValue(): string;

@@ -88,1 +88,7 @@ export declare function implementsTagOnClass(): string;

export declare function multipleContextTypes(): string;
export declare function graphQLNameHasLeadingNewlines(name: string, tagName: string): string;
export declare function graphQLTagNameHasWhitespace(tagName: string): string;
export declare function subscriptionFieldNotAsyncIterable(): string;
export declare function nonSubscriptionFieldAsyncIterable(): string;
export declare function operationTypeNotUnknown(): string;
export declare function expectedNullableArgumentToBeOptional(): string;
"use strict";
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: 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.typeTagOnAliasOfNonObjectOrUnknown = exports.typeTagOnUnnamedClass = 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.multipleContextTypes = exports.unexpectedParamSpreadForContextParam = exports.expectedTypeAnnotationOnContextToHaveDeclaration = exports.expectedTypeAnnotationOnContextToBeResolvable = exports.expectedTypeAnnotationOfReferenceOnContext = exports.expectedTypeAnnotationOnContext = exports.unresolvedTypeReference = exports.invalidTypePassedToFieldFunction = exports.parameterPropertyMissingType = exports.parameterPropertyNotPublic = exports.parameterWithoutModifiers = exports.duplicateInterfaceTag = exports.duplicateTag = exports.implementsTagOnTypeAlias = exports.implementsTagOnInterface = exports.implementsTagOnClass = exports.implementsTagMissingValue = exports.mergedInterfaces = exports.nonNullTypeCannotBeOptional = exports.killsParentOnExceptionOnNullable = exports.killsParentOnExceptionWithWrongConfig = exports.expectedIdentifier = exports.pluralTypeMissingParameter = exports.unknownGraphQLType = exports.unsupportedTypeLiteral = exports.defaultArgPropertyMissingInitializer = void 0;
exports.expectedNullableArgumentToBeOptional = exports.operationTypeNotUnknown = exports.nonSubscriptionFieldAsyncIterable = exports.subscriptionFieldNotAsyncIterable = exports.graphQLTagNameHasWhitespace = exports.graphQLNameHasLeadingNewlines = exports.multipleContextTypes = exports.unexpectedParamSpreadForContextParam = exports.expectedTypeAnnotationOnContextToHaveDeclaration = exports.expectedTypeAnnotationOnContextToBeResolvable = exports.expectedTypeAnnotationOfReferenceOnContext = exports.expectedTypeAnnotationOnContext = exports.unresolvedTypeReference = exports.invalidTypePassedToFieldFunction = exports.parameterPropertyMissingType = exports.parameterPropertyNotPublic = exports.parameterWithoutModifiers = exports.duplicateInterfaceTag = exports.duplicateTag = exports.implementsTagOnTypeAlias = exports.implementsTagOnInterface = exports.implementsTagOnClass = exports.implementsTagMissingValue = exports.mergedInterfaces = exports.nonNullTypeCannotBeOptional = exports.killsParentOnExceptionOnNullable = exports.killsParentOnExceptionWithWrongConfig = exports.expectedIdentifier = exports.pluralTypeMissingParameter = exports.unknownGraphQLType = exports.unsupportedTypeLiteral = exports.defaultArgPropertyMissingInitializer = void 0;
var Extractor_1 = require("./Extractor");
// TODO: Move these to short URLS that are easier to keep from breaking.
var DOC_URLS = {
mergedInterfaces: "https://grats.capt.dev/docs/dockblock-tags/interfaces/#merged-interfaces",
parameterProperties: "https://grats.capt.dev/docs/dockblock-tags/fields#class-based-fields",
typeImplementsInterface: "TODO"
mergedInterfaces: "https://grats.capt.dev/docs/docblock-tags/interfaces/#merged-interfaces",
parameterProperties: "https://grats.capt.dev/docs/docblock-tags/fields#class-based-fields",
};

@@ -120,3 +119,3 @@ /**

function typeTagOnAliasOfNonObjectOrUnknown() {
return "Expected `@".concat(Extractor_1.TYPE_TAG, "` type to be a type literal or `unknown`. For example: `type Foo = { bar: string }` or `type Query = unknown`.");
return "Expected `@".concat(Extractor_1.TYPE_TAG, "` type to be an object type literal (`{ }`) or `unknown`. For example: `type Foo = { bar: string }` or `type Query = unknown`.");
}

@@ -249,12 +248,12 @@ exports.typeTagOnAliasOfNonObjectOrUnknown = typeTagOnAliasOfNonObjectOrUnknown;

function killsParentOnExceptionOnNullable() {
return "Unexpected `@".concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` tag. `@").concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` is unnessesary on fields that are already nullable.");
return "Unexpected `@".concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` tag. `@").concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` is unnecessary on fields that are already nullable.");
}
exports.killsParentOnExceptionOnNullable = killsParentOnExceptionOnNullable;
function nonNullTypeCannotBeOptional() {
return "Unexpected optional argument that does not also accept `null`. Optional arguments in GraphQL may get passed an explict `null` value. This means optional arguments must be typed to also accept `null`.";
return "Unexpected optional argument that does not also accept `null`. Optional arguments in GraphQL may get passed an explicit `null` value. This means optional arguments must be typed to also accept `null`.";
}
exports.nonNullTypeCannotBeOptional = nonNullTypeCannotBeOptional;
function mergedInterfaces(interfaceName) {
function mergedInterfaces() {
return [
"Unexpected merged interface `".concat(interfaceName, "`."),
"Unexpected merged interface.",
"If an interface is declared multiple times in a scope, TypeScript merges them.",

@@ -280,3 +279,3 @@ "To avoid ambiguity Grats does not support using merged interfaces as GraphQL interfaces.",

function implementsTagOnTypeAlias() {
return "`@".concat(Extractor_1.IMPLEMENTS_TAG_DEPRECATED, "` has been deprecated. Types which implement GraphQL interfaces should be defined using TypeScript class or interface declarations. Learn more: ").concat(DOC_URLS.typeImplementsInterface, ".");
return "`@".concat(Extractor_1.IMPLEMENTS_TAG_DEPRECATED, "` has been deprecated. Types which implement GraphQL interfaces should be defined using TypeScript class or interface declarations.");
}

@@ -344,1 +343,25 @@ exports.implementsTagOnTypeAlias = implementsTagOnTypeAlias;

exports.multipleContextTypes = multipleContextTypes;
function graphQLNameHasLeadingNewlines(name, tagName) {
return "Expected the GraphQL name `".concat(name, "` to be on the same line as it's `@").concat(tagName, "` tag.");
}
exports.graphQLNameHasLeadingNewlines = graphQLNameHasLeadingNewlines;
function graphQLTagNameHasWhitespace(tagName) {
return "Expected text following a `@".concat(tagName, "` tag to be a GraphQL name. If you intended this text to be a description, place it at the top of the docblock before any `@tags`.");
}
exports.graphQLTagNameHasWhitespace = graphQLTagNameHasWhitespace;
function subscriptionFieldNotAsyncIterable() {
return "Expected fields on `Subscription` to return an AsyncIterable.";
}
exports.subscriptionFieldNotAsyncIterable = subscriptionFieldNotAsyncIterable;
function nonSubscriptionFieldAsyncIterable() {
return "Unexpected AsyncIterable. Only fields on `Subscription` should return an AsyncIterable.";
}
exports.nonSubscriptionFieldAsyncIterable = nonSubscriptionFieldAsyncIterable;
function operationTypeNotUnknown() {
return "Operation types `Query`, `Mutation`, and `Subscription` must be defined as type aliases of `unknown`. E.g. `type Query = unknown`.";
}
exports.operationTypeNotUnknown = operationTypeNotUnknown;
function expectedNullableArgumentToBeOptional() {
return "Expected nullable argument to be optional. graphql-js may not define properties where an undefined argument is passed. To guard against this add a `?` to the end of the argument name to make it optional.";
}
exports.expectedNullableArgumentToBeOptional = expectedNullableArgumentToBeOptional;

@@ -1,7 +0,7 @@

import { FieldDefinitionNode, InputValueDefinitionNode, NamedTypeNode, NameNode, TypeNode, StringValueNode, ConstValueNode, ConstDirectiveNode, EnumValueDefinitionNode, ConstObjectFieldNode, ConstObjectValueNode, ConstListValueNode } from "graphql";
import { NameNode } from "graphql";
import { DiagnosticsResult } from "./utils/DiagnosticError";
import * as ts from "typescript";
import { GratsDefinitionNode, TypeContext } from "./TypeContext";
import { NameDefinition } from "./TypeContext";
import { ConfigOptions } from "./lib";
import { GraphQLConstructor } from "./GraphQLConstructor";
import { GratsDefinitionNode } from "./GraphQLConstructor";
export declare const LIBRARY_IMPORT_NAME = "grats";

@@ -20,3 +20,10 @@ export declare const LIBRARY_NAME = "Grats";

export declare const ALL_TAGS: string[];
type ArgDefaults = Map<string, ts.Expression>;
export type ExtractionSnapshot = {
readonly definitions: GratsDefinitionNode[];
readonly unresolvedNames: Map<ts.Node, NameNode>;
readonly nameDefinitions: Map<ts.Node, NameDefinition>;
readonly contextReferences: Array<ts.Node>;
readonly typesWithTypenameField: Set<string>;
readonly interfaceDeclarations: Array<ts.InterfaceDeclaration>;
};
/**

@@ -32,80 +39,2 @@ * Extracts GraphQL definitions from TypeScript source code.

*/
export declare class Extractor {
definitions: GratsDefinitionNode[];
sourceFile: ts.SourceFile;
ctx: TypeContext;
configOptions: ConfigOptions;
errors: ts.Diagnostic[];
gql: GraphQLConstructor;
constructor(sourceFile: ts.SourceFile, ctx: TypeContext, buildOptions: ConfigOptions);
extract(): DiagnosticsResult<GratsDefinitionNode[]>;
extractType(node: ts.Node, tag: ts.JSDocTag): void;
extractScalar(node: ts.Node, tag: ts.JSDocTag): void;
extractInterface(node: ts.Node, tag: ts.JSDocTag): void;
extractEnum(node: ts.Node, tag: ts.JSDocTag): void;
extractInput(node: ts.Node, tag: ts.JSDocTag): void;
extractUnion(node: ts.Node, tag: ts.JSDocTag): void;
/** Error handling and location juggling */
report(node: ts.Node, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): null;
reportUnhandled(node: ts.Node, positionKind: "type" | "field" | "field type" | "input" | "input field" | "union member" | "constant value" | "union" | "enum value", message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): null;
related(node: ts.Node, message: string): ts.DiagnosticRelatedInformation;
diagnosticAnnotatedLocation(node: ts.Node): {
start: number;
length: number;
filepath: ts.SourceFile;
};
/** TypeScript traversals */
unionTypeAliasDeclaration(node: ts.TypeAliasDeclaration, tag: ts.JSDocTag): null | undefined;
functionDeclarationExtendType(node: ts.FunctionDeclaration, tag: ts.JSDocTag): null | undefined;
typeReferenceFromParam(typeParam: ts.ParameterDeclaration): NameNode | null;
namedFunctionExportName(node: ts.FunctionDeclaration): ts.Identifier | null;
scalarTypeAliasDeclaration(node: ts.TypeAliasDeclaration, tag: ts.JSDocTag): null | undefined;
inputTypeAliasDeclaration(node: ts.TypeAliasDeclaration, tag: ts.JSDocTag): null | undefined;
collectInputFields(node: ts.TypeAliasDeclaration): Array<InputValueDefinitionNode> | null;
collectInputField(node: ts.PropertySignature): InputValueDefinitionNode | null;
typeClassDeclaration(node: ts.ClassDeclaration, tag: ts.JSDocTag): null | undefined;
typeInterfaceDeclaration(node: ts.InterfaceDeclaration, tag: ts.JSDocTag): null | undefined;
typeTypeAliasDeclaration(node: ts.TypeAliasDeclaration, tag: ts.JSDocTag): null | undefined;
checkForTypenameProperty(node: ts.ClassDeclaration | ts.InterfaceDeclaration | ts.TypeLiteralNode, expectedName: string): void;
isValidTypeNameProperty(member: ts.ClassElement | ts.TypeElement, expectedName: string): boolean;
isValidTypenamePropertyDeclaration(node: ts.PropertyDeclaration, expectedName: string): boolean;
isValidTypenamePropertySignature(node: ts.PropertySignature, expectedName: string): boolean;
isValidTypenamePropertyType(node: ts.TypeNode, expectedName: string): boolean;
collectInterfaces(node: ts.ClassDeclaration | ts.InterfaceDeclaration | ts.TypeAliasDeclaration): Array<NamedTypeNode> | null;
reportTagInterfaces(node: ts.TypeAliasDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration): null | undefined;
collectHeritageInterfaces(node: ts.ClassDeclaration | ts.InterfaceDeclaration): Array<NamedTypeNode> | null;
symbolHasGqlTag(node: ts.Node): boolean;
hasGqlTag(node: ts.Node): boolean;
interfaceInterfaceDeclaration(node: ts.InterfaceDeclaration, tag: ts.JSDocTag): null | undefined;
collectFields(node: ts.ClassDeclaration | ts.InterfaceDeclaration | ts.TypeLiteralNode): Array<FieldDefinitionNode>;
constructorParam(node: ts.ParameterDeclaration): FieldDefinitionNode | null;
collectArgs(argsParam: ts.ParameterDeclaration): ReadonlyArray<InputValueDefinitionNode> | null;
collectArgDefaults(node: ts.ObjectBindingPattern): ArgDefaults;
collectConstValue(node: ts.Expression): ConstValueNode | null;
collectArrayLiteral(node: ts.ArrayLiteralExpression): ConstListValueNode | null;
collectObjectLiteral(node: ts.ObjectLiteralExpression): ConstObjectValueNode | null;
collectObjectField(node: ts.ObjectLiteralElementLike): ConstObjectFieldNode | null;
collectArg(node: ts.TypeElement, defaults?: Map<string, ts.Expression> | null): InputValueDefinitionNode | null;
enumEnumDeclaration(node: ts.EnumDeclaration, tag: ts.JSDocTag): void;
enumTypeAliasDeclaration(node: ts.TypeAliasDeclaration, tag: ts.JSDocTag): void;
enumTypeAliasVariants(node: ts.TypeAliasDeclaration): EnumValueDefinitionNode[] | null;
collectEnumValues(node: ts.EnumDeclaration): ReadonlyArray<EnumValueDefinitionNode>;
entityName(node: ts.ClassDeclaration | ts.MethodDeclaration | ts.MethodSignature | ts.PropertyDeclaration | ts.InterfaceDeclaration | ts.PropertySignature | ts.EnumDeclaration | ts.TypeAliasDeclaration | ts.FunctionDeclaration | ts.ParameterDeclaration, tag: ts.JSDocTag): NameNode | null;
validateContextParameter(node: ts.ParameterDeclaration): null | undefined;
methodDeclaration(node: ts.MethodDeclaration | ts.MethodSignature): FieldDefinitionNode | null;
collectMethodType(node: ts.TypeNode): TypeNode | null;
collectPropertyType(node: ts.TypeNode): TypeNode | null;
maybeUnwrapePromise(node: ts.TypeNode): ts.TypeNode | null;
collectDescription(node: ts.Node): StringValueNode | null;
collectDeprecated(node: ts.Node): ConstDirectiveNode | null;
property(node: ts.PropertyDeclaration | ts.PropertySignature): FieldDefinitionNode | null;
collectType(node: ts.TypeNode): TypeNode | null;
typeReference(node: ts.TypeReferenceNode): TypeNode | null;
isNullish(node: ts.Node): boolean;
expectIdentifier(node: ts.Node): ts.Identifier | null;
findTag(node: ts.Node, tagName: string): ts.JSDocTag | null;
handleErrorBubbling(parentNode: ts.Node, type: TypeNode): TypeNode;
exportDirective(nameNode: ts.Node, filename: string, functionName: string): ConstDirectiveNode;
fieldNameDirective(nameNode: ts.Node, name: string): ConstDirectiveNode;
}
export {};
export declare function extract(options: ConfigOptions, sourceFile: ts.SourceFile): DiagnosticsResult<ExtractionSnapshot>;

@@ -29,4 +29,4 @@ "use strict";

};
exports.__esModule = true;
exports.Extractor = exports.ALL_TAGS = exports.KILLS_PARENT_ON_EXCEPTION_TAG = exports.IMPLEMENTS_TAG_DEPRECATED = 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;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extract = exports.ALL_TAGS = exports.KILLS_PARENT_ON_EXCEPTION_TAG = exports.IMPLEMENTS_TAG_DEPRECATED = 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,3 +39,3 @@ var DiagnosticError_1 = require("./utils/DiagnosticError");

var GraphQLConstructor_1 = require("./GraphQLConstructor");
var serverDirectives_1 = require("./serverDirectives");
var gratsRoot_1 = require("./gratsRoot");
exports.LIBRARY_IMPORT_NAME = "grats";

@@ -64,2 +64,3 @@ exports.LIBRARY_NAME = "Grats";

var DEPRECATED_TAG = "deprecated";
var OPERATION_TYPES = new Set(["Query", "Mutation", "Subscription"]);
/**

@@ -75,11 +76,26 @@ * Extracts GraphQL definitions from TypeScript source code.

*/
function extract(options, sourceFile) {
var extractor = new Extractor(options);
return extractor.extract(sourceFile);
}
exports.extract = extract;
var Extractor = /** @class */ (function () {
function Extractor(sourceFile, ctx, buildOptions) {
function Extractor(buildOptions) {
this.definitions = [];
// Snapshot data
this.unresolvedNames = new Map();
this.nameDefinitions = new Map();
this.contextReferences = [];
this.typesWithTypenameField = new Set();
this.interfaceDeclarations = [];
this.errors = [];
this.sourceFile = sourceFile;
this.ctx = ctx;
this.configOptions = buildOptions;
this.gql = new GraphQLConstructor_1.GraphQLConstructor(sourceFile);
this.gql = new GraphQLConstructor_1.GraphQLConstructor();
}
Extractor.prototype.markUnresolvedType = function (node, name) {
this.unresolvedNames.set(node, name);
};
Extractor.prototype.recordTypeName = function (node, name, kind) {
this.nameDefinitions.set(node, { name: name, kind: kind });
};
// Traverse all nodes, checking each one for its JSDoc tags.

@@ -89,5 +105,5 @@ // If we find a tag we recognize, we extract the relevant information,

// supported.
Extractor.prototype.extract = function () {
Extractor.prototype.extract = function (sourceFile) {
var _this = this;
(0, JSDoc_1.traverseJSDocTags)(this.sourceFile, function (node, tag) {
(0, JSDoc_1.traverseJSDocTags)(sourceFile, function (node, tag) {
var e_1, _a;

@@ -152,3 +168,3 @@ switch (tag.tagName.text) {

try {
if (ALL_TAGS_1_1 && !ALL_TAGS_1_1.done && (_a = ALL_TAGS_1["return"])) _a.call(ALL_TAGS_1);
if (ALL_TAGS_1_1 && !ALL_TAGS_1_1.done && (_a = ALL_TAGS_1.return)) _a.call(ALL_TAGS_1);
}

@@ -166,3 +182,10 @@ finally { if (e_1) throw e_1.error; }

}
return (0, DiagnosticError_1.ok)(this.definitions);
return (0, DiagnosticError_1.ok)({
definitions: this.definitions,
unresolvedNames: this.unresolvedNames,
nameDefinitions: this.nameDefinitions,
contextReferences: this.contextReferences,
typesWithTypenameField: this.typesWithTypenameField,
interfaceDeclarations: this.interfaceDeclarations,
});
};

@@ -228,13 +251,3 @@ Extractor.prototype.extractType = function (node, tag) {

Extractor.prototype.report = function (node, message, relatedInformation) {
var start = node.getStart();
var length = node.getEnd() - start;
this.errors.push({
messageText: message,
file: this.sourceFile,
code: DiagnosticError_1.FAKE_ERROR_CODE,
category: ts.DiagnosticCategory.Error,
start: start,
length: length,
relatedInformation: relatedInformation
});
this.errors.push((0, DiagnosticError_1.tsErr)(node, message, relatedInformation));
return null;

@@ -249,17 +262,2 @@ };

};
Extractor.prototype.related = function (node, message) {
return {
category: ts.DiagnosticCategory.Message,
code: 0,
file: node.getSourceFile(),
start: node.getStart(),
length: node.getWidth(),
messageText: message
};
};
Extractor.prototype.diagnosticAnnotatedLocation = function (node) {
var start = node.getStart();
var end = node.getEnd();
return { start: start, length: end - start, filepath: this.sourceFile };
};
/** TypeScript traversals */

@@ -274,3 +272,3 @@ Extractor.prototype.unionTypeAliasDeclaration = function (node, tag) {

}
var description = this.collectDescription(node.name);
var description = this.collectDescription(node);
var types = [];

@@ -284,3 +282,3 @@ try {

var namedType = this.gql.namedType(member.typeName, TypeContext_1.UNRESOLVED_REFERENCE_NAME);
this.ctx.markUnresolvedType(member.typeName, namedType.name);
this.markUnresolvedType(member.typeName, namedType.name);
types.push(namedType);

@@ -292,7 +290,7 @@ }

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_2) throw e_2.error; }
}
this.ctx.recordTypeName(node.name, name, "UNION");
this.recordTypeName(node.name, name, "UNION");
this.definitions.push(this.gql.unionTypeDefinition(node, name, types, description));

@@ -317,5 +315,6 @@ };

}
var type = this.collectMethodType(node.type);
if (type == null)
var returnType = this.collectReturnType(node.type);
if (returnType == null)
return null;
var type = returnType.type, isStream = returnType.isStream;
var args = null;

@@ -330,3 +329,3 @@ var argsParam = node.parameters[1];

}
var description = this.collectDescription(funcName);
var description = this.collectDescription(node);
if (!ts.isSourceFile(node.parent)) {

@@ -336,8 +335,12 @@ return this.report(node, E.functionFieldNotTopLevel());

// TODO: Does this work in the browser?
var filename = this.ctx.getDestFilePath(node.parent);
var tsModulePath = (0, gratsRoot_1.relativePath)(node.getSourceFile().fileName);
var directives = [
this.exportDirective(funcName, filename, funcName.text),
this.gql.exportedDirective(funcName, {
tsModulePath: tsModulePath,
exportedFunctionName: funcName.text,
argCount: node.parameters.length,
}),
];
if (funcName.text !== name.value) {
directives.push(this.fieldNameDirective(funcName, funcName.text));
if (isStream) {
directives.push(this.gql.asyncIterableDirective(node.type));
}

@@ -360,3 +363,3 @@ var deprecated = this.collectDeprecated(node);

var typeName = this.gql.name(nameNode, TypeContext_1.UNRESOLVED_REFERENCE_NAME);
this.ctx.markUnresolvedType(nameNode, typeName);
this.markUnresolvedType(nameNode, typeName);
return typeName;

@@ -388,4 +391,4 @@ };

return null;
var description = this.collectDescription(node.name);
this.ctx.recordTypeName(node.name, name, "SCALAR");
var description = this.collectDescription(node);
this.recordTypeName(node.name, name, "SCALAR");
this.definitions.push(this.gql.scalarTypeDefinition(node, name, description));

@@ -397,4 +400,4 @@ };

return null;
var description = this.collectDescription(node.name);
this.ctx.recordTypeName(node.name, name, "INPUT_OBJECT");
var description = this.collectDescription(node);
this.recordTypeName(node.name, name, "INPUT_OBJECT");
var fields = this.collectInputFields(node);

@@ -425,3 +428,3 @@ var deprecatedDirective = this.collectDeprecated(node);

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -443,3 +446,3 @@ finally { if (e_3) throw e_3.error; }

var type = node.questionToken == null ? inner : this.gql.nullableType(inner);
var description = this.collectDescription(node.name);
var description = this.collectDescription(node);
var deprecatedDirective = this.collectDeprecated(node);

@@ -455,9 +458,17 @@ return this.gql.inputValueDefinition(node, this.gql.name(id, id.text), type, deprecatedDirective == null ? null : [deprecatedDirective], null, description);

return null;
var description = this.collectDescription(node.name);
this.validateOperationTypes(node.name, name.value);
var description = this.collectDescription(node);
var fields = this.collectFields(node);
var interfaces = this.collectInterfaces(node);
this.ctx.recordTypeName(node.name, name, "TYPE");
this.recordTypeName(node.name, name, "TYPE");
this.checkForTypenameProperty(node, name.value);
this.definitions.push(this.gql.objectTypeDefinition(node, name, fields, interfaces, description));
};
Extractor.prototype.validateOperationTypes = function (node, name) {
// TODO: If we start supporting defining operation types using
// non-standard names, we will need to update this logic.
if (OPERATION_TYPES.has(name)) {
this.report(node, E.operationTypeNotUnknown());
}
};
Extractor.prototype.typeInterfaceDeclaration = function (node, tag) {

@@ -467,6 +478,7 @@ var name = this.entityName(node, tag);

return null;
var description = this.collectDescription(node.name);
this.validateOperationTypes(node.name, name.value);
var description = this.collectDescription(node);
var fields = this.collectFields(node);
var interfaces = this.collectInterfaces(node);
this.ctx.recordTypeName(node.name, name, "INTERFACE");
this.recordTypeName(node.name, name, "INTERFACE");
this.checkForTypenameProperty(node, name.value);

@@ -482,2 +494,3 @@ this.definitions.push(this.gql.objectTypeDefinition(node, name, fields, interfaces, description));

if (ts.isTypeLiteralNode(node.type)) {
this.validateOperationTypes(node.type, name.value);
fields = this.collectFields(node.type);

@@ -495,4 +508,4 @@ interfaces = this.collectInterfaces(node);

}
var description = this.collectDescription(node.name);
this.ctx.recordTypeName(node.name, name, "TYPE");
var description = this.collectDescription(node);
this.recordTypeName(node.name, name, "TYPE");
this.definitions.push(this.gql.objectTypeDefinition(node, name, fields, interfaces, description));

@@ -506,3 +519,3 @@ };

if (hasTypename) {
this.ctx.recordHasTypenameField(expectedName);
this.typesWithTypenameField.add(expectedName);
}

@@ -601,6 +614,5 @@ };

.filter(function (expression) { return ts.isIdentifier(expression); })
.filter(function (expression) { return _this.symbolHasGqlTag(expression); })
.map(function (expression) {
var namedType = _this.gql.namedType(expression, TypeContext_1.UNRESOLVED_REFERENCE_NAME);
_this.ctx.markUnresolvedType(expression, namedType.name);
_this.markUnresolvedType(expression, namedType.name);
return namedType;

@@ -615,11 +627,2 @@ });

};
Extractor.prototype.symbolHasGqlTag = function (node) {
var symbol = this.ctx.checker.getSymbolAtLocation(node);
if (symbol == null)
return false;
var declaration = this.ctx.findSymbolDeclaration(symbol);
if (declaration == null)
return false;
return this.hasGqlTag(declaration);
};
Extractor.prototype.hasGqlTag = function (node) {

@@ -631,3 +634,2 @@ return ts.getJSDocTags(node).some(function (tag) {

Extractor.prototype.interfaceInterfaceDeclaration = function (node, tag) {
var _this = this;
var name = this.entityName(node, tag);

@@ -637,23 +639,7 @@ if (name == null || name.value == null) {

}
// Prevent using merged interfaces as GraphQL interfaces.
// https://www.typescriptlang.org/docs/handbook/declaration-merging.html#merging-interfaces
var symbol = this.ctx.checker.getSymbolAtLocation(node.name);
if (symbol != null &&
symbol.declarations != null &&
symbol.declarations.length > 1) {
var otherLocations = symbol.declarations
.filter(function (d) { return d !== node && ts.isInterfaceDeclaration(d); })
.map(function (d) {
var _a;
var locNode = (_a = ts.getNameOfDeclaration(d)) !== null && _a !== void 0 ? _a : d;
return _this.related(locNode, "Other declaration");
});
if (otherLocations.length > 0) {
return this.report(node.name, E.mergedInterfaces(name.value), otherLocations);
}
}
var description = this.collectDescription(node.name);
this.interfaceDeclarations.push(node);
var description = this.collectDescription(node);
var interfaces = this.collectInterfaces(node);
var fields = this.collectFields(node);
this.ctx.recordTypeName(node.name, name, "INTERFACE");
this.recordTypeName(node.name, name, "INTERFACE");
this.definitions.push(this.gql.interfaceTypeDefinition(node, name, fields, interfaces, description));

@@ -681,3 +667,3 @@ };

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -741,3 +727,5 @@ finally { if (e_4) throw e_4.error; }

if (id.text !== name.value) {
directives = [this.fieldNameDirective(node.name, id.text)];
directives = [
this.gql.propertyNameDirective(node.name, { name: id.text }),
];
}

@@ -751,3 +739,3 @@ var type = this.collectType(node.type);

}
var description = this.collectDescription(node.name);
var description = this.collectDescription(node);
return this.gql.fieldDefinition(node, name, this.handleErrorBubbling(node, type), null, directives, description);

@@ -784,3 +772,3 @@ };

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -807,3 +795,3 @@ finally { if (e_5) throw e_5.error; }

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -824,3 +812,3 @@ finally { if (e_6) throw e_6.error; }

else if (this.isNullish(node)) {
return this.gql["null"](node);
return this.gql.null(node);
}

@@ -860,3 +848,3 @@ else if (node.kind === ts.SyntaxKind.TrueKeyword) {

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -889,3 +877,3 @@ finally { if (e_7) throw e_7.error; }

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -933,12 +921,20 @@ finally { if (e_8) throw e_8.error; }

return null;
if (type.kind !== graphql_1.Kind.NON_NULL_TYPE && !node.questionToken) {
// If a field is passed an argument value, and that argument is not defined in the request,
// `graphql-js` will not define the argument property. Therefore we must ensure the argument
// is not just nullable, but optional.
return this.report(node.name, E.expectedNullableArgumentToBeOptional());
}
if (node.questionToken) {
/*
// TODO: Don't allow args that are optional but don't accept null
if (type.kind === Kind.NON_NULL_TYPE) {
return this.report(node.questionToken, E.nonNullTypeCannotBeOptional());
// Question mark means we can handle the argument being undefined in the
// object literal, but if we are going to type the GraphQL arg as
// optional, the code must also be able to handle an explicit null.
//
// TODO: This will catch { a?: string } but not { a?: string | undefined }.
if (type.kind === graphql_1.Kind.NON_NULL_TYPE) {
return this.report(node.questionToken, E.nonNullTypeCannotBeOptional());
}
*/
type = this.gql.nullableType(type);
}
var description = this.collectDescription(node.name);
var description = this.collectDescription(node);
var defaultValue = null;

@@ -959,5 +955,5 @@ if (defaults != null) {

}
var description = this.collectDescription(node.name);
var description = this.collectDescription(node);
var values = this.collectEnumValues(node);
this.ctx.recordTypeName(node.name, name, "ENUM");
this.recordTypeName(node.name, name, "ENUM");
this.definitions.push(this.gql.enumTypeDefinition(node, name, values, description));

@@ -973,4 +969,4 @@ };

return;
var description = this.collectDescription(node.name);
this.ctx.recordTypeName(node.name, name, "ENUM");
var description = this.collectDescription(node);
this.recordTypeName(node.name, name, "ENUM");
this.definitions.push(this.gql.enumTypeDefinition(node, name, values, description));

@@ -980,3 +976,2 @@ };

var e_9, _a;
var _b;
// Semantically we only support deriving enums from type aliases that

@@ -999,23 +994,4 @@ // are unions of string literals. However, in the edge case of a union

try {
for (var _c = __values(node.type.types), _d = _c.next(); !_d.done; _d = _c.next()) {
var member = _d.value;
// TODO: Complete this feature
if (ts.isTypeReferenceNode(member)) {
if (member.typeName.kind === ts.SyntaxKind.Identifier) {
var symbol = this.ctx.checker.getSymbolAtLocation(member.typeName);
if (((_b = symbol === null || symbol === void 0 ? void 0 : symbol.declarations) === null || _b === void 0 ? void 0 : _b.length) === 1) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var declaration = symbol.declarations[0];
if (ts.isTypeAliasDeclaration(declaration)) {
if (ts.isLiteralTypeNode(declaration.type) &&
ts.isStringLiteral(declaration.type.literal)) {
var deprecatedDirective = this.collectDeprecated(declaration);
var memberDescription = this.collectDescription(declaration.name);
values.push(this.gql.enumValueDefinition(node, this.gql.name(declaration.type.literal, declaration.type.literal.text), deprecatedDirective ? [deprecatedDirective] : [], memberDescription));
continue;
}
}
}
}
}
for (var _b = __values(node.type.types), _c = _b.next(); !_c.done; _c = _b.next()) {
var member = _c.value;
if (!ts.isLiteralTypeNode(member) ||

@@ -1034,3 +1010,3 @@ !ts.isStringLiteral(member.literal)) {

try {
if (_d && !_d.done && (_a = _c["return"])) _a.call(_c);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -1052,3 +1028,3 @@ finally { if (e_9) throw e_9.error; }

}
var description = this.collectDescription(member.name);
var description = this.collectDescription(member);
var deprecated = this.collectDeprecated(member);

@@ -1061,3 +1037,3 @@ values.push(this.gql.enumValueDefinition(member, this.gql.name(member.initializer, member.initializer.text), deprecated ? [deprecated] : undefined, description));

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -1073,3 +1049,24 @@ finally { if (e_10) throw e_10.error; }

// FIXME: Use the _value_'s location not the tag's
return this.gql.name(tag, commentName);
var locNode = tag;
// Test for leading newlines using the raw text
var hasLeadingNewlines = /\n/.test(trimTrailingCommentLines(tag.getText()));
var hasInternalWhitespace = /\s/.test(commentName);
var validationMessage = graphQLNameValidationMessage(commentName);
if (hasLeadingNewlines && validationMessage == null) {
// TODO: Offer quick fix.
return this.report(locNode, E.graphQLNameHasLeadingNewlines(commentName, tag.tagName.text));
}
if (hasLeadingNewlines || hasInternalWhitespace) {
return this.report(locNode, E.graphQLTagNameHasWhitespace(tag.tagName.text));
}
// No whitespace, but still invalid. We will assume they meant this to
// be a GraphQL name but didn't provide a valid identifier.
//
// NOTE: We can't let GraphQL validation handle this, because it throws rather
// than returning a validation message. Presumably because it expects token
// validation to be done during lexing/parsing.
if (validationMessage !== null) {
return this.report(locNode, validationMessage);
}
return this.gql.name(locNode, commentName);
}

@@ -1103,22 +1100,3 @@ }

}
var symbol = this.ctx.checker.getSymbolAtLocation(node.type.typeName);
if (symbol == null) {
return this.report(node.type.typeName, E.expectedTypeAnnotationOnContextToBeResolvable());
}
var declaration = this.ctx.findSymbolDeclaration(symbol);
if (declaration == null) {
return this.report(node.type.typeName, E.expectedTypeAnnotationOnContextToHaveDeclaration());
}
if (this.ctx.gqlContext == null) {
// This is the first typed context value we've seen...
this.ctx.gqlContext = {
declaration: declaration,
firstReference: node.type.typeName
};
}
else if (this.ctx.gqlContext.declaration !== declaration) {
return this.report(node.type.typeName, E.multipleContextTypes(), [
this.related(this.ctx.gqlContext.firstReference, "A different type reference was used here"),
]);
}
this.contextReferences.push(node.type.typeName);
};

@@ -1135,3 +1113,6 @@ Extractor.prototype.methodDeclaration = function (node) {

}
var type = this.collectMethodType(node.type);
var returnType = this.collectReturnType(node.type);
if (returnType == null)
return null;
var type = returnType.type, isStream = returnType.isStream;
// We already reported an error

@@ -1149,3 +1130,3 @@ if (type == null)

}
var description = this.collectDescription(node.name);
var description = this.collectDescription(node);
var id = this.expectIdentifier(node.name);

@@ -1156,4 +1137,9 @@ if (id == null)

if (id.text !== name.value) {
directives = [this.fieldNameDirective(node.name, id.text)];
directives = [
this.gql.propertyNameDirective(node.name, { name: id.text }),
];
}
if (isStream) {
directives.push(this.gql.asyncIterableDirective(node.type));
}
var deprecated = this.collectDeprecated(node);

@@ -1165,11 +1151,29 @@ if (deprecated != null) {

};
Extractor.prototype.collectMethodType = function (node) {
var inner = this.maybeUnwrapePromise(node);
Extractor.prototype.collectReturnType = function (node) {
if (ts.isTypeReferenceNode(node)) {
var identifier = this.expectIdentifier(node.typeName);
if (identifier == null)
return null;
if (identifier.text == "AsyncIterable") {
if (node.typeArguments == null || node.typeArguments.length === 0) {
// TODO: Better error?
return this.report(node, E.promiseMissingTypeArg());
}
var t_1 = this.collectType(node.typeArguments[0]);
if (t_1 == null)
return null;
return { type: t_1, isStream: true };
}
}
var inner = this.maybeUnwrapPromise(node);
if (inner == null)
return null;
return this.collectType(inner);
var t = this.collectType(inner);
if (t == null)
return null;
return { type: t, isStream: false };
};
Extractor.prototype.collectPropertyType = function (node) {
// TODO: Handle function types here.
var inner = this.maybeUnwrapePromise(node);
var inner = this.maybeUnwrapPromise(node);
if (inner == null)

@@ -1179,3 +1183,3 @@ return null;

};
Extractor.prototype.maybeUnwrapePromise = function (node) {
Extractor.prototype.maybeUnwrapPromise = function (node) {
if (ts.isTypeReferenceNode(node)) {

@@ -1186,3 +1190,3 @@ var identifier = this.expectIdentifier(node.typeName);

if (identifier.text === "Promise") {
if (node.typeArguments == null) {
if (node.typeArguments == null || node.typeArguments.length === 0) {
return this.report(node, E.promiseMissingTypeArg());

@@ -1196,11 +1200,12 @@ }

Extractor.prototype.collectDescription = function (node) {
var symbol = this.ctx.checker.getSymbolAtLocation(node);
if (symbol == null) {
return this.report(node, E.cannotResolveSymbolForDescription());
var docs =
// @ts-ignore Exposed as stable in https://github.com/microsoft/TypeScript/pull/53627
ts.getJSDocCommentsAndTags(node);
var comment = docs
.filter(function (doc) { return doc.kind === ts.SyntaxKind.JSDoc; })
.map(function (doc) { return doc.comment; })
.join("");
if (comment) {
return this.gql.string(node, comment.trim(), true);
}
var doc = symbol.getDocumentationComment(this.ctx.checker);
var description = ts.displayPartsToString(doc);
if (description) {
return this.gql.string(node, description, true);
}
return null;

@@ -1238,3 +1243,3 @@ };

var type = node.questionToken == null ? inner : this.gql.nullableType(inner);
var description = this.collectDescription(node.name);
var description = this.collectDescription(node);
var directives = [];

@@ -1249,3 +1254,5 @@ var id = this.expectIdentifier(node.name);

if (id.text !== name.value) {
directives = [this.fieldNameDirective(node.name, id.text)];
directives = [
this.gql.propertyNameDirective(node.name, { name: id.text }),
];
}

@@ -1282,3 +1289,3 @@ return this.gql.fieldDefinition(node, name, this.handleErrorBubbling(node, type), null, directives, description);

var incompatibleVariants = rest.map(function (tsType) {
return _this.related(tsType, "Other non-nullish type");
return (0, DiagnosticError_1.tsRelated)(tsType, "Other non-nullish type");
});

@@ -1335,3 +1342,3 @@ this.report(first, E.expectedOneNonNullishType(), incompatibleVariants);

var namedType = this.gql.namedType(node, TypeContext_1.UNRESOLVED_REFERENCE_NAME);
this.ctx.markUnresolvedType(node.typeName, namedType.name);
this.markUnresolvedType(node.typeName, namedType.name);
return this.gql.nonNullType(node, namedType);

@@ -1360,3 +1367,2 @@ }

Extractor.prototype.findTag = function (node, tagName) {
var _this = this;
var tags = ts

@@ -1370,3 +1376,3 @@ .getJSDocTags(node)

var additionalTags = tags.slice(1).map(function (tag) {
return _this.related(tag, "Additional tag");
return (0, DiagnosticError_1.tsRelated)(tag, "Additional tag");
});

@@ -1381,3 +1387,3 @@ var message = tagName === exports.IMPLEMENTS_TAG_DEPRECATED

// It is a GraphQL best practice to model all fields as nullable. This allows
// the server to handle field level exections by simply returning null for
// the server to handle field level executions by simply returning null for
// that field.

@@ -1402,16 +1408,17 @@ // https://graphql.org/learn/best-practices/#nullability

};
/* Grats directives */
Extractor.prototype.exportDirective = function (nameNode, filename, functionName) {
return this.gql.constDirective(nameNode, this.gql.name(nameNode, serverDirectives_1.EXPORTED_DIRECTIVE), [
this.gql.constArgument(nameNode, this.gql.name(nameNode, serverDirectives_1.EXPORTED_FILENAME_ARG), this.gql.string(nameNode, filename)),
this.gql.constArgument(nameNode, this.gql.name(nameNode, serverDirectives_1.EXPORTED_FUNCTION_NAME_ARG), this.gql.string(nameNode, functionName)),
]);
};
Extractor.prototype.fieldNameDirective = function (nameNode, name) {
return this.gql.constDirective(nameNode, this.gql.name(nameNode, serverDirectives_1.METHOD_NAME_DIRECTIVE), [
this.gql.constArgument(nameNode, this.gql.name(nameNode, serverDirectives_1.METHOD_NAME_ARG), this.gql.string(nameNode, name)),
]);
};
return Extractor;
}());
exports.Extractor = Extractor;
function graphQLNameValidationMessage(name) {
try {
(0, graphql_1.assertName)(name);
return null;
}
catch (e) {
return e.message;
}
}
// Trims any number of whitespace-only lines including any lines that simply
// contain a `*` surrounded by whitespace.
function trimTrailingCommentLines(text) {
return text.replace(/(\s*\n\s*\*?\s*)+$/, "");
}

@@ -1,7 +0,15 @@

import { ListTypeNode, NamedTypeNode, Location as GraphQLLocation, NameNode, Token, TypeNode, NonNullTypeNode, StringValueNode, ConstValueNode, ConstDirectiveNode, ConstArgumentNode, UnionTypeDefinitionNode, FieldDefinitionNode, InputValueDefinitionNode, FloatValueNode, IntValueNode, NullValueNode, BooleanValueNode, ConstListValueNode, ConstObjectValueNode, ConstObjectFieldNode, ObjectTypeDefinitionNode, EnumValueDefinitionNode, ScalarTypeDefinitionNode, InputObjectTypeDefinitionNode, EnumTypeDefinitionNode, InterfaceTypeDefinitionNode } from "graphql";
import { ListTypeNode, NamedTypeNode, Location as GraphQLLocation, NameNode, Token, TypeNode, NonNullTypeNode, StringValueNode, ConstValueNode, ConstDirectiveNode, ConstArgumentNode, UnionTypeDefinitionNode, FieldDefinitionNode, InputValueDefinitionNode, FloatValueNode, IntValueNode, NullValueNode, BooleanValueNode, ConstListValueNode, ConstObjectValueNode, ConstObjectFieldNode, ObjectTypeDefinitionNode, EnumValueDefinitionNode, ScalarTypeDefinitionNode, InputObjectTypeDefinitionNode, EnumTypeDefinitionNode, InterfaceTypeDefinitionNode, DefinitionNode, Location } from "graphql";
import * as ts from "typescript";
import { AbstractFieldDefinitionNode } from "./TypeContext";
import { ExportedMetadata, PropertyNameMetadata } from "./metadataDirectives";
export type GratsDefinitionNode = DefinitionNode | AbstractFieldDefinitionNode;
export type AbstractFieldDefinitionNode = {
readonly kind: "AbstractFieldDefinition";
readonly loc: Location;
readonly onType: NameNode;
readonly field: FieldDefinitionNode;
};
export declare class GraphQLConstructor {
sourceFile: ts.SourceFile;
constructor(sourceFile: ts.SourceFile);
exportedDirective(node: ts.Node, exported: ExportedMetadata): ConstDirectiveNode;
propertyNameDirective(node: ts.Node, propertyName: PropertyNameMetadata): ConstDirectiveNode;
asyncIterableDirective(node: ts.Node): ConstDirectiveNode;
unionTypeDefinition(node: ts.Node, name: NameNode, types: NamedTypeNode[], description: StringValueNode | null): UnionTypeDefinitionNode;

@@ -34,3 +42,3 @@ objectTypeDefinition(node: ts.Node, name: NameNode, fields: FieldDefinitionNode[], interfaces: NamedTypeNode[] | null, description: StringValueNode | null): ObjectTypeDefinitionNode;

_loc(node: ts.Node): GraphQLLocation;
_dummyToken(pos: number): Token;
_dummyToken(sourceFile: ts.SourceFile, pos: number): Token;
}
"use strict";
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GraphQLConstructor = void 0;
var graphql_1 = require("graphql");
var metadataDirectives_1 = require("./metadataDirectives");
var GraphQLConstructor = /** @class */ (function () {
function GraphQLConstructor(sourceFile) {
this.sourceFile = sourceFile;
function GraphQLConstructor() {
}
/* Metadata Directives */
GraphQLConstructor.prototype.exportedDirective = function (node, exported) {
return (0, metadataDirectives_1.makeExportedDirective)(this._loc(node), exported);
};
GraphQLConstructor.prototype.propertyNameDirective = function (node, propertyName) {
return (0, metadataDirectives_1.makePropertyNameDirective)(this._loc(node), propertyName);
};
GraphQLConstructor.prototype.asyncIterableDirective = function (node) {
return (0, metadataDirectives_1.makeAsyncIterableDirective)(this._loc(node));
};
/* Top Level Types */

@@ -16,3 +26,3 @@ GraphQLConstructor.prototype.unionTypeDefinition = function (node, name, types, description) {

name: name,
types: types
types: types,
};

@@ -28,3 +38,3 @@ };

fields: fields,
interfaces: interfaces !== null && interfaces !== void 0 ? interfaces : undefined
interfaces: interfaces !== null && interfaces !== void 0 ? interfaces : undefined,
};

@@ -40,3 +50,3 @@ };

fields: fields,
interfaces: interfaces !== null && interfaces !== void 0 ? interfaces : undefined
interfaces: interfaces !== null && interfaces !== void 0 ? interfaces : undefined,
};

@@ -50,3 +60,3 @@ };

name: name,
values: values
values: values,
};

@@ -60,3 +70,3 @@ };

onType: onType,
field: field
field: field,
};

@@ -73,3 +83,3 @@ };

arguments: args !== null && args !== void 0 ? args : undefined,
directives: this._optionalList(directives)
directives: this._optionalList(directives),
};

@@ -88,3 +98,3 @@ };

defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : undefined,
directives: this._optionalList(directives)
directives: this._optionalList(directives),
};

@@ -98,3 +108,3 @@ };

name: name,
directives: directives
directives: directives,
};

@@ -108,3 +118,3 @@ };

name: name,
directives: undefined
directives: undefined,
};

@@ -119,3 +129,3 @@ };

fields: fields !== null && fields !== void 0 ? fields : undefined,
directives: this._optionalList(directives)
directives: this._optionalList(directives),
};

@@ -131,3 +141,3 @@ };

loc: this._loc(node),
name: this.name(node, value)
name: this.name(node, value),
};

@@ -166,3 +176,3 @@ };

name: name,
arguments: this._optionalList(args)
arguments: this._optionalList(args),
};

@@ -179,3 +189,3 @@ };

};
GraphQLConstructor.prototype["null"] = function (node) {
GraphQLConstructor.prototype.null = function (node) {
return { kind: graphql_1.Kind.NULL, loc: this._loc(node) };

@@ -196,9 +206,10 @@ };

GraphQLConstructor.prototype._loc = function (node) {
var source = new graphql_1.Source(this.sourceFile.text, this.sourceFile.fileName);
var startToken = this._dummyToken(node.getStart());
var endToken = this._dummyToken(node.getEnd());
var sourceFile = node.getSourceFile();
var source = new graphql_1.Source(sourceFile.text, sourceFile.fileName);
var startToken = this._dummyToken(sourceFile, node.getStart());
var endToken = this._dummyToken(sourceFile, node.getEnd());
return new graphql_1.Location(startToken, endToken, source);
};
GraphQLConstructor.prototype._dummyToken = function (pos) {
var _a = this.sourceFile.getLineAndCharacterOfPosition(pos), line = _a.line, character = _a.character;
GraphQLConstructor.prototype._dummyToken = function (sourceFile, pos) {
var _a = sourceFile.getLineAndCharacterOfPosition(pos), line = _a.line, character = _a.character;
return new graphql_1.Token(graphql_1.TokenKind.SOF, pos, pos, line, character, undefined);

@@ -205,0 +216,0 @@ };

@@ -1,3 +0,2 @@

import * as ts from "typescript";
export declare function getRelativeOutputPath(options: ts.ParsedCommandLine, sourceFile: ts.SourceFile): string;
export declare function relativePath(absolute: string): string;
export declare function resolveRelativePath(relativePath: string): string;
"use strict";
exports.__esModule = true;
exports.resolveRelativePath = exports.getRelativeOutputPath = void 0;
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveRelativePath = exports.relativePath = void 0;
var path_1 = require("path");
var ts = require("typescript");
// Grats parses TypeScript files and finds resolvers. If the field resolver is a

@@ -13,16 +12,7 @@ // named export, Grats needs to be able to import that file during execution.

// step and the runtime can agree on. This path is that thing.
var gratsRoot = __dirname;
function getRelativeOutputPath(options, sourceFile) {
var fileNames = ts.getOutputFileNames(options, sourceFile.fileName, true);
// ts.getOutputFileNames returns a list of files that includes both the .d.ts
// and .js files.
var jsFileNames = fileNames.filter(function (fileName) { return fileName.endsWith(".js"); });
if (jsFileNames.length !== 1) {
throw new Error("Grats: Expected ts.getOutputFileNames to return exactly one `.js` file. " +
"Found ".concat(jsFileNames.length, "}. This is a bug in Grats. I'd appreciate it if ") +
"you could open an issue.");
}
return (0, path_1.relative)(gratsRoot, fileNames[0]);
var gratsRoot = (0, path_1.join)(__dirname, "../..");
function relativePath(absolute) {
return (0, path_1.relative)(gratsRoot, absolute);
}
exports.getRelativeOutputPath = getRelativeOutputPath;
exports.relativePath = relativePath;
function resolveRelativePath(relativePath) {

@@ -29,0 +19,0 @@ return (0, path_1.resolve)(gratsRoot, relativePath);

@@ -1,10 +0,7 @@

import { GraphQLSchema } from "graphql";
import * as ts from "typescript";
import { ParsedCommandLineGrats } from "./lib";
import { ReportableDiagnostics, Result } from "./utils/DiagnosticError";
export { printSDLWithoutDirectives } from "./printSchema";
export * from "./Types";
export * from "./lib";
type RuntimeOptions = {
emitSchemaFile?: string;
};
export declare function extractGratsSchemaAtRuntime(runtimeOptions: RuntimeOptions): GraphQLSchema;
export declare function buildSchemaFromSDL(sdl: string): GraphQLSchema;
export declare function getParsedTsConfig(configPath?: string): ts.ParsedCommandLine;
export { codegen } from "./codegen";
export declare function getParsedTsConfig(configFile: string): Result<ParsedCommandLineGrats, ReportableDiagnostics>;

@@ -16,39 +16,15 @@ "use strict";

};
exports.__esModule = true;
exports.getParsedTsConfig = exports.buildSchemaFromSDL = exports.extractGratsSchemaAtRuntime = void 0;
var graphql_1 = require("graphql");
var utils_1 = require("@graphql-tools/utils");
var fs = require("fs");
Object.defineProperty(exports, "__esModule", { value: true });
exports.getParsedTsConfig = exports.codegen = exports.printSDLWithoutDirectives = void 0;
var ts = require("typescript");
var lib_1 = require("./lib");
var DiagnosticError_1 = require("./utils/DiagnosticError");
var printSchema_1 = require("./printSchema");
Object.defineProperty(exports, "printSDLWithoutDirectives", { enumerable: true, get: function () { return printSchema_1.printSDLWithoutDirectives; } });
__exportStar(require("./Types"), exports);
__exportStar(require("./lib"), exports);
// Build an executable schema from a set of files. Note that if extraction
// fails, this function will exit the process and print a helpful error
// message.
function extractGratsSchemaAtRuntime(runtimeOptions) {
var parsedTsConfig = getParsedTsConfig();
var schemaResult = (0, lib_1.buildSchemaResult)(parsedTsConfig);
if (schemaResult.kind === "ERROR") {
console.error(schemaResult.err.formatDiagnosticsWithColorAndContext());
process.exit(1);
}
var runtimeSchema = schemaResult.value;
if (runtimeOptions.emitSchemaFile) {
runtimeSchema = (0, graphql_1.lexicographicSortSchema)(runtimeSchema);
var sdl = (0, utils_1.printSchemaWithDirectives)(runtimeSchema, { assumeValid: true });
var filePath = runtimeOptions.emitSchemaFile;
fs.writeFileSync(filePath, sdl);
}
return runtimeSchema;
}
exports.extractGratsSchemaAtRuntime = extractGratsSchemaAtRuntime;
function buildSchemaFromSDL(sdl) {
var schema = (0, graphql_1.buildSchema)(sdl);
return (0, lib_1.applyServerDirectives)(schema);
}
exports.buildSchemaFromSDL = buildSchemaFromSDL;
var codegen_1 = require("./codegen");
Object.defineProperty(exports, "codegen", { enumerable: true, get: function () { return codegen_1.codegen; } });
// #FIXME: Report diagnostics instead of throwing!
function getParsedTsConfig(configPath) {
var configFile = configPath || ts.findConfigFile(process.cwd(), ts.sys.fileExists);
function getParsedTsConfig(configFile) {
if (!configFile) {

@@ -60,7 +36,10 @@ throw new Error("Grats: Could not find tsconfig.json");

var parsed = ts.getParsedCommandLineOfConfigFile(configFile, undefined, configFileHost);
if (!parsed || parsed.errors.length > 0) {
throw new Error("Grats: Could not parse tsconfig.json");
if (!parsed) {
throw new Error("Grats: Could not locate tsconfig.json");
}
return parsed;
if (parsed.errors.length > 0) {
return (0, DiagnosticError_1.err)(DiagnosticError_1.ReportableDiagnostics.fromDiagnostics(parsed.errors));
}
return (0, DiagnosticError_1.ok)((0, lib_1.validateGratsOptions)(parsed));
}
exports.getParsedTsConfig = getParsedTsConfig;

@@ -1,3 +0,3 @@

import { GratsDefinitionNode, TypeContext } from "./TypeContext";
import { DiagnosticsResult } from "./utils/DiagnosticError";
import { GratsDefinitionNode } from "./GraphQLConstructor";
import { TypeContext } from "./TypeContext";
import { DefaultMap } from "./utils/helpers";

@@ -12,2 +12,2 @@ export type InterfaceImplementor = {

*/
export declare function computeInterfaceMap(typeContext: TypeContext, docs: GratsDefinitionNode[]): DiagnosticsResult<InterfaceMap>;
export declare function computeInterfaceMap(typeContext: TypeContext, docs: GratsDefinitionNode[]): InterfaceMap;

@@ -13,5 +13,4 @@ "use strict";

};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeInterfaceMap = void 0;
var DiagnosticError_1 = require("./utils/DiagnosticError");
var helpers_1 = require("./utils/helpers");

@@ -30,3 +29,2 @@ var graphql_1 = require("graphql");

};
var errors = [];
try {

@@ -48,3 +46,3 @@ for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {

kind: "INTERFACE",
name: doc.name.value
name: doc.name.value,
});

@@ -56,3 +54,3 @@ }

try {
if (_g && !_g.done && (_b = _f["return"])) _b.call(_f);
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
}

@@ -78,3 +76,3 @@ finally { if (e_2) throw e_2.error; }

try {
if (_j && !_j.done && (_c = _h["return"])) _c.call(_h);
if (_j && !_j.done && (_c = _h.return)) _c.call(_h);
}

@@ -90,11 +88,8 @@ finally { if (e_3) throw e_3.error; }

try {
if (docs_1_1 && !docs_1_1.done && (_a = docs_1["return"])) _a.call(docs_1);
if (docs_1_1 && !docs_1_1.done && (_a = docs_1.return)) _a.call(docs_1);
}
finally { if (e_1) throw e_1.error; }
}
if (errors.length > 0) {
return (0, DiagnosticError_1.err)(errors);
}
return (0, DiagnosticError_1.ok)(graph);
return graph;
}
exports.computeInterfaceMap = computeInterfaceMap;

@@ -1,10 +0,13 @@

import { GraphQLSchema } from "graphql";
import { Result, ReportableDiagnostics } from "./utils/DiagnosticError";
import { DocumentNode, GraphQLSchema } from "graphql";
import { DiagnosticsResult, Result, ReportableDiagnostics } from "./utils/DiagnosticError";
import * as ts from "typescript";
export { applyServerDirectives } from "./serverDirectives";
export type ConfigOptions = {
nullableByDefault?: boolean;
reportTypeScriptTypeErrors?: boolean;
};
export declare function buildSchemaResult(options: ts.ParsedCommandLine): Result<GraphQLSchema, ReportableDiagnostics>;
export declare function buildSchemaResultWithHost(options: ts.ParsedCommandLine, compilerHost: ts.CompilerHost): Result<GraphQLSchema, ReportableDiagnostics>;
import { ExtractionSnapshot } from "./Extractor";
import { ParsedCommandLineGrats } from "./gratsConfig";
export * from "./gratsConfig";
export declare function buildSchemaResult(options: ParsedCommandLineGrats): Result<GraphQLSchema, ReportableDiagnostics>;
export declare function buildSchemaResultWithHost(options: ParsedCommandLineGrats, compilerHost: ts.CompilerHost): Result<GraphQLSchema, ReportableDiagnostics>;
/**
* Given a merged snapshot representing the whole program, construct a GraphQL
* schema document with metadata directives attached.
*/
export declare function docFromSnapshot(program: ts.Program, host: ts.CompilerHost, snapshot: ExtractionSnapshot): DiagnosticsResult<DocumentNode>;
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {

@@ -24,2 +13,5 @@ if (k2 === undefined) k2 = k;

}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __values = (this && this.__values) || function(o) {

@@ -36,14 +28,36 @@ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;

};
exports.__esModule = true;
exports.buildSchemaResultWithHost = exports.buildSchemaResult = exports.applyServerDirectives = void 0;
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.docFromSnapshot = exports.buildSchemaResultWithHost = exports.buildSchemaResult = void 0;
var graphql_1 = require("graphql");
var DiagnosticError_1 = require("./utils/DiagnosticError");
var ts = require("typescript");
var Extractor_1 = require("./Extractor");
var TypeContext_1 = require("./TypeContext");
var validate_1 = require("graphql/validation/validate");
var serverDirectives_1 = require("./serverDirectives");
var validateTypenames_1 = require("./validations/validateTypenames");
var snapshotsFromProgram_1 = require("./transforms/snapshotsFromProgram");
var validateMergedInterfaces_1 = require("./validations/validateMergedInterfaces");
var validateContextReferences_1 = require("./validations/validateContextReferences");
var metadataDirectives_1 = require("./metadataDirectives");
var helpers_1 = require("./utils/helpers");
var serverDirectives_2 = require("./serverDirectives");
__createBinding(exports, serverDirectives_2, "applyServerDirectives");
var addInterfaceFields_1 = require("./transforms/addInterfaceFields");
var filterNonGqlInterfaces_1 = require("./transforms/filterNonGqlInterfaces");
var resolveTypes_1 = require("./transforms/resolveTypes");
var validateAsyncIterable_1 = require("./validations/validateAsyncIterable");
__exportStar(require("./gratsConfig"), exports);
// Construct a schema, using GraphQL schema language

@@ -60,81 +74,65 @@ // Exported for tests that want to intercept diagnostic errors.

function buildSchemaResultWithHost(options, compilerHost) {
var gratsOptions = parseGratsOptions(options);
var schemaResult = extractSchema(options, gratsOptions, compilerHost);
var schemaResult = extractSchema(options, compilerHost);
if (schemaResult.kind === "ERROR") {
return (0, DiagnosticError_1.err)(new DiagnosticError_1.ReportableDiagnostics(compilerHost, schemaResult.err));
}
return (0, DiagnosticError_1.ok)((0, serverDirectives_1.applyServerDirectives)(schemaResult.value));
return (0, DiagnosticError_1.ok)(schemaResult.value);
}
exports.buildSchemaResultWithHost = buildSchemaResultWithHost;
// TODO: Make this return diagnostics
function parseGratsOptions(options) {
var _a, _b;
var gratsOptions = __assign({}, ((_b = (_a = options.raw) === null || _a === void 0 ? void 0 : _a.grats) !== null && _b !== void 0 ? _b : {}));
if (gratsOptions.nullableByDefault === undefined) {
gratsOptions.nullableByDefault = true;
function extractSchema(options, host) {
var program = ts.createProgram(options.fileNames, options.options, host);
var snapshotsResult = (0, snapshotsFromProgram_1.snapshotsFromProgram)(program, options);
if (snapshotsResult.kind === "ERROR") {
return snapshotsResult;
}
else if (typeof gratsOptions.nullableByDefault !== "boolean") {
throw new Error("Grats: The Grats config option `nullableByDefault` must be a boolean if provided.");
var snapshot = reduceSnapshots(snapshotsResult.value);
var docResult = docFromSnapshot(program, host, snapshot);
if (docResult.kind === "ERROR") {
return docResult;
}
if (gratsOptions.reportTypeScriptTypeErrors === undefined) {
gratsOptions.reportTypeScriptTypeErrors = false;
return buildSchemaFromDocumentNode(docResult.value, snapshot.typesWithTypenameField);
}
// Given a SDL AST, build and validate a GraphQLSchema.
function buildSchemaFromDocumentNode(doc, typesWithTypenameField) {
// TODO: Currently this does not detect definitions that shadow builtins
// (`String`, `Int`, etc). However, if we pass a second param (extending an
// existing schema) we do! So, we should find a way to validate that we don't
// shadow builtins.
var validationErrors = (0, validate_1.validateSDL)(doc).map(function (e) {
return (0, DiagnosticError_1.graphQlErrorToDiagnostic)(e);
});
if (validationErrors.length > 0) {
return (0, DiagnosticError_1.err)(validationErrors);
}
else if (typeof gratsOptions.reportTypeScriptTypeErrors !== "boolean") {
throw new Error("Grats: The Grats config option `reportTypeScriptTypeErrors` must be a boolean if provided");
var schema = (0, graphql_1.buildASTSchema)(doc, { assumeValidSDL: true });
var diagnostics = (0, graphql_1.validateSchema)(schema)
// FIXME: Handle case where query is not defined (no location)
.filter(function (e) { return e.source && e.locations && e.positions; })
.map(function (e) { return (0, DiagnosticError_1.graphQlErrorToDiagnostic)(e); });
if (diagnostics.length > 0) {
return (0, DiagnosticError_1.err)(diagnostics);
}
// FIXME: Check for unknown options
return gratsOptions;
var typenameDiagnostics = (0, validateTypenames_1.validateTypenames)(schema, typesWithTypenameField);
if (typenameDiagnostics.length > 0)
return (0, DiagnosticError_1.err)(typenameDiagnostics);
return (0, DiagnosticError_1.ok)(schema);
}
function extractSchema(options, gratsOptions, host) {
/**
* Given a merged snapshot representing the whole program, construct a GraphQL
* schema document with metadata directives attached.
*/
function docFromSnapshot(program, host, snapshot) {
var e_1, _a, e_2, _b;
var program = ts.createProgram(options.fileNames, options.options, host);
var checker = program.getTypeChecker();
var ctx = new TypeContext_1.TypeContext(options, checker, host);
var definitions = Array.from(serverDirectives_1.DIRECTIVES_AST.definitions);
var errors = [];
var ctx = new TypeContext_1.TypeContext(checker, host);
// Validate the snapshot
var mergedResult = (0, DiagnosticError_1.combineResults)((0, validateMergedInterfaces_1.validateMergedInterfaces)(checker, snapshot.interfaceDeclarations), (0, validateContextReferences_1.validateContextReferences)(ctx, snapshot.contextReferences));
if (mergedResult.kind === "ERROR") {
return mergedResult;
}
try {
for (var _c = __values(program.getSourceFiles()), _d = _c.next(); !_d.done; _d = _c.next()) {
var sourceFile = _d.value;
// If the file doesn't contain any GraphQL definitions, skip it.
if (!/@gql/i.test(sourceFile.text)) {
continue;
}
if (gratsOptions.reportTypeScriptTypeErrors) {
// If the user asked for us to report TypeScript errors, then we'll report them.
var typeErrors = ts.getPreEmitDiagnostics(program, sourceFile);
if (typeErrors.length > 0) {
(0, helpers_1.extend)(errors, typeErrors);
continue;
}
}
else {
// Otherwise, we will only report syntax errors, since they will prevent us from
// extracting any GraphQL definitions.
var syntaxErrors = program.getSyntacticDiagnostics(sourceFile);
if (syntaxErrors.length > 0) {
// It's not very helpful to report multiple syntax errors, so just report
// the first one.
errors.push(syntaxErrors[0]);
continue;
}
}
var extractor = new Extractor_1.Extractor(sourceFile, ctx, gratsOptions);
var extractedResult = extractor.extract();
if (extractedResult.kind === "ERROR") {
(0, helpers_1.extend)(errors, extractedResult.err);
continue;
}
try {
for (var _e = (e_2 = void 0, __values(extractedResult.value)), _f = _e.next(); !_f.done; _f = _e.next()) {
var definition = _f.value;
definitions.push(definition);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e["return"])) _b.call(_e);
}
finally { if (e_2) throw e_2.error; }
}
// Propagate snapshot data to type context
for (var _c = __values(snapshot.unresolvedNames), _d = _c.next(); !_d.done; _d = _c.next()) {
var _e = __read(_d.value, 2), node = _e[0], typeName = _e[1];
ctx.markUnresolvedType(node, typeName);
}

@@ -145,66 +143,62 @@ }

try {
if (_d && !_d.done && (_a = _c["return"])) _a.call(_c);
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
if (errors.length > 0) {
return (0, DiagnosticError_1.err)(errors);
try {
for (var _f = __values(snapshot.nameDefinitions), _g = _f.next(); !_g.done; _g = _f.next()) {
var _h = __read(_g.value, 2), node = _h[0], definition = _h[1];
ctx.recordTypeName(node, definition.name, definition.kind);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
}
finally { if (e_2) throw e_2.error; }
}
// Fixup the schema SDL
var definitions = Array.from(metadataDirectives_1.DIRECTIVES_AST.definitions);
(0, helpers_1.extend)(definitions, snapshot.definitions);
// If you define a field on an interface using the functional style, we need to add
// that field to each concrete type as well. This must be done after all types are created,
// but before we validate the schema.
var definitionsResult = ctx.handleAbstractDefinitions(definitions);
var definitionsResult = (0, addInterfaceFields_1.addInterfaceFields)(ctx, definitions);
if (definitionsResult.kind === "ERROR") {
return definitionsResult;
}
var docResult = ctx.resolveTypes({
var filteredDoc = (0, filterNonGqlInterfaces_1.filterNonGqlInterfaces)(ctx, {
kind: graphql_1.Kind.DOCUMENT,
definitions: definitionsResult.value
definitions: definitionsResult.value,
});
var docResult = (0, resolveTypes_1.resolveTypes)(ctx, filteredDoc);
if (docResult.kind === "ERROR")
return docResult;
var doc = docResult.value;
// TODO: Currently this does not detect definitions that shadow builtins
// (`String`, `Int`, etc). However, if we pass a second param (extending an
// existing schema) we do! So, we should find a way to validate that we don't
// shadow builtins.
var validationErrors = (0, validate_1.validateSDL)(doc).map(function (e) {
return (0, DiagnosticError_1.graphQlErrorToDiagnostic)(e);
});
if (validationErrors.length > 0) {
return (0, DiagnosticError_1.err)(validationErrors);
var subscriptionsValidationResult = (0, validateAsyncIterable_1.validateAsyncIterable)(doc);
if (subscriptionsValidationResult.kind === "ERROR") {
return subscriptionsValidationResult;
}
var schema = (0, graphql_1.buildASTSchema)(doc, { assumeValidSDL: true });
var diagnostics = (0, graphql_1.validateSchema)(schema)
// FIXME: Handle case where query is not defined (no location)
.filter(function (e) { return e.source && e.locations && e.positions; })
.map(function (e) { return (0, DiagnosticError_1.graphQlErrorToDiagnostic)(e); });
if (diagnostics.length > 0) {
return (0, DiagnosticError_1.err)(diagnostics);
}
var typenameDiagnostics = validateTypename(schema, ctx);
if (typenameDiagnostics.length > 0)
return (0, DiagnosticError_1.err)(typenameDiagnostics);
return (0, DiagnosticError_1.ok)(schema);
return (0, DiagnosticError_1.ok)(doc);
}
function validateTypename(schema, ctx) {
var e_3, _a, e_4, _b;
var _c, _d;
var typenameDiagnostics = [];
var abstractTypes = Object.values(schema.getTypeMap()).filter(graphql_1.isAbstractType);
exports.docFromSnapshot = docFromSnapshot;
// Given a list of snapshots, merge them into a single snapshot.
function reduceSnapshots(snapshots) {
var e_3, _a, e_4, _b, e_5, _c, e_6, _d, e_7, _e, e_8, _f, e_9, _g;
var result = {
definitions: [],
nameDefinitions: new Map(),
unresolvedNames: new Map(),
contextReferences: [],
typesWithTypenameField: new Set(),
interfaceDeclarations: [],
};
try {
for (var abstractTypes_1 = __values(abstractTypes), abstractTypes_1_1 = abstractTypes_1.next(); !abstractTypes_1_1.done; abstractTypes_1_1 = abstractTypes_1.next()) {
var type = abstractTypes_1_1.value;
// TODO: If we already implement resolveType, we don't need to check implementors
var typeImplementors = schema.getPossibleTypes(type).filter(graphql_1.isType);
for (var snapshots_1 = __values(snapshots), snapshots_1_1 = snapshots_1.next(); !snapshots_1_1.done; snapshots_1_1 = snapshots_1.next()) {
var snapshot = snapshots_1_1.value;
try {
for (var typeImplementors_1 = (e_4 = void 0, __values(typeImplementors)), typeImplementors_1_1 = typeImplementors_1.next(); !typeImplementors_1_1.done; typeImplementors_1_1 = typeImplementors_1.next()) {
var implementor = typeImplementors_1_1.value;
if (!ctx.hasTypename.has(implementor.name)) {
var loc = (_d = (_c = implementor.astNode) === null || _c === void 0 ? void 0 : _c.name) === null || _d === void 0 ? void 0 : _d.loc;
if (loc == null) {
throw new Error("Grats expected the parsed type `".concat(implementor.name, "` to have location information. This is a bug in Grats. Please report it."));
}
typenameDiagnostics.push((0, DiagnosticError_1.diagnosticAtGraphQLLocation)("Missing __typename on `".concat(implementor.name, "`. The type `").concat(type.name, "` is used in a union or interface, so it must have a `__typename` field."), loc));
}
for (var _h = (e_4 = void 0, __values(snapshot.definitions)), _j = _h.next(); !_j.done; _j = _h.next()) {
var definition = _j.value;
result.definitions.push(definition);
}

@@ -215,6 +209,71 @@ }

try {
if (typeImplementors_1_1 && !typeImplementors_1_1.done && (_b = typeImplementors_1["return"])) _b.call(typeImplementors_1);
if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
}
finally { if (e_4) throw e_4.error; }
}
try {
for (var _k = (e_5 = void 0, __values(snapshot.nameDefinitions)), _l = _k.next(); !_l.done; _l = _k.next()) {
var _m = __read(_l.value, 2), node = _m[0], definition = _m[1];
result.nameDefinitions.set(node, definition);
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_l && !_l.done && (_c = _k.return)) _c.call(_k);
}
finally { if (e_5) throw e_5.error; }
}
try {
for (var _o = (e_6 = void 0, __values(snapshot.unresolvedNames)), _p = _o.next(); !_p.done; _p = _o.next()) {
var _q = __read(_p.value, 2), node = _q[0], typeName = _q[1];
result.unresolvedNames.set(node, typeName);
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_p && !_p.done && (_d = _o.return)) _d.call(_o);
}
finally { if (e_6) throw e_6.error; }
}
try {
for (var _r = (e_7 = void 0, __values(snapshot.contextReferences)), _s = _r.next(); !_s.done; _s = _r.next()) {
var contextReference = _s.value;
result.contextReferences.push(contextReference);
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_s && !_s.done && (_e = _r.return)) _e.call(_r);
}
finally { if (e_7) throw e_7.error; }
}
try {
for (var _t = (e_8 = void 0, __values(snapshot.typesWithTypenameField)), _u = _t.next(); !_u.done; _u = _t.next()) {
var typeName = _u.value;
result.typesWithTypenameField.add(typeName);
}
}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {
try {
if (_u && !_u.done && (_f = _t.return)) _f.call(_t);
}
finally { if (e_8) throw e_8.error; }
}
try {
for (var _v = (e_9 = void 0, __values(snapshot.interfaceDeclarations)), _w = _v.next(); !_w.done; _w = _v.next()) {
var interfaceDeclaration = _w.value;
result.interfaceDeclarations.push(interfaceDeclaration);
}
}
catch (e_9_1) { e_9 = { error: e_9_1 }; }
finally {
try {
if (_w && !_w.done && (_g = _v.return)) _g.call(_v);
}
finally { if (e_9) throw e_9.error; }
}
}

@@ -225,7 +284,7 @@ }

try {
if (abstractTypes_1_1 && !abstractTypes_1_1.done && (_a = abstractTypes_1["return"])) _a.call(abstractTypes_1);
if (snapshots_1_1 && !snapshots_1_1.done && (_a = snapshots_1.return)) _a.call(snapshots_1);
}
finally { if (e_3) throw e_3.error; }
}
return typenameDiagnostics;
return result;
}
"use strict";
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.locate = void 0;

@@ -4,0 +4,0 @@ var graphql_1 = require("graphql");

@@ -60,7 +60,6 @@ "use strict";

};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
var path = require("path");
var TestRunner_1 = require("./TestRunner");
var lib_1 = require("../lib");
var utils_1 = require("@graphql-tools/utils");
var ts = require("typescript");

@@ -71,2 +70,7 @@ var graphql_1 = require("graphql");

var DiagnosticError_1 = require("../utils/DiagnosticError");
var fs_1 = require("fs");
var codegen_1 = require("../codegen");
var utils_1 = require("@graphql-tools/utils");
var jest_diff_1 = require("jest-diff");
var printSchema_1 = require("../printSchema");
var program = new commander_1.Command();

@@ -81,3 +85,3 @@ program

return __awaiter(void 0, void 0, void 0, function () {
var filterRegex, failures, testDirs_1, testDirs_1_1, _b, fixturesDir_1, transformer, runner, e_1_1;
var filterRegex, failures, testDirs_1, testDirs_1_1, _b, fixturesDir_1, transformer, testFilePattern, ignoreFilePattern, runner, e_1_1;
var e_1, _c;

@@ -96,4 +100,4 @@ return __generator(this, function (_d) {

if (!!testDirs_1_1.done) return [3 /*break*/, 5];
_b = testDirs_1_1.value, fixturesDir_1 = _b.fixturesDir, transformer = _b.transformer;
runner = new TestRunner_1["default"](fixturesDir_1, !!write, filterRegex, transformer);
_b = testDirs_1_1.value, fixturesDir_1 = _b.fixturesDir, transformer = _b.transformer, testFilePattern = _b.testFilePattern, ignoreFilePattern = _b.ignoreFilePattern;
runner = new TestRunner_1.default(fixturesDir_1, !!write, filterRegex, testFilePattern, ignoreFilePattern, transformer);
return [4 /*yield*/, runner.run()];

@@ -113,3 +117,3 @@ case 3:

try {
if (testDirs_1_1 && !testDirs_1_1.done && (_c = testDirs_1["return"])) _c.call(testDirs_1);
if (testDirs_1_1 && !testDirs_1_1.done && (_c = testDirs_1.return)) _c.call(testDirs_1);
}

@@ -133,6 +137,9 @@ finally { if (e_1) throw e_1.error; }

fixturesDir: fixturesDir,
testFilePattern: /\.ts$/,
ignoreFilePattern: null,
transformer: function (code, fileName) {
var firstLine = code.split("\n")[0];
var options = {
nullableByDefault: true
nullableByDefault: true,
schemaHeader: null,
};

@@ -144,11 +151,14 @@ if (firstLine.startsWith("// {")) {

}
var files = ["".concat(fixturesDir, "/").concat(fileName), "src/Types.ts"];
var parsedOptions = {
var files = [
"".concat(fixturesDir, "/").concat(fileName),
path.join(__dirname, "../Types.ts"),
];
var parsedOptions = (0, lib_1.validateGratsOptions)({
options: {},
raw: {
grats: options
grats: options,
},
errors: [],
fileNames: files
};
fileNames: files,
});
// https://stackoverflow.com/a/66604532/1263117

@@ -162,2 +172,4 @@ var compilerHost = ts.createCompilerHost(parsedOptions.options,

}
// We run codegen here just ensure that it doesn't throw.
var executableSchema = (0, codegen_1.codegen)(schemaResult.value, "".concat(fixturesDir, "/").concat(fileName));
var LOCATION_REGEX = /^\/\/ Locate: (.*)/;

@@ -171,32 +183,29 @@ var locationMatch = code.match(LOCATION_REGEX);

return new DiagnosticError_1.ReportableDiagnostics(compilerHost, [
(0, DiagnosticError_1.diagnosticAtGraphQLLocation)("Located here", locResult.value),
(0, DiagnosticError_1.gqlErr)(locResult.value, "Located here"),
]).formatDiagnosticsWithContext();
}
else {
return (0, utils_1.printSchemaWithDirectives)(schemaResult.value, {
assumeValid: true
var sdl = (0, utils_1.printSchemaWithDirectives)(schemaResult.value, {
assumeValid: true,
});
return "-- SDL --\n".concat(sdl, "\n-- TypeScript --\n").concat(executableSchema);
}
}
},
},
{
fixturesDir: integrationFixturesDir,
testFilePattern: /index.ts$/,
ignoreFilePattern: /schema.ts$/,
transformer: function (code, fileName) { return __awaiter(void 0, void 0, void 0, function () {
var filePath, server, options, files, parsedOptions, schemaResult, schema, data;
var filePath, schemaPath, options, files, parsedOptions, schemaResult, tsSchema, server, schemaModule, actualSchema, schemaDiff, data;
return __generator(this, function (_a) {
var _b;
switch (_a.label) {
case 0:
filePath = "".concat(integrationFixturesDir, "/").concat(fileName);
return [4 /*yield*/, (_b = filePath, Promise.resolve().then(function () { return require(_b); }))];
case 1:
server = _a.sent();
if (server.query == null || typeof server.query !== "string") {
throw new Error("Expected `".concat(filePath, "` to export a query text as `query`"));
}
schemaPath = path.join(path.dirname(filePath), "schema.ts");
options = {
nullableByDefault: true
nullableByDefault: true,
};
files = [filePath, "src/Types.ts"];
parsedOptions = {
files = [filePath, path.join(__dirname, "../Types.ts")];
parsedOptions = (0, lib_1.validateGratsOptions)({
options: {

@@ -206,10 +215,10 @@ // Required to enable ts-node to locate function exports

outDir: "dist",
configFilePath: "tsconfig.json"
configFilePath: "tsconfig.json",
},
raw: {
grats: options
grats: options,
},
errors: [],
fileNames: files
};
fileNames: files,
});
schemaResult = (0, lib_1.buildSchemaResult)(parsedOptions);

@@ -219,9 +228,26 @@ if (schemaResult.kind === "ERROR") {

}
schema = schemaResult.value;
tsSchema = (0, codegen_1.codegen)(schemaResult.value, schemaPath);
(0, fs_1.writeFileSync)(schemaPath, tsSchema);
return [4 /*yield*/, Promise.resolve("".concat(filePath)).then(function (s) { return require(s); })];
case 1:
server = _a.sent();
if (server.query == null || typeof server.query !== "string") {
throw new Error("Expected `".concat(filePath, "` to export a query text as `query`"));
}
return [4 /*yield*/, Promise.resolve("".concat(schemaPath)).then(function (s) { return require(s); })];
case 2:
schemaModule = _a.sent();
actualSchema = schemaModule.getSchema();
schemaDiff = compareSchemas(actualSchema, schemaResult.value);
if (schemaDiff) {
console.log(schemaDiff);
// TODO: Make this an actual test failure, not an error
throw new Error("The codegen schema does not match the SDL schema.");
}
return [4 /*yield*/, (0, graphql_1.graphql)({
schema: schema,
schema: actualSchema,
source: server.query,
rootValue: server.Query != null ? new server.Query() : null
variableValues: server.variables,
})];
case 2:
case 3:
data = _a.sent();

@@ -231,5 +257,14 @@ return [2 /*return*/, JSON.stringify(data, null, 2)];

});
}); }
}); },
},
];
// Returns null if the schemas are equal, otherwise returns a string diff.
function compareSchemas(actual, expected) {
var actualSDL = (0, printSchema_1.printSDLWithoutDirectives)(actual);
var expectedSDL = (0, printSchema_1.printSDLWithoutDirectives)(expected);
if (actualSDL === expectedSDL) {
return null;
}
return (0, jest_diff_1.diff)(expectedSDL, actualSDL);
}
program.parse();

@@ -15,3 +15,3 @@ type Transformer = (code: string, filename: string) => Promise<string> | string;

_transformer: Transformer;
constructor(fixturesDir: string, write: boolean, filter: string | null, transformer: Transformer);
constructor(fixturesDir: string, write: boolean, filter: string | null, testFilePattern: RegExp, ignoreFilePattern: RegExp | null, transformer: Transformer);
run(): Promise<boolean>;

@@ -18,0 +18,0 @@ _testFixture(fixture: string): Promise<void>;

@@ -49,3 +49,3 @@ "use strict";

};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");

@@ -60,3 +60,3 @@ var path = require("path");

var TestRunner = /** @class */ (function () {
function TestRunner(fixturesDir, write, filter, transformer) {
function TestRunner(fixturesDir, write, filter, testFilePattern, ignoreFilePattern, transformer) {
var e_1, _a;

@@ -74,3 +74,3 @@ this._testFixtures = [];

var fileName = _c.value;
if (fileName.endsWith(".ts")) {
if (testFilePattern.test(fileName)) {
this._testFixtures.push(fileName);

@@ -82,3 +82,3 @@ var filePath = path.join(fixturesDir, fileName);

}
else {
else if (!ignoreFilePattern || !ignoreFilePattern.test(fileName)) {
this._otherFiles.add(fileName);

@@ -91,3 +91,3 @@ }

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -125,3 +125,3 @@ finally { if (e_1) throw e_1.error; }

try {
if (_b && !_b.done && (_g = _a["return"])) _g.call(_a);
if (_b && !_b.done && (_g = _a.return)) _g.call(_a);
}

@@ -151,3 +151,3 @@ finally { if (e_2) throw e_2.error; }

try {
if (_d && !_d.done && (_h = _c["return"])) _h.call(_c);
if (_d && !_d.done && (_h = _c.return)) _h.call(_c);
}

@@ -168,3 +168,3 @@ finally { if (e_3) throw e_3.error; }

try {
if (_f && !_f.done && (_j = _e["return"])) _j.call(_e);
if (_f && !_f.done && (_j = _e.return)) _j.call(_e);
}

@@ -191,3 +191,3 @@ finally { if (e_4) throw e_4.error; }

if (this._otherFiles.has(expectedFileName)) {
this._otherFiles["delete"](expectedFileName);
this._otherFiles.delete(expectedFileName);
}

@@ -247,3 +247,3 @@ else {

}());
exports["default"] = TestRunner;
exports.default = TestRunner;
function readdirSyncRecursive(dir) {

@@ -266,3 +266,3 @@ var e_6, _a, e_7, _b;

try {
if (_f && !_f.done && (_b = _e["return"])) _b.call(_e);
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}

@@ -280,3 +280,3 @@ finally { if (e_7) throw e_7.error; }

try {
if (_d && !_d.done && (_a = _c["return"])) _a.call(_c);
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}

@@ -283,0 +283,0 @@ finally { if (e_6) throw e_6.error; }

@@ -1,26 +0,10 @@

import { DefinitionNode, DocumentNode, FieldDefinitionNode, Location, NameNode } from "graphql";
import { NameNode } from "graphql";
import * as ts from "typescript";
import { DiagnosticResult, DiagnosticsResult } from "./utils/DiagnosticError";
import { InterfaceMap } from "./InterfaceGraph";
export declare const UNRESOLVED_REFERENCE_NAME = "__UNRESOLVED_REFERENCE__";
type NameDefinition = {
export type NameDefinition = {
name: NameNode;
kind: "TYPE" | "INTERFACE" | "UNION" | "SCALAR" | "INPUT_OBJECT" | "ENUM";
};
export type GratsDefinitionNode = DefinitionNode | AbstractFieldDefinitionNode;
export type AbstractFieldDefinitionNode = {
readonly kind: "AbstractFieldDefinition";
readonly loc: Location;
readonly onType: NameNode;
readonly field: FieldDefinitionNode;
};
/**
* Information about the GraphQL context type. We track the first value we see,
* and then validate that any other values we see are the same.
*/
type GqlContext = {
declaration: ts.Node;
firstReference: ts.Node;
};
/**
* Used to track TypeScript references.

@@ -40,22 +24,12 @@ *

host: ts.CompilerHost;
_options: ts.ParsedCommandLine;
_symbolToName: Map<ts.Symbol, NameDefinition>;
_unresolvedTypes: Map<NameNode, ts.Symbol>;
gqlContext: GqlContext | null;
hasTypename: Set<string>;
constructor(options: ts.ParsedCommandLine, checker: ts.TypeChecker, host: ts.CompilerHost);
constructor(checker: ts.TypeChecker, host: ts.CompilerHost);
recordTypeName(node: ts.Node, name: NameNode, kind: NameDefinition["kind"]): void;
recordHasTypenameField(name: string): void;
markUnresolvedType(node: ts.Node, name: NameNode): void;
findSymbolDeclaration(startSymbol: ts.Symbol): ts.Declaration | null;
resolveSymbol(startSymbol: ts.Symbol): ts.Symbol;
resolveTypes(doc: DocumentNode): DiagnosticsResult<DocumentNode>;
handleAbstractDefinitions(docs: GratsDefinitionNode[]): DiagnosticsResult<DefinitionNode[]>;
addAbstractFieldDefinition(doc: AbstractFieldDefinitionNode, interfaceGraph: InterfaceMap): DiagnosticsResult<DefinitionNode[]>;
resolveNamedType(unresolved: NameNode): DiagnosticResult<NameNode>;
err(loc: Location, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.Diagnostic;
relatedInformation(loc: Location, message: string): ts.DiagnosticRelatedInformation;
validateInterfaceImplementorsHaveTypenameField(): DiagnosticResult<null>;
getDestFilePath(sourceFile: ts.SourceFile): string;
unresolvedNameIsGraphQL(unresolved: NameNode): boolean;
getNameDefinition(nameNode: NameNode): DiagnosticsResult<NameDefinition>;
}
export {};

@@ -13,24 +13,7 @@ "use strict";

};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TypeContext = exports.UNRESOLVED_REFERENCE_NAME = void 0;
var graphql_1 = require("graphql");
var ts = require("typescript");
var DiagnosticError_1 = require("./utils/DiagnosticError");
var gratsRoot_1 = require("./gratsRoot");
var serverDirectives_1 = require("./serverDirectives");
var Extractor_1 = require("./Extractor");
var E = require("./Errors");
var InterfaceGraph_1 = require("./InterfaceGraph");
var helpers_1 = require("./utils/helpers");
exports.UNRESOLVED_REFERENCE_NAME = "__UNRESOLVED_REFERENCE__";

@@ -50,13 +33,10 @@ /**

var TypeContext = /** @class */ (function () {
function TypeContext(options, checker, host) {
function TypeContext(checker, host) {
this._symbolToName = new Map();
this._unresolvedTypes = new Map();
// The resolver context declaration, if it has been encountered.
// Gets mutated by Extractor.
this.gqlContext = null;
this.hasTypename = new Set();
this._options = options;
this.checker = checker;
this.host = host;
}
// Record that a GraphQL construct of type `kind` with the name `name` is
// declared at `node`.
TypeContext.prototype.recordTypeName = function (node, name, kind) {

@@ -74,5 +54,3 @@ var symbol = this.checker.getSymbolAtLocation(node);

};
TypeContext.prototype.recordHasTypenameField = function (name) {
this.hasTypename.add(name);
};
// Record that a type reference `node`
TypeContext.prototype.markUnresolvedType = function (node, name) {

@@ -106,158 +84,2 @@ var symbol = this.checker.getSymbolAtLocation(node);

};
TypeContext.prototype.resolveTypes = function (doc) {
var _a;
var _this = this;
var errors = [];
var newDoc = (0, graphql_1.visit)(doc, (_a = {},
_a[graphql_1.Kind.NAME] = function (t) {
var namedTypeResult = _this.resolveNamedType(t);
if (namedTypeResult.kind === "ERROR") {
errors.push(namedTypeResult.err);
return t;
}
return namedTypeResult.value;
},
_a));
if (errors.length > 0) {
return (0, DiagnosticError_1.err)(errors);
}
return (0, DiagnosticError_1.ok)(newDoc);
};
TypeContext.prototype.handleAbstractDefinitions = function (docs) {
var e_1, _a;
var newDocs = [];
var errors = [];
var interfaceGraphResult = (0, InterfaceGraph_1.computeInterfaceMap)(this, docs);
if (interfaceGraphResult.kind === "ERROR") {
return interfaceGraphResult;
}
var interfaceGraph = interfaceGraphResult.value;
try {
for (var docs_1 = __values(docs), docs_1_1 = docs_1.next(); !docs_1_1.done; docs_1_1 = docs_1.next()) {
var doc = docs_1_1.value;
if (doc.kind === "AbstractFieldDefinition") {
var abstractDocResults = this.addAbstractFieldDefinition(doc, interfaceGraph);
if (abstractDocResults.kind === "ERROR") {
(0, helpers_1.extend)(errors, abstractDocResults.err);
}
else {
(0, helpers_1.extend)(newDocs, abstractDocResults.value);
}
}
else {
newDocs.push(doc);
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (docs_1_1 && !docs_1_1.done && (_a = docs_1["return"])) _a.call(docs_1);
}
finally { if (e_1) throw e_1.error; }
}
if (errors.length > 0) {
return (0, DiagnosticError_1.err)(errors);
}
return (0, DiagnosticError_1.ok)(newDocs);
};
// A field definition may be on a concrete type, or on an interface. If it's on an interface,
// we need to add it to each concrete type that implements the interface.
TypeContext.prototype.addAbstractFieldDefinition = function (doc, interfaceGraph) {
var e_2, _a;
var _b;
var newDocs = [];
var typeNameResult = this.resolveNamedType(doc.onType);
if (typeNameResult.kind === "ERROR") {
return (0, DiagnosticError_1.err)([typeNameResult.err]);
}
var symbol = this._unresolvedTypes.get(doc.onType);
if (symbol == null) {
// This should have already been handled by resolveNamedType
throw new Error("Expected to find unresolved type.");
}
var nameDefinition = this._symbolToName.get(symbol);
if (nameDefinition == null) {
// This should have already been handled by resolveNamedType
throw new Error("Expected to find name definition.");
}
switch (nameDefinition.kind) {
case "TYPE":
// Extending a type, is just adding a field to it.
newDocs.push({
kind: graphql_1.Kind.OBJECT_TYPE_EXTENSION,
name: doc.onType,
fields: [doc.field],
loc: doc.loc
});
break;
case "INTERFACE": {
// Extending an interface is a bit more complicated. We need to add the field
// to the interface, and to each type that implements the interface.
// The interface field definition is not executable, so we don't
// need to annotate it with the details of the implementation.
var directives = (_b = doc.field.directives) === null || _b === void 0 ? void 0 : _b.filter(function (directive) {
return directive.name.value !== serverDirectives_1.EXPORTED_DIRECTIVE;
});
newDocs.push({
kind: graphql_1.Kind.INTERFACE_TYPE_EXTENSION,
name: doc.onType,
fields: [__assign(__assign({}, doc.field), { directives: directives })]
});
try {
for (var _c = __values(interfaceGraph.get(nameDefinition.name.value)), _d = _c.next(); !_d.done; _d = _c.next()) {
var implementor = _d.value;
var name = {
kind: graphql_1.Kind.NAME,
value: implementor.name,
loc: doc.loc
};
switch (implementor.kind) {
case "TYPE":
newDocs.push({
kind: graphql_1.Kind.OBJECT_TYPE_EXTENSION,
name: name,
fields: [doc.field],
loc: doc.loc
});
break;
case "INTERFACE":
newDocs.push({
kind: graphql_1.Kind.INTERFACE_TYPE_EXTENSION,
name: name,
fields: [__assign(__assign({}, doc.field), { directives: directives })],
loc: doc.loc
});
break;
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c["return"])) _a.call(_c);
}
finally { if (e_2) throw e_2.error; }
}
break;
}
default: {
// Extending any other type of definition is not supported.
var loc = doc.onType.loc;
if (loc == null) {
throw new Error("Expected onType to have a location.");
}
var relatedLoc = nameDefinition.name.loc;
if (relatedLoc == null) {
throw new Error("Expected nameDefinition to have a location.");
}
return (0, DiagnosticError_1.err)([
this.err(loc, E.invalidTypePassedToFieldFunction(), [
this.relatedInformation(relatedLoc, "This is the type that was passed to `@".concat(Extractor_1.FIELD_TAG, "`.")),
]),
]);
}
}
return (0, DiagnosticError_1.ok)(newDocs);
};
TypeContext.prototype.resolveNamedType = function (unresolved) {

@@ -277,35 +99,30 @@ var symbol = this._unresolvedTypes.get(unresolved);

}
return (0, DiagnosticError_1.err)(this.err(unresolved.loc, E.unresolvedTypeReference()));
return (0, DiagnosticError_1.err)((0, DiagnosticError_1.gqlErr)(unresolved.loc, E.unresolvedTypeReference()));
}
return (0, DiagnosticError_1.ok)(__assign(__assign({}, unresolved), { value: nameDefinition.name.value }));
};
TypeContext.prototype.err = function (loc, message, relatedInformation) {
return {
messageText: message,
start: loc.start,
length: loc.end - loc.start,
category: ts.DiagnosticCategory.Error,
code: DiagnosticError_1.FAKE_ERROR_CODE,
file: ts.createSourceFile(loc.source.name, loc.source.body, ts.ScriptTarget.Latest),
relatedInformation: relatedInformation
};
TypeContext.prototype.unresolvedNameIsGraphQL = function (unresolved) {
var symbol = this._unresolvedTypes.get(unresolved);
return symbol != null && this._symbolToName.has(symbol);
};
TypeContext.prototype.relatedInformation = function (loc, message) {
return {
category: ts.DiagnosticCategory.Message,
code: DiagnosticError_1.FAKE_ERROR_CODE,
messageText: message,
file: ts.createSourceFile(loc.source.name, loc.source.body, ts.ScriptTarget.Latest),
start: loc.start,
length: loc.end - loc.start
};
// TODO: Merge this with resolveNamedType
TypeContext.prototype.getNameDefinition = function (nameNode) {
var typeNameResult = this.resolveNamedType(nameNode);
if (typeNameResult.kind === "ERROR") {
return (0, DiagnosticError_1.err)([typeNameResult.err]);
}
var symbol = this._unresolvedTypes.get(nameNode);
if (symbol == null) {
// This should have already been handled by resolveNamedType
throw new Error("Expected to find unresolved type.");
}
var nameDefinition = this._symbolToName.get(symbol);
if (nameDefinition == null) {
// This should have already been handled by resolveNamedType
throw new Error("Expected to find name definition.");
}
return (0, DiagnosticError_1.ok)(nameDefinition);
};
TypeContext.prototype.validateInterfaceImplementorsHaveTypenameField = function () {
return (0, DiagnosticError_1.ok)(null);
};
TypeContext.prototype.getDestFilePath = function (sourceFile) {
return (0, gratsRoot_1.getRelativeOutputPath)(this._options, sourceFile);
};
return TypeContext;
}());
exports.TypeContext = TypeContext;
"use strict";
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });

@@ -16,6 +16,9 @@ import { GraphQLError, Location, Source } from "graphql";

export declare function err<E>(err: E): Err<E>;
export declare function collectResults<T>(results: DiagnosticsResult<T>[]): DiagnosticsResult<T[]>;
export declare function combineResults<T, U>(result1: DiagnosticsResult<T>, result2: DiagnosticsResult<U>): DiagnosticsResult<[T, U]>;
export declare class ReportableDiagnostics {
_host: ts.CompilerHost;
_host: ts.FormatDiagnosticsHost;
_diagnostics: ts.Diagnostic[];
constructor(host: ts.CompilerHost, diagnostics: ts.Diagnostic[]);
constructor(host: ts.FormatDiagnosticsHost, diagnostics: ts.Diagnostic[]);
static fromDiagnostics(diagnostics: ts.Diagnostic[]): ReportableDiagnostics;
formatDiagnosticsWithColorAndContext(): string;

@@ -26,4 +29,7 @@ formatDiagnosticsWithContext(): string;

export declare function graphQlErrorToDiagnostic(error: GraphQLError): ts.Diagnostic;
export declare function diagnosticAtGraphQLLocation(message: string, loc: Location): ts.Diagnostic;
export declare function gqlErr(loc: Location, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.Diagnostic;
export declare function gqlRelated(loc: Location, message: string): ts.DiagnosticRelatedInformation;
export declare function tsErr(node: ts.Node, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.Diagnostic;
export declare function tsRelated(node: ts.Node, message: string): ts.DiagnosticRelatedInformation;
export declare function graphqlSourceToSourceFile(source: Source): ts.SourceFile;
export {};
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __read = (this && this.__read) || function (o, n) {

@@ -18,15 +29,13 @@ var m = typeof Symbol === "function" && o[Symbol.iterator];

};
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
return to.concat(ar || Array.prototype.slice.call(from));
};
exports.__esModule = true;
exports.graphqlSourceToSourceFile = exports.diagnosticAtGraphQLLocation = exports.graphQlErrorToDiagnostic = exports.FAKE_ERROR_CODE = exports.ReportableDiagnostics = exports.err = exports.ok = void 0;
Object.defineProperty(exports, "__esModule", { value: true });
exports.graphqlSourceToSourceFile = exports.tsRelated = exports.tsErr = exports.gqlRelated = exports.gqlErr = exports.graphQlErrorToDiagnostic = exports.FAKE_ERROR_CODE = exports.ReportableDiagnostics = exports.combineResults = exports.collectResults = exports.err = exports.ok = void 0;
var ts = require("typescript");

@@ -41,2 +50,43 @@ function ok(value) {

exports.err = err;
function collectResults(results) {
var e_1, _a;
var errors = [];
var values = [];
try {
for (var results_1 = __values(results), results_1_1 = results_1.next(); !results_1_1.done; results_1_1 = results_1.next()) {
var result = results_1_1.value;
if (result.kind === "ERROR") {
errors.push.apply(errors, __spreadArray([], __read(result.err), false));
}
else {
values.push(result.value);
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (results_1_1 && !results_1_1.done && (_a = results_1.return)) _a.call(results_1);
}
finally { if (e_1) throw e_1.error; }
}
if (errors.length > 0) {
return err(errors);
}
return ok(values);
}
exports.collectResults = collectResults;
function combineResults(result1, result2) {
if (result1.kind === "ERROR" && result2.kind === "ERROR") {
return err(__spreadArray(__spreadArray([], __read(result1.err), false), __read(result2.err), false));
}
if (result1.kind === "ERROR") {
return result1;
}
if (result2.kind === "ERROR") {
return result2;
}
return ok([result1.value, result2.value]);
}
exports.combineResults = combineResults;
var ReportableDiagnostics = /** @class */ (function () {

@@ -47,2 +97,12 @@ function ReportableDiagnostics(host, diagnostics) {

}
// If you don't have a host, for example if you error while parsing the
// tsconfig, you can use this method and one will be created for you.
ReportableDiagnostics.fromDiagnostics = function (diagnostics) {
var formatHost = {
getCanonicalFileName: function (path) { return path; },
getCurrentDirectory: ts.sys.getCurrentDirectory,
getNewLine: function () { return ts.sys.newLine; },
};
return new ReportableDiagnostics(formatHost, diagnostics);
};
ReportableDiagnostics.prototype.formatDiagnosticsWithColorAndContext = function () {

@@ -61,3 +121,3 @@ var formatted = ts.formatDiagnosticsWithColorAndContext(this._diagnostics, this._host);

exports.ReportableDiagnostics = ReportableDiagnostics;
// A madeup error code that we use to fake a TypeScript error code.
// A made-up error code that we use to fake a TypeScript error code.
// We pick a very random number to avoid collisions with real error messages.

@@ -73,3 +133,3 @@ exports.FAKE_ERROR_CODE = 349389149282;

function graphQlErrorToDiagnostic(error) {
var e_1, _a;
var e_2, _a;
var position = error.positions[0];

@@ -79,3 +139,3 @@ if (position == null) {

}
// Start with baseline location infromation
// Start with baseline location information
var start = position;

@@ -99,18 +159,11 @@ var length = 1;

}
relatedInformation.push({
category: ts.DiagnosticCategory.Message,
code: exports.FAKE_ERROR_CODE,
messageText: "Related location",
file: graphqlSourceToSourceFile(relatedNode.loc.source),
start: relatedNode.loc.start,
length: relatedNode.loc.end - relatedNode.loc.start
});
relatedInformation.push(gqlRelated(relatedNode.loc, "Related location"));
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (rest_1_1 && !rest_1_1.done && (_a = rest_1["return"])) _a.call(rest_1);
if (rest_1_1 && !rest_1_1.done && (_a = rest_1.return)) _a.call(rest_1);
}
finally { if (e_1) throw e_1.error; }
finally { if (e_2) throw e_2.error; }
}

@@ -131,7 +184,7 @@ }

length: length,
relatedInformation: relatedInformation
relatedInformation: relatedInformation,
};
}
exports.graphQlErrorToDiagnostic = graphQlErrorToDiagnostic;
function diagnosticAtGraphQLLocation(message, loc) {
function gqlErr(loc, message, relatedInformation) {
return {

@@ -143,6 +196,44 @@ messageText: message,

start: loc.start,
length: loc.end - loc.start
length: loc.end - loc.start,
relatedInformation: relatedInformation,
};
}
exports.diagnosticAtGraphQLLocation = diagnosticAtGraphQLLocation;
exports.gqlErr = gqlErr;
function gqlRelated(loc, message) {
return {
category: ts.DiagnosticCategory.Message,
code: exports.FAKE_ERROR_CODE,
messageText: message,
file: graphqlSourceToSourceFile(loc.source),
start: loc.start,
length: loc.end - loc.start,
};
}
exports.gqlRelated = gqlRelated;
function tsErr(node, message, relatedInformation) {
var start = node.getStart();
var length = node.getEnd() - start;
var sourceFile = node.getSourceFile();
return {
messageText: message,
file: sourceFile,
code: exports.FAKE_ERROR_CODE,
category: ts.DiagnosticCategory.Error,
start: start,
length: length,
relatedInformation: relatedInformation,
};
}
exports.tsErr = tsErr;
function tsRelated(node, message) {
return {
category: ts.DiagnosticCategory.Message,
code: 0,
file: node.getSourceFile(),
start: node.getStart(),
length: node.getWidth(),
messageText: message,
};
}
exports.tsRelated = tsRelated;
function graphqlSourceToSourceFile(source) {

@@ -149,0 +240,0 @@ return ts.createSourceFile(source.name, source.body, ts.ScriptTarget.Latest);

@@ -13,3 +13,3 @@ "use strict";

};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extend = exports.DefaultMap = void 0;

@@ -43,3 +43,3 @@ var DefaultMap = /** @class */ (function () {

try {
if (b_1_1 && !b_1_1.done && (_a = b_1["return"])) _a.call(b_1);
if (b_1_1 && !b_1_1.done && (_a = b_1.return)) _a.call(b_1);
}

@@ -46,0 +46,0 @@ finally { if (e_1) throw e_1.error; }

@@ -13,3 +13,3 @@ "use strict";

};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.traverseJSDocTags = void 0;

@@ -42,3 +42,3 @@ var ts = require("typescript");

try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}

@@ -45,0 +45,0 @@ finally { if (e_1) throw e_1.error; }

{
"name": "grats",
"version": "0.0.0-main-6626f659",
"version": "0.0.0-main-663d2ac4",
"main": "dist/src/index.js",

@@ -12,8 +12,8 @@ "bin": "dist/src/cli.js",

"dependencies": {
"@graphql-tools/utils": "^9.2.1",
"commander": "^10.0.0",
"graphql": "^16.6.0",
"typescript": "^4.9.5"
"typescript": "^5.0.2"
},
"devDependencies": {
"@graphql-tools/utils": "^9.2.1",
"@types/node": "^18.14.6",

@@ -26,2 +26,3 @@ "@typescript-eslint/eslint-plugin": "^5.55.0",

"path-browserify": "^1.0.1",
"prettier": "^2.8.7",
"process": "^0.11.10",

@@ -33,3 +34,3 @@ "ts-node": "^10.9.1"

},
"packageManager": "pnpm@8.1.1",
"packageManager": "pnpm@8.12.0",
"engines": {

@@ -43,4 +44,5 @@ "node": ">=16 <=21",

"build": "tsc --build",
"lint": "eslint src/**/*.ts"
"format": "prettier . --write",
"lint": "eslint src/**/*.ts && prettier . --check"
}
}

@@ -1,5 +0,1 @@

# -=[ ALPHA SOFTWARE ]=-
**Grats is still experimental. Feel free to try it out and give feedback, but they api is still in flux**
# Grats: Implementation-First GraphQL for TypeScript

@@ -9,2 +5,4 @@

_Beta Software: Grats is largely stable and being used in production in multiple places. If you encounter any issues, dont hesitate to let us know._
**What if building a GraphQL server were as simple as just writing functions?**

@@ -21,4 +19,30 @@

## Read the docs: https://grats.capt.dev/
## Example
Here's what it looks like to define a User type with a greeting field using Grats:
```ts
/** @gqlType */
class User {
/** @gqlField */
name: string;
/** @gqlField */
greet(args: { greeting: string }): string {
return `${args.greeting}, ${this.name}`;
}
}
```
After running `npx grats`, you'll find a `schema.ts` module that exports an executable schema, and a `schema.graphql` file contins your GraphQL schema definition:
```graphql
type User {
name: String
greet(greeting: String!): String
}
```
That's just the begining! To learn more, **Read the docs: https://grats.capt.dev/**
## Contributing

@@ -25,0 +49,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc