Comparing version
{ | ||
"name": "grats", | ||
"version": "0.0.27", | ||
"version": "0.0.32", | ||
"main": "dist/src/index.js", | ||
@@ -22,6 +22,6 @@ "bin": "dist/src/cli.js", | ||
"graphql": "^16.9.0", | ||
"typescript": "5.5.4" | ||
"typescript": "5.5.4", | ||
"semver": "^7.5.4" | ||
}, | ||
"devDependencies": { | ||
"@graphql-tools/utils": "^9.2.1", | ||
"@types/node": "^18.14.6", | ||
@@ -37,3 +37,2 @@ "@types/semver": "^7.5.6", | ||
"process": "^0.11.10", | ||
"semver": "^7.5.4", | ||
"ts-node": "^10.9.1" | ||
@@ -46,4 +45,3 @@ }, | ||
"engines": { | ||
"node": ">=16 <=21", | ||
"pnpm": ">=8 <=9" | ||
"node": ">=16 <=21" | ||
}, | ||
@@ -50,0 +48,0 @@ "bugs": { |
@@ -41,2 +41,4 @@ #!/usr/bin/env node | ||
exports.formatLoc = formatLoc; | ||
var E = require("./Errors"); | ||
var graphql_1 = require("graphql"); | ||
var _1 = require("./"); | ||
@@ -52,2 +54,3 @@ var lib_1 = require("./lib"); | ||
var DiagnosticError_1 = require("./utils/DiagnosticError"); | ||
var Result_1 = require("./utils/Result"); | ||
var program = new commander_1.Command(); | ||
@@ -78,9 +81,4 @@ program | ||
var tsconfig = _a.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 config = handleDiagnostics(getTsConfig(tsconfig)).config; | ||
var schema = handleDiagnostics(buildSchemaAndDocResultForCli(config)).schema; | ||
var loc = (0, Locate_1.locate)(schema, entity); | ||
@@ -98,3 +96,3 @@ if (loc.kind === "ERROR") { | ||
function startWatchMode(tsconfig) { | ||
var _a = getTsConfigOrReportAndExit(tsconfig), config = _a.config, configPath = _a.configPath; | ||
var _a = handleDiagnostics(getTsConfig(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]); }); | ||
@@ -112,13 +110,29 @@ watchHost.afterProgramCreate = function (program) { | ||
} | ||
function isUserDefinedType(type) { | ||
return type instanceof graphql_1.GraphQLObjectType && !type.name.startsWith("__"); | ||
} | ||
/** | ||
* Like `buildSchemaAndDocResult` but applies a few additional validations that | ||
* are considered helpful for CLI usage, like warning if you have no types defined.. | ||
*/ | ||
function buildSchemaAndDocResultForCli(config) { | ||
var result = (0, lib_1.buildSchemaAndDocResult)(config); | ||
if (result.kind === "ERROR") { | ||
return result; | ||
} | ||
var types = Object.values(result.value.schema.getTypeMap()); | ||
if (!types.some(function (t) { return isUserDefinedType(t); })) { | ||
return (0, Result_1.err)(DiagnosticError_1.ReportableDiagnostics.fromDiagnostics([ | ||
(0, DiagnosticError_1.locationlessErr)(E.noTypesDefined()), | ||
])); | ||
} | ||
return result; | ||
} | ||
/** | ||
* 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); | ||
} | ||
writeSchemaFilesAndReport(schemaAndDocResult.value, config, configPath); | ||
var _a = handleDiagnostics(getTsConfig(tsconfig)), config = _a.config, configPath = _a.configPath; | ||
var schemaAndDoc = handleDiagnostics(buildSchemaAndDocResultForCli(config)); | ||
writeSchemaFilesAndReport(schemaAndDoc, config, configPath); | ||
} | ||
@@ -129,6 +143,6 @@ /** | ||
function writeSchemaFilesAndReport(schemaAndDoc, config, configPath) { | ||
var schema = schemaAndDoc.schema, doc = schemaAndDoc.doc; | ||
var schema = schemaAndDoc.schema, doc = schemaAndDoc.doc, resolvers = schemaAndDoc.resolvers; | ||
var gratsConfig = config.raw.grats; | ||
var dest = (0, path_1.resolve)((0, path_1.dirname)(configPath), gratsConfig.tsSchema); | ||
var code = (0, printSchema_1.printExecutableSchema)(schema, gratsConfig, dest); | ||
var code = (0, printSchema_1.printExecutableSchema)(schema, resolvers, gratsConfig, dest); | ||
(0, fs_1.writeFileSync)(dest, code); | ||
@@ -140,2 +154,7 @@ console.error("Grats: Wrote TypeScript schema to `".concat(dest, "`.")); | ||
console.error("Grats: Wrote schema to `".concat(absOutput, "`.")); | ||
if (config.raw.grats.EXPERIMENTAL__emitMetadata) { | ||
var absOutput_1 = (0, path_1.resolve)((0, path_1.dirname)(configPath), gratsConfig.graphqlSchema.replace(/\.graphql$/, ".json")); | ||
(0, fs_1.writeFileSync)(absOutput_1, JSON.stringify(resolvers, null, 2)); | ||
console.error("Grats: Wrote resolver signatures to `".concat(absOutput_1, "`.")); | ||
} | ||
} | ||
@@ -149,14 +168,26 @@ /** | ||
} | ||
/** | ||
* Utility function to report diagnostics to the console. | ||
*/ | ||
function handleDiagnostics(result) { | ||
if (result.kind === "ERROR") { | ||
console.error(result.err.formatDiagnosticsWithColorAndContext()); | ||
process.exit(1); | ||
} | ||
return result.value; | ||
} | ||
// Locate and read the tsconfig.json file | ||
function getTsConfigOrReportAndExit(tsconfig) { | ||
var configPath = tsconfig || ts.findConfigFile(process.cwd(), ts.sys.fileExists); | ||
function getTsConfig(tsconfig) { | ||
var cwd = process.cwd(); | ||
var configPath = tsconfig || ts.findConfigFile(cwd, ts.sys.fileExists); | ||
if (configPath == null) { | ||
throw new Error("Grats: Could not find tsconfig.json"); | ||
return (0, Result_1.err)(DiagnosticError_1.ReportableDiagnostics.fromDiagnostics([ | ||
(0, DiagnosticError_1.locationlessErr)(E.tsConfigNotFound(cwd)), | ||
])); | ||
} | ||
var optionsResult = (0, _1.getParsedTsConfig)(configPath); | ||
if (optionsResult.kind === "ERROR") { | ||
console.error(optionsResult.err.formatDiagnosticsWithColorAndContext()); | ||
process.exit(1); | ||
return (0, Result_1.err)(optionsResult.err); | ||
} | ||
return { configPath: configPath, config: optionsResult.value }; | ||
return (0, Result_1.ok)({ configPath: configPath, config: optionsResult.value }); | ||
} | ||
@@ -163,0 +194,0 @@ // Format a location for printing to the console. Tools like VS Code and iTerm |
@@ -13,2 +13,3 @@ export declare const ISSUE_URL = "https://github.com/captbaritone/grats/issues"; | ||
export declare function fieldTagOnWrongNode(): string; | ||
export declare function rootFieldTagOnWrongNode(typeName: string): string; | ||
export declare function killsParentOnExceptionOnWrongNode(): string; | ||
@@ -108,4 +109,2 @@ export declare function wrongCasingForGratsTag(actual: string, expected: string): string; | ||
export declare function gqlFieldParentMissingTag(): string; | ||
export declare function missingSpecifiedByUrl(): string; | ||
export declare function specifiedByOnWrongNode(): string; | ||
export declare function missingGenericType(templateName: string, paramName: string): string; | ||
@@ -129,1 +128,21 @@ export declare function nonGraphQLGenericType(templateName: string, paramName: string): string; | ||
export declare function invalidResolverParamType(): string; | ||
export declare function exportedArrowFunctionNotConst(): string; | ||
export declare function exportedFieldVariableMultipleDeclarations(n: number): string; | ||
export declare function fieldVariableNotTopLevelExported(): string; | ||
export declare function fieldVariableIsNotArrowFunction(): string; | ||
export declare function positionalResolverArgDoesNotHaveName(): string; | ||
export declare function positionalArgAndArgsObject(): string; | ||
export declare function contextOrInfoUsedInGraphQLPosition(kind: "CONTEXT" | "INFO"): string; | ||
export declare function typeWithNoFields(kind: string, typeName: string): string; | ||
export declare function noTypesDefined(): string; | ||
export declare function tsConfigNotFound(cwd: string): string; | ||
export declare function cyclicDerivedContext(): string; | ||
export declare function invalidDerivedContextArgType(): string; | ||
export declare function missingReturnTypeForDerivedResolver(): string; | ||
export declare function derivedResolverInvalidReturnType(): string; | ||
export declare function directiveTagOnWrongNode(): string; | ||
export declare function directiveTagCommentNotText(): string; | ||
export declare function specifiedByDeprecated(): string; | ||
export declare function directiveTagNoComment(): string; | ||
export declare function directiveFunctionNotNamed(): string; | ||
export declare function directiveArgumentNotObject(): string; |
@@ -5,2 +5,3 @@ "use strict"; | ||
exports.fieldTagOnWrongNode = fieldTagOnWrongNode; | ||
exports.rootFieldTagOnWrongNode = rootFieldTagOnWrongNode; | ||
exports.killsParentOnExceptionOnWrongNode = killsParentOnExceptionOnWrongNode; | ||
@@ -100,4 +101,2 @@ exports.wrongCasingForGratsTag = wrongCasingForGratsTag; | ||
exports.gqlFieldParentMissingTag = gqlFieldParentMissingTag; | ||
exports.missingSpecifiedByUrl = missingSpecifiedByUrl; | ||
exports.specifiedByOnWrongNode = specifiedByOnWrongNode; | ||
exports.missingGenericType = missingGenericType; | ||
@@ -121,2 +120,22 @@ exports.nonGraphQLGenericType = nonGraphQLGenericType; | ||
exports.invalidResolverParamType = invalidResolverParamType; | ||
exports.exportedArrowFunctionNotConst = exportedArrowFunctionNotConst; | ||
exports.exportedFieldVariableMultipleDeclarations = exportedFieldVariableMultipleDeclarations; | ||
exports.fieldVariableNotTopLevelExported = fieldVariableNotTopLevelExported; | ||
exports.fieldVariableIsNotArrowFunction = fieldVariableIsNotArrowFunction; | ||
exports.positionalResolverArgDoesNotHaveName = positionalResolverArgDoesNotHaveName; | ||
exports.positionalArgAndArgsObject = positionalArgAndArgsObject; | ||
exports.contextOrInfoUsedInGraphQLPosition = contextOrInfoUsedInGraphQLPosition; | ||
exports.typeWithNoFields = typeWithNoFields; | ||
exports.noTypesDefined = noTypesDefined; | ||
exports.tsConfigNotFound = tsConfigNotFound; | ||
exports.cyclicDerivedContext = cyclicDerivedContext; | ||
exports.invalidDerivedContextArgType = invalidDerivedContextArgType; | ||
exports.missingReturnTypeForDerivedResolver = missingReturnTypeForDerivedResolver; | ||
exports.derivedResolverInvalidReturnType = derivedResolverInvalidReturnType; | ||
exports.directiveTagOnWrongNode = directiveTagOnWrongNode; | ||
exports.directiveTagCommentNotText = directiveTagCommentNotText; | ||
exports.specifiedByDeprecated = specifiedByDeprecated; | ||
exports.directiveTagNoComment = directiveTagNoComment; | ||
exports.directiveFunctionNotNamed = directiveFunctionNotNamed; | ||
exports.directiveArgumentNotObject = directiveArgumentNotObject; | ||
var Extractor_1 = require("./Extractor"); | ||
@@ -141,4 +160,7 @@ exports.ISSUE_URL = "https://github.com/captbaritone/grats/issues"; | ||
function fieldTagOnWrongNode() { | ||
return "`@".concat(Extractor_1.FIELD_TAG, "` can only be used on method/property declarations, signatures, or function declarations."); | ||
return "`@".concat(Extractor_1.FIELD_TAG, "` can only be used on method/property declarations, signatures, function or static method declarations."); | ||
} | ||
function rootFieldTagOnWrongNode(typeName) { | ||
return "`@gql".concat(typeName, "Field` can only be used on function or static method declarations."); | ||
} | ||
function killsParentOnExceptionOnWrongNode() { | ||
@@ -168,3 +190,3 @@ return "Unexpected `@".concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "`. `@").concat(Extractor_1.KILLS_PARENT_ON_EXCEPTION_TAG, "` can only be used in field annotation docblocks. Perhaps you are missing a `@").concat(Extractor_1.FIELD_TAG, "` tag?"); | ||
function invalidInputTagUsage() { | ||
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 }`"); | ||
return "`@".concat(Extractor_1.INPUT_TAG, "` can only be used on type alias, interface declarations or type unions. e.g. `type MyInput = { foo: string }` or `interface MyInput { foo: string }`"); | ||
} | ||
@@ -175,3 +197,3 @@ function invalidUnionTagUsage() { | ||
function expectedUnionTypeNode() { | ||
return "Expected a TypeScript union. `@".concat(Extractor_1.UNION_TAG, "` can only be used on TypeScript unions. e.g. `type MyUnion = TypeA | TypeB`"); | ||
return "Expected a TypeScript union. `@".concat(Extractor_1.UNION_TAG, "` can only be used on TypeScript unions or a single type reference. e.g. `type MyUnion = TypeA | TypeB` or `type MyUnion = TypeA`"); | ||
} | ||
@@ -336,3 +358,3 @@ function expectedUnionTypeReference() { | ||
function expectedNameIdentifier() { | ||
return "Expected an name identifier. Grats expected to find a name here which it could use to derive the GraphQL name."; | ||
return "Expected a name identifier. Grats expected to find a name here which it could use to derive the GraphQL name."; | ||
} | ||
@@ -462,9 +484,2 @@ // TODO: Add code action | ||
} | ||
function missingSpecifiedByUrl() { | ||
return "Expected `@".concat(Extractor_1.SPECIFIED_BY_TAG, "` tag to be followed by a URL. This URL will be used as the `url` argument to the `@specifiedBy` directive in the generated GraphQL schema. See https://spec.graphql.org/draft/#sec--specifiedBy for more information."); | ||
} | ||
// TODO: Add code action | ||
function specifiedByOnWrongNode() { | ||
return "Unexpected `@".concat(Extractor_1.SPECIFIED_BY_TAG, "` tag on non-scalar declaration. `@").concat(Extractor_1.SPECIFIED_BY_TAG, "` can only be used on custom scalar declarations. Are you missing a `@").concat(Extractor_1.SCALAR_TAG, "` tag?"); | ||
} | ||
function missingGenericType(templateName, paramName) { | ||
@@ -525,1 +540,62 @@ return "Missing type argument for generic GraphQL type. Expected `".concat(templateName, "` to be passed a GraphQL type argument for type parameter `").concat(paramName, "`."); | ||
} | ||
function exportedArrowFunctionNotConst() { | ||
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` arrow function to be declared as `const`."); | ||
} | ||
function exportedFieldVariableMultipleDeclarations(n) { | ||
return "Expected only one declaration when defining a `@".concat(Extractor_1.FIELD_TAG, "`, found ").concat(n, "."); | ||
} | ||
function fieldVariableNotTopLevelExported() { | ||
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` to be an exported top-level declaration. Grats needs to import resolver functions into it's generated schema module, so the resolver function must be exported from the module."); | ||
} | ||
function fieldVariableIsNotArrowFunction() { | ||
return "Expected `@".concat(Extractor_1.FIELD_TAG, "` on variable declaration to be attached to an arrow function."); | ||
} | ||
function positionalResolverArgDoesNotHaveName() { | ||
return "Expected resolver argument to have a name. Grats needs to be able to see the name of the argument in order to derive a GraphQL argument name."; | ||
} | ||
function positionalArgAndArgsObject() { | ||
return "Unexpected arguments object in resolver that is also using positional GraphQL arguments. Grats expects that either all GraphQL arguments will be defined in a single object, or that all GraphQL arguments will be defined using positional arguments. The two strategies may not be combined."; | ||
} | ||
function contextOrInfoUsedInGraphQLPosition(kind) { | ||
var tag = kind === "CONTEXT" ? Extractor_1.CONTEXT_TAG : Extractor_1.INFO_TAG; | ||
return "Cannot use `".concat(tag, "` as a type in GraphQL type position."); | ||
} | ||
function typeWithNoFields(kind, typeName) { | ||
return "".concat(kind, " `").concat(typeName, "` must define one or more fields.\n\nDefine a field by adding `/** @").concat(Extractor_1.FIELD_TAG, " */` above a field, property, attribute or method of this type, or above a function that has `").concat(typeName, "` as its first argument."); | ||
} | ||
function noTypesDefined() { | ||
return "Grats could not find any GraphQL types defined in this project.\n\nDeclare a type by adding a `/** @".concat(Extractor_1.TYPE_TAG, " */` docblock above a class, interface, or type alias declaration.\nGrats looks for docblock tags in any TypeScript file included in your TypeScript project."); | ||
} | ||
function tsConfigNotFound(cwd) { | ||
return "Grats: Could not find `tsconfig.json` searching in ".concat(cwd, ".\n\nSee https://www.typescriptlang.org/download/ for instructors on how to add TypeScript to your project. Then run `npx tsc --init` to create a `tsconfig.json` file."); | ||
} | ||
function cyclicDerivedContext() { | ||
return "Cyclic dependency detected in derived context. This derived context value depends upon itself."; | ||
} | ||
function invalidDerivedContextArgType() { | ||
return "Invalid type for derived context function argument. Derived context functions may only accept other `@gqlContext` types as arguments."; | ||
} | ||
function missingReturnTypeForDerivedResolver() { | ||
return 'Expected derived resolver to have an explicit return type. This is needed to allow Grats to "see" which type to treat as a derived context type.'; | ||
} | ||
function derivedResolverInvalidReturnType() { | ||
return "Expected derived resolver function's return type to be a type reference. Grats uses this type reference to determine which type to treat as a derived context type."; | ||
} | ||
function directiveTagOnWrongNode() { | ||
return "`@".concat(Extractor_1.DIRECTIVE_TAG, "` can only be used on function declarations."); | ||
} | ||
function directiveTagCommentNotText() { | ||
return "Expected Grats JSDoc tag value to be simple text."; | ||
} | ||
function specifiedByDeprecated() { | ||
return 'The `@specifiedBy` tag has been deprecated in favor of `@gqlAnnotate`. Use `@gqlAnnotate specified(url: "http://example.com")` instead.'; | ||
} | ||
function directiveTagNoComment() { | ||
return "Expected `@gqlDirective` tag to specify at least one location."; | ||
} | ||
function directiveFunctionNotNamed() { | ||
return "Expected `@gqlDirective` function to be named."; | ||
} | ||
function directiveArgumentNotObject() { | ||
return "Expected first argument of a `@gqlDirective` function to be typed using an inline object literal."; | ||
} |
import { NameNode, DefinitionNode } from "graphql"; | ||
import { DiagnosticsResult } from "./utils/DiagnosticError"; | ||
import * as ts from "typescript"; | ||
import { NameDefinition } from "./TypeContext"; | ||
import { DeclarationDefinition, NameDefinition } from "./TypeContext"; | ||
export declare const LIBRARY_IMPORT_NAME = "grats"; | ||
@@ -14,2 +14,7 @@ export declare const LIBRARY_NAME = "Grats"; | ||
export declare const INPUT_TAG = "gqlInput"; | ||
export declare const DIRECTIVE_TAG = "gqlDirective"; | ||
export declare const ANNOTATE_TAG = "gqlAnnotate"; | ||
export declare const QUERY_FIELD_TAG = "gqlQueryField"; | ||
export declare const MUTATION_FIELD_TAG = "gqlMutationField"; | ||
export declare const SUBSCRIPTION_FIELD_TAG = "gqlSubscriptionField"; | ||
export declare const CONTEXT_TAG = "gqlContext"; | ||
@@ -20,4 +25,4 @@ export declare const INFO_TAG = "gqlInfo"; | ||
export declare const ALL_TAGS: string[]; | ||
export declare const SPECIFIED_BY_TAG = "specifiedBy"; | ||
export declare const ONE_OF_TAG = "oneOf"; | ||
export declare const OPERATION_TYPES: Set<string>; | ||
export type ExtractionSnapshot = { | ||
@@ -27,2 +32,3 @@ readonly definitions: DefinitionNode[]; | ||
readonly nameDefinitions: Map<ts.DeclarationStatement, NameDefinition>; | ||
readonly implicitNameDefinitions: Map<DeclarationDefinition, ts.TypeReferenceNode>; | ||
readonly typesWithTypename: Set<string>; | ||
@@ -29,0 +35,0 @@ readonly interfaceDeclarations: Array<ts.InterfaceDeclaration>; |
@@ -1,24 +0,20 @@ | ||
import { ListTypeNode, NamedTypeNode, Location as GraphQLLocation, NameNode, TypeNode, NonNullTypeNode, StringValueNode, ConstValueNode, ConstDirectiveNode, ConstArgumentNode, UnionTypeDefinitionNode, FieldDefinitionNode, InputValueDefinitionNode, FloatValueNode, IntValueNode, NullValueNode, BooleanValueNode, ConstListValueNode, ConstObjectValueNode, ConstObjectFieldNode, ObjectTypeDefinitionNode, EnumValueDefinitionNode, ScalarTypeDefinitionNode, InputObjectTypeDefinitionNode, EnumTypeDefinitionNode, InterfaceTypeDefinitionNode, ASTNode, ObjectTypeExtensionNode } from "graphql"; | ||
import { ListTypeNode, NamedTypeNode, Location as GraphQLLocation, NameNode, TypeNode, NonNullTypeNode, StringValueNode, ConstValueNode, ConstDirectiveNode, ConstArgumentNode, UnionTypeDefinitionNode, FieldDefinitionNode, InputValueDefinitionNode, FloatValueNode, IntValueNode, NullValueNode, BooleanValueNode, ConstListValueNode, ConstObjectValueNode, ConstObjectFieldNode, ObjectTypeDefinitionNode, EnumValueDefinitionNode, ScalarTypeDefinitionNode, InputObjectTypeDefinitionNode, EnumTypeDefinitionNode, InterfaceTypeDefinitionNode, ASTNode, ObjectTypeExtensionNode, DirectiveDefinitionNode, EnumValueNode } from "graphql"; | ||
import * as ts from "typescript"; | ||
import { UnresolvedResolverParam } from "./metadataDirectives"; | ||
import { TsLocatableNode } from "./utils/DiagnosticError"; | ||
import { DiagnosticResult, TsLocatableNode } from "./utils/DiagnosticError"; | ||
import { InputValueDefinitionNodeOrResolverArg, ResolverSignature } from "./resolverSignature"; | ||
export declare class GraphQLConstructor { | ||
fieldMetadataDirective(node: ts.Node, metadata: { | ||
tsModulePath: string | null; | ||
name: string | null; | ||
exportName: string | null; | ||
}): ConstDirectiveNode; | ||
killsParentOnExceptionDirective(node: ts.Node): ConstDirectiveNode; | ||
unionTypeDefinition(node: ts.Node, name: NameNode, types: NamedTypeNode[], description: StringValueNode | null): UnionTypeDefinitionNode; | ||
objectTypeDefinition(node: ts.Node, name: NameNode, fields: FieldDefinitionNode[], interfaces: NamedTypeNode[] | null, description: StringValueNode | null, hasTypeNameField: boolean, exported: { | ||
directiveDefinition(node: ts.Node, name: NameNode, args: readonly InputValueDefinitionNode[] | null, repeatable: boolean, locations: readonly NameNode[], description: StringValueNode | null): DirectiveDefinitionNode; | ||
unionTypeDefinition(node: ts.Node, name: NameNode, types: NamedTypeNode[], description: StringValueNode | null, directives: readonly ConstDirectiveNode[] | null): UnionTypeDefinitionNode; | ||
objectTypeDefinition(node: ts.Node, name: NameNode, fields: FieldDefinitionNode[], interfaces: NamedTypeNode[] | null, description: StringValueNode | null, directives: readonly ConstDirectiveNode[] | null, hasTypeNameField: boolean, exported: { | ||
tsModulePath: string; | ||
exportName: string | null; | ||
} | null): ObjectTypeDefinitionNode; | ||
interfaceTypeDefinition(node: ts.Node, name: NameNode, fields: FieldDefinitionNode[], interfaces: NamedTypeNode[] | null, description: StringValueNode | null): InterfaceTypeDefinitionNode; | ||
enumTypeDefinition(node: ts.Node, name: NameNode, values: readonly EnumValueDefinitionNode[], description: StringValueNode | null): EnumTypeDefinitionNode; | ||
abstractFieldDefinition(node: ts.Node, onType: NameNode, field: FieldDefinitionNode): ObjectTypeExtensionNode; | ||
fieldDefinition(node: ts.Node, name: NameNode, type: TypeNode, args: readonly InputValueDefinitionNode[] | null, directives: readonly ConstDirectiveNode[], description: StringValueNode | null, resolverParams: UnresolvedResolverParam[] | null): FieldDefinitionNode; | ||
interfaceTypeDefinition(node: ts.Node, name: NameNode, fields: FieldDefinitionNode[], interfaces: NamedTypeNode[] | null, description: StringValueNode | null, directives: readonly ConstDirectiveNode[] | null): InterfaceTypeDefinitionNode; | ||
enumTypeDefinition(node: ts.Node, name: NameNode, values: readonly EnumValueDefinitionNode[], description: StringValueNode | null, directives: readonly ConstDirectiveNode[] | null): EnumTypeDefinitionNode; | ||
abstractFieldDefinition(node: ts.Node, onType: NameNode, field: FieldDefinitionNode, mayBeInterface?: boolean): ObjectTypeExtensionNode; | ||
fieldDefinition(node: ts.Node, name: NameNode, type: TypeNode, args: readonly InputValueDefinitionNode[] | null, directives: readonly ConstDirectiveNode[], description: StringValueNode | null, killsParentOnException: NameNode | null, resolver: ResolverSignature): FieldDefinitionNode; | ||
constObjectField(node: ts.Node, name: NameNode, value: ConstValueNode): ConstObjectFieldNode; | ||
inputValueDefinition(node: ts.Node, name: NameNode, type: TypeNode, directives: readonly ConstDirectiveNode[] | null, defaultValue: ConstValueNode | null, description: StringValueNode | null): InputValueDefinitionNode; | ||
enumValueDefinition(node: ts.Node, name: NameNode, directives: readonly ConstDirectiveNode[] | undefined, description: StringValueNode | null): EnumValueDefinitionNode; | ||
inputValueDefinitionOrResolverArg(node: ts.Node, name: DiagnosticResult<NameNode>, type: TypeNode, directives: readonly ConstDirectiveNode[] | null, defaultValue: ConstValueNode | null, description: StringValueNode | null): InputValueDefinitionNodeOrResolverArg; | ||
enumValueDefinition(node: ts.Node, name: NameNode, directives: readonly ConstDirectiveNode[] | undefined, description: StringValueNode | null, tsName: string | null): EnumValueDefinitionNode; | ||
scalarTypeDefinition(node: ts.Node, name: NameNode, directives: readonly ConstDirectiveNode[] | null, description: StringValueNode | null): ScalarTypeDefinitionNode; | ||
@@ -35,3 +31,3 @@ inputObjectTypeDefinition(node: ts.Node, name: NameNode, fields: InputValueDefinitionNode[] | null, directives: readonly ConstDirectiveNode[] | null, description: StringValueNode | null): InputObjectTypeDefinitionNode; | ||
constArgument(node: ts.Node, name: NameNode, value: ConstValueNode): ConstArgumentNode; | ||
constDirective(node: ts.Node, name: NameNode, args: ReadonlyArray<ConstArgumentNode> | null): ConstDirectiveNode; | ||
constDirective(node: ts.Node, name: NameNode, args: ReadonlyArray<ConstArgumentNode> | null, isAmbiguous?: boolean): ConstDirectiveNode; | ||
string(node: ts.Node, value: string, block?: boolean): StringValueNode; | ||
@@ -42,4 +38,5 @@ float(node: ts.Node, value: string): FloatValueNode; | ||
boolean(node: ts.Node, value: boolean): BooleanValueNode; | ||
enum(node: ts.Node, value: string): EnumValueNode; | ||
_optionalList<T>(input: readonly T[] | null): readonly T[] | undefined; | ||
} | ||
export declare function loc(node: TsLocatableNode): GraphQLLocation; |
@@ -17,3 +17,2 @@ "use strict"; | ||
var graphql_1 = require("graphql"); | ||
var metadataDirectives_1 = require("./metadataDirectives"); | ||
var helpers_1 = require("./utils/helpers"); | ||
@@ -23,21 +22,18 @@ var GraphQLConstructor = /** @class */ (function () { | ||
} | ||
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.exportName != null) { | ||
args.push(this.constArgument(node, this.name(node, metadataDirectives_1.EXPORT_NAME_ARG), this.string(node, metadata.exportName))); | ||
} | ||
return this.constDirective(node, this.name(node, metadataDirectives_1.FIELD_METADATA_DIRECTIVE), args); | ||
}; | ||
GraphQLConstructor.prototype.killsParentOnExceptionDirective = function (node) { | ||
return (0, metadataDirectives_1.makeKillsParentOnExceptionDirective)(loc(node)); | ||
}; | ||
/* Top Level Types */ | ||
GraphQLConstructor.prototype.unionTypeDefinition = function (node, name, types, description) { | ||
GraphQLConstructor.prototype.directiveDefinition = function (node, name, args, repeatable, locations, description) { | ||
return { | ||
kind: graphql_1.Kind.DIRECTIVE_DEFINITION, | ||
loc: loc(node), | ||
name: name, | ||
// "Real" arguments are undefined for now. Later they will be derived from | ||
// `resolverArgs`. | ||
arguments: this._optionalList(args), | ||
repeatable: repeatable, | ||
locations: locations, | ||
description: description !== null && description !== void 0 ? description : undefined, | ||
}; | ||
}; | ||
GraphQLConstructor.prototype.unionTypeDefinition = function (node, name, types, description, directives) { | ||
return { | ||
kind: graphql_1.Kind.UNION_TYPE_DEFINITION, | ||
@@ -48,5 +44,6 @@ loc: loc(node), | ||
types: types, | ||
directives: this._optionalList(directives), | ||
}; | ||
}; | ||
GraphQLConstructor.prototype.objectTypeDefinition = function (node, name, fields, interfaces, description, hasTypeNameField, exported) { | ||
GraphQLConstructor.prototype.objectTypeDefinition = function (node, name, fields, interfaces, description, directives, hasTypeNameField, exported) { | ||
return { | ||
@@ -61,5 +58,6 @@ kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION, | ||
exported: exported !== null && exported !== void 0 ? exported : undefined, | ||
directives: this._optionalList(directives), | ||
}; | ||
}; | ||
GraphQLConstructor.prototype.interfaceTypeDefinition = function (node, name, fields, interfaces, description) { | ||
GraphQLConstructor.prototype.interfaceTypeDefinition = function (node, name, fields, interfaces, description, directives) { | ||
return { | ||
@@ -69,9 +67,9 @@ kind: graphql_1.Kind.INTERFACE_TYPE_DEFINITION, | ||
description: description !== null && description !== void 0 ? description : undefined, | ||
directives: undefined, | ||
name: name, | ||
fields: fields, | ||
interfaces: interfaces !== null && interfaces !== void 0 ? interfaces : undefined, | ||
directives: this._optionalList(directives), | ||
}; | ||
}; | ||
GraphQLConstructor.prototype.enumTypeDefinition = function (node, name, values, description) { | ||
GraphQLConstructor.prototype.enumTypeDefinition = function (node, name, values, description, directives) { | ||
return { | ||
@@ -83,6 +81,8 @@ kind: graphql_1.Kind.ENUM_TYPE_DEFINITION, | ||
values: values, | ||
directives: this._optionalList(directives), | ||
}; | ||
}; | ||
/* Top Level Extensions */ | ||
GraphQLConstructor.prototype.abstractFieldDefinition = function (node, onType, field) { | ||
GraphQLConstructor.prototype.abstractFieldDefinition = function (node, onType, field, mayBeInterface) { | ||
if (mayBeInterface === void 0) { mayBeInterface = true; } | ||
return { | ||
@@ -93,7 +93,7 @@ kind: graphql_1.Kind.OBJECT_TYPE_EXTENSION, | ||
fields: [field], | ||
mayBeInterface: true, | ||
mayBeInterface: mayBeInterface, | ||
}; | ||
}; | ||
/* Field Definitions */ | ||
GraphQLConstructor.prototype.fieldDefinition = function (node, name, type, args, directives, description, resolverParams) { | ||
GraphQLConstructor.prototype.fieldDefinition = function (node, name, type, args, directives, description, killsParentOnException, resolver) { | ||
return { | ||
@@ -107,3 +107,4 @@ kind: graphql_1.Kind.FIELD_DEFINITION, | ||
directives: this._optionalList(directives), | ||
resolverParams: resolverParams !== null && resolverParams !== void 0 ? resolverParams : undefined, | ||
resolver: resolver, | ||
killsParentOnException: killsParentOnException !== null && killsParentOnException !== void 0 ? killsParentOnException : undefined, | ||
}; | ||
@@ -125,4 +126,15 @@ }; | ||
}; | ||
GraphQLConstructor.prototype.enumValueDefinition = function (node, name, directives, description) { | ||
GraphQLConstructor.prototype.inputValueDefinitionOrResolverArg = function (node, name, type, directives, defaultValue, description) { | ||
return { | ||
kind: graphql_1.Kind.INPUT_VALUE_DEFINITION, | ||
loc: loc(node), | ||
description: description !== null && description !== void 0 ? description : undefined, | ||
name: name, | ||
type: type, | ||
defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : undefined, | ||
directives: this._optionalList(directives), | ||
}; | ||
}; | ||
GraphQLConstructor.prototype.enumValueDefinition = function (node, name, directives, description, tsName) { | ||
return { | ||
kind: graphql_1.Kind.ENUM_VALUE_DEFINITION, | ||
@@ -133,2 +145,3 @@ loc: loc(node), | ||
directives: directives, | ||
tsName: tsName !== null && tsName !== void 0 ? tsName : undefined, | ||
}; | ||
@@ -200,3 +213,4 @@ }; | ||
}; | ||
GraphQLConstructor.prototype.constDirective = function (node, name, args) { | ||
GraphQLConstructor.prototype.constDirective = function (node, name, args, isAmbiguous) { | ||
if (isAmbiguous === void 0) { isAmbiguous = false; } | ||
return { | ||
@@ -207,2 +221,3 @@ kind: graphql_1.Kind.DIRECTIVE, | ||
arguments: this._optionalList(args), | ||
isAmbiguous: isAmbiguous, | ||
}; | ||
@@ -225,2 +240,5 @@ }; | ||
}; | ||
GraphQLConstructor.prototype.enum = function (node, value) { | ||
return { kind: graphql_1.Kind.ENUM, loc: loc(node), value: value }; | ||
}; | ||
GraphQLConstructor.prototype._optionalList = function (input) { | ||
@@ -227,0 +245,0 @@ if (input == null || input.length === 0) { |
@@ -11,2 +11,4 @@ import * as ts from "typescript"; | ||
importModuleSpecifierEnding: string; | ||
EXPERIMENTAL__emitMetadata: boolean; | ||
EXPERIMENTAL__emitResolverMap: boolean; | ||
}; | ||
@@ -13,0 +15,0 @@ export type ParsedCommandLineGrats = Omit<ts.ParsedCommandLine, "raw"> & { |
@@ -37,2 +37,4 @@ "use strict"; | ||
"importModuleSpecifierEnding", | ||
"EXPERIMENTAL__emitMetadata", | ||
"EXPERIMENTAL__emitResolverMap", | ||
]); | ||
@@ -128,3 +130,21 @@ // TODO: Make this return diagnostics | ||
} | ||
if (gratsOptions.EXPERIMENTAL__emitMetadata === undefined) { | ||
gratsOptions.EXPERIMENTAL__emitMetadata = false; | ||
} | ||
else if (typeof gratsOptions.EXPERIMENTAL__emitMetadata !== "boolean") { | ||
throw new Error("Grats: The Grats config option `EXPERIMENTAL__emitMetadata` must be a boolean if provided."); | ||
} | ||
else { | ||
console.warn("Grats: The `EXPERIMENTAL__emitMetadata` option is experimental and will be renamed or removed in a future release."); | ||
} | ||
if (gratsOptions.EXPERIMENTAL__emitResolverMap === undefined) { | ||
gratsOptions.EXPERIMENTAL__emitResolverMap = false; | ||
} | ||
else if (typeof gratsOptions.EXPERIMENTAL__emitResolverMap !== "boolean") { | ||
throw new Error("Grats: The Grats config option `EXPERIMENTAL__emitResolverMap` must be a boolean if provided."); | ||
} | ||
else { | ||
console.warn("Grats: The `EXPERIMENTAL__emitResolverMap` option is experimental and will be renamed or removed in a future release."); | ||
} | ||
return __assign(__assign({}, options), { raw: __assign(__assign({}, options.raw), { grats: gratsOptions }) }); | ||
} |
@@ -8,3 +8,3 @@ import { ParsedCommandLineGrats } from "./gratsConfig"; | ||
export { extract } from "./Extractor"; | ||
export { codegen } from "./codegen"; | ||
export { codegen } from "./codegen/schemaCodegen"; | ||
export declare function getParsedTsConfig(configFile: string): Result<ParsedCommandLineGrats, ReportableDiagnostics>; |
@@ -30,9 +30,6 @@ "use strict"; | ||
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; } }); | ||
var schemaCodegen_1 = require("./codegen/schemaCodegen"); | ||
Object.defineProperty(exports, "codegen", { enumerable: true, get: function () { return schemaCodegen_1.codegen; } }); | ||
// #FIXME: Report diagnostics instead of throwing! | ||
function getParsedTsConfig(configFile) { | ||
if (!configFile) { | ||
throw new Error("Grats: Could not find tsconfig.json"); | ||
} | ||
// https://github.com/microsoft/TypeScript/blob/46d70d79cd0dd00d19e4c617d6ebb25e9f3fc7de/src/compiler/watch.ts#L216 | ||
@@ -39,0 +36,0 @@ var configFileHost = ts.sys; |
@@ -6,2 +6,3 @@ import { DocumentNode, GraphQLSchema } from "graphql"; | ||
import { ParsedCommandLineGrats } from "./gratsConfig"; | ||
import { Metadata } from "./metadata"; | ||
export { initTsPlugin } from "./tsPlugin/initTsPlugin"; | ||
@@ -12,2 +13,3 @@ export { GratsConfig } from "./gratsConfig"; | ||
doc: DocumentNode; | ||
resolvers: Metadata; | ||
}; | ||
@@ -18,3 +20,10 @@ export declare function buildSchemaAndDocResult(options: ParsedCommandLineGrats): Result<SchemaAndDoc, ReportableDiagnostics>; | ||
* The core transformation pipeline of Grats. | ||
* | ||
* To keep the Grats codebase clean and maintainable, we've broken the | ||
* implementation into a series of transformations that each perform a small, | ||
* well-defined task. | ||
* | ||
* This function orchestrates the transformations and, as such, gives a good | ||
* high-level overview of how Grats works. | ||
*/ | ||
export declare function extractSchemaAndDoc(options: ParsedCommandLineGrats, program: ts.Program): DiagnosticsWithoutLocationResult<SchemaAndDoc>; |
@@ -44,3 +44,2 @@ "use strict"; | ||
var validateMergedInterfaces_1 = require("./validations/validateMergedInterfaces"); | ||
var metadataDirectives_1 = require("./metadataDirectives"); | ||
var addInterfaceFields_1 = require("./transforms/addInterfaceFields"); | ||
@@ -56,2 +55,7 @@ var filterNonGqlInterfaces_1 = require("./transforms/filterNonGqlInterfaces"); | ||
var resolveResolverParams_1 = require("./transforms/resolveResolverParams"); | ||
var customSpecValidations_1 = require("./validations/customSpecValidations"); | ||
var makeResolverSignature_1 = require("./transforms/makeResolverSignature"); | ||
var addImplicitRootTypes_1 = require("./transforms/addImplicitRootTypes"); | ||
var validateDirectiveArguments_1 = require("./validations/validateDirectiveArguments"); | ||
var coerceDefaultEnumValues_1 = require("./transforms/coerceDefaultEnumValues"); | ||
// Export the TypeScript plugin implementation used by | ||
@@ -78,2 +82,9 @@ // grats-ts-plugin | ||
* The core transformation pipeline of Grats. | ||
* | ||
* To keep the Grats codebase clean and maintainable, we've broken the | ||
* implementation into a series of transformations that each perform a small, | ||
* well-defined task. | ||
* | ||
* This function orchestrates the transformations and, as such, gives a good | ||
* high-level overview of how Grats works. | ||
*/ | ||
@@ -87,16 +98,24 @@ function extractSchemaAndDoc(options, program) { | ||
var checker = program.getTypeChecker(); | ||
var ctx = TypeContext_1.TypeContext.fromSnapshot(checker, snapshot); | ||
var ctxResult = TypeContext_1.TypeContext.fromSnapshot(checker, snapshot); | ||
if (ctxResult.kind === "ERROR") { | ||
return ctxResult; | ||
} | ||
var ctx = ctxResult.value; | ||
// Collect validation errors | ||
var validationResult = (0, Result_1.concatResults)((0, validateMergedInterfaces_1.validateMergedInterfaces)(checker, snapshot.interfaceDeclarations), (0, validateDuplicateContextOrInfo_1.validateDuplicateContextOrInfo)(ctx)); | ||
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); }) | ||
// Filter out any `implements` clauses that are not GraphQL interfaces. | ||
.map(function (definitions) { return (0, filterNonGqlInterfaces_1.filterNonGqlInterfaces)(ctx, definitions); }) | ||
.map(function () { return (0, filterNonGqlInterfaces_1.filterNonGqlInterfaces)(ctx, snapshot.definitions); }) | ||
// Determine which positional resolver arguments: GraphQL arguments, | ||
// context, derived context, or info. | ||
.andThen(function (definitions) { return (0, resolveResolverParams_1.resolveResolverParams)(ctx, definitions); }) | ||
// Follow TypeScript type references to determine the GraphQL types | ||
// being referenced. | ||
.andThen(function (definitions) { return (0, resolveTypes_1.resolveTypes)(ctx, 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. | ||
// Convert string literals used as default values for enums into GraphQL | ||
// enums where appropriate. | ||
.map(function (definitions) { return (0, coerceDefaultEnumValues_1.coerceDefaultEnumValues)(ctx, 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); }) | ||
@@ -110,6 +129,13 @@ // Convert the definitions into a DocumentNode | ||
.andThen(function (doc) { return (0, applyDefaultNullability_1.applyDefaultNullability)(doc, config); }) | ||
// Ensure we have Query/Mutation/Subscription types if they've been extended with | ||
// `@gqlQueryField` and friends. | ||
.map(function (doc) { return (0, addImplicitRootTypes_1.addImplicitRootTypes)(doc); }) | ||
// Merge any `extend` definitions into their base definitions. | ||
.map(function (doc) { return (0, mergeExtensions_1.mergeExtensions)(doc); }) | ||
// Perform custom validations that reimplement spec validation rules | ||
// with more tailored error messages. | ||
.andThen(function (doc) { return (0, customSpecValidations_1.customSpecValidations)(doc); }) | ||
// Sort the definitions in the document to ensure a stable output. | ||
.map(function (doc) { return (0, sortSchemaAst_1.sortSchemaAst)(doc); }) | ||
.andThen(function (doc) { return specValidateSDL(doc); }) | ||
.result(); | ||
@@ -120,10 +146,20 @@ if (docResult.kind === "ERROR") { | ||
var doc = docResult.value; | ||
var resolvers = (0, makeResolverSignature_1.makeResolverSignature)(doc); | ||
// Build and validate the schema with regards to the GraphQL spec. | ||
return (new Result_1.ResultPipe(buildSchemaFromDoc(doc)) | ||
return (new Result_1.ResultPipe(buildSchema(doc)) | ||
// Apply the "Type Validation" sub-sections of the specification's | ||
// "Type System" section. | ||
.andThen(function (schema) { return specSchemaValidation(schema); }) | ||
// The above spec validation fails to catch type errors in directive | ||
// arguments, so Grats checks these manually. | ||
.andThen(function (schema) { return (0, validateDirectiveArguments_1.validateDirectiveArguments)(schema, 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); }) | ||
// Validate that semantic nullability directives are not in conflict | ||
// with type nullability. | ||
.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 }); }) | ||
// Combine the schema, document and resolver metadata into a single | ||
// result. | ||
.map(function (schema) { return ({ schema: schema, doc: doc, resolvers: resolvers }); }) | ||
.result()); | ||
@@ -133,4 +169,6 @@ }) | ||
} | ||
// Given a SDL AST, build and validate a GraphQLSchema. | ||
function buildSchemaFromDoc(doc) { | ||
function buildSchema(doc) { | ||
return (0, Result_2.ok)((0, graphql_1.buildASTSchema)(doc, { assumeValidSDL: true })); | ||
} | ||
function specValidateSDL(doc) { | ||
// TODO: Currently this does not detect definitions that shadow builtins | ||
@@ -140,21 +178,24 @@ // (`String`, `Int`, etc). However, if we pass a second param (extending an | ||
// shadow builtins. | ||
var validationErrors = (0, validate_1.validateSDL)(doc); | ||
return asDiagnostics(doc, validate_1.validateSDL); | ||
} | ||
function specSchemaValidation(schema) { | ||
return asDiagnostics(schema, graphql_1.validateSchema); | ||
} | ||
// Utility to map GraphQL validation errors to a Result of | ||
function asDiagnostics(value, validate) { | ||
var validationErrors = validate(value).filter( | ||
// FIXME: Handle case where query is not defined (no location) | ||
function (e) { return e.source && e.locations && e.positions; }); | ||
if (validationErrors.length > 0) { | ||
return (0, Result_2.err)(validationErrors.map(DiagnosticError_1.graphQlErrorToDiagnostic)); | ||
} | ||
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)); | ||
} | ||
return (0, Result_2.ok)(schema); | ||
return (0, Result_2.ok)(value); | ||
} | ||
// 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; | ||
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(), | ||
implicitNameDefinitions: new Map(), | ||
unresolvedNames: new Map(), | ||
@@ -168,4 +209,4 @@ typesWithTypename: new Set(), | ||
try { | ||
for (var _g = (e_2 = void 0, __values(snapshot.definitions)), _h = _g.next(); !_h.done; _h = _g.next()) { | ||
var definition = _h.value; | ||
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); | ||
@@ -177,3 +218,3 @@ } | ||
try { | ||
if (_h && !_h.done && (_b = _g.return)) _b.call(_g); | ||
if (_j && !_j.done && (_b = _h.return)) _b.call(_h); | ||
} | ||
@@ -183,4 +224,4 @@ finally { if (e_2) throw e_2.error; } | ||
try { | ||
for (var _j = (e_3 = void 0, __values(snapshot.nameDefinitions)), _k = _j.next(); !_k.done; _k = _j.next()) { | ||
var _l = __read(_k.value, 2), node = _l[0], definition = _l[1]; | ||
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); | ||
@@ -192,3 +233,3 @@ } | ||
try { | ||
if (_k && !_k.done && (_c = _j.return)) _c.call(_j); | ||
if (_l && !_l.done && (_c = _k.return)) _c.call(_k); | ||
} | ||
@@ -198,4 +239,4 @@ finally { if (e_3) throw e_3.error; } | ||
try { | ||
for (var _m = (e_4 = void 0, __values(snapshot.unresolvedNames)), _o = _m.next(); !_o.done; _o = _m.next()) { | ||
var _p = __read(_o.value, 2), node = _p[0], typeName = _p[1]; | ||
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); | ||
@@ -207,3 +248,3 @@ } | ||
try { | ||
if (_o && !_o.done && (_d = _m.return)) _d.call(_m); | ||
if (_p && !_p.done && (_d = _o.return)) _d.call(_o); | ||
} | ||
@@ -213,5 +254,5 @@ finally { if (e_4) throw e_4.error; } | ||
try { | ||
for (var _q = (e_5 = void 0, __values(snapshot.typesWithTypename)), _r = _q.next(); !_r.done; _r = _q.next()) { | ||
var typeName = _r.value; | ||
result.typesWithTypename.add(typeName); | ||
for (var _r = (e_5 = void 0, __values(snapshot.implicitNameDefinitions)), _s = _r.next(); !_s.done; _s = _r.next()) { | ||
var _t = __read(_s.value, 2), node = _t[0], definition = _t[1]; | ||
result.implicitNameDefinitions.set(node, definition); | ||
} | ||
@@ -222,3 +263,3 @@ } | ||
try { | ||
if (_r && !_r.done && (_e = _q.return)) _e.call(_q); | ||
if (_s && !_s.done && (_e = _r.return)) _e.call(_r); | ||
} | ||
@@ -228,5 +269,5 @@ finally { if (e_5) throw e_5.error; } | ||
try { | ||
for (var _s = (e_6 = void 0, __values(snapshot.interfaceDeclarations)), _t = _s.next(); !_t.done; _t = _s.next()) { | ||
var interfaceDeclaration = _t.value; | ||
result.interfaceDeclarations.push(interfaceDeclaration); | ||
for (var _u = (e_6 = void 0, __values(snapshot.typesWithTypename)), _v = _u.next(); !_v.done; _v = _u.next()) { | ||
var typeName = _v.value; | ||
result.typesWithTypename.add(typeName); | ||
} | ||
@@ -237,6 +278,19 @@ } | ||
try { | ||
if (_t && !_t.done && (_f = _s.return)) _f.call(_s); | ||
if (_v && !_v.done && (_f = _u.return)) _f.call(_u); | ||
} | ||
finally { if (e_6) throw e_6.error; } | ||
} | ||
try { | ||
for (var _w = (e_7 = void 0, __values(snapshot.interfaceDeclarations)), _x = _w.next(); !_x.done; _x = _w.next()) { | ||
var interfaceDeclaration = _x.value; | ||
result.interfaceDeclarations.push(interfaceDeclaration); | ||
} | ||
} | ||
catch (e_7_1) { e_7 = { error: e_7_1 }; } | ||
finally { | ||
try { | ||
if (_x && !_x.done && (_g = _w.return)) _g.call(_w); | ||
} | ||
finally { if (e_7) throw e_7.error; } | ||
} | ||
} | ||
@@ -243,0 +297,0 @@ } |
@@ -25,3 +25,3 @@ "use strict"; | ||
} | ||
return (0, Result_1.ok)((0, helpers_1.loc)(type.astNode.name)); | ||
return (0, Result_1.ok)((0, helpers_1.nullThrows)(type.astNode.name.loc)); | ||
} | ||
@@ -40,3 +40,3 @@ if (!(type instanceof graphql_1.GraphQLObjectType || | ||
} | ||
return (0, Result_1.ok)((0, helpers_1.loc)(field.astNode.name)); | ||
return (0, Result_1.ok)((0, helpers_1.nullThrows)(field.astNode.name.loc)); | ||
} | ||
@@ -43,0 +43,0 @@ var ENTITY_NAME_REGEX = /^([A-Za-z0-9_]+)(?:\.([A-Za-z0-9_]+))?$/; |
import { DocumentNode, GraphQLSchema } from "graphql"; | ||
import { GratsConfig } from "./gratsConfig"; | ||
import { Metadata } from "./metadata"; | ||
/** | ||
@@ -7,3 +8,3 @@ * Prints code for a TypeScript module that exports a GraphQLSchema. | ||
*/ | ||
export declare function printExecutableSchema(schema: GraphQLSchema, config: GratsConfig, destination: string): string; | ||
export declare function printExecutableSchema(schema: GraphQLSchema, resolvers: Metadata, config: GratsConfig, destination: string): string; | ||
export declare function applyTypeScriptHeader(config: GratsConfig, code: string): string; | ||
@@ -10,0 +11,0 @@ /** |
@@ -9,4 +9,4 @@ "use strict"; | ||
var graphql_1 = require("graphql"); | ||
var codegen_1 = require("./codegen"); | ||
var metadataDirectives_1 = require("./metadataDirectives"); | ||
var schemaCodegen_1 = require("./codegen/schemaCodegen"); | ||
var resolverMapCodegen_1 = require("./codegen/resolverMapCodegen"); | ||
/** | ||
@@ -16,4 +16,6 @@ * Prints code for a TypeScript module that exports a GraphQLSchema. | ||
*/ | ||
function printExecutableSchema(schema, config, destination) { | ||
var code = (0, codegen_1.codegen)(schema, config, destination); | ||
function printExecutableSchema(schema, resolvers, config, destination) { | ||
var code = config.EXPERIMENTAL__emitResolverMap | ||
? (0, resolverMapCodegen_1.resolverMapCodegen)(schema, resolvers, config, destination) | ||
: (0, schemaCodegen_1.codegen)(schema, resolvers, config, destination); | ||
return applyTypeScriptHeader(config, code); | ||
@@ -37,8 +39,2 @@ } | ||
var trimmed = (0, graphql_1.visit)(doc, { | ||
DirectiveDefinition: function (t) { | ||
return metadataDirectives_1.METADATA_DIRECTIVE_NAMES.has(t.name.value) ? null : t; | ||
}, | ||
Directive: function (t) { | ||
return metadataDirectives_1.METADATA_DIRECTIVE_NAMES.has(t.name.value) ? null : t; | ||
}, | ||
ScalarTypeDefinition: function (t) { | ||
@@ -45,0 +41,0 @@ return graphql_1.specifiedScalarTypes.some(function (scalar) { return scalar.name === t.name.value; }) |
"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 __values = (this && this.__values) || function(o) { | ||
@@ -33,3 +22,2 @@ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
var Extractor_1 = require("../Extractor"); | ||
var metadataDirectives_1 = require("../metadataDirectives"); | ||
/** | ||
@@ -81,3 +69,3 @@ * Grats allows you to define GraphQL fields on TypeScript interfaces using | ||
var e_2, _a; | ||
var _b, _c; | ||
var _b; | ||
var newDocs = []; | ||
@@ -103,15 +91,10 @@ var definitionResult = ctx.gqlNameDefinitionForGqlName(doc.name); | ||
// 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 = (_c = field.directives) === null || _c === void 0 ? void 0 : _c.filter(function (directive) { | ||
return directive.name.value !== metadataDirectives_1.FIELD_METADATA_DIRECTIVE; | ||
}); | ||
newDocs.push({ | ||
kind: graphql_1.Kind.INTERFACE_TYPE_EXTENSION, | ||
name: doc.name, | ||
fields: [__assign(__assign({}, field), { directives: directives })], | ||
fields: [field], | ||
}); | ||
try { | ||
for (var _d = __values(interfaceGraph.get(nameDefinition.name.value)), _e = _d.next(); !_e.done; _e = _d.next()) { | ||
var implementor = _e.value; | ||
for (var _c = __values(interfaceGraph.get(nameDefinition.name.value)), _d = _c.next(); !_d.done; _d = _c.next()) { | ||
var implementor = _d.value; | ||
var name = { | ||
@@ -136,3 +119,3 @@ kind: graphql_1.Kind.NAME, | ||
name: name, | ||
fields: [__assign(__assign({}, field), { directives: directives })], | ||
fields: [field], | ||
loc: doc.loc, | ||
@@ -147,3 +130,3 @@ }); | ||
try { | ||
if (_e && !_e.done && (_a = _d.return)) _a.call(_d); | ||
if (_d && !_d.done && (_a = _c.return)) _a.call(_c); | ||
} | ||
@@ -156,6 +139,4 @@ finally { if (e_2) throw e_2.error; } | ||
// Extending any other type of definition is not supported. | ||
var loc = (0, helpers_1.nullThrows)(doc.name.loc); | ||
var relatedLoc = (0, helpers_1.nullThrows)(nameDefinition.name.loc); | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(loc, E.invalidTypePassedToFieldFunction(), [ | ||
(0, DiagnosticError_1.gqlRelated)(relatedLoc, "This is the type that was passed to `@".concat(Extractor_1.FIELD_TAG, "`.")), | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(doc.name, E.invalidTypePassedToFieldFunction(), [ | ||
(0, DiagnosticError_1.gqlRelated)(nameDefinition.name, "This is the type that was passed to `@".concat(Extractor_1.FIELD_TAG, "`.")), | ||
])); | ||
@@ -162,0 +143,0 @@ } |
@@ -44,3 +44,2 @@ "use strict"; | ||
var E = require("../Errors"); | ||
var metadataDirectives_1 = require("../metadataDirectives"); | ||
var publicDirectives_1 = require("../publicDirectives"); | ||
@@ -60,12 +59,12 @@ var GraphQLConstructor_1 = require("../GraphQLConstructor"); | ||
_b[graphql_1.Kind.FIELD_DEFINITION] = function (t) { | ||
var _a, _b; | ||
var killsParent = (_a = t.directives) === null || _a === void 0 ? void 0 : _a.find(function (d) { return d.name.value === metadataDirectives_1.KILLS_PARENT_ON_EXCEPTION_DIRECTIVE; }); | ||
var _a; | ||
var killsParent = t.killsParentOnException; | ||
if (killsParent) { | ||
// You can only use @killsParentOnException if nullableByDefault is on. | ||
if (!nullableByDefault) { | ||
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(killsParent), E.killsParentOnExceptionWithWrongConfig())); | ||
errors.push((0, DiagnosticError_1.gqlErr)(killsParent, E.killsParentOnExceptionWithWrongConfig())); | ||
} | ||
// You can't use @killsParentOnException if it's been typed as nullable | ||
if (t.type.kind !== graphql_1.Kind.NON_NULL_TYPE) { | ||
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(killsParent), E.killsParentOnExceptionOnNullable())); | ||
errors.push((0, DiagnosticError_1.gqlErr)(killsParent, E.killsParentOnExceptionOnNullable())); | ||
} | ||
@@ -79,5 +78,5 @@ // Set the location of the NON_NULL_TYPE wrapper to the location of the | ||
var type = gql.nullableType(t.type); | ||
var directives = (_b = t.directives) !== null && _b !== void 0 ? _b : []; | ||
var directives = (_a = t.directives) !== null && _a !== void 0 ? _a : []; | ||
if (strictSemanticNullability) { | ||
var semanticNullability = (0, publicDirectives_1.makeSemanticNonNullDirective)((0, helpers_1.loc)(t.type)); | ||
var semanticNullability = (0, publicDirectives_1.makeSemanticNonNullDirective)((0, helpers_1.nullThrows)(t.type.loc)); | ||
directives = __spreadArray(__spreadArray([], __read(directives), false), [semanticNullability], false); | ||
@@ -84,0 +83,0 @@ } |
@@ -13,5 +13,42 @@ "use strict"; | ||
}; | ||
var __values = (this && this.__values) || function(o) { | ||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; | ||
if (m) return m.call(o); | ||
if (o && typeof o.length === "number") return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); | ||
}; | ||
var __read = (this && this.__read) || function (o, n) { | ||
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; | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.resolveResolverParams = resolveResolverParams; | ||
var graphql_1 = require("graphql"); | ||
var TypeContext_1 = require("../TypeContext"); | ||
var Result_1 = require("../utils/Result"); | ||
@@ -21,2 +58,3 @@ var DiagnosticError_1 = require("../utils/DiagnosticError"); | ||
var E = require("../Errors"); | ||
var GraphQLConstructor_1 = require("../GraphQLConstructor"); | ||
function resolveResolverParams(ctx, definitions) { | ||
@@ -30,2 +68,3 @@ var resolver = new ResolverParamsResolver(ctx); | ||
this.ctx = ctx; | ||
this.gql = new GraphQLConstructor_1.GraphQLConstructor(); | ||
} | ||
@@ -46,39 +85,192 @@ ResolverParamsResolver.prototype.resolve = function (definitions) { | ||
ResolverParamsResolver.prototype.transformField = function (field) { | ||
var _this = this; | ||
if (field.resolverParams == null) { | ||
var e_1, _a, e_2, _b; | ||
var resolver = (0, helpers_1.nullThrows)(field.resolver); | ||
if (resolver.kind === "property" || resolver.arguments == null) { | ||
return field; | ||
} | ||
var nextResolverParams = field.resolverParams.map(function (param) { | ||
return _this.transformParam(param); | ||
}); | ||
return __assign(__assign({}, field), { resolverParams: nextResolverParams }); | ||
// Resolve all the params individually | ||
var resolverParams = []; | ||
try { | ||
for (var _c = __values(resolver.arguments), _d = _c.next(); !_d.done; _d = _c.next()) { | ||
var param = _d.value; | ||
var transformed = this.transformParam(param); | ||
if (transformed == null) | ||
return field; | ||
resolverParams.push(transformed); | ||
} | ||
} | ||
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; } | ||
} | ||
// Now we check to see if the params are a valid combination... | ||
var args = resolverParams.find(function (param) { return param.kind === "argumentsObject"; }); | ||
var positionalArgs = resolverParams.filter(function (param) { return param.kind === "named"; }); | ||
if (args != null && positionalArgs.length > 0) { | ||
this.errors.push((0, DiagnosticError_1.tsErr)((0, helpers_1.nullThrows)(args.node), E.positionalArgAndArgsObject(), [ | ||
(0, DiagnosticError_1.tsRelated)(positionalArgs[0].node, "Positional GraphQL argument defined here"), | ||
])); | ||
return field; | ||
} | ||
var fieldArgs = field.arguments == null ? [] : __spreadArray([], __read(field.arguments), false); | ||
try { | ||
// Add any positional args to the field's arguments | ||
for (var positionalArgs_1 = __values(positionalArgs), positionalArgs_1_1 = positionalArgs_1.next(); !positionalArgs_1_1.done; positionalArgs_1_1 = positionalArgs_1.next()) { | ||
var positionalArg = positionalArgs_1_1.value; | ||
fieldArgs.push(positionalArg.inputDefinition); | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (positionalArgs_1_1 && !positionalArgs_1_1.done && (_b = positionalArgs_1.return)) _b.call(positionalArgs_1); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
var newResolver = __assign(__assign({}, resolver), { arguments: resolverParams }); | ||
return __assign(__assign({}, field), { arguments: fieldArgs, resolver: newResolver }); | ||
}; | ||
ResolverParamsResolver.prototype.transformParam = function (param) { | ||
ResolverParamsResolver.prototype.transformParam = function (param, seenDerivedContextValues) { | ||
var _a, _b; | ||
switch (param.kind) { | ||
case "named": | ||
case "argumentsObject": | ||
case "information": | ||
case "context": | ||
case "derivedContext": | ||
case "source": | ||
return param; | ||
case "unresolved": { | ||
var resolved = this.ctx.gqlNameDefinitionForGqlName(param.namedTypeNode.name); | ||
if (resolved.kind === "ERROR") { | ||
this.errors.push(resolved.err); | ||
return param; | ||
} | ||
switch (resolved.value.kind) { | ||
case "CONTEXT": | ||
return { kind: "named", name: "context" }; | ||
case "INFO": | ||
return { kind: "named", name: "info" }; | ||
default: { | ||
this.errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(param.namedTypeNode), E.invalidResolverParamType())); | ||
return param; | ||
var unwrappedType = this.gql.nullableType(param.inputDefinition.type); | ||
if (unwrappedType.kind === "NamedType" && | ||
unwrappedType.name.value === TypeContext_1.UNRESOLVED_REFERENCE_NAME) { | ||
var resolved = this.ctx.gqlNameDefinitionForGqlName(unwrappedType.name); | ||
if (resolved.kind === "ERROR") { | ||
this.errors.push(resolved.err); | ||
return null; | ||
} | ||
switch (resolved.value.kind) { | ||
case "DERIVED_CONTEXT": { | ||
var derivedContextArg = this.resolveDerivedContext(param.node, resolved.value, seenDerivedContextValues); | ||
if (derivedContextArg === null) | ||
return null; | ||
return derivedContextArg; | ||
} | ||
case "CONTEXT": | ||
return { kind: "context", node: param.node }; | ||
case "INFO": | ||
return { kind: "information", node: param.node }; | ||
default: { | ||
// We'll assume it's supposed to be a positional arg. | ||
return (_a = this.resolveToPositionalArg(param)) !== null && _a !== void 0 ? _a : param; | ||
} | ||
} | ||
} | ||
// This can't be a context or info param so we'll assume it's supposed | ||
// to be a positional arg. | ||
return (_b = this.resolveToPositionalArg(param)) !== null && _b !== void 0 ? _b : param; | ||
} | ||
default: { | ||
var _exhaustive = param; | ||
throw new Error("Unexpected param kind"); | ||
// @ts-expect-error | ||
throw new Error("Unexpected param kind ".concat(param.kind)); | ||
} | ||
} | ||
}; | ||
ResolverParamsResolver.prototype.resolveDerivedContext = function (node, // Argument | ||
definition, seenDerivedContextValues) { | ||
var e_3, _a; | ||
var path = definition.path, exportName = definition.exportName, args = definition.args; | ||
var key = "".concat(path, ":").concat(exportName); | ||
if (seenDerivedContextValues == null) { | ||
// We're resolving the arg of a resolver. Initiate the map. | ||
seenDerivedContextValues = new Map(); | ||
} | ||
else { | ||
if (seenDerivedContextValues.has(key)) { | ||
this.errors.push(this.cycleError(node, definition, seenDerivedContextValues)); | ||
return null; | ||
} | ||
} | ||
seenDerivedContextValues.set(key, node); | ||
var newArgs = []; | ||
try { | ||
for (var args_1 = __values(args), args_1_1 = args_1.next(); !args_1_1.done; args_1_1 = args_1.next()) { | ||
var arg = args_1_1.value; | ||
var resolvedArg = this.transformParam(arg, seenDerivedContextValues); | ||
if (resolvedArg === null) { | ||
continue; | ||
} | ||
switch (resolvedArg.kind) { | ||
case "context": | ||
newArgs.push(resolvedArg); | ||
break; | ||
case "derivedContext": | ||
// Here we know that the argument `node` maps to a derived context | ||
// `definition` which itself depends another derived resolver `resolvedArg`. | ||
// `definition`. | ||
newArgs.push(resolvedArg); | ||
break; | ||
default: | ||
this.errors.push((0, DiagnosticError_1.tsErr)(resolvedArg.node, E.invalidDerivedContextArgType())); | ||
} | ||
} | ||
} | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
try { | ||
if (args_1_1 && !args_1_1.done && (_a = args_1.return)) _a.call(args_1); | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
} | ||
return { kind: "derivedContext", node: node, path: path, exportName: exportName, args: newArgs }; | ||
}; | ||
ResolverParamsResolver.prototype.resolveToPositionalArg = function (unresolved) { | ||
if (unresolved.inputDefinition.name.kind === "ERROR") { | ||
this.errors.push(unresolved.inputDefinition.name.err); | ||
return null; | ||
} | ||
return { | ||
kind: "named", | ||
name: unresolved.inputDefinition.name.value.value, | ||
inputDefinition: __assign(__assign({}, unresolved.inputDefinition), { name: unresolved.inputDefinition.name.value }), | ||
node: unresolved.node, | ||
}; | ||
}; | ||
/** | ||
* Some slightly complicated logic to construct nice errors in the case of | ||
* cycles where derived resolvers ultimately depend upon themselves. | ||
* | ||
* The `@gqlContext` tag is the main location. If it's a direct cycle, we | ||
* report one related location, of the argument which points back to itself. | ||
* | ||
* If there are multiple nodes in the cycle, we report a related location for | ||
* each node in the cycle, with a message that depends on the position of the | ||
* node in the cycle. | ||
*/ | ||
ResolverParamsResolver.prototype.cycleError = function (node, definition, seenDerivedContextValues) { | ||
// We trim off the first node because that points to a resolver argument. | ||
var nodes = Array.from(seenDerivedContextValues.values()).slice(1); | ||
// The cycle completes with this node, so we include it in the list. | ||
nodes.push(node); | ||
var related = nodes.map(function (def, i) { | ||
if (nodes.length === 1) { | ||
return (0, DiagnosticError_1.tsRelated)(def, "This derived context depends on itself"); | ||
} | ||
var isFirst = i === 0; | ||
var isLast = i === nodes.length - 1; | ||
(0, helpers_1.invariant)(!(isFirst && isLast), "Should not be both first and last"); | ||
if (isFirst) { | ||
return (0, DiagnosticError_1.tsRelated)(def, "This derived context depends on"); | ||
} | ||
else if (!isLast) { | ||
return (0, DiagnosticError_1.tsRelated)(def, "Which in turn depends on"); | ||
} | ||
return (0, DiagnosticError_1.tsRelated)(def, "Which ultimately creates a cycle back to the initial derived context"); | ||
}); | ||
return (0, DiagnosticError_1.gqlErr)(definition.name, E.cyclicDerivedContext(), related); | ||
}; | ||
return ResolverParamsResolver; | ||
}()); |
@@ -288,4 +288,4 @@ "use strict"; | ||
if (definition.interfaces && definition.interfaces.length > 0) { | ||
var loc_1 = (0, helpers_1.loc)(definition.interfaces[0].name); | ||
this._errors.push((0, DiagnosticError_1.gqlErr)(loc_1, E.genericTypeImplementsInterface())); | ||
var item = definition.interfaces[0].name; | ||
this._errors.push((0, DiagnosticError_1.gqlErr)(item, E.genericTypeImplementsInterface())); | ||
} | ||
@@ -332,4 +332,4 @@ } | ||
definition.kind === graphql_1.Kind.UNION_TYPE_DEFINITION || | ||
definition.kind === graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION || | ||
definition.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION); | ||
definition.kind === graphql_1.Kind.INTERFACE_TYPE_DEFINITION || | ||
definition.kind === graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION); | ||
} | ||
@@ -336,0 +336,0 @@ function getTypeParameters(declaration) { |
import { InputObjectTypeDefinitionNode, InterfaceTypeDefinitionNode, NameNode, ObjectTypeDefinitionNode, UnionTypeDefinitionNode } from "graphql"; | ||
import * as ts from "typescript"; | ||
import { DiagnosticResult } from "./utils/DiagnosticError"; | ||
import { DiagnosticResult, DiagnosticsResult } from "./utils/DiagnosticError"; | ||
import { ExtractionSnapshot } from "./Extractor"; | ||
import { ResolverArgument } from "./resolverSignature"; | ||
export declare const UNRESOLVED_REFERENCE_NAME = "__UNRESOLVED_REFERENCE__"; | ||
export type DerivedResolverDefinition = { | ||
name: NameNode; | ||
path: string; | ||
exportName: string | null; | ||
args: ResolverArgument[]; | ||
kind: "DERIVED_CONTEXT"; | ||
}; | ||
export type NameDefinition = { | ||
@@ -10,2 +18,3 @@ name: NameNode; | ||
}; | ||
export type DeclarationDefinition = NameDefinition | DerivedResolverDefinition; | ||
type TsIdentifier = number; | ||
@@ -26,10 +35,10 @@ /** | ||
checker: ts.TypeChecker; | ||
_declarationToName: Map<ts.Declaration, NameDefinition>; | ||
_declarationToDefinition: Map<ts.Declaration, DeclarationDefinition>; | ||
_unresolvedNodes: Map<TsIdentifier, ts.EntityName>; | ||
_idToDeclaration: Map<TsIdentifier, ts.Declaration>; | ||
static fromSnapshot(checker: ts.TypeChecker, snapshot: ExtractionSnapshot): TypeContext; | ||
static fromSnapshot(checker: ts.TypeChecker, snapshot: ExtractionSnapshot): DiagnosticsResult<TypeContext>; | ||
constructor(checker: ts.TypeChecker); | ||
private _recordTypeName; | ||
private _recordDeclaration; | ||
private _markUnresolvedType; | ||
allNameDefinitions(): Iterable<NameDefinition>; | ||
allDefinitions(): Iterable<DeclarationDefinition>; | ||
findSymbolDeclaration(startSymbol: ts.Symbol): ts.Declaration | null; | ||
@@ -39,3 +48,3 @@ private resolveSymbol; | ||
unresolvedNameIsGraphQL(unresolved: NameNode): boolean; | ||
gqlNameDefinitionForGqlName(nameNode: NameNode): DiagnosticResult<NameDefinition>; | ||
gqlNameDefinitionForGqlName(nameNode: NameNode): DiagnosticResult<DeclarationDefinition>; | ||
gqlNameForTsName(node: ts.EntityName): DiagnosticResult<string>; | ||
@@ -42,0 +51,0 @@ private maybeTsDeclarationForTsName; |
@@ -46,3 +46,2 @@ "use strict"; | ||
var E = require("./Errors"); | ||
var helpers_1 = require("./utils/helpers"); | ||
exports.UNRESOLVED_REFERENCE_NAME = "__UNRESOLVED_REFERENCE__"; | ||
@@ -63,3 +62,3 @@ /** | ||
function TypeContext(checker) { | ||
this._declarationToName = new Map(); | ||
this._declarationToDefinition = new Map(); | ||
this._unresolvedNodes = new Map(); | ||
@@ -70,7 +69,8 @@ this._idToDeclaration = new Map(); | ||
TypeContext.fromSnapshot = function (checker, snapshot) { | ||
var e_1, _a, e_2, _b; | ||
var e_1, _a, e_2, _b, e_3, _c; | ||
var errors = []; | ||
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]; | ||
for (var _d = __values(snapshot.unresolvedNames), _e = _d.next(); !_e.done; _e = _d.next()) { | ||
var _f = __read(_e.value, 2), node = _f[0], typeName = _f[1]; | ||
self._markUnresolvedType(node, typeName); | ||
@@ -82,3 +82,3 @@ } | ||
try { | ||
if (_d && !_d.done && (_a = _c.return)) _a.call(_c); | ||
if (_e && !_e.done && (_a = _d.return)) _a.call(_d); | ||
} | ||
@@ -88,5 +88,5 @@ 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); | ||
for (var _g = __values(snapshot.nameDefinitions), _h = _g.next(); !_h.done; _h = _g.next()) { | ||
var _j = __read(_h.value, 2), node = _j[0], definition = _j[1]; | ||
self._recordDeclaration(node, definition); | ||
} | ||
@@ -97,13 +97,42 @@ } | ||
try { | ||
if (_g && !_g.done && (_b = _f.return)) _b.call(_f); | ||
if (_h && !_h.done && (_b = _g.return)) _b.call(_g); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
return self; | ||
try { | ||
for (var _k = __values(snapshot.implicitNameDefinitions), _l = _k.next(); !_l.done; _l = _k.next()) { | ||
var _m = __read(_l.value, 2), definition = _m[0], reference = _m[1]; | ||
var declaration = self.maybeTsDeclarationForTsName(reference.typeName); | ||
if (declaration == null) { | ||
errors.push((0, DiagnosticError_1.tsErr)(reference.typeName, E.unresolvedTypeReference())); | ||
continue; | ||
} | ||
var existing = self._declarationToDefinition.get(declaration); | ||
if (existing != null) { | ||
errors.push((0, DiagnosticError_1.tsErr)(declaration, "Multiple derived contexts defined for given type", [ | ||
(0, DiagnosticError_1.gqlRelated)(definition.name, "One was defined here"), | ||
(0, DiagnosticError_1.gqlRelated)(existing.name, "Another here"), | ||
])); | ||
continue; | ||
} | ||
self._recordDeclaration(declaration, definition); | ||
} | ||
} | ||
catch (e_3_1) { e_3 = { error: e_3_1 }; } | ||
finally { | ||
try { | ||
if (_l && !_l.done && (_c = _k.return)) _c.call(_k); | ||
} | ||
finally { if (e_3) throw e_3.error; } | ||
} | ||
if (errors.length > 0) { | ||
return (0, Result_1.err)(errors); | ||
} | ||
return (0, Result_1.ok)(self); | ||
}; | ||
// Record that a GraphQL construct of type `kind` with the name `name` is | ||
// declared at `node`. | ||
TypeContext.prototype._recordTypeName = function (node, name, kind) { | ||
this._idToDeclaration.set(name.tsIdentifier, node); | ||
this._declarationToName.set(node, { name: name, kind: kind }); | ||
TypeContext.prototype._recordDeclaration = function (node, definition) { | ||
this._idToDeclaration.set(definition.name.tsIdentifier, node); | ||
this._declarationToDefinition.set(node, definition); | ||
}; | ||
@@ -114,4 +143,4 @@ // Record that a type references `node` | ||
}; | ||
TypeContext.prototype.allNameDefinitions = function () { | ||
return this._declarationToName.values(); | ||
TypeContext.prototype.allDefinitions = function () { | ||
return this._declarationToDefinition.values(); | ||
}; | ||
@@ -151,8 +180,11 @@ TypeContext.prototype.findSymbolDeclaration = function (startSymbol) { | ||
if (ts.isTypeParameterDeclaration(declarationResult.value)) { | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(unresolved), "Type parameters are not supported in this context.")); | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(unresolved, "Type parameters are not supported in this context.")); | ||
} | ||
var nameDefinition = this._declarationToName.get(declarationResult.value); | ||
var nameDefinition = this._declarationToDefinition.get(declarationResult.value); | ||
if (nameDefinition == null) { | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(unresolved), E.unresolvedTypeReference())); | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(unresolved, E.unresolvedTypeReference())); | ||
} | ||
if (nameDefinition.kind === "CONTEXT" || nameDefinition.kind === "INFO") { | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(unresolved, E.contextOrInfoUsedInGraphQLPosition(nameDefinition.kind), [(0, DiagnosticError_1.gqlRelated)(nameDefinition.name, "Defined here")])); | ||
} | ||
return (0, Result_1.ok)(__assign(__assign({}, unresolved), { value: nameDefinition.name.value })); | ||
@@ -167,3 +199,3 @@ }; | ||
return false; | ||
return this._declarationToName.has(declaration); | ||
return this._declarationToDefinition.has(declaration); | ||
}; | ||
@@ -177,7 +209,7 @@ TypeContext.prototype.gqlNameDefinitionForGqlName = function (nameNode) { | ||
if (declaration == null) { | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(nameNode), E.unresolvedTypeReference())); | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(nameNode, E.unresolvedTypeReference())); | ||
} | ||
var definition = this._declarationToName.get(declaration); | ||
var definition = this._declarationToDefinition.get(declaration); | ||
if (definition == null) { | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(nameNode), E.unresolvedTypeReference())); | ||
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(nameNode, E.unresolvedTypeReference())); | ||
} | ||
@@ -197,6 +229,11 @@ return (0, Result_1.ok)(definition); | ||
} | ||
var nameDefinition = this._declarationToName.get(declarationResult.value); | ||
var nameDefinition = this._declarationToDefinition.get(declarationResult.value); | ||
if (nameDefinition == null) { | ||
return (0, Result_1.err)((0, DiagnosticError_1.tsErr)(node, E.unresolvedTypeReference())); | ||
} | ||
if (nameDefinition.kind === "CONTEXT" || nameDefinition.kind === "INFO") { | ||
return (0, Result_1.err)((0, DiagnosticError_1.tsErr)(node, E.contextOrInfoUsedInGraphQLPosition(nameDefinition.kind), [ | ||
(0, DiagnosticError_1.gqlRelated)(nameDefinition.name, "Defined here"), | ||
])); | ||
} | ||
return (0, Result_1.ok)(nameDefinition.name.value); | ||
@@ -222,2 +259,3 @@ }; | ||
if (!declaration) { | ||
console.log(definition); | ||
throw new Error("Could not find declaration for ".concat(name.value)); | ||
@@ -224,0 +262,0 @@ } |
@@ -23,4 +23,9 @@ import { GraphQLError, Location, Source } from "graphql"; | ||
export declare function graphQlErrorToDiagnostic(error: GraphQLError): 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 locationlessErr(message: string): ts.Diagnostic; | ||
export declare function gqlErr(item: { | ||
loc?: Location; | ||
}, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.DiagnosticWithLocation; | ||
export declare function gqlRelated(item: { | ||
loc?: Location; | ||
}, message: string): ts.DiagnosticRelatedInformation; | ||
export declare function rangeErr(file: ts.SourceFile, commentRange: ts.CommentRange, message: string, relatedInformation?: ts.DiagnosticRelatedInformation[], fix?: ts.CodeFixAction): FixableDiagnosticWithLocation; | ||
@@ -27,0 +32,0 @@ /** |
@@ -32,2 +32,3 @@ "use strict"; | ||
exports.graphQlErrorToDiagnostic = graphQlErrorToDiagnostic; | ||
exports.locationlessErr = locationlessErr; | ||
exports.gqlErr = gqlErr; | ||
@@ -103,3 +104,3 @@ exports.gqlRelated = gqlRelated; | ||
} | ||
relatedInformation.push(gqlRelated(relatedNode.loc, "Related location")); | ||
relatedInformation.push(gqlRelated(relatedNode, "Related location")); | ||
} | ||
@@ -132,5 +133,20 @@ } | ||
} | ||
function gqlErr(loc, message, relatedInformation) { | ||
function locationlessErr(message) { | ||
return { | ||
messageText: message, | ||
file: undefined, | ||
code: exports.FAKE_ERROR_CODE, | ||
category: ts.DiagnosticCategory.Error, | ||
start: undefined, | ||
length: undefined, | ||
source: "Grats", | ||
}; | ||
} | ||
function gqlErr(item, message, relatedInformation) { | ||
if (item.loc == null) { | ||
throw new Error("Expected item to have loc"); | ||
} | ||
var loc = item.loc; | ||
return { | ||
messageText: message, | ||
file: graphqlSourceToSourceFile(loc.source), | ||
@@ -145,3 +161,7 @@ code: exports.FAKE_ERROR_CODE, | ||
} | ||
function gqlRelated(loc, message) { | ||
function gqlRelated(item, message) { | ||
if (item.loc == null) { | ||
throw new Error("Expected item to have loc"); | ||
} | ||
var loc = item.loc; | ||
return { | ||
@@ -148,0 +168,0 @@ category: ts.DiagnosticCategory.Message, |
@@ -1,2 +0,1 @@ | ||
import { Location } from "graphql"; | ||
export declare class DefaultMap<K, V> { | ||
@@ -9,5 +8,2 @@ 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: { | ||
@@ -19,1 +15,2 @@ astNode?: T | undefined | null; | ||
export declare function nullThrows<T>(value: T | null | undefined): T; | ||
export declare function isNonNull<T>(value: T | null | undefined): value is T; |
@@ -16,3 +16,2 @@ "use strict"; | ||
exports.extend = extend; | ||
exports.loc = loc; | ||
exports.astNode = astNode; | ||
@@ -22,2 +21,3 @@ exports.uniqueId = uniqueId; | ||
exports.nullThrows = nullThrows; | ||
exports.isNonNull = isNonNull; | ||
var DefaultMap = /** @class */ (function () { | ||
@@ -55,8 +55,2 @@ function DefaultMap(getDefault) { | ||
} | ||
function loc(item) { | ||
if (item.loc == null) { | ||
throw new Error("Expected item to have loc"); | ||
} | ||
return item.loc; | ||
} | ||
function astNode(item) { | ||
@@ -83,1 +77,6 @@ if (item.astNode == null) { | ||
} | ||
// Predicate function for filtering out null values | ||
// Includes TypeScript refinement for narrowing the type | ||
function isNonNull(value) { | ||
return value != null; | ||
} |
@@ -19,3 +19,2 @@ "use strict"; | ||
var E = require("../Errors"); | ||
var helpers_1 = require("../utils/helpers"); | ||
/** | ||
@@ -41,3 +40,3 @@ * Ensure that all fields on `Subscription` return an AsyncIterable and transform | ||
if (inner.kind !== graphql_1.Kind.LIST_TYPE || !inner.isAsyncIterable) { | ||
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(field.type), E.subscriptionFieldNotAsyncIterable())); | ||
errors.push((0, DiagnosticError_1.gqlErr)(field.type, E.subscriptionFieldNotAsyncIterable())); | ||
return field; | ||
@@ -44,0 +43,0 @@ } |
@@ -17,3 +17,2 @@ "use strict"; | ||
var DiagnosticError_1 = require("../utils/DiagnosticError"); | ||
var helpers_1 = require("../utils/helpers"); | ||
var E = require("../Errors"); | ||
@@ -26,3 +25,3 @@ function validateDuplicateContextOrInfo(ctx) { | ||
try { | ||
for (var _b = __values(ctx.allNameDefinitions()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
for (var _b = __values(ctx.allDefinitions()), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var namedDefinition = _c.value; | ||
@@ -32,4 +31,4 @@ switch (namedDefinition.kind) { | ||
if (ctxDefinition != null) { | ||
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(namedDefinition.name), E.duplicateContextTag(), [ | ||
(0, DiagnosticError_1.gqlRelated)((0, helpers_1.loc)(ctxDefinition.name), "`@gqlContext` previously defined here."), | ||
errors.push((0, DiagnosticError_1.gqlErr)(namedDefinition.name, E.duplicateContextTag(), [ | ||
(0, DiagnosticError_1.gqlRelated)(ctxDefinition.name, "`@gqlContext` previously defined here."), | ||
])); | ||
@@ -42,3 +41,3 @@ continue; | ||
if (infoDefinition != null) { | ||
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(namedDefinition.name), E.userDefinedInfoTag())); | ||
errors.push((0, DiagnosticError_1.gqlErr)(namedDefinition.name, E.userDefinedInfoTag())); | ||
continue; | ||
@@ -45,0 +44,0 @@ } |
@@ -60,5 +60,3 @@ "use strict"; | ||
if (typeSemanticNonNull == null) { | ||
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(interfaceSemanticNonNull), "Interface field `".concat(implementor.name, ".").concat(implementorField.name, "` expects a non-nullable type but `").concat(interfaceType.name, ".").concat(interfaceField.name, "` is nullable."), [ | ||
(0, DiagnosticError_1.gqlRelated)((0, helpers_1.loc)((0, helpers_1.astNode)(implementorField).type), "Related location"), | ||
])); | ||
errors.push((0, DiagnosticError_1.gqlErr)(interfaceSemanticNonNull, "Interface field `".concat(implementor.name, ".").concat(implementorField.name, "` expects a non-nullable type but `").concat(interfaceType.name, ".").concat(interfaceField.name, "` is nullable."), [(0, DiagnosticError_1.gqlRelated)((0, helpers_1.astNode)(implementorField).type, "Related location")])); | ||
} | ||
@@ -65,0 +63,0 @@ } |
@@ -42,3 +42,3 @@ "use strict"; | ||
: E.genericTypeUsedAsUnionMember(); | ||
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(ast.name), message)); | ||
errors.push((0, DiagnosticError_1.gqlErr)(ast.name, message)); | ||
} | ||
@@ -49,4 +49,4 @@ else if (!hasTypename.has(implementor.name) && ast.exported == null) { | ||
: E.concreteTypenameInUnionCannotBeResolved(implementor.name, type.name); | ||
var err_1 = (0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(ast.name), message, [ | ||
(0, DiagnosticError_1.gqlRelated)((0, helpers_1.loc)((0, helpers_1.nullThrows)(type.astNode).name), "".concat(type.name, " is defined here:")), | ||
var err_1 = (0, DiagnosticError_1.gqlErr)(ast.name, message, [ | ||
(0, DiagnosticError_1.gqlRelated)((0, helpers_1.nullThrows)(type.astNode).name, "".concat(type.name, " is defined here:")), | ||
]); | ||
@@ -53,0 +53,0 @@ errors.push(err_1); |
{ | ||
"name": "grats", | ||
"version": "0.0.0-main-df51f741", | ||
"version": "0.0.0-main-df550a4f", | ||
"main": "dist/src/index.js", | ||
@@ -15,6 +15,6 @@ "bin": "dist/src/cli.js", | ||
"graphql": "^16.9.0", | ||
"typescript": "5.5.4" | ||
"typescript": "5.5.4", | ||
"semver": "^7.5.4" | ||
}, | ||
"devDependencies": { | ||
"@graphql-tools/utils": "^9.2.1", | ||
"@types/node": "^18.14.6", | ||
@@ -30,3 +30,2 @@ "@types/semver": "^7.5.6", | ||
"process": "^0.11.10", | ||
"semver": "^7.5.4", | ||
"ts-node": "^10.9.1" | ||
@@ -38,4 +37,3 @@ }, | ||
"engines": { | ||
"node": ">=16 <=21", | ||
"pnpm": ">=8 <=9" | ||
"node": ">=16 <=21" | ||
}, | ||
@@ -42,0 +40,0 @@ "bugs": { |
# Grats: Implementation-First GraphQL for TypeScript | ||
[](https://capt.dev/grats-chat) | ||
_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._ | ||
**The simplest way to build a GraphQL server in TypeScript** | ||
@@ -48,2 +44,4 @@ | ||
[](https://capt.dev/grats-chat) | ||
## Contributing | ||
@@ -50,0 +48,0 @@ |
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
454706
25.25%11
-15.38%100
25%9533
27.74%0
-100%4
33.33%64
-3.03%+ Added
+ Added