Huge News!Announcing our $40M Series B led by Abstract Ventures.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-05c86aca to 0.0.0-main-05c9a8df

dist/src/codegen.d.ts

41

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

@@ -9,3 +9,4 @@ "bin": "dist/src/cli.js",

"files": [
"dist"
"dist",
"!dist/src/tests"
],

@@ -15,13 +16,15 @@ "scripts": {

"integration-tests": "node src/tests/integration.mjs",
"build": "tsc --build",
"lint": "eslint src/**/*.ts"
"build": "rm -rf dist/ && tsc --build",
"format": "prettier . --write",
"lint": "eslint . && 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",
"@types/semver": "^7.5.6",
"@typescript-eslint/eslint-plugin": "^5.55.0",

@@ -33,3 +36,5 @@ "@typescript-eslint/parser": "^5.55.0",

"path-browserify": "^1.0.1",
"prettier": "^2.8.7",
"process": "^0.11.10",
"semver": "^7.5.4",
"ts-node": "^10.9.1"

@@ -40,7 +45,27 @@ },

},
"packageManager": "pnpm@8.1.1",
"packageManager": "pnpm@8.12.0",
"engines": {
"node": ">=16 <=21",
"pnpm": "^8"
}
},
"bugs": {
"url": "https://github.com/captbaritone/grats/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/captbaritone/grats.git"
},
"author": {
"name": "Jordan Eldredge",
"email": "jordan@jordaneldredge.com",
"url": "https://jordaneldredge.com"
},
"keywords": [
"graphql",
"typescript",
"resolvers",
"schema",
"code-first",
"implementation-first"
]
}

108

dist/src/cli.js

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

};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.formatLoc = void 0;
var graphql_1 = require("graphql");
var _1 = require("./");
var lib_1 = require("./lib");
var utils_1 = require("@graphql-tools/utils");
var commander_1 = require("commander");

@@ -51,2 +49,5 @@ var fs_1 = require("fs");

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

@@ -57,9 +58,14 @@ 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")
.option("--watch", "Watch for changes and rebuild schema files as needed")
.action(function (_a) {
var output = _a.output, tsconfig = _a.tsconfig;
var tsconfig = _a.tsconfig, watch = _a.watch;
return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_b) {
build(output, tsconfig);
if (watch) {
startWatchMode(tsconfig);
}
else {
runBuild(tsconfig);
}
return [2 /*return*/];

@@ -75,3 +81,9 @@ });

var tsconfig = _a.tsconfig;
var schema = buildSchema(tsconfig);
var config = getTsConfigOrReportAndExit(tsconfig).config;
var schemaAndDocResult = (0, lib_1.buildSchemaAndDocResult)(config);
if (schemaAndDocResult.kind === "ERROR") {
console.error(schemaAndDocResult.err.formatDiagnosticsWithColorAndContext());
process.exit(1);
}
var schema = schemaAndDocResult.value.schema;
var loc = (0, Locate_1.locate)(schema, entity);

@@ -85,31 +97,65 @@ if (loc.kind === "ERROR") {

program.parse();
function build(output, tsconfig) {
var schema = buildSchema(tsconfig);
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, "`."));
}
else {
console.log(schemaStr);
}
/**
* Run the compiler in watch mode.
*/
function startWatchMode(tsconfig) {
var _a = getTsConfigOrReportAndExit(tsconfig), config = _a.config, configPath = _a.configPath;
var watchHost = ts.createWatchCompilerHost(configPath, {}, ts.sys, ts.createSemanticDiagnosticsBuilderProgram, function (diagnostic) { return reportDiagnostics([diagnostic]); }, function (diagnostic) { return reportDiagnostics([diagnostic]); });
watchHost.afterProgramCreate = function (program) {
// For now we just rebuild the schema on every change.
var schemaResult = (0, lib_1.extractSchemaAndDoc)(config, program.getProgram());
if (schemaResult.kind === "ERROR") {
reportDiagnostics(schemaResult.err);
return;
}
writeSchemaFilesAndReport(schemaResult.value, config, configPath);
};
ts.createWatchProgram(watchHost);
}
function buildSchema(tsconfig) {
if (tsconfig && !(0, fs_1.existsSync)(tsconfig)) {
console.error("Grats: Could not find tsconfig.json at `".concat(tsconfig, "`."));
/**
* Run the compiler performing a single build.
*/
function runBuild(tsconfig) {
var _a = getTsConfigOrReportAndExit(tsconfig), config = _a.config, configPath = _a.configPath;
var schemaAndDocResult = (0, lib_1.buildSchemaAndDocResult)(config);
if (schemaAndDocResult.kind === "ERROR") {
console.error(schemaAndDocResult.err.formatDiagnosticsWithColorAndContext());
process.exit(1);
}
var parsed = (0, _1.getParsedTsConfig)(tsconfig);
// FIXME: Validate config!
// https://github.com/tsconfig/bases
var schemaResult = (0, lib_1.buildSchemaResult)(parsed);
if (schemaResult.kind === "ERROR") {
console.error(schemaResult.err.formatDiagnosticsWithColorAndContext());
writeSchemaFilesAndReport(schemaAndDocResult.value, config, configPath);
}
/**
* Serializes the SDL and TypeScript schema to disk and reports to the console.
*/
function writeSchemaFilesAndReport(schemaAndDoc, config, configPath) {
var schema = schemaAndDoc.schema, doc = schemaAndDoc.doc;
var gratsOptions = config.raw.grats;
var dest = (0, path_1.resolve)((0, path_1.dirname)(configPath), gratsOptions.tsSchema);
var code = (0, printSchema_1.printExecutableSchema)(schema, gratsOptions, dest);
(0, fs_1.writeFileSync)(dest, code);
console.error("Grats: Wrote TypeScript schema to `".concat(dest, "`."));
var schemaStr = (0, printSchema_1.printGratsSDL)(doc, 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, "`."));
}
/**
* Utility function to report diagnostics to the console.
*/
function reportDiagnostics(diagnostics) {
var reportable = DiagnosticError_1.ReportableDiagnostics.fromDiagnostics(diagnostics);
console.error(reportable.formatDiagnosticsWithColorAndContext());
}
// Locate and read the tsconfig.json file
function getTsConfigOrReportAndExit(tsconfig) {
var configPath = tsconfig || ts.findConfigFile(process.cwd(), ts.sys.fileExists);
if (configPath == null) {
throw new Error("Grats: Could not find tsconfig.json");
}
var optionsResult = (0, _1.getParsedTsConfig)(configPath);
if (optionsResult.kind === "ERROR") {
console.error(optionsResult.err.formatDiagnosticsWithColorAndContext());
process.exit(1);
}
return schemaResult.value;
return { configPath: configPath, config: optionsResult.value };
}

@@ -116,0 +162,0 @@ // Format a location for printing to the console. Tools like VS Code and iTerm

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

export declare const ISSUE_URL = "https://github.com/captbaritone/grats/issues";
/**

@@ -33,2 +34,3 @@ * Error messages for Grats

export declare function inputTypeFieldNotProperty(): string;
export declare function inputInterfaceFieldNotProperty(): string;
export declare function inputFieldUntyped(): string;

@@ -54,3 +56,3 @@ export declare function typeTagOnUnnamedClass(): string;

export declare function methodMissingType(): string;
export declare function promiseMissingTypeArg(): string;
export declare function wrapperMissingTypeArg(): string;
export declare function cannotResolveSymbolForDescription(): string;

@@ -67,8 +69,7 @@ export declare function propertyFieldMissingType(): string;

export declare function pluralTypeMissingParameter(): string;
export declare function expectedIdentifier(): string;
export declare function expectedNameIdentifier(): string;
export declare function killsParentOnExceptionWithWrongConfig(): string;
export declare function killsParentOnExceptionOnNullable(): string;
export declare function nonNullTypeCannotBeOptional(): string;
export declare function mergedInterfaces(interfaceName: string): string;
export declare function implementsTagMissingValue(): string;
export declare function mergedInterfaces(): string;
export declare function implementsTagOnClass(): string;

@@ -90,1 +91,10 @@ export declare function implementsTagOnInterface(): 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;
export declare function gqlTagInLineComment(): string;
export declare function gqlTagInNonJSDocBlockComment(): string;
export declare function gqlTagInDetachedJSDocBlockComment(): string;
"use strict";
exports.__esModule = true;
exports.defaultArgPropertyMissingName = exports.defaultArgElementIsNotAssignment = exports.defaultValueIsNotLiteral = exports.ambiguousNumberType = exports.expectedOneNonNullishType = exports.propertyFieldMissingType = exports.cannotResolveSymbolForDescription = exports.promiseMissingTypeArg = exports.methodMissingType = exports.gqlEntityMissingName = exports.enumVariantMissingInitializer = exports.enumVariantNotStringLiteral = exports.enumTagOnInvalidNode = exports.argNotTyped = exports.argNameNotLiteral = exports.argIsNotProperty = exports.argumentParamIsNotObject = exports.argumentParamIsMissingType = exports.typeNameDoesNotMatchExpected = exports.typeNameTypeNotStringLiteral = exports.typeNameMissingTypeAnnotation = exports.typeNameInitializerWrong = exports.typeNameInitializeNotString = exports.typeNameMissingInitializer = exports.typeNameNotDeclaration = exports.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;
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultValueIsNotLiteral = exports.ambiguousNumberType = exports.expectedOneNonNullishType = exports.propertyFieldMissingType = exports.cannotResolveSymbolForDescription = exports.wrapperMissingTypeArg = 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.inputInterfaceFieldNotProperty = 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 = exports.ISSUE_URL = void 0;
exports.gqlTagInDetachedJSDocBlockComment = exports.gqlTagInNonJSDocBlockComment = exports.gqlTagInLineComment = 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.mergedInterfaces = exports.nonNullTypeCannotBeOptional = exports.killsParentOnExceptionOnNullable = exports.killsParentOnExceptionWithWrongConfig = exports.expectedNameIdentifier = exports.pluralTypeMissingParameter = exports.unknownGraphQLType = exports.unsupportedTypeLiteral = exports.defaultArgPropertyMissingInitializer = exports.defaultArgPropertyMissingName = exports.defaultArgElementIsNotAssignment = void 0;
var Extractor_1 = require("./Extractor");
exports.ISSUE_URL = "https://github.com/captbaritone/grats/issues";
// 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",
commentSyntax: "https://grats.capt.dev/docs/getting-started/comment-syntax",
};

@@ -40,31 +41,31 @@ /**

function invalidTypeTagUsage() {
return "`@".concat(Extractor_1.TYPE_TAG, "` can only be used on class or interface declarations.");
return "`@".concat(Extractor_1.TYPE_TAG, "` can only be used on class, interface or type declarations. e.g. `class MyType {}`");
}
exports.invalidTypeTagUsage = invalidTypeTagUsage;
function invalidScalarTagUsage() {
return "`@".concat(Extractor_1.SCALAR_TAG, "` can only be used on type alias declarations.");
return "`@".concat(Extractor_1.SCALAR_TAG, "` can only be used on type alias declarations. e.g. `type MyScalar = string`");
}
exports.invalidScalarTagUsage = invalidScalarTagUsage;
function invalidInterfaceTagUsage() {
return "`@".concat(Extractor_1.INTERFACE_TAG, "` can only be used on interface declarations.");
return "`@".concat(Extractor_1.INTERFACE_TAG, "` can only be used on interface declarations. e.g. `interface MyInterface {}`");
}
exports.invalidInterfaceTagUsage = invalidInterfaceTagUsage;
function invalidEnumTagUsage() {
return "`@".concat(Extractor_1.ENUM_TAG, "` can only be used on enum declarations or TypeScript unions.");
return "`@".concat(Extractor_1.ENUM_TAG, "` can only be used on enum declarations or TypeScript unions. e.g. `enum MyEnum {}` or `type MyEnum = \"foo\" | \"bar\"`");
}
exports.invalidEnumTagUsage = invalidEnumTagUsage;
function invalidInputTagUsage() {
return "`@".concat(Extractor_1.INPUT_TAG, "` can only be used on type alias declarations.");
return "`@".concat(Extractor_1.INPUT_TAG, "` can only be used on type alias or interface declarations. e.g. `type MyInput = { foo: string }` or `interface MyInput { foo: string }`");
}
exports.invalidInputTagUsage = invalidInputTagUsage;
function invalidUnionTagUsage() {
return "`@".concat(Extractor_1.UNION_TAG, "` can only be used on type alias declarations.");
return "`@".concat(Extractor_1.UNION_TAG, "` can only be used on type alias declarations. e.g. `type MyUnion = TypeA | TypeB`");
}
exports.invalidUnionTagUsage = invalidUnionTagUsage;
function expectedUnionTypeNode() {
return "Expected a TypeScript union. `@".concat(Extractor_1.UNION_TAG, "` can only be used on TypeScript unions.");
return "Expected a TypeScript union. `@".concat(Extractor_1.UNION_TAG, "` can only be used on TypeScript unions. e.g. `type MyUnion = TypeA | TypeB`");
}
exports.expectedUnionTypeNode = expectedUnionTypeNode;
function expectedUnionTypeReference() {
return "Expected `@".concat(Extractor_1.UNION_TAG, "` union members to be type references.");
return "Expected `@".concat(Extractor_1.UNION_TAG, "` union members to be type references. Grats expects union members to be references to something annotated with `@gqlType`.");
}

@@ -77,131 +78,137 @@ exports.expectedUnionTypeReference = expectedUnionTypeReference;

function invalidReturnTypeForFunctionField() {
return "Expected GraphQL field to have an explicit return type.";
return 'Expected GraphQL field to have an explicit return type. This is needed to allow Grats to "see" the type of the field.';
}
exports.invalidReturnTypeForFunctionField = invalidReturnTypeForFunctionField;
function functionFieldNotTopLevel() {
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` function to be a top-level declaration.");
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` function to be a top-level declaration. Grats needs to import resolver functions into it's generated schema module, so the resolver function must be an exported.");
}
exports.functionFieldNotTopLevel = functionFieldNotTopLevel;
var FUNCTION_PARENT_TYPE_CONTEXT = "Grats treats the first argument as the parent object of the field. Therefore Grats needs to see the _type_ of the first argument in order to know to which type/interface this field should be added.";
function functionFieldParentTypeMissing() {
return "Expected first argument of a `@".concat(Extractor_1.FIELD_TAG, "` function to have an explicit type annotation.");
return "Expected first argument of a `@".concat(Extractor_1.FIELD_TAG, "` function to have an explicit type annotation. ").concat(FUNCTION_PARENT_TYPE_CONTEXT);
}
exports.functionFieldParentTypeMissing = functionFieldParentTypeMissing;
function functionFieldParentTypeNotValid() {
return "Expected first argument of a `@".concat(Extractor_1.FIELD_TAG, "` function to be typed as a `@").concat(Extractor_1.TYPE_TAG, "` type.");
return "Expected first argument of a `@".concat(Extractor_1.FIELD_TAG, "` function to be typed as a type reference. ").concat(FUNCTION_PARENT_TYPE_CONTEXT);
}
exports.functionFieldParentTypeNotValid = functionFieldParentTypeNotValid;
function functionFieldNotNamed() {
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` function to be named.");
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` function to be named. Grats uses the name of the function to derive the name of the GraphQL field. Additionally, Grats needs to import resolver functions into it's generated schema module, so the resolver function must be a named export.");
}
exports.functionFieldNotNamed = functionFieldNotNamed;
function functionFieldDefaultExport() {
return "Expected a `@".concat(Extractor_1.FIELD_TAG, "` function to be a named export, not a default export.");
return "Expected a `@".concat(Extractor_1.FIELD_TAG, "` function to be a named export, not a default export. Grats needs to import resolver functions into it's generated schema module, so the resolver function must be a named export.");
}
exports.functionFieldDefaultExport = functionFieldDefaultExport;
function functionFieldNotNamedExport() {
return "Expected a `@".concat(Extractor_1.FIELD_TAG, "` function to be a named export.");
return "Expected a `@".concat(Extractor_1.FIELD_TAG, "` function to be a named export. Grats needs to import resolver functions into it's generated schema module, so the resolver function must be a named export.");
}
exports.functionFieldNotNamedExport = functionFieldNotNamedExport;
function inputTypeNotLiteral() {
return "`@".concat(Extractor_1.INPUT_TAG, "` can only be used on type literals.");
return "`@".concat(Extractor_1.INPUT_TAG, "` can only be used on type literals. e.g. `type MyInput = { foo: string }`");
}
exports.inputTypeNotLiteral = inputTypeNotLiteral;
function inputTypeFieldNotProperty() {
return "`@".concat(Extractor_1.INPUT_TAG, "` types only support property signature members.");
return "`@".concat(Extractor_1.INPUT_TAG, "` types only support property signature members. e.g. `type MyInput = { foo: string }`");
}
exports.inputTypeFieldNotProperty = inputTypeFieldNotProperty;
function inputInterfaceFieldNotProperty() {
return "`@".concat(Extractor_1.INPUT_TAG, "` interfaces only support property signature members. e.g. `interface MyInput { foo: string }`");
}
exports.inputInterfaceFieldNotProperty = inputInterfaceFieldNotProperty;
function inputFieldUntyped() {
return "Input field must have a type annotation.";
return 'Input field must have an explicit type annotation. Grats uses the type annotation to determine the type of the field, so it must be explicit in order for Grats to "see" the type.';
}
exports.inputFieldUntyped = inputFieldUntyped;
function typeTagOnUnnamedClass() {
return "Unexpected `@".concat(Extractor_1.TYPE_TAG, "` annotation on unnamed class declaration.");
return "Unexpected `@".concat(Extractor_1.TYPE_TAG, "` annotation on unnamed class declaration. Grats uses the name of the class to derive the name of the GraphQL type. Consider naming the class.");
}
exports.typeTagOnUnnamedClass = typeTagOnUnnamedClass;
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`.");
}
exports.typeTagOnAliasOfNonObjectOrUnknown = typeTagOnAliasOfNonObjectOrUnknown;
function typeNameNotDeclaration() {
return "Expected `__typename` to be a property declaration.";
return "Expected `__typename` to be a property declaration. For example: `__typename: \"MyType\"`.";
}
exports.typeNameNotDeclaration = typeNameNotDeclaration;
var TYPENAME_CONTEXT = "This lets Grats know that the GraphQL executor will be able to derive the type of the object at runtime.";
function typeNameMissingInitializer() {
return "Expected `__typename` property to have an initializer or a string literal type. For example: `__typename = \"MyType\"` or `__typename: \"MyType\";`.";
return "Expected `__typename` property to have an initializer or a string literal type. For example: `__typename = \"MyType\"` or `__typename: \"MyType\";`. ".concat(TYPENAME_CONTEXT);
}
exports.typeNameMissingInitializer = typeNameMissingInitializer;
function typeNameInitializeNotString() {
return "Expected `__typename` property initializer to be a string literal. For example: `__typename = \"MyType\"` or `__typename: \"MyType\";`.";
return "Expected `__typename` property initializer to be a string literal. For example: `__typename = \"MyType\"` or `__typename: \"MyType\";`. ".concat(TYPENAME_CONTEXT);
}
exports.typeNameInitializeNotString = typeNameInitializeNotString;
function typeNameInitializerWrong(expected, actual) {
return "Expected `__typename` property initializer to be `\"".concat(expected, "\"`, found `\"").concat(actual, "\"`.");
return "Expected `__typename` property initializer to be `\"".concat(expected, "\"`, found `\"").concat(actual, "\"`. ").concat(TYPENAME_CONTEXT);
}
exports.typeNameInitializerWrong = typeNameInitializerWrong;
function typeNameMissingTypeAnnotation(expected) {
return "Expected `__typename` property signature to specify the typename as a string literal string type. For example `__typename: \"".concat(expected, "\";`");
return "Expected `__typename` property signature to specify the typename as a string literal string type. For example `__typename: \"".concat(expected, "\";`. ").concat(TYPENAME_CONTEXT);
}
exports.typeNameMissingTypeAnnotation = typeNameMissingTypeAnnotation;
function typeNameTypeNotStringLiteral(expected) {
return "Expected `__typename` property signature to specify the typename as a string literal string type. For example `__typename: \"".concat(expected, "\";`");
return "Expected `__typename` property signature to specify the typename as a string literal string type. For example `__typename: \"".concat(expected, "\";`. ").concat(TYPENAME_CONTEXT);
}
exports.typeNameTypeNotStringLiteral = typeNameTypeNotStringLiteral;
function typeNameDoesNotMatchExpected(expected) {
return "Expected `__typename` property to be `\"".concat(expected, "\"`");
return "Expected `__typename` property to be `\"".concat(expected, "\"`. ").concat(TYPENAME_CONTEXT);
}
exports.typeNameDoesNotMatchExpected = typeNameDoesNotMatchExpected;
function argumentParamIsMissingType() {
return "Expected GraphQL field arguments to have a TypeScript type. If there are no arguments, you can use `args: unknown`.";
return "Expected GraphQL field arguments to have an explicit type annotation. If there are no arguments, you can use `args: unknown`. Grats needs to be able to see the type of the arguments to generate a GraphQL schema.";
}
exports.argumentParamIsMissingType = argumentParamIsMissingType;
function argumentParamIsNotObject() {
return "Expected GraphQL field arguments to be typed using a literal object: `{someField: string}`. If there are no arguments, you can use `args: unknown`.";
return "Expected GraphQL field arguments to be typed using an inline literal object: `{someField: string}`. If there are no arguments, you can use `args: unknown`. Grats needs to be able to see the type of the arguments to generate a GraphQL schema.";
}
exports.argumentParamIsNotObject = argumentParamIsNotObject;
function argIsNotProperty() {
return "Expected GraphQL field argument type to be a property signature.";
return "Expected GraphQL field argument type to be a property signature. For example: `{ someField: string }`. Grats needs to be able to see the type of the arguments to generate a GraphQL schema.";
}
exports.argIsNotProperty = argIsNotProperty;
function argNameNotLiteral() {
return "Expected GraphQL field argument names to be a literal.";
return "Expected GraphQL field argument names to be a literal. For example: `{ someField: string }`. Grats needs to be able to see the type of the arguments to generate a GraphQL schema.";
}
exports.argNameNotLiteral = argNameNotLiteral;
function argNotTyped() {
return "Expected GraphQL field argument to have a type.";
return "Expected GraphQL field argument to have an explicit type annotation. For example: `{ someField: string }`. Grats needs to be able to see the type of the arguments to generate a GraphQL schema.";
}
exports.argNotTyped = argNotTyped;
function enumTagOnInvalidNode() {
return "Expected `@".concat(Extractor_1.ENUM_TAG, "` to be a union type, or a string literal in the edge case of a single value enum.");
return "Expected `@".concat(Extractor_1.ENUM_TAG, "` to be a union type, or a string literal in the edge case of a single value enum. For example: `type MyEnum = \"foo\" | \"bar\"` or `type MyEnum = \"foo\"`.");
}
exports.enumTagOnInvalidNode = enumTagOnInvalidNode;
function enumVariantNotStringLiteral() {
return "Expected `@".concat(Extractor_1.ENUM_TAG, "` enum members to be string literal types. For example: `'foo'`.");
return "Expected `@".concat(Extractor_1.ENUM_TAG, "` enum members to be string literal types. For example: `'foo'`. Grats needs to be able to see the concrete value of the enum member to generate the GraphQL schema.");
}
exports.enumVariantNotStringLiteral = enumVariantNotStringLiteral;
function enumVariantMissingInitializer() {
return "Expected `@".concat(Extractor_1.ENUM_TAG, "` enum members to have string literal initializers. For example: `FOO = 'foo'`.");
return "Expected `@".concat(Extractor_1.ENUM_TAG, "` enum members to have string literal initializers. For example: `FOO = 'foo'`. In GraphQL enum values are strings, and Grats needs to be able to see the concrete value of the enum member to generate the GraphQL schema.");
}
exports.enumVariantMissingInitializer = enumVariantMissingInitializer;
function gqlEntityMissingName() {
return "Expected GraphQL entity to have a name.";
return "Expected GraphQL entity to have a name. Grats uses the name of the entity to derive the name of the GraphQL construct.";
}
exports.gqlEntityMissingName = gqlEntityMissingName;
function methodMissingType() {
return "Expected GraphQL field to have a type.";
return "Expected GraphQL field methods to have an explicitly defined return type. Grats needs to be able to see the type of the field to generate its type in the GraphQL schema.";
}
exports.methodMissingType = methodMissingType;
function promiseMissingTypeArg() {
return "Expected type reference to have type arguments.";
function wrapperMissingTypeArg() {
return "Expected wrapper type reference to have type arguments. Grats needs to be able to see the return type in order to generate a GraphQL schema.";
}
exports.promiseMissingTypeArg = promiseMissingTypeArg;
exports.wrapperMissingTypeArg = wrapperMissingTypeArg;
function cannotResolveSymbolForDescription() {
return "Expected TypeScript to be able to resolve this GraphQL entity to a symbol.";
return "Expected TypeScript to be able to resolve this GraphQL entity to a symbol. Is it possible that this type is not defined in this file? Grats needs to follow type references to their declaration in order to determine which GraphQL name is being referenced.";
}
exports.cannotResolveSymbolForDescription = cannotResolveSymbolForDescription;
function propertyFieldMissingType() {
return "Expected GraphQL field to have a type.";
return "Expected GraphQL field to have an explicitly defined type annotation. Grats needs to be able to see the type of the field to generate a field's type in the GraphQL schema.";
}
exports.propertyFieldMissingType = propertyFieldMissingType;
function expectedOneNonNullishType() {
return "Expected exactly one non-nullish type.";
return "Expected exactly one non-nullish type. GraphQL does not support fields returning an arbitrary union of types. Consider defining an explicit `@".concat(Extractor_1.UNION_TAG, "` union type and returning that.");
}

@@ -214,50 +221,50 @@ exports.expectedOneNonNullishType = expectedOneNonNullishType;

function defaultValueIsNotLiteral() {
return "Expected GraphQL field argument default values to be a literal.";
return 'Expected GraphQL field argument default values to be a literal. Grats interprets argument defaults as GraphQL default values, which must be literals. For example: `10` or `"foo"`.';
}
exports.defaultValueIsNotLiteral = defaultValueIsNotLiteral;
function defaultArgElementIsNotAssignment() {
return "Expected object literal property to be a property assignment.";
return "Expected property to be a default assignment. For example: `{ first = 10}`. Grats needs to extract a literal GraphQL value here, and that requires Grats being able to see the literal value in the source code.";
}
exports.defaultArgElementIsNotAssignment = defaultArgElementIsNotAssignment;
function defaultArgPropertyMissingName() {
return "Expected object literal property to have a name.";
return "Expected object literal property to have a name. Grats needs to extract a literal value here, and that requires Grats being able to see the literal value and its field name in the source code.";
}
exports.defaultArgPropertyMissingName = defaultArgPropertyMissingName;
function defaultArgPropertyMissingInitializer() {
return "Expected object literal property to have an initializer. For example: `{ offset = 10}`.";
return "Expected object literal property to have an initializer. For example: `{ offset = 10}`. Grats needs to extract a literal GraphQL value here, and that requires Grats being able to see the literal value in the source code.";
}
exports.defaultArgPropertyMissingInitializer = defaultArgPropertyMissingInitializer;
function unsupportedTypeLiteral() {
return "Unexpected type literal. You may want to define a named GraphQL type elsewhere and reference it here.";
return "Unexpected type literal. Grats expects types in GraphQL positions to be scalar types, or reference a named GraphQL type directly. You may want to define a named GraphQL type elsewhere and reference it here.";
}
exports.unsupportedTypeLiteral = unsupportedTypeLiteral;
function unknownGraphQLType() {
return "Unknown GraphQL type.";
return "Unknown GraphQL type. Grats doe not know how to map this type to a GraphQL type. You may want to define a named GraphQL type elsewhere and reference it here. If you think Grats should be able to infer a GraphQL type from this type, please file an issue.";
}
exports.unknownGraphQLType = unknownGraphQLType;
function pluralTypeMissingParameter() {
return "Expected type reference to have type arguments.";
return "Expected wrapper type reference to have type arguments. Grats needs to be able to see the return type in order to generate a GraphQL schema.";
}
exports.pluralTypeMissingParameter = pluralTypeMissingParameter;
function expectedIdentifier() {
return "Expected an identifier.";
function expectedNameIdentifier() {
return "Expected an name identifier. Grats expected to find a name here which it could use to derive the GraphQL name.";
}
exports.expectedIdentifier = expectedIdentifier;
exports.expectedNameIdentifier = expectedNameIdentifier;
function killsParentOnExceptionWithWrongConfig() {
return "Unexpected `@".concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` tag. `@").concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` is only supported when the Grats config `nullableByDefault` is enabled.");
return "Unexpected `@".concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` tag. `@").concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` is only supported when the Grats config option `nullableByDefault` is enabled in your `tsconfig.json`.");
}
exports.killsParentOnExceptionWithWrongConfig = killsParentOnExceptionWithWrongConfig;
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 on field typed as nullable. `@").concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` will force a field to appear as non-nullable in the schema, so it's implementation must also be non-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 by the GraphQL executor. This means optional arguments must be typed to also accept `null`. Consider adding `| null` to the end of the argument type.";
}
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.",
"To avoid ambiguity Grats does not support using merged interfaces as GraphQL interfaces.",
"To avoid ambiguity Grats does not support using merged interfaces as GraphQL definitions.",
"Consider using a unique name for your TypeScript interface and renaming it.\n\n",

@@ -268,6 +275,2 @@ "Learn more: ".concat(DOC_URLS.mergedInterfaces),

exports.mergedInterfaces = mergedInterfaces;
function implementsTagMissingValue() {
return "Expected `@".concat(Extractor_1.IMPLEMENTS_TAG_DEPRECATED, "` to be followed by one or more interface names.");
}
exports.implementsTagMissingValue = implementsTagMissingValue;
function implementsTagOnClass() {

@@ -282,3 +285,3 @@ return "`@".concat(Extractor_1.IMPLEMENTS_TAG_DEPRECATED, "` has been deprecated. Instead use `class MyType implements MyInterface`.");

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.");
}

@@ -309,3 +312,3 @@ exports.implementsTagOnTypeAlias = implementsTagOnTypeAlias;

function parameterPropertyMissingType() {
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` parameter property to have a type annotation.");
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` parameter property to have an explicit type annotation. Grats needs to be able to see the type of the parameter property to generate a GraphQL schema.");
}

@@ -318,11 +321,11 @@ exports.parameterPropertyMissingType = parameterPropertyMissingType;

function unresolvedTypeReference() {
return "This type is not a valid GraphQL type. Did you mean to annotate it's definition with a `/** @gql */` tag such as `/** @gqlType */` or `/** @gqlInput **/`?";
return "Unable to resolve type reference. In order to generate a GraphQL schema, Grats needs to determine which GraphQL type is being referenced. This requires being able to resolve type references to their `@gql` annotated declaration. However this reference could not be resolved. Is it possible that this type is not defined in this file?";
}
exports.unresolvedTypeReference = unresolvedTypeReference;
function expectedTypeAnnotationOnContext() {
return "Expected context parameter to have a type annotation. Grats validates that your context parameter is type-safe by checking all context values reference the same type declaration.";
return "Expected context parameter to have an explicit type annotation. Grats validates that your context parameter is type-safe by checking that all context values reference the same type declaration.";
}
exports.expectedTypeAnnotationOnContext = expectedTypeAnnotationOnContext;
function expectedTypeAnnotationOfReferenceOnContext() {
return "Expected context parameter's type to be a type reference Grats validates that your context parameter is type-safe by checking all context values reference the same type declaration.";
return "Expected context parameter's type to be a type reference. Grats validates that your context parameter is type-safe by checking that all context values reference the same type declaration.";
}

@@ -333,3 +336,3 @@ exports.expectedTypeAnnotationOfReferenceOnContext = expectedTypeAnnotationOfReferenceOnContext;

// TODO: I don't think we have a test case that triggers this error.
return "Unable to resolve context parameter type. Grats validates that your context parameter is type-safe by checking all context values reference the same type declaration.";
return "Unable to resolve context parameter type. Grats validates that your context parameter is type-safe by checking that all context values reference the same type declaration.";
}

@@ -342,3 +345,3 @@ exports.expectedTypeAnnotationOnContextToBeResolvable = expectedTypeAnnotationOnContextToBeResolvable;

function unexpectedParamSpreadForContextParam() {
return "Unexpected spread parameter in context parameter position. Grats expects the context parameter to be a single, explicitly typed, argument.";
return "Unexpected spread parameter in context parameter position. Grats expects the context parameter to be a single, explicitly-typed argument.";
}

@@ -350,1 +353,37 @@ exports.unexpectedParamSpreadForContextParam = unexpectedParamSpreadForContextParam;

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`. Fields on `Subscription` model a subscription, which is a stream of events. Grats expects fields on `Subscription` to return an `AsyncIterable` which can be used to model this stream.";
}
exports.subscriptionFieldNotAsyncIterable = subscriptionFieldNotAsyncIterable;
function nonSubscriptionFieldAsyncIterable() {
return "Unexpected AsyncIterable. Only fields on `Subscription` should return an `AsyncIterable`. Non-subscription fields are only expected to return a single value.";
}
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`. This is because GraphQL servers do not have an agreed upon way to produce root values, and Grats errs on the side of safety. If you are trying to implement dependency injection, consider using the `context` argument passed to each resolver instead. If you have a strong use case for a concrete root value, please file an issue.";
}
exports.operationTypeNotUnknown = operationTypeNotUnknown;
function expectedNullableArgumentToBeOptional() {
return "Expected nullable argument to _also_ be optional (`?`). graphql-js may omit properties on the argument object where an undefined GraphQL variable is passed, or if the argument is omitted in the operation text. To ensure your resolver is capable of handing this scenario, add a `?` to the end of the argument name to make it optional. e.g. `{greeting?: string | null}`";
}
exports.expectedNullableArgumentToBeOptional = expectedNullableArgumentToBeOptional;
function gqlTagInLineComment() {
return "Unexpected Grats tag in line (`//`) comment. Grats looks for tags in JSDoc-style block comments. e.g. `/** @gqlType */`. For more information see: ".concat(DOC_URLS.commentSyntax);
}
exports.gqlTagInLineComment = gqlTagInLineComment;
function gqlTagInNonJSDocBlockComment() {
return "Unexpected Grats tag in non-JSDoc-style block comment. Grats only looks for tags in JSDoc-style block comments which start with `/**`. For more information see: ".concat(DOC_URLS.commentSyntax);
}
exports.gqlTagInNonJSDocBlockComment = gqlTagInNonJSDocBlockComment;
function gqlTagInDetachedJSDocBlockComment() {
return "Unexpected Grats tag in detached docblock. Grats was unable to determine which TypeScript declaration this docblock is associated with. Moving the docblock to a position with is unambiguously \"above\" the relevant declaration may help. For more information see: ".concat(DOC_URLS.commentSyntax);
}
exports.gqlTagInDetachedJSDocBlockComment = gqlTagInDetachedJSDocBlockComment;

@@ -1,10 +0,8 @@

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 { ConfigOptions } from "./lib";
import { GraphQLConstructor } from "./GraphQLConstructor";
import { NameDefinition } from "./TypeContext";
import { GratsDefinitionNode } from "./GraphQLConstructor";
export declare const LIBRARY_IMPORT_NAME = "grats";
export declare const LIBRARY_NAME = "Grats";
export declare const ISSUE_URL = "https://github.com/captbaritone/grats/issues";
export declare const TYPE_TAG = "gqlType";

@@ -20,3 +18,10 @@ export declare const FIELD_TAG = "gqlField";

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 typesWithTypename: Set<string>;
readonly interfaceDeclarations: Array<ts.InterfaceDeclaration>;
};
/**

@@ -32,80 +37,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(sourceFile: ts.SourceFile): DiagnosticsResult<ExtractionSnapshot>;

@@ -29,6 +29,7 @@ "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.LIBRARY_NAME = exports.LIBRARY_IMPORT_NAME = void 0;
var graphql_1 = require("graphql");
var DiagnosticError_1 = require("./utils/DiagnosticError");
var Result_1 = require("./utils/Result");
var ts = require("typescript");

@@ -39,6 +40,8 @@ var TypeContext_1 = require("./TypeContext");

var GraphQLConstructor_1 = require("./GraphQLConstructor");
var serverDirectives_1 = require("./serverDirectives");
var gratsRoot_1 = require("./gratsRoot");
var Errors_1 = require("./Errors");
var comments_1 = require("./comments");
var helpers_1 = require("./utils/helpers");
exports.LIBRARY_IMPORT_NAME = "grats";
exports.LIBRARY_NAME = "Grats";
exports.ISSUE_URL = "https://github.com/captbaritone/grats/issues";
exports.TYPE_TAG = "gqlType";

@@ -64,2 +67,3 @@ exports.FIELD_TAG = "gqlField";

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

@@ -75,11 +79,25 @@ * Extracts GraphQL definitions from TypeScript source code.

*/
function extract(sourceFile) {
var extractor = new Extractor();
return extractor.extract(sourceFile);
}
exports.extract = extract;
var Extractor = /** @class */ (function () {
function Extractor(sourceFile, ctx, buildOptions) {
function Extractor() {
this.definitions = [];
// Snapshot data
this.unresolvedNames = new Map();
this.nameDefinitions = new Map();
this.contextReferences = [];
this.typesWithTypename = 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,6 +107,8 @@ // 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) {
var seenCommentPositions = new Set();
(0, JSDoc_1.traverseJSDocTags)(sourceFile, function (node, tag) {
var e_1, _a;
seenCommentPositions.add(tag.parent.pos);
switch (tag.tagName.text) {

@@ -119,2 +139,3 @@ case exports.TYPE_TAG:

ts.isMethodDeclaration(node) ||
ts.isGetAccessorDeclaration(node) ||
ts.isPropertyDeclaration(node) ||

@@ -135,2 +156,3 @@ ts.isMethodSignature(node) ||

}
// TODO: Report invalid location as well
break;

@@ -154,3 +176,3 @@ }

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);
}

@@ -165,6 +187,15 @@ finally { if (e_1) throw e_1.error; }

});
var errors = (0, comments_1.detectInvalidComments)(sourceFile, seenCommentPositions);
(0, helpers_1.extend)(this.errors, errors);
if (this.errors.length > 0) {
return (0, DiagnosticError_1.err)(this.errors);
return (0, Result_1.err)(this.errors);
}
return (0, DiagnosticError_1.ok)(this.definitions);
return (0, Result_1.ok)({
definitions: this.definitions,
unresolvedNames: this.unresolvedNames,
nameDefinitions: this.nameDefinitions,
contextReferences: this.contextReferences,
typesWithTypename: this.typesWithTypename,
interfaceDeclarations: this.interfaceDeclarations,
});
};

@@ -216,2 +247,5 @@ Extractor.prototype.extractType = function (node, tag) {

}
else if (ts.isInterfaceDeclaration(node)) {
this.inputInterfaceDeclaration(node, tag);
}
else {

@@ -231,13 +265,3 @@ this.report(tag, E.invalidInputTagUsage());

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;

@@ -248,21 +272,6 @@ };

Extractor.prototype.reportUnhandled = function (node, positionKind, message, relatedInformation) {
var suggestion = "If you think ".concat(exports.LIBRARY_NAME, " should be able to infer this ").concat(positionKind, ", please report an issue at ").concat(exports.ISSUE_URL, ".");
var suggestion = "If you think ".concat(exports.LIBRARY_NAME, " should be able to infer this ").concat(positionKind, ", please report an issue at ").concat(Errors_1.ISSUE_URL, ".");
var completedMessage = "".concat(message, "\n\n").concat(suggestion);
return this.report(node, completedMessage, relatedInformation);
};
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 */

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

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

@@ -287,3 +296,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);

@@ -295,7 +304,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));

@@ -320,5 +329,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, asyncIterable = returnType.asyncIterable;
var args = null;

@@ -333,3 +343,3 @@ var argsParam = node.parameters[1];

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

@@ -339,9 +349,11 @@ 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.fieldMetadataDirective(funcName, {
tsModulePath: tsModulePath,
name: funcName.text,
argCount: node.parameters.length,
asyncIterable: asyncIterable,
}),
];
if (funcName.text !== name.value) {
directives.push(this.fieldNameDirective(funcName, funcName.text));
}
var deprecated = this.collectDeprecated(node);

@@ -351,3 +363,7 @@ if (deprecated != null) {

}
var field = this.gql.fieldDefinition(node, name, this.handleErrorBubbling(node, type), args, directives, description);
var killsParentOnExceptionDirective = this.killsParentOnExceptionDirective(node);
if (killsParentOnExceptionDirective != null) {
directives.push(killsParentOnExceptionDirective);
}
var field = this.gql.fieldDefinition(node, name, type, args, directives, description);
this.definitions.push(this.gql.abstractFieldDefinition(node, typeName, field));

@@ -364,3 +380,3 @@ };

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

@@ -392,4 +408,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));

@@ -401,4 +417,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);

@@ -408,5 +424,36 @@ var deprecatedDirective = this.collectDeprecated(node);

};
Extractor.prototype.collectInputFields = function (node) {
Extractor.prototype.inputInterfaceDeclaration = function (node, tag) {
var e_3, _a;
var name = this.entityName(node, tag);
if (name == null)
return null;
var description = this.collectDescription(node);
this.recordTypeName(node.name, name, "INPUT_OBJECT");
var fields = [];
try {
for (var _b = __values(node.members), _c = _b.next(); !_c.done; _c = _b.next()) {
var member = _c.value;
if (!ts.isPropertySignature(member)) {
this.reportUnhandled(member, "input field", E.inputTypeFieldNotProperty());
continue;
}
var field = this.collectInputField(member);
if (field != null)
fields.push(field);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_3) throw e_3.error; }
}
this.interfaceDeclarations.push(node);
var deprecatedDirective = this.collectDeprecated(node);
this.definitions.push(this.gql.inputObjectTypeDefinition(node, name, fields, deprecatedDirective == null ? null : [deprecatedDirective], description));
};
Extractor.prototype.collectInputFields = function (node) {
var e_4, _a;
var fields = [];
if (!ts.isTypeLiteralNode(node.type)) {

@@ -427,8 +474,8 @@ return this.reportUnhandled(node, "input", E.inputTypeNotLiteral());

}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_3) throw e_3.error; }
finally { if (e_4) throw e_4.error; }
}

@@ -438,3 +485,3 @@ return fields.length === 0 ? null : fields;

Extractor.prototype.collectInputField = function (node) {
var id = this.expectIdentifier(node.name);
var id = this.expectNameIdentifier(node.name);
if (id == null)

@@ -449,3 +496,3 @@ return null;

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);

@@ -461,9 +508,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) {

@@ -473,6 +528,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, "TYPE");
this.checkForTypenameProperty(node, name.value);

@@ -488,2 +544,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);

@@ -501,4 +558,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));

@@ -512,3 +569,3 @@ };

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

@@ -607,6 +664,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;

@@ -621,11 +677,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) {

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

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

@@ -643,23 +689,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));

@@ -671,3 +701,3 @@ };

ts.forEachChild(node, function (node) {
var e_4, _a;
var e_5, _a;
if (ts.isConstructorDeclaration(node)) {

@@ -685,11 +715,13 @@ try {

}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_4) throw e_4.error; }
finally { if (e_5) throw e_5.error; }
}
}
if (ts.isMethodDeclaration(node) || ts.isMethodSignature(node)) {
if (ts.isMethodDeclaration(node) ||
ts.isMethodSignature(node) ||
ts.isGetAccessorDeclaration(node)) {
var field = _this.methodDeclaration(node);

@@ -746,6 +778,10 @@ if (field != null) {

}
var directives = [];
if (id.text !== name.value) {
directives = [this.fieldNameDirective(node.name, id.text)];
}
var directives = [
this.gql.fieldMetadataDirective(node.name, {
name: id.text == name.value ? null : id.text,
tsModulePath: null,
argCount: null,
asyncIterable: null,
}),
];
var type = this.collectType(node.type);

@@ -758,7 +794,11 @@ if (type == null)

}
var description = this.collectDescription(node.name);
return this.gql.fieldDefinition(node, name, this.handleErrorBubbling(node, type), null, directives, description);
var description = this.collectDescription(node);
var killsParentOnExceptionDirective = this.killsParentOnExceptionDirective(node);
if (killsParentOnExceptionDirective != null) {
directives.push(killsParentOnExceptionDirective);
}
return this.gql.fieldDefinition(node, name, type, null, directives, description);
};
Extractor.prototype.collectArgs = function (argsParam) {
var e_5, _a;
var e_6, _a;
var args = [];

@@ -788,8 +828,8 @@ var argsType = argsParam.type;

}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_5) throw e_5.error; }
finally { if (e_6) throw e_6.error; }
}

@@ -799,3 +839,3 @@ return args;

Extractor.prototype.collectArgDefaults = function (node) {
var e_6, _a;
var e_7, _a;
var defaults = new Map();

@@ -812,8 +852,8 @@ try {

}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_6) throw e_6.error; }
finally { if (e_7) throw e_7.error; }
}

@@ -832,3 +872,3 @@ return defaults;

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

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

Extractor.prototype.collectArrayLiteral = function (node) {
var e_7, _a;
var e_8, _a;
var values = [];

@@ -866,8 +906,8 @@ var errors = false;

}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_7) throw e_7.error; }
finally { if (e_8) throw e_8.error; }
}

@@ -880,3 +920,3 @@ if (errors) {

Extractor.prototype.collectObjectLiteral = function (node) {
var e_8, _a;
var e_9, _a;
var fields = [];

@@ -896,8 +936,8 @@ var errors = false;

}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
catch (e_9_1) { e_9 = { error: e_9_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_8) throw e_8.error; }
finally { if (e_9) throw e_9.error; }
}

@@ -916,3 +956,3 @@ if (errors) {

}
var name = this.expectIdentifier(node.name);
var name = this.expectNameIdentifier(node.name);
if (name == null)

@@ -944,12 +984,8 @@ return null;

return null;
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());
}
*/
type = this.gql.nullableType(type);
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());
}
var description = this.collectDescription(node.name);
var defaultValue = null;

@@ -962,2 +998,16 @@ if (defaults != null) {

}
if (node.questionToken && defaultValue == null) {
// 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.
//
// ... unless there is a default value. In that case, the default will be
// used argument is omitted or references an undefined variable.
// 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);
var deprecatedDirective = this.collectDeprecated(node);

@@ -971,5 +1021,5 @@ return this.gql.inputValueDefinition(node, this.gql.name(node.name, node.name.text), type, deprecatedDirective == null ? null : [deprecatedDirective], defaultValue, description);

}
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));

@@ -985,9 +1035,8 @@ };

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));
};
Extractor.prototype.enumTypeAliasVariants = function (node) {
var e_9, _a;
var _b;
var e_10, _a;
// Semantically we only support deriving enums from type aliases that

@@ -1010,23 +1059,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) ||

@@ -1042,8 +1072,8 @@ !ts.isStringLiteral(member.literal)) {

}
catch (e_9_1) { e_9 = { error: e_9_1 }; }
catch (e_10_1) { e_10 = { error: e_10_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c["return"])) _a.call(_c);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_9) throw e_9.error; }
finally { if (e_10) throw e_10.error; }
}

@@ -1053,3 +1083,3 @@ return values;

Extractor.prototype.collectEnumValues = function (node) {
var e_10, _a;
var e_11, _a;
var values = [];

@@ -1064,3 +1094,3 @@ try {

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

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

}
catch (e_10_1) { e_10 = { error: e_10_1 }; }
catch (e_11_1) { e_11 = { error: e_11_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b["return"])) _a.call(_b);
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_10) throw e_10.error; }
finally { if (e_11) throw e_11.error; }
}

@@ -1085,3 +1115,24 @@ return values;

// 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);
}

@@ -1092,3 +1143,3 @@ }

}
var id = this.expectIdentifier(node.name);
var id = this.expectNameIdentifier(node.name);
if (id == null)

@@ -1116,22 +1167,3 @@ return null;

}
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);
};

@@ -1148,3 +1180,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, asyncIterable = returnType.asyncIterable;
// We already reported an error

@@ -1162,10 +1197,14 @@ if (type == null)

}
var description = this.collectDescription(node.name);
var id = this.expectIdentifier(node.name);
var description = this.collectDescription(node);
var id = this.expectNameIdentifier(node.name);
if (id == null)
return null;
var directives = [];
if (id.text !== name.value) {
directives = [this.fieldNameDirective(node.name, id.text)];
}
var directives = [
this.gql.fieldMetadataDirective(node.name, {
name: id.text === name.value ? null : id.text,
tsModulePath: null,
argCount: isCallable(node) ? node.parameters.length : null,
asyncIterable: asyncIterable,
}),
];
var deprecated = this.collectDeprecated(node);

@@ -1175,13 +1214,35 @@ if (deprecated != null) {

}
return this.gql.fieldDefinition(node, name, this.handleErrorBubbling(node, type), args, directives, description);
var killsParentOnExceptionDirective = this.killsParentOnExceptionDirective(node);
if (killsParentOnExceptionDirective != null) {
directives.push(killsParentOnExceptionDirective);
}
return this.gql.fieldDefinition(node, name, type, args, directives, description);
};
Extractor.prototype.collectMethodType = function (node) {
var inner = this.maybeUnwrapePromise(node);
Extractor.prototype.collectReturnType = function (node) {
if (ts.isTypeReferenceNode(node)) {
var identifier = this.expectNameIdentifier(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.wrapperMissingTypeArg());
}
var t_1 = this.collectType(node.typeArguments[0]);
if (t_1 == null)
return null;
return { type: t_1, asyncIterable: identifier };
}
}
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 };
};
Extractor.prototype.collectPropertyType = function (node) {
// TODO: Handle function types here.
var inner = this.maybeUnwrapePromise(node);
var inner = this.maybeUnwrapPromise(node);
if (inner == null)

@@ -1191,10 +1252,10 @@ return null;

};
Extractor.prototype.maybeUnwrapePromise = function (node) {
Extractor.prototype.maybeUnwrapPromise = function (node) {
if (ts.isTypeReferenceNode(node)) {
var identifier = this.expectIdentifier(node.typeName);
var identifier = this.expectNameIdentifier(node.typeName);
if (identifier == null)
return null;
if (identifier.text === "Promise") {
if (node.typeArguments == null) {
return this.report(node, E.promiseMissingTypeArg());
if (node.typeArguments == null || node.typeArguments.length === 0) {
return this.report(node, E.wrapperMissingTypeArg());
}

@@ -1207,11 +1268,12 @@ return node.typeArguments[0];

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;

@@ -1249,5 +1311,5 @@ };

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

@@ -1259,6 +1321,13 @@ return null;

}
if (id.text !== name.value) {
directives = [this.fieldNameDirective(node.name, id.text)];
directives.push(this.gql.fieldMetadataDirective(node.name, {
name: id.text === name.value ? null : id.text,
tsModulePath: null,
argCount: null,
asyncIterable: null,
}));
var killsParentOnExceptionDirective = this.killsParentOnExceptionDirective(node);
if (killsParentOnExceptionDirective != null) {
directives.push(killsParentOnExceptionDirective);
}
return this.gql.fieldDefinition(node, name, this.handleErrorBubbling(node, type), null, directives, description);
return this.gql.fieldDefinition(node, name, type, null, directives, description);
};

@@ -1293,3 +1362,3 @@ // TODO: Support separate modes for input and output types

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

@@ -1300,3 +1369,3 @@ this.report(first, E.expectedOneNonNullishType(), incompatibleVariants);

if (node.types.length > 1) {
return this.gql.nullableType(type);
return this.gql.withLocation(node, this.gql.nullableType(type));
}

@@ -1325,3 +1394,3 @@ return this.gql.nonNullType(node, type);

Extractor.prototype.typeReference = function (node) {
var identifier = this.expectIdentifier(node.typeName);
var identifier = this.expectNameIdentifier(node.typeName);
if (identifier == null)

@@ -1348,3 +1417,3 @@ return null;

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);

@@ -1366,10 +1435,9 @@ }

};
Extractor.prototype.expectIdentifier = function (node) {
Extractor.prototype.expectNameIdentifier = function (node) {
if (ts.isIdentifier(node)) {
return node;
}
return this.report(node, E.expectedIdentifier());
return this.report(node, E.expectedNameIdentifier());
};
Extractor.prototype.findTag = function (node, tagName) {
var _this = this;
var tags = ts

@@ -1383,8 +1451,5 @@ .getJSDocTags(node)

var additionalTags = tags.slice(1).map(function (tag) {
return _this.related(tag, "Additional tag");
return (0, DiagnosticError_1.tsRelated)(tag, "Additional tag");
});
var message = tagName === exports.IMPLEMENTS_TAG_DEPRECATED
? E.duplicateInterfaceTag()
: E.duplicateTag(tagName);
return this.report(tags[0], message, additionalTags);
return this.report(tags[0], E.duplicateTag(tagName), additionalTags);
}

@@ -1394,36 +1459,31 @@ return tags[0];

// 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.
// https://graphql.org/learn/best-practices/#nullability
Extractor.prototype.handleErrorBubbling = function (parentNode, type) {
Extractor.prototype.killsParentOnExceptionDirective = function (parentNode) {
var tags = ts.getJSDocTags(parentNode);
var killsParentOnExceptions = tags.find(function (tag) { return tag.tagName.text === exports.KILLS_PARENT_ON_EXCEPTION_TAG; });
if (killsParentOnExceptions) {
if (!this.configOptions.nullableByDefault) {
this.report(killsParentOnExceptions.tagName, E.killsParentOnExceptionWithWrongConfig());
}
if (type.kind !== graphql_1.Kind.NON_NULL_TYPE) {
this.report(killsParentOnExceptions.tagName, E.killsParentOnExceptionOnNullable());
}
return type;
return this.gql.killsParentOnExceptionDirective(killsParentOnExceptions.tagName);
}
if (this.configOptions.nullableByDefault) {
return this.gql.nullableType(type);
}
return type;
return null;
};
/* 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*)+$/, "");
}
function isCallable(node) {
return ts.isMethodDeclaration(node) || ts.isMethodSignature(node);
}

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

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, ASTNode } from "graphql";
import * as ts from "typescript";
import { AbstractFieldDefinitionNode } from "./TypeContext";
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);
fieldMetadataDirective(node: ts.Node, metadata: {
tsModulePath: string | null;
name: string | null;
argCount: number | null;
asyncIterable?: ts.Node | null;
}): ConstDirectiveNode;
killsParentOnExceptionDirective(node: ts.Node): ConstDirectiveNode;
unionTypeDefinition(node: ts.Node, name: NameNode, types: NamedTypeNode[], description: StringValueNode | null): UnionTypeDefinitionNode;

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

list(node: ts.Node, values: ConstValueNode[]): ConstListValueNode;
withLocation<T = ASTNode>(node: ts.Node, value: T): T;
constArgument(node: ts.Node, name: NameNode, value: ConstValueNode): ConstArgumentNode;

@@ -35,3 +47,3 @@ constDirective(node: ts.Node, name: NameNode, args: ReadonlyArray<ConstArgumentNode> | null): ConstDirectiveNode;

_loc(node: ts.Node): GraphQLLocation;
_dummyToken(pos: number): Token;
_dummyToken(sourceFile: ts.SourceFile, pos: number): Token;
}
"use strict";
exports.__esModule = true;
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);
};
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() {
}
GraphQLConstructor.prototype.fieldMetadataDirective = function (node, metadata) {
var args = [];
if (metadata.tsModulePath != null) {
args.push(this.constArgument(node, this.name(node, metadataDirectives_1.TS_MODULE_PATH_ARG), this.string(node, metadata.tsModulePath)));
}
if (metadata.name != null) {
args.push(this.constArgument(node, this.name(node, metadataDirectives_1.FIELD_NAME_ARG), this.string(node, metadata.name)));
}
if (metadata.argCount != null) {
args.push(this.constArgument(node, this.name(node, metadataDirectives_1.ARG_COUNT), this.int(node, metadata.argCount.toString())));
}
if (metadata.asyncIterable) {
args.push(this.constArgument(metadata.asyncIterable, this.name(node, metadataDirectives_1.ASYNC_ITERABLE_ARG), this.boolean(node, true)));
}
return this.constDirective(node, this.name(node, metadataDirectives_1.FIELD_METADATA_DIRECTIVE), args);
};
GraphQLConstructor.prototype.killsParentOnExceptionDirective = function (node) {
return (0, metadataDirectives_1.makeKillsParentOnExceptionDirective)(this._loc(node));
};
/* Top Level Types */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@@ -158,2 +188,5 @@ };

};
GraphQLConstructor.prototype.withLocation = function (node, value) {
return __assign(__assign({}, value), { loc: this._loc(node) });
};
GraphQLConstructor.prototype.constArgument = function (node, name, value) {

@@ -167,3 +200,3 @@ return { kind: graphql_1.Kind.ARGUMENT, loc: this._loc(node), name: name, value: value };

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

@@ -180,3 +213,3 @@ };

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

@@ -197,9 +230,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);

@@ -206,0 +240,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,9 @@

import { GraphQLSchema } from "graphql";
import * as ts from "typescript";
import { ParsedCommandLineGrats } from "./gratsConfig";
import { ReportableDiagnostics } from "./utils/DiagnosticError";
import { Result } from "./utils/Result";
export { printSDLWithoutMetadata } 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 { extract } from "./Extractor";
export { codegen } from "./codegen";
export declare function getParsedTsConfig(configFile: string): Result<ParsedCommandLineGrats, ReportableDiagnostics>;

@@ -16,39 +16,19 @@ "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.extract = exports.printSDLWithoutMetadata = void 0;
var ts = require("typescript");
var lib_1 = require("./lib");
var gratsConfig_1 = require("./gratsConfig");
var DiagnosticError_1 = require("./utils/DiagnosticError");
var Result_1 = require("./utils/Result");
var printSchema_1 = require("./printSchema");
Object.defineProperty(exports, "printSDLWithoutMetadata", { enumerable: true, get: function () { return printSchema_1.printSDLWithoutMetadata; } });
__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;
// Used by the experimental TypeScript plugin
var Extractor_1 = require("./Extractor");
Object.defineProperty(exports, "extract", { enumerable: true, get: function () { return Extractor_1.extract; } });
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 +40,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, Result_1.err)(DiagnosticError_1.ReportableDiagnostics.fromDiagnostics(parsed.errors));
}
return (0, Result_1.ok)((0, gratsConfig_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,16 @@

import { GraphQLSchema } from "graphql";
import { Result, ReportableDiagnostics } from "./utils/DiagnosticError";
import { DocumentNode, GraphQLSchema } from "graphql";
import { DiagnosticsWithoutLocationResult, ReportableDiagnostics } from "./utils/DiagnosticError";
import { Result } from "./utils/Result";
import * as ts from "typescript";
export { applyServerDirectives } from "./serverDirectives";
export type ConfigOptions = {
nullableByDefault?: boolean;
reportTypeScriptTypeErrors?: boolean;
import { ParsedCommandLineGrats } from "./gratsConfig";
export { initTsPlugin } from "./tsPlugin/initTsPlugin";
export type SchemaAndDoc = {
schema: GraphQLSchema;
doc: DocumentNode;
};
export declare function buildSchemaResult(options: ts.ParsedCommandLine): Result<GraphQLSchema, ReportableDiagnostics>;
export declare function buildSchemaResultWithHost(options: ts.ParsedCommandLine, compilerHost: ts.CompilerHost): Result<GraphQLSchema, ReportableDiagnostics>;
export declare function buildSchemaAndDocResult(options: ParsedCommandLineGrats): Result<SchemaAndDoc, ReportableDiagnostics>;
export declare function buildSchemaAndDocResultWithHost(options: ParsedCommandLineGrats, compilerHost: ts.CompilerHost): Result<SchemaAndDoc, ReportableDiagnostics>;
/**
* The core transformation pipeline of Grats.
*/
export declare function extractSchemaAndDoc(options: ParsedCommandLineGrats, program: ts.Program): DiagnosticsWithoutLocationResult<SchemaAndDoc>;
"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) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __values = (this && this.__values) || function(o) {

@@ -35,17 +13,45 @@ 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.extractSchemaAndDoc = exports.buildSchemaAndDocResultWithHost = exports.buildSchemaAndDocResult = exports.initTsPlugin = void 0;
var graphql_1 = require("graphql");
var DiagnosticError_1 = require("./utils/DiagnosticError");
var Result_1 = require("./utils/Result");
var Result_2 = require("./utils/Result");
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 helpers_1 = require("./utils/helpers");
var serverDirectives_2 = require("./serverDirectives");
__createBinding(exports, serverDirectives_2, "applyServerDirectives");
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 addInterfaceFields_1 = require("./transforms/addInterfaceFields");
var filterNonGqlInterfaces_1 = require("./transforms/filterNonGqlInterfaces");
var resolveTypes_1 = require("./transforms/resolveTypes");
var validateAsyncIterable_1 = require("./validations/validateAsyncIterable");
var applyDefaultNullability_1 = require("./transforms/applyDefaultNullability");
var mergeExtensions_1 = require("./transforms/mergeExtensions");
var sortSchemaAst_1 = require("./transforms/sortSchemaAst");
var validateSemanticNullability_1 = require("./validations/validateSemanticNullability");
var initTsPlugin_1 = require("./tsPlugin/initTsPlugin");
Object.defineProperty(exports, "initTsPlugin", { enumerable: true, get: function () { return initTsPlugin_1.initTsPlugin; } });
// Construct a schema, using GraphQL schema language
// Exported for tests that want to intercept diagnostic errors.
function buildSchemaResult(options) {
function buildSchemaAndDocResult(options) {
// https://stackoverflow.com/a/66604532/1263117

@@ -55,154 +61,129 @@ var compilerHost = ts.createCompilerHost(options.options,

true);
return buildSchemaResultWithHost(options, compilerHost);
return buildSchemaAndDocResultWithHost(options, compilerHost);
}
exports.buildSchemaResult = buildSchemaResult;
function buildSchemaResultWithHost(options, compilerHost) {
var gratsOptions = parseGratsOptions(options);
var schemaResult = extractSchema(options, gratsOptions, 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));
exports.buildSchemaAndDocResult = buildSchemaAndDocResult;
function buildSchemaAndDocResultWithHost(options, compilerHost) {
var program = ts.createProgram(options.fileNames, options.options, compilerHost);
return new Result_1.ResultPipe(extractSchemaAndDoc(options, program))
.mapErr(function (e) { return new DiagnosticError_1.ReportableDiagnostics(compilerHost, e); })
.result();
}
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;
exports.buildSchemaAndDocResultWithHost = buildSchemaAndDocResultWithHost;
/**
* The core transformation pipeline of Grats.
*/
function extractSchemaAndDoc(options, program) {
return new Result_1.ResultPipe((0, snapshotsFromProgram_1.extractSnapshotsFromProgram)(program, options))
.map(function (snapshots) { return combineSnapshots(snapshots); })
.andThen(function (snapshot) {
var typesWithTypename = snapshot.typesWithTypename;
var config = options.raw.grats;
var checker = program.getTypeChecker();
var ctx = TypeContext_1.TypeContext.fromSnapshot(checker, snapshot);
// Collect validation errors
var validationResult = (0, Result_1.concatResults)((0, validateMergedInterfaces_1.validateMergedInterfaces)(checker, snapshot.interfaceDeclarations), (0, validateContextReferences_1.validateContextReferences)(ctx, snapshot.contextReferences));
var docResult = new Result_1.ResultPipe(validationResult)
// Add the metadata directive definitions to definitions
// found in the snapshot.
.map(function () { return (0, metadataDirectives_1.addMetadataDirectives)(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.
.andThen(function (definitions) { return (0, addInterfaceFields_1.addInterfaceFields)(ctx, definitions); })
// Convert the definitions into a DocumentNode
.map(function (definitions) { return ({ kind: graphql_1.Kind.DOCUMENT, definitions: definitions }); })
// Filter out any `implements` clauses that are not GraphQL interfaces.
.map(function (doc) { return (0, filterNonGqlInterfaces_1.filterNonGqlInterfaces)(ctx, doc); })
// Apply default nullability to fields and arguments, and detect any misuse of
// `@killsParentOnException`.
.andThen(function (doc) { return (0, applyDefaultNullability_1.applyDefaultNullability)(doc, config); })
// Resolve TypeScript type references to the GraphQL types they represent (or error).
.andThen(function (doc) { return (0, resolveTypes_1.resolveTypes)(ctx, doc); })
// Ensure all subscription fields, and _only_ subscription fields, return an AsyncIterable.
.andThen(function (doc) { return (0, validateAsyncIterable_1.validateAsyncIterable)(doc); })
// Merge any `extend` definitions into their base definitions.
.map(function (doc) { return (0, mergeExtensions_1.mergeExtensions)(doc); })
// Sort the definitions in the document to ensure a stable output.
.map(function (doc) { return (0, sortSchemaAst_1.sortSchemaAst)(doc); })
.result();
if (docResult.kind === "ERROR") {
return docResult;
}
var doc = docResult.value;
// Build and validate the schema with regards to the GraphQL spec.
return (new Result_1.ResultPipe(buildSchemaFromDoc(doc))
// Ensure that every type which implements an interface or is a member of a
// union has a __typename field.
.andThen(function (schema) { return (0, validateTypenames_1.validateTypenames)(schema, typesWithTypename); })
.andThen(function (schema) { return (0, validateSemanticNullability_1.validateSemanticNullability)(schema, config); })
// Combine the schema and document into a single result.
.map(function (schema) { return ({ schema: schema, doc: doc }); })
.result());
})
.result();
}
exports.extractSchemaAndDoc = extractSchemaAndDoc;
// Given a SDL AST, build and validate a GraphQLSchema.
function buildSchemaFromDoc(doc) {
// 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);
if (validationErrors.length > 0) {
return (0, Result_2.err)(validationErrors.map(DiagnosticError_1.graphQlErrorToDiagnostic));
}
else if (typeof gratsOptions.nullableByDefault !== "boolean") {
throw new Error("Grats: The Grats config option `nullableByDefault` 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; });
if (diagnostics.length > 0) {
return (0, Result_2.err)(diagnostics.map(DiagnosticError_1.graphQlErrorToDiagnostic));
}
if (gratsOptions.reportTypeScriptTypeErrors === undefined) {
gratsOptions.reportTypeScriptTypeErrors = false;
}
else if (typeof gratsOptions.reportTypeScriptTypeErrors !== "boolean") {
throw new Error("Grats: The Grats config option `reportTypeScriptTypeErrors` must be a boolean if provided");
}
// FIXME: Check for unknown options
return gratsOptions;
return (0, Result_2.ok)(schema);
}
function extractSchema(options, gratsOptions, host) {
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 = [];
// Given a list of snapshots, merge them into a single snapshot.
function combineSnapshots(snapshots) {
var e_1, _a, e_2, _b, e_3, _c, e_4, _d, e_5, _e, e_6, _f, e_7, _g;
var result = {
definitions: [],
nameDefinitions: new Map(),
unresolvedNames: new Map(),
contextReferences: [],
typesWithTypename: new Set(),
interfaceDeclarations: [],
};
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;
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 _h = (e_2 = void 0, __values(snapshot.definitions)), _j = _h.next(); !_j.done; _j = _h.next()) {
var definition = _j.value;
result.definitions.push(definition);
}
}
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;
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_j && !_j.done && (_b = _h.return)) _b.call(_h);
}
finally { if (e_2) throw e_2.error; }
}
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);
for (var _k = (e_3 = 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_2_1) { e_2 = { error: e_2_1 }; }
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e["return"])) _b.call(_e);
if (_l && !_l.done && (_c = _k.return)) _c.call(_k);
}
finally { if (e_2) throw e_2.error; }
finally { if (e_3) throw e_3.error; }
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
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);
}
// 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);
if (definitionsResult.kind === "ERROR") {
return definitionsResult;
}
var docResult = ctx.resolveTypes({
kind: graphql_1.Kind.DOCUMENT,
definitions: definitionsResult.value
});
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 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);
}
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);
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);
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 _o = (e_4 = 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);
}

@@ -213,16 +194,55 @@ }

try {
if (typeImplementors_1_1 && !typeImplementors_1_1.done && (_b = typeImplementors_1["return"])) _b.call(typeImplementors_1);
if (_p && !_p.done && (_d = _o.return)) _d.call(_o);
}
finally { if (e_4) throw e_4.error; }
}
try {
for (var _r = (e_5 = void 0, __values(snapshot.contextReferences)), _s = _r.next(); !_s.done; _s = _r.next()) {
var contextReference = _s.value;
result.contextReferences.push(contextReference);
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_s && !_s.done && (_e = _r.return)) _e.call(_r);
}
finally { if (e_5) throw e_5.error; }
}
try {
for (var _t = (e_6 = void 0, __values(snapshot.typesWithTypename)), _u = _t.next(); !_u.done; _u = _t.next()) {
var typeName = _u.value;
result.typesWithTypename.add(typeName);
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_u && !_u.done && (_f = _t.return)) _f.call(_t);
}
finally { if (e_6) throw e_6.error; }
}
try {
for (var _v = (e_7 = void 0, __values(snapshot.interfaceDeclarations)), _w = _v.next(); !_w.done; _w = _v.next()) {
var interfaceDeclaration = _w.value;
result.interfaceDeclarations.push(interfaceDeclaration);
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_w && !_w.done && (_g = _v.return)) _g.call(_v);
}
finally { if (e_7) throw e_7.error; }
}
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
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; }
finally { if (e_1) throw e_1.error; }
}
return typenameDiagnostics;
return result;
}
import { GraphQLSchema, Location } from "graphql";
import { Result } from "./utils/DiagnosticError";
import { Result } from "./utils/Result";
/**

@@ -4,0 +4,0 @@ * Given an entity name of the format `ParentType` or `ParentType.fieldName`,

"use strict";
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", { value: true });
exports.locate = void 0;
var graphql_1 = require("graphql");
var DiagnosticError_1 = require("./utils/DiagnosticError");
var Result_1 = require("./utils/Result");
var helpers_1 = require("./utils/helpers");
/**

@@ -18,9 +19,9 @@ * Given an entity name of the format `ParentType` or `ParentType.fieldName`,

if (type == null) {
return (0, DiagnosticError_1.err)("Cannot locate type `".concat(entity.parent, "`."));
return (0, Result_1.err)("Cannot locate type `".concat(entity.parent, "`."));
}
if (entity.field == null) {
if (type.astNode == null || type.astNode.name.loc == null) {
if (type.astNode == null) {
throw new Error("Grats bug: Cannot find location of type `".concat(entity.parent, "`."));
}
return (0, DiagnosticError_1.ok)(type.astNode.name.loc);
return (0, Result_1.ok)((0, helpers_1.loc)(type.astNode.name));
}

@@ -30,12 +31,12 @@ if (!(type instanceof graphql_1.GraphQLObjectType ||

type instanceof graphql_1.GraphQLInputObjectType)) {
return (0, DiagnosticError_1.err)("Cannot locate field `".concat(entity.field, "` on type `").concat(entity.parent, "`. Only object types, interfaces, and input objects have fields."));
return (0, Result_1.err)("Cannot locate field `".concat(entity.field, "` on type `").concat(entity.parent, "`. Only object types, interfaces, and input objects have fields."));
}
var field = type.getFields()[entity.field];
if (field == null) {
return (0, DiagnosticError_1.err)("Cannot locate field `".concat(entity.field, "` on type `").concat(entity.parent, "`."));
return (0, Result_1.err)("Cannot locate field `".concat(entity.field, "` on type `").concat(entity.parent, "`."));
}
if (field.astNode == null || field.astNode.name.loc == null) {
if (field.astNode == null) {
throw new Error("Grats bug: Cannot find location of field `".concat(entity.field, "` on type `").concat(entity.parent, "`."));
}
return (0, DiagnosticError_1.ok)(field.astNode.name.loc);
return (0, Result_1.ok)((0, helpers_1.loc)(field.astNode.name));
}

@@ -47,7 +48,7 @@ exports.locate = locate;

if (match == null) {
return (0, DiagnosticError_1.err)("Invalid entity name: `".concat(entityName, "`. Expected `ParentType` or `ParentType.fieldName`."));
return (0, Result_1.err)("Invalid entity name: `".concat(entityName, "`. Expected `ParentType` or `ParentType.fieldName`."));
}
var parent = match[1];
var field = match[2] || null;
return (0, DiagnosticError_1.ok)({ parent: parent, field: field });
return (0, Result_1.ok)({ parent: parent, field: field });
}

@@ -1,26 +0,11 @@

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";
import { ExtractionSnapshot } from "./Extractor";
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.

@@ -39,23 +24,13 @@ *

checker: ts.TypeChecker;
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);
recordTypeName(node: ts.Node, name: NameNode, kind: NameDefinition["kind"]): void;
recordHasTypenameField(name: string): void;
markUnresolvedType(node: ts.Node, name: NameNode): void;
static fromSnapshot(checker: ts.TypeChecker, snapshot: ExtractionSnapshot): TypeContext;
constructor(checker: ts.TypeChecker);
_recordTypeName(node: ts.Node, name: NameNode, kind: NameDefinition["kind"]): 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 {};

@@ -24,12 +24,24 @@ "use strict";

};
exports.__esModule = true;
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.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 Result_1 = require("./utils/Result");
var E = require("./Errors");
var InterfaceGraph_1 = require("./InterfaceGraph");
var helpers_1 = require("./utils/helpers");

@@ -50,14 +62,41 @@ exports.UNRESOLVED_REFERENCE_NAME = "__UNRESOLVED_REFERENCE__";

var TypeContext = /** @class */ (function () {
function TypeContext(options, checker, host) {
function TypeContext(checker) {
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;
}
TypeContext.prototype.recordTypeName = function (node, name, kind) {
TypeContext.fromSnapshot = function (checker, snapshot) {
var e_1, _a, e_2, _b;
var self = new TypeContext(checker);
try {
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];
self._markUnresolvedType(node, typeName);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
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];
self._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; }
}
return self;
};
// Record that a GraphQL construct of type `kind` with the name `name` is
// declared at `node`.
TypeContext.prototype._recordTypeName = function (node, name, kind) {
var symbol = this.checker.getSymbolAtLocation(node);

@@ -74,6 +113,4 @@ if (symbol == null) {

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

@@ -106,70 +143,28 @@ if (symbol == null) {

};
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);
}
TypeContext.prototype.resolveNamedType = function (unresolved) {
var symbol = this._unresolvedTypes.get(unresolved);
if (symbol == null) {
if (unresolved.value === exports.UNRESOLVED_REFERENCE_NAME) {
// This is a logic error on our side.
throw new Error("Unexpected unresolved reference name.");
}
return (0, Result_1.ok)(unresolved);
}
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; }
var nameDefinition = this._symbolToName.get(symbol);
if (nameDefinition == null) {
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(unresolved), E.unresolvedTypeReference()));
}
if (errors.length > 0) {
return (0, DiagnosticError_1.err)(errors);
}
return (0, DiagnosticError_1.ok)(newDocs);
return (0, Result_1.ok)(__assign(__assign({}, unresolved), { value: nameDefinition.name.value }));
};
// 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);
TypeContext.prototype.unresolvedNameIsGraphQL = function (unresolved) {
var symbol = this._unresolvedTypes.get(unresolved);
return symbol != null && this._symbolToName.has(symbol);
};
// 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]);
return (0, Result_1.err)([typeNameResult.err]);
}
var symbol = this._unresolvedTypes.get(doc.onType);
var symbol = this._unresolvedTypes.get(nameNode);
if (symbol == null) {

@@ -184,128 +179,6 @@ // This should have already been handled by resolveNamedType

}
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);
return (0, Result_1.ok)(nameDefinition);
};
TypeContext.prototype.resolveNamedType = function (unresolved) {
var symbol = this._unresolvedTypes.get(unresolved);
if (symbol == null) {
if (unresolved.value === exports.UNRESOLVED_REFERENCE_NAME) {
// This is a logic error on our side.
throw new Error("Unexpected unresolved reference name.");
}
return (0, DiagnosticError_1.ok)(unresolved);
}
var nameDefinition = this._symbolToName.get(symbol);
if (nameDefinition == null) {
if (unresolved.loc == null) {
throw new Error("Expected namedType to have a location.");
}
return (0, DiagnosticError_1.err)(this.err(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.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
};
};
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 });
import { GraphQLError, Location, Source } from "graphql";
import * as ts from "typescript";
type Ok<T> = {
kind: "OK";
value: T;
};
type Err<E> = {
kind: "ERROR";
err: E;
};
export type Result<T, E> = Ok<T> | Err<E>;
export type DiagnosticResult<T> = Result<T, ts.Diagnostic>;
export type DiagnosticsResult<T> = Result<T, ts.Diagnostic[]>;
export declare function ok<T>(value: T): Ok<T>;
export declare function err<E>(err: E): Err<E>;
import { Result } from "./Result";
export type DiagnosticResult<T> = Result<T, ts.DiagnosticWithLocation>;
export type DiagnosticsResult<T> = Result<T, ts.DiagnosticWithLocation[]>;
export type DiagnosticsWithoutLocationResult<T> = Result<T, ts.Diagnostic[]>;
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;

@@ -25,4 +17,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.DiagnosticWithLocation;
export declare function gqlRelated(loc: Location, message: string): ts.DiagnosticRelatedInformation;
export declare function rangeErr(file: ts.SourceFile, commentRange: ts.CommentRange, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.DiagnosticWithLocation;
export declare function tsErr(node: ts.Node, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.DiagnosticWithLocation;
export declare function tsRelated(node: ts.Node, message: string): ts.DiagnosticRelatedInformation;
export declare function graphqlSourceToSourceFile(source: Source): ts.SourceFile;
export {};

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

};
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.rangeErr = exports.gqlRelated = exports.gqlErr = exports.graphQlErrorToDiagnostic = exports.FAKE_ERROR_CODE = exports.ReportableDiagnostics = void 0;
var ts = require("typescript");
function ok(value) {
return { kind: "OK", value: value };
}
exports.ok = ok;
function err(err) {
return { kind: "ERROR", err: err };
}
exports.err = err;
var ReportableDiagnostics = /** @class */ (function () {

@@ -46,2 +38,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 () {

@@ -60,3 +62,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.

@@ -77,3 +79,3 @@ exports.FAKE_ERROR_CODE = 349389149282;

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

@@ -97,10 +99,3 @@ 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"));
}

@@ -111,3 +106,3 @@ }

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);
}

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

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

@@ -142,6 +138,61 @@ messageText: message,

start: loc.start,
length: loc.end - loc.start
length: loc.end - loc.start,
relatedInformation: relatedInformation,
source: "Grats",
};
}
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 rangeErr(file, commentRange, message, relatedInformation) {
var start = commentRange.pos;
var length = commentRange.end - commentRange.pos;
return {
messageText: message,
file: file,
code: exports.FAKE_ERROR_CODE,
category: ts.DiagnosticCategory.Error,
start: start,
length: length,
relatedInformation: relatedInformation,
source: "Grats",
};
}
exports.rangeErr = rangeErr;
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,
source: "Grats",
};
}
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) {

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

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

import { Location } from "graphql";
export declare class DefaultMap<K, V> {

@@ -8,1 +9,7 @@ private readonly getDefault;

export declare function extend<T>(a: T[], b: readonly T[]): void;
export declare function loc(item: {
loc?: Location;
}): Location;
export declare function astNode<T>(item: {
astNode?: T | undefined | null;
}): T;

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

};
exports.__esModule = true;
exports.extend = exports.DefaultMap = void 0;
Object.defineProperty(exports, "__esModule", { value: true });
exports.astNode = exports.loc = exports.extend = exports.DefaultMap = void 0;
var DefaultMap = /** @class */ (function () {

@@ -43,3 +43,3 @@ function DefaultMap(getDefault) {

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);
}

@@ -50,1 +50,15 @@ finally { if (e_1) throw e_1.error; }

exports.extend = extend;
function loc(item) {
if (item.loc == null) {
throw new Error("Expected item to have loc");
}
return item.loc;
}
exports.loc = loc;
function astNode(item) {
if (item.astNode == null) {
throw new Error("Expected item to have astNode");
}
return item.astNode;
}
exports.astNode = astNode;

@@ -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-05c86aca",
"version": "0.0.0-main-05c9a8df",
"main": "dist/src/index.js",

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

"files": [
"dist"
"dist",
"!dist/src/tests"
],
"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",
"@types/semver": "^7.5.6",
"@typescript-eslint/eslint-plugin": "^5.55.0",

@@ -26,3 +28,5 @@ "@typescript-eslint/parser": "^5.55.0",

"path-browserify": "^1.0.1",
"prettier": "^2.8.7",
"process": "^0.11.10",
"semver": "^7.5.4",
"ts-node": "^10.9.1"

@@ -33,3 +37,3 @@ },

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

@@ -39,8 +43,29 @@ "node": ">=16 <=21",

},
"bugs": {
"url": "https://github.com/captbaritone/grats/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/captbaritone/grats.git"
},
"author": {
"name": "Jordan Eldredge",
"email": "jordan@jordaneldredge.com",
"url": "https://jordaneldredge.com"
},
"keywords": [
"graphql",
"typescript",
"resolvers",
"schema",
"code-first",
"implementation-first"
],
"scripts": {
"test": "ts-node src/tests/test.ts",
"integration-tests": "node src/tests/integration.mjs",
"build": "tsc --build",
"lint": "eslint src/**/*.ts"
"build": "rm -rf dist/ && tsc --build",
"format": "prettier . --write",
"lint": "eslint . && 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, don't 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 contains your GraphQL schema definition:
```graphql
type User {
name: String
greet(greeting: String!): String
}
```
That's just the beginning! To learn more, **Read the docs: https://grats.capt.dev/**
## Contributing

@@ -33,3 +57,3 @@

- [@bradzacher](https://github.com/bradzacher) for tips on how to handle TypeScript ASTs.
- Everyone who worked on Meta's Hack GraphQL server, the developer experince of which inspired this project.
- Everyone who worked on Meta's Hack GraphQL server, the developer experience of which inspired this project.
- A number of other projects which seem to have explored similar ideas in the past:

@@ -36,0 +60,0 @@ - [ts2gql](https://github.com/convoyinc/ts2gql)

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