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

grats

Package Overview
Dependencies
Maintainers
1
Versions
240
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grats - npm Package Compare versions

Comparing version 0.0.0-main-03b23474 to 0.0.0-main-055d3f1c

dist/src/codegenHelpers.d.ts

29

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

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

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

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

"integration-tests": "node src/tests/integration.mjs",
"build": "tsc --build",
"build": "rm -rf dist/ && tsc --build",
"format": "prettier . --write",

@@ -47,3 +48,23 @@ "lint": "eslint . && prettier . --check"

"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"
]
}

29

dist/src/cli.js

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

exports.formatLoc = void 0;
var graphql_1 = require("graphql");
var _1 = require("./");

@@ -81,8 +80,9 @@ var lib_1 = require("./lib");

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

@@ -103,3 +103,3 @@ console.error(loc.err);

// For now we just rebuild the schema on every change.
var schemaResult = (0, lib_1.extractSchema)(config, program.getProgram());
var schemaResult = (0, lib_1.extractSchemaAndDoc)(config, program.getProgram());
if (schemaResult.kind === "ERROR") {

@@ -118,9 +118,8 @@ reportDiagnostics(schemaResult.err);

var _a = getTsConfigOrReportAndExit(tsconfig), config = _a.config, configPath = _a.configPath;
var schemaResult = (0, lib_1.buildSchemaResult)(config);
if (schemaResult.kind === "ERROR") {
console.error(schemaResult.err.formatDiagnosticsWithColorAndContext());
var schemaAndDocResult = (0, lib_1.buildSchemaAndDocResult)(config);
if (schemaAndDocResult.kind === "ERROR") {
console.error(schemaAndDocResult.err.formatDiagnosticsWithColorAndContext());
process.exit(1);
}
var sortedSchema = (0, graphql_1.lexicographicSortSchema)(schemaResult.value);
writeSchemaFilesAndReport(sortedSchema, config, configPath);
writeSchemaFilesAndReport(schemaAndDocResult.value, config, configPath);
}

@@ -130,10 +129,10 @@ /**

*/
function writeSchemaFilesAndReport(schema, config, configPath) {
var sortedSchema = (0, graphql_1.lexicographicSortSchema)(schema);
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)(sortedSchema, gratsOptions, dest);
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)(sortedSchema, gratsOptions);
var schemaStr = (0, printSchema_1.printGratsSDL)(doc, gratsOptions);
var absOutput = (0, path_1.resolve)((0, path_1.dirname)(configPath), gratsOptions.graphqlSchema);

@@ -140,0 +139,0 @@ (0, fs_1.writeFileSync)(absOutput, schemaStr);

"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 __read = (this && this.__read) || function (o, n) {

@@ -34,2 +45,6 @@ var m = typeof Symbol === "function" && o[Symbol.iterator];

var gratsRoot_1 = require("./gratsRoot");
var publicDirectives_1 = require("./publicDirectives");
var codegenHelpers_1 = require("./codegenHelpers");
var helpers_1 = require("./utils/helpers");
var RESOLVER_ARGS = ["source", "args", "context", "info"];
var F = ts.factory;

@@ -47,2 +62,3 @@ // Given a GraphQL SDL, returns the a string of TypeScript code that generates a

this._imports = [];
this._helpers = new Map();
this._typeDefinitions = new Set();

@@ -145,3 +161,3 @@ this._graphQLImports = new Set();

this.description(obj.description),
this.fields(obj),
this.fields(obj, false),
this.interfaces(obj),

@@ -152,9 +168,17 @@ ]);

var _this = this;
var args = ["source", "args", "context", "info"];
var exported = fieldDirective(field, metadataDirectives_1.EXPORTED_DIRECTIVE);
if (exported != null) {
var exportedMetadata = (0, metadataDirectives_1.parseExportedDirective)(exported);
var module_1 = exportedMetadata.tsModulePath;
var funcName = exportedMetadata.exportedFunctionName;
var argCount = exportedMetadata.argCount;
var metadataDirective = fieldDirective(field, metadataDirectives_1.FIELD_METADATA_DIRECTIVE);
if (metadataDirective == null) {
throw new Error("Expected to find metadata directive.");
}
var metadata = (0, metadataDirectives_1.parseFieldMetadataDirective)(metadataDirective);
if (metadata.tsModulePath != null) {
var module_1 = metadata.tsModulePath;
var funcName = metadata.name;
if (funcName == null) {
throw new Error("Expected to find name in metadata directive.");
}
var argCount = metadata.argCount;
if (argCount == null) {
throw new Error("Expected to find argCount in metadata directive.");
}
var abs = (0, gratsRoot_1.resolveRelativePath)(module_1);

@@ -164,3 +188,3 @@ var relative = stripExt(path.relative(path.dirname(this._destination), abs));

this.import("./".concat(relative), [{ name: funcName, as: resolverName }]);
var usedArgs = args.slice(0, argCount);
var usedArgs = RESOLVER_ARGS.slice(0, argCount);
return this.method(methodName, usedArgs.map(function (name) {

@@ -174,22 +198,60 @@ return _this.param(name);

}
var propertyName = fieldDirective(field, metadataDirectives_1.FIELD_NAME_DIRECTIVE);
if (propertyName != null) {
var name = (0, metadataDirectives_1.parsePropertyNameDirective)(propertyName).name;
var prop = F.createPropertyAccessExpression(F.createIdentifier("source"), F.createIdentifier(name));
var callExpression = F.createCallExpression(prop, undefined, args.map(function (name) {
return F.createIdentifier(name);
}));
var isFunc = F.createStrictEquality(F.createTypeOfExpression(prop), F.createStringLiteral("function"));
var ternary = F.createConditionalExpression(isFunc, undefined, callExpression, undefined, prop);
return this.method(methodName, args.map(function (name) {
return _this.param(name);
}), [F.createReturnStatement(ternary)]);
if (metadata.name != null) {
var prop = F.createPropertyAccessExpression(F.createIdentifier("source"), F.createIdentifier(metadata.name));
var valueExpression = prop;
if (metadata.argCount != null) {
valueExpression = F.createCallExpression(prop, undefined, RESOLVER_ARGS.map(function (name) {
return F.createIdentifier(name);
}));
}
return this.method(methodName, RESOLVER_ARGS.map(function (name) { return _this.param(name); }), [F.createReturnStatement(valueExpression)]);
}
// If the resolver name matches the field name, and the field is not backed by a function,
// we can just use the default resolver.
return null;
};
Codegen.prototype.fields = function (obj) {
// If a field is smantically non-null, we need to wrap the resolver in a
// runtime check to ensure that the resolver does not return null.
Codegen.prototype.maybeApplySemanticNullRuntimeCheck = function (field, method_) {
var _a;
var semanticNonNull = fieldDirective(field, publicDirectives_1.SEMANTIC_NON_NULL_DIRECTIVE);
if (semanticNonNull == null) {
return method_;
}
if (!this._helpers.has(codegenHelpers_1.ASSERT_NON_NULL_HELPER)) {
this._helpers.set(codegenHelpers_1.ASSERT_NON_NULL_HELPER, (0, codegenHelpers_1.createAssertNonNullHelper)());
}
var method = method_ !== null && method_ !== void 0 ? method_ : this.defaultResolverMethod();
var bodyStatements = (_a = method.body) === null || _a === void 0 ? void 0 : _a.statements;
if (bodyStatements == null || bodyStatements.length === 0) {
throw new Error("Expected method to have a body");
}
var foundReturn = false;
var newBodyStatements = bodyStatements.map(function (statement) {
if (ts.isReturnStatement(statement)) {
if (statement.expression == null) {
throw new Error("Expected return statement to have an expression");
}
foundReturn = true;
// We need to wrap the return statement in a call to the runtime check
return F.createReturnStatement(F.createCallExpression(F.createIdentifier(codegenHelpers_1.ASSERT_NON_NULL_HELPER), [], [statement.expression]));
}
return statement;
});
if (!foundReturn) {
throw new Error("Expected method to have a return statement");
}
return __assign(__assign({}, method), { body: F.createBlock(newBodyStatements, true) });
};
Codegen.prototype.defaultResolverMethod = function () {
var _this = this;
return this.method("resolve", RESOLVER_ARGS.map(function (name) { return _this.param(name); }), [
F.createReturnStatement(F.createCallExpression(this.graphQLImport("defaultFieldResolver"), undefined, RESOLVER_ARGS.map(function (name) { return F.createIdentifier(name); }))),
]);
};
Codegen.prototype.fields = function (obj, isInterface) {
var _this = this;
var fields = Object.entries(obj.getFields()).map(function (_a) {
var _b = __read(_a, 2), name = _b[0], field = _b[1];
return F.createPropertyAssignment(name, _this.fieldConfig(field, obj.name));
return F.createPropertyAssignment(name, _this.fieldConfig(field, obj.name, isInterface));
});

@@ -222,3 +284,3 @@ return this.method("fields", [], [F.createReturnStatement(this.objectLiteral(fields))]);

F.createPropertyAssignment("name", F.createStringLiteral(obj.name)),
this.fields(obj),
this.fields(obj, true),
this.interfaces(obj),

@@ -299,4 +361,4 @@ ]);

};
Codegen.prototype.fieldConfig = function (field, parentTypeName) {
return this.objectLiteral(__spreadArray([
Codegen.prototype.fieldConfig = function (field, parentTypeName, isInterface) {
var props = [
this.description(field.description),

@@ -308,14 +370,25 @@ this.deprecated(field),

? F.createPropertyAssignment("args", this.argMap(field.args))
: null
], __read(this.fieldMethods(field, parentTypeName)), false));
: null,
];
if (!isInterface) {
(0, helpers_1.extend)(props, this.fieldMethods(field, parentTypeName));
}
return this.objectLiteral(props);
};
Codegen.prototype.fieldMethods = function (field, parentTypeName) {
var asyncIterable = fieldDirective(field, metadataDirectives_1.ASYNC_ITERABLE_TYPE_DIRECTIVE);
if (asyncIterable == null) {
return [this.resolveMethod(field, "resolve", parentTypeName)];
var metadataDirective = fieldDirective(field, metadataDirectives_1.FIELD_METADATA_DIRECTIVE);
if (metadataDirective == null) {
throw new Error("Expected to find metadata directive.");
}
// Note: We assume the default name is used here. When custom operation types are supported
// we'll need to update this.
if (parentTypeName !== "Subscription") {
var resolve = this.resolveMethod(field, "resolve", parentTypeName);
return [this.maybeApplySemanticNullRuntimeCheck(field, resolve)];
}
return [
// TODO: Maybe avoid adding `assertNonNull` for subscription resolvers?
this.resolveMethod(field, "subscribe", parentTypeName),
// Identity function (method?)
this.method("resolve", [this.param("payload")], [F.createReturnStatement(F.createIdentifier("payload"))]),
this.maybeApplySemanticNullRuntimeCheck(field, this.method("resolve", [this.param("payload")], [F.createReturnStatement(F.createIdentifier("payload"))])),
];

@@ -464,4 +537,4 @@ };

// Helper for the common case of a single string argument.
Codegen.prototype.param = function (name) {
return F.createParameterDeclaration(undefined, undefined, name, undefined, undefined, undefined);
Codegen.prototype.param = function (name, type) {
return F.createParameterDeclaration(undefined, undefined, name, undefined, type, undefined);
};

@@ -483,3 +556,3 @@ Codegen.prototype.import = function (from, names) {

this.import("graphql", __spreadArray([], __read(this._graphQLImports), false).map(function (name) { return ({ name: name }); }));
return printer.printList(ts.ListFormat.MultiLine, F.createNodeArray(__spreadArray(__spreadArray([], __read(this._imports), false), __read(this._statements), false)), sourceFile);
return printer.printList(ts.ListFormat.MultiLine, F.createNodeArray(__spreadArray(__spreadArray(__spreadArray([], __read(this._imports), false), __read(this._helpers.values()), false), __read(this._statements), false)), sourceFile);
};

@@ -486,0 +559,0 @@ return Codegen;

@@ -34,2 +34,3 @@ export declare const ISSUE_URL = "https://github.com/captbaritone/grats/issues";

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

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

export declare function wrapperMissingTypeArg(): string;
export declare function invalidWrapperOnInputType(wrapperName: string): string;
export declare function cannotResolveSymbolForDescription(): string;

@@ -92,4 +94,10 @@ export declare function propertyFieldMissingType(): 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;
export declare function gqlFieldTagOnInputType(): string;
export declare function gqlFieldParentMissingTag(): string;
export declare function missingSpecifiedByUrl(): string;
export declare function specifiedByOnWrongNode(): string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultArgElementIsNotAssignment = 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.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.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 = void 0;
exports.ambiguousNumberType = exports.expectedOneNonNullishType = exports.propertyFieldMissingType = exports.cannotResolveSymbolForDescription = exports.invalidWrapperOnInputType = 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.specifiedByOnWrongNode = exports.missingSpecifiedByUrl = exports.gqlFieldParentMissingTag = exports.gqlFieldTagOnInputType = exports.gqlTagInDetachedJSDocBlockComment = exports.gqlTagInNonJSDocBlockComment = exports.gqlTagInLineComment = exports.expectedNullableArgumentToBeOptional = exports.operationTypeNotUnknown = 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 = exports.defaultValueIsNotLiteral = void 0;
var Extractor_1 = require("./Extractor");

@@ -11,2 +11,3 @@ exports.ISSUE_URL = "https://github.com/captbaritone/grats/issues";

parameterProperties: "https://grats.capt.dev/docs/docblock-tags/fields#class-based-fields",
commentSyntax: "https://grats.capt.dev/docs/getting-started/comment-syntax",
};

@@ -24,3 +25,3 @@ /**

function fieldTagOnWrongNode() {
return "`@".concat(Extractor_1.FIELD_TAG, "` can only be used on method/property declarations or signatures.");
return "`@".concat(Extractor_1.FIELD_TAG, "` can only be used on method/property declarations, signatures, or function declarations.");
}

@@ -58,3 +59,3 @@ exports.fieldTagOnWrongNode = fieldTagOnWrongNode;

function invalidInputTagUsage() {
return "`@".concat(Extractor_1.INPUT_TAG, "` can only be used on type alias declarations. e.g. `type MyInput = { foo: string }`");
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 }`");
}

@@ -115,2 +116,6 @@ exports.invalidInputTagUsage = invalidInputTagUsage;

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() {

@@ -201,2 +206,6 @@ 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.wrapperMissingTypeArg = wrapperMissingTypeArg;
function invalidWrapperOnInputType(wrapperName) {
return "Invalid input type. `".concat(wrapperName, "` is not a valid type when used as a GraphQL input value.");
}
exports.invalidWrapperOnInputType = invalidWrapperOnInputType;
function cannotResolveSymbolForDescription() {

@@ -266,3 +275,3 @@ 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.";

"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",

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

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() {

@@ -370,1 +375,29 @@ 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.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;
function gqlFieldTagOnInputType() {
return "The tag `@".concat(Extractor_1.FIELD_TAG, "` is not needed on fields of input types. All fields are automatically included as part of the input type. This tag can be safely removed.");
}
exports.gqlFieldTagOnInputType = gqlFieldTagOnInputType;
function gqlFieldParentMissingTag() {
return "Unexpected `@".concat(Extractor_1.FIELD_TAG, "`. The parent construct must be either a `@").concat(Extractor_1.TYPE_TAG, "` or `@").concat(Extractor_1.INTERFACE_TAG, "` tag. Are you missing one of these tags?");
}
exports.gqlFieldParentMissingTag = gqlFieldParentMissingTag;
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.");
}
exports.missingSpecifiedByUrl = missingSpecifiedByUrl;
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?");
}
exports.specifiedByOnWrongNode = specifiedByOnWrongNode;

@@ -18,2 +18,3 @@ import { NameNode } from "graphql";

export declare const ALL_TAGS: string[];
export declare const SPECIFIED_BY_TAG = "specifiedBy";
export type ExtractionSnapshot = {

@@ -20,0 +21,0 @@ readonly definitions: GratsDefinitionNode[];

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

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;
exports.extract = exports.SPECIFIED_BY_TAG = 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");

@@ -42,2 +42,4 @@ var DiagnosticError_1 = require("./utils/DiagnosticError");

var Errors_1 = require("./Errors");
var comments_1 = require("./comments");
var helpers_1 = require("./utils/helpers");
exports.LIBRARY_IMPORT_NAME = "grats";

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

var DEPRECATED_TAG = "deprecated";
exports.SPECIFIED_BY_TAG = "specifiedBy";
var OPERATION_TYPES = new Set(["Query", "Mutation", "Subscription"]);

@@ -106,4 +109,6 @@ /**

var _this = this;
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) {

@@ -132,21 +137,40 @@ case exports.TYPE_TAG:

}
else if (!(ts.isParameter(node) ||
ts.isMethodDeclaration(node) ||
ts.isPropertyDeclaration(node) ||
ts.isMethodSignature(node) ||
ts.isPropertySignature(node))) {
// Right now this happens via deep traversal
// Note: Keep this in sync with `collectFields`
_this.reportUnhandled(node, "field", E.fieldTagOnWrongNode());
else {
// Non-function fields must be defined as a decent of something that
// is annotated with @gqlType or @gqlInterface.
//
// The actual field will get extracted when we traverse the parent, but
// we need to report an error if the parent is not a valid type or is not
// annotated with @gqlType or @gqlInterface. Otherwise, the user may get
// confused as to why the field is not showing up in the schema.
var parent = getFieldParent(node);
// If there was no valid parent, report an error.
if (parent === null) {
_this.reportUnhandled(node, "field", E.fieldTagOnWrongNode());
}
else if (_this.hasTag(parent, exports.INPUT_TAG)) {
// You don't need to add `@gqlField` to input types, but it's an
// easy mistake to think you might need to. We report a helpful
// error in this case.
_this.report(tag, E.gqlFieldTagOnInputType());
}
else if (!_this.hasTag(parent, exports.TYPE_TAG) &&
!_this.hasTag(parent, exports.INTERFACE_TAG)) {
_this.report(tag, E.gqlFieldParentMissingTag());
}
}
break;
case exports.KILLS_PARENT_ON_EXCEPTION_TAG: {
var hasFieldTag = ts.getJSDocTags(node).some(function (t) {
return t.tagName.text === exports.FIELD_TAG;
});
if (!hasFieldTag) {
if (!_this.hasTag(node, exports.FIELD_TAG)) {
_this.report(tag.tagName, E.killsParentOnExceptionOnWrongNode());
}
// TODO: Report invalid location as well
break;
}
case exports.SPECIFIED_BY_TAG: {
if (!_this.hasTag(node, exports.SCALAR_TAG)) {
_this.report(tag.tagName, E.specifiedByOnWrongNode());
}
break;
}
default:

@@ -178,2 +202,4 @@ {

});
var errors = (0, comments_1.detectInvalidComments)(sourceFile, seenCommentPositions);
(0, helpers_1.extend)(this.errors, errors);
if (this.errors.length > 0) {

@@ -236,2 +262,5 @@ return (0, Result_1.err)(this.errors);

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

@@ -310,6 +339,5 @@ this.report(tag, E.invalidInputTagUsage());

}
var returnType = this.collectReturnType(node.type);
if (returnType == null)
var type = this.collectType(node.type, { kind: "OUTPUT" });
if (type == null)
return null;
var type = returnType.type, isStream = returnType.isStream;
var args = null;

@@ -331,11 +359,8 @@ var argsParam = node.parameters[1];

var directives = [
this.gql.exportedDirective(funcName, {
this.gql.fieldMetadataDirective(funcName, {
tsModulePath: tsModulePath,
exportedFunctionName: funcName.text,
name: funcName.text,
argCount: node.parameters.length,
}),
];
if (isStream) {
directives.push(this.gql.asyncIterableDirective(node.type));
}
var deprecated = this.collectDeprecated(node);

@@ -390,3 +415,5 @@ if (deprecated != null) {

this.recordTypeName(node.name, name, "SCALAR");
this.definitions.push(this.gql.scalarTypeDefinition(node, name, description));
// TODO: Can a scalar be deprecated?
var specifiedByDirective = this.collectSpecifiedBy(node);
this.definitions.push(this.gql.scalarTypeDefinition(node, name, specifiedByDirective == null ? null : [specifiedByDirective], description));
};

@@ -403,5 +430,36 @@ Extractor.prototype.inputTypeAliasDeclaration = function (node, tag) {

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

@@ -422,3 +480,3 @@ 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 {

@@ -428,3 +486,3 @@ try {

}
finally { if (e_3) throw e_3.error; }
finally { if (e_4) throw e_4.error; }
}

@@ -440,3 +498,3 @@ return fields.length === 0 ? null : fields;

}
var inner = this.collectType(node.type);
var inner = this.collectType(node.type, { kind: "INPUT" });
if (inner == null)

@@ -479,3 +537,3 @@ return null;

var interfaces = this.collectInterfaces(node);
this.recordTypeName(node.name, name, "INTERFACE");
this.recordTypeName(node.name, name, "TYPE");
this.checkForTypenameProperty(node, name.value);

@@ -641,3 +699,3 @@ this.definitions.push(this.gql.objectTypeDefinition(node, name, fields, interfaces, description));

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

@@ -655,3 +713,3 @@ try {

}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {

@@ -661,6 +719,8 @@ try {

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

@@ -717,9 +777,10 @@ if (field != null) {

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

@@ -739,3 +800,3 @@ return null;

Extractor.prototype.collectArgs = function (argsParam) {
var e_5, _a;
var e_6, _a;
var args = [];

@@ -765,3 +826,3 @@ 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 {

@@ -771,3 +832,3 @@ try {

}
finally { if (e_5) throw e_5.error; }
finally { if (e_6) throw e_6.error; }
}

@@ -777,3 +838,3 @@ return args;

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

@@ -790,3 +851,3 @@ try {

}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {

@@ -796,3 +857,3 @@ try {

}
finally { if (e_6) throw e_6.error; }
finally { if (e_7) throw e_7.error; }
}

@@ -828,3 +889,3 @@ return defaults;

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

@@ -844,3 +905,3 @@ var errors = false;

}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {

@@ -850,3 +911,3 @@ try {

}
finally { if (e_7) throw e_7.error; }
finally { if (e_8) throw e_8.error; }
}

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

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

@@ -875,3 +936,3 @@ var errors = false;

}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
catch (e_9_1) { e_9 = { error: e_9_1 }; }
finally {

@@ -881,3 +942,3 @@ try {

}
finally { if (e_8) throw e_8.error; }
finally { if (e_9) throw e_9.error; }
}

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

}
var type = this.collectType(node.type);
var type = this.collectType(node.type, { kind: "INPUT" });
if (type == null)

@@ -930,3 +991,10 @@ return null;

}
if (node.questionToken) {
var defaultValue = null;
if (defaults != null) {
var def = defaults.get(node.name.text);
if (def != null) {
defaultValue = this.collectConstValue(def);
}
}
if (node.questionToken && defaultValue == null) {
// Question mark means we can handle the argument being undefined in the

@@ -936,2 +1004,4 @@ // object literal, but if we are going to type the GraphQL arg as

//
// ... 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 }.

@@ -944,9 +1014,2 @@ if (type.kind === graphql_1.Kind.NON_NULL_TYPE) {

var description = this.collectDescription(node);
var defaultValue = null;
if (defaults != null) {
var def = defaults.get(node.name.text);
if (def != null) {
defaultValue = this.collectConstValue(def);
}
}
var deprecatedDirective = this.collectDeprecated(node);

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

Extractor.prototype.enumTypeAliasVariants = function (node) {
var e_9, _a;
var e_10, _a;
// Semantically we only support deriving enums from type aliases that

@@ -1009,3 +1072,3 @@ // are unions of string literals. However, in the edge case of a union

}
catch (e_9_1) { e_9 = { error: e_9_1 }; }
catch (e_10_1) { e_10 = { error: e_10_1 }; }
finally {

@@ -1015,3 +1078,3 @@ try {

}
finally { if (e_9) throw e_9.error; }
finally { if (e_10) throw e_10.error; }
}

@@ -1021,3 +1084,3 @@ return values;

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

@@ -1037,3 +1100,3 @@ try {

}
catch (e_10_1) { e_10 = { error: e_10_1 }; }
catch (e_11_1) { e_11 = { error: e_11_1 }; }
finally {

@@ -1043,3 +1106,3 @@ try {

}
finally { if (e_10) throw e_10.error; }
finally { if (e_11) throw e_11.error; }
}

@@ -1115,6 +1178,5 @@ return values;

}
var returnType = this.collectReturnType(node.type);
if (returnType == null)
var type = this.collectType(node.type, { kind: "OUTPUT" });
if (type == null)
return null;
var type = returnType.type, isStream = returnType.isStream;
// We already reported an error

@@ -1136,11 +1198,9 @@ if (type == null)

return null;
var directives = [];
if (id.text !== name.value) {
directives = [
this.gql.propertyNameDirective(node.name, { name: id.text }),
];
}
if (isStream) {
directives.push(this.gql.asyncIterableDirective(node.type));
}
var directives = [
this.gql.fieldMetadataDirective(node.name, {
name: id.text === name.value ? null : id.text,
tsModulePath: null,
argCount: isCallable(node) ? node.parameters.length : null,
}),
];
var deprecated = this.collectDeprecated(node);

@@ -1156,47 +1216,2 @@ if (deprecated != null) {

};
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, isStream: true };
}
}
var inner = this.maybeUnwrapPromise(node);
if (inner == null)
return null;
var t = this.collectType(inner);
if (t == null)
return null;
return { type: t, isStream: false };
};
Extractor.prototype.collectPropertyType = function (node) {
// TODO: Handle function types here.
var inner = this.maybeUnwrapPromise(node);
if (inner == null)
return null;
return this.collectType(inner);
};
Extractor.prototype.maybeUnwrapPromise = function (node) {
if (ts.isTypeReferenceNode(node)) {
var identifier = this.expectNameIdentifier(node.typeName);
if (identifier == null)
return null;
if (identifier.text === "Promise") {
if (node.typeArguments == null || node.typeArguments.length === 0) {
return this.report(node, E.wrapperMissingTypeArg());
}
return node.typeArguments[0];
}
}
return node;
};
Extractor.prototype.collectDescription = function (node) {

@@ -1229,2 +1244,14 @@ var docs =

};
Extractor.prototype.collectSpecifiedBy = function (node) {
var tag = this.findTag(node, exports.SPECIFIED_BY_TAG);
if (tag == null)
return null;
var urlComment = tag.comment && ts.getTextOfJSDocComment(tag.comment);
if (urlComment == null) {
return this.report(tag, "Expected @specifiedBy tag to be followed by a URL.");
}
// FIXME: Use the _value_'s location not the tag's
var reason = this.gql.constArgument(tag, this.gql.name(tag, "url"), this.gql.string(tag, urlComment));
return this.gql.constDirective(tag.tagName, this.gql.name(node, exports.SPECIFIED_BY_TAG), [reason]);
};
Extractor.prototype.property = function (node) {

@@ -1241,3 +1268,3 @@ var tag = this.findTag(node, exports.FIELD_TAG);

}
var inner = this.collectPropertyType(node.type);
var inner = this.collectType(node.type, { kind: "OUTPUT" });
// We already reported an error

@@ -1256,7 +1283,7 @@ if (inner == null)

}
if (id.text !== name.value) {
directives = [
this.gql.propertyNameDirective(node.name, { name: id.text }),
];
}
directives.push(this.gql.fieldMetadataDirective(node.name, {
name: id.text === name.value ? null : id.text,
tsModulePath: null,
argCount: null,
}));
var killsParentOnExceptionDirective = this.killsParentOnExceptionDirective(node);

@@ -1270,6 +1297,6 @@ if (killsParentOnExceptionDirective != null) {

// For input nodes and field may only be optional if `null` is a valid value.
Extractor.prototype.collectType = function (node) {
Extractor.prototype.collectType = function (node, ctx) {
var _this = this;
if (ts.isTypeReferenceNode(node)) {
var type = this.typeReference(node);
var type = this.typeReference(node, ctx);
if (type == null)

@@ -1280,3 +1307,3 @@ return null;

else if (ts.isArrayTypeNode(node)) {
var element = this.collectType(node.elementType);
var element = this.collectType(node.elementType, ctx);
if (element == null)

@@ -1291,3 +1318,3 @@ return null;

}
var type = this.collectType(types[0]);
var type = this.collectType(types[0], ctx);
if (type == null)

@@ -1305,3 +1332,3 @@ return null;

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

@@ -1311,3 +1338,3 @@ return this.gql.nonNullType(node, type);

else if (ts.isParenthesizedTypeNode(node)) {
return this.collectType(node.type);
return this.collectType(node.type, ctx);
}

@@ -1330,3 +1357,3 @@ else if (node.kind === ts.SyntaxKind.StringKeyword) {

};
Extractor.prototype.typeReference = function (node) {
Extractor.prototype.typeReference = function (node, ctx) {
var identifier = this.expectNameIdentifier(node.typeName);

@@ -1336,14 +1363,37 @@ if (identifier == null)

var typeName = identifier.text;
// Some types are not valid as input types. Validate that here:
if (ctx.kind === "INPUT") {
switch (typeName) {
case "AsyncIterable":
return this.report(node, "`AsyncIterable` is not a valid as an input type.");
case "Promise":
return this.report(node, "`Promise` is not a valid as an input type.");
}
}
switch (typeName) {
case "Array":
case "Iterator":
case "ReadonlyArray": {
case "ReadonlyArray":
case "AsyncIterable": {
if (node.typeArguments == null) {
return this.report(node, E.pluralTypeMissingParameter());
}
var element = this.collectType(node.typeArguments[0]);
var element = this.collectType(node.typeArguments[0], ctx);
if (element == null)
return null;
return this.gql.nonNullType(node, this.gql.listType(node, element));
var listType = this.gql.listType(node, element);
if (typeName === "AsyncIterable") {
listType.isAsyncIterable = true;
}
return this.gql.nonNullType(node, listType);
}
case "Promise": {
if (node.typeArguments == null) {
return this.report(node, E.wrapperMissingTypeArg());
}
var element = this.collectType(node.typeArguments[0], ctx);
if (element == null)
return null;
return element;
}
default: {

@@ -1393,2 +1443,8 @@ // We may not have encountered the definition of this type yet. So, we

};
Extractor.prototype.hasTag = function (node, tagName) {
var tags = ts
.getJSDocTags(node)
.filter(function (tag) { return tag.tagName.escapedText === tagName; });
return tags.length > 0;
};
// It is a GraphQL best practice to model all fields as nullable. This allows

@@ -1422,1 +1478,35 @@ // the server to handle field level executions by simply returning null for

}
function isCallable(node) {
return ts.isMethodDeclaration(node) || ts.isMethodSignature(node);
}
// Given a node annotated as @gqlField, finds the parent node that is
// expected to be annotated with @gqlType or @gqlInterface.
//
// Note that this is basically a reverse encoding of the traversal
// we do from the @gqlType or @gqlInterface node to the fields.
// This code needs to stay in sync with the traversal code, but should do so
// safely since, if it doesn't match we'd end up with test errors.
function getFieldParent(node) {
if (ts.isMethodDeclaration(node) ||
ts.isGetAccessorDeclaration(node) ||
ts.isPropertyDeclaration(node)) {
return node.parent;
}
else if (ts.isParameter(node)) {
if (ts.isConstructorDeclaration(node.parent)) {
return node.parent.parent;
}
return null;
}
else if (ts.isPropertySignature(node) || ts.isMethodSignature(node)) {
if (ts.isTypeLiteralNode(node.parent) &&
ts.isTypeAliasDeclaration(node.parent.parent)) {
return node.parent.parent;
}
else if (ts.isInterfaceDeclaration(node.parent)) {
return node.parent;
}
return null;
}
return null;
}

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

import { ListTypeNode, NamedTypeNode, Location as GraphQLLocation, NameNode, Token, TypeNode, NonNullTypeNode, StringValueNode, ConstValueNode, ConstDirectiveNode, ConstArgumentNode, UnionTypeDefinitionNode, FieldDefinitionNode, InputValueDefinitionNode, FloatValueNode, IntValueNode, NullValueNode, BooleanValueNode, ConstListValueNode, ConstObjectValueNode, ConstObjectFieldNode, ObjectTypeDefinitionNode, EnumValueDefinitionNode, ScalarTypeDefinitionNode, InputObjectTypeDefinitionNode, EnumTypeDefinitionNode, InterfaceTypeDefinitionNode, DefinitionNode, Location } from "graphql";
import { 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 { ExportedMetadata, PropertyNameMetadata } from "./metadataDirectives";
export type GratsDefinitionNode = DefinitionNode | AbstractFieldDefinitionNode;

@@ -12,5 +11,7 @@ export type AbstractFieldDefinitionNode = {

export declare class GraphQLConstructor {
exportedDirective(node: ts.Node, exported: ExportedMetadata): ConstDirectiveNode;
propertyNameDirective(node: ts.Node, propertyName: PropertyNameMetadata): ConstDirectiveNode;
asyncIterableDirective(node: ts.Node): ConstDirectiveNode;
fieldMetadataDirective(node: ts.Node, metadata: {
tsModulePath: string | null;
name: string | null;
argCount: number | null;
}): ConstDirectiveNode;
killsParentOnExceptionDirective(node: ts.Node): ConstDirectiveNode;

@@ -26,3 +27,3 @@ unionTypeDefinition(node: ts.Node, name: NameNode, types: NamedTypeNode[], description: StringValueNode | null): UnionTypeDefinitionNode;

enumValueDefinition(node: ts.Node, name: NameNode, directives: readonly ConstDirectiveNode[] | undefined, description: StringValueNode | null): EnumValueDefinitionNode;
scalarTypeDefinition(node: ts.Node, name: NameNode, description: StringValueNode | null): ScalarTypeDefinitionNode;
scalarTypeDefinition(node: ts.Node, name: NameNode, directives: readonly ConstDirectiveNode[] | null, description: StringValueNode | null): ScalarTypeDefinitionNode;
inputObjectTypeDefinition(node: ts.Node, name: NameNode, fields: InputValueDefinitionNode[] | null, directives: readonly ConstDirectiveNode[] | null, description: StringValueNode | null): InputObjectTypeDefinitionNode;

@@ -36,2 +37,3 @@ name(node: ts.Node, value: string): NameNode;

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;

@@ -38,0 +40,0 @@ constDirective(node: ts.Node, name: NameNode, args: ReadonlyArray<ConstArgumentNode> | null): ConstDirectiveNode;

"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);
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -9,12 +20,15 @@ exports.GraphQLConstructor = void 0;

}
/* Metadata Directives */
GraphQLConstructor.prototype.exportedDirective = function (node, exported) {
return (0, metadataDirectives_1.makeExportedDirective)(this._loc(node), exported);
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())));
}
return this.constDirective(node, this.name(node, metadataDirectives_1.FIELD_METADATA_DIRECTIVE), args);
};
GraphQLConstructor.prototype.propertyNameDirective = function (node, propertyName) {
return (0, metadataDirectives_1.makePropertyNameDirective)(this._loc(node), propertyName);
};
GraphQLConstructor.prototype.asyncIterableDirective = function (node) {
return (0, metadataDirectives_1.makeAsyncIterableDirective)(this._loc(node));
};
GraphQLConstructor.prototype.killsParentOnExceptionDirective = function (node) {

@@ -108,3 +122,3 @@ return (0, metadataDirectives_1.makeKillsParentOnExceptionDirective)(this._loc(node));

};
GraphQLConstructor.prototype.scalarTypeDefinition = function (node, name, description) {
GraphQLConstructor.prototype.scalarTypeDefinition = function (node, name, directives, description) {
return {

@@ -115,3 +129,3 @@ kind: graphql_1.Kind.SCALAR_TYPE_DEFINITION,

name: name,
directives: undefined,
directives: this._optionalList(directives),
};

@@ -163,2 +177,5 @@ };

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

@@ -165,0 +182,0 @@ return { kind: graphql_1.Kind.ARGUMENT, loc: this._loc(node), name: name, value: value };

@@ -6,2 +6,3 @@ import * as ts from "typescript";

nullableByDefault: boolean;
strictSemanticNullability: boolean;
reportTypeScriptTypeErrors: boolean;

@@ -11,3 +12,3 @@ schemaHeader: string | null;

};
export type ParsedCommandLineGrats = ts.ParsedCommandLine & {
export type ParsedCommandLineGrats = Omit<ts.ParsedCommandLine, "raw"> & {
raw: {

@@ -14,0 +15,0 @@ grats: ConfigOptions;

@@ -13,2 +13,13 @@ "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.");
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -18,6 +29,32 @@ exports.validateGratsOptions = void 0;

var DEFAULT_TYPESCRIPT_HEADER = "/**\n * Executable schema generated by Grats (https://grats.capt.dev)\n * Do not manually edit. Regenerate by running `npx grats`.\n */";
var VALID_CONFIG_KEYS = new Set([
"graphqlSchema",
"tsSchema",
"nullableByDefault",
"strictSemanticNullability",
"reportTypeScriptTypeErrors",
"schemaHeader",
"tsSchemaHeader",
]);
// TODO: Make this return diagnostics
function validateGratsOptions(options) {
var _a, _b;
var gratsOptions = __assign({}, ((_b = (_a = options.raw) === null || _a === void 0 ? void 0 : _a.grats) !== null && _b !== void 0 ? _b : {}));
var e_1, _a;
var _b, _c;
var gratsOptions = __assign({}, ((_c = (_b = options.raw) === null || _b === void 0 ? void 0 : _b.grats) !== null && _c !== void 0 ? _c : {}));
try {
for (var _d = __values(Object.keys(gratsOptions)), _e = _d.next(); !_e.done; _e = _d.next()) {
var key = _e.value;
if (!VALID_CONFIG_KEYS.has(key)) {
// TODO: Suggest similar?
throw new Error("Grats: Unknown Grats config option `".concat(key, "`"));
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
}
finally { if (e_1) throw e_1.error; }
}
if (gratsOptions.nullableByDefault === undefined) {

@@ -29,2 +66,12 @@ gratsOptions.nullableByDefault = true;

}
if (gratsOptions.strictSemanticNullability === undefined) {
gratsOptions.strictSemanticNullability = false;
}
else if (typeof gratsOptions.strictSemanticNullability !== "boolean") {
throw new Error("Grats: The Grats config option `strictSemanticNullability` must be a boolean if provided.");
}
else if (gratsOptions.strictSemanticNullability &&
!gratsOptions.nullableByDefault) {
throw new Error("Grats: The Grats config option `strictSemanticNullability` cannot be true if `nullableByDefault` is false.");
}
if (gratsOptions.reportTypeScriptTypeErrors === undefined) {

@@ -53,5 +100,11 @@ gratsOptions.reportTypeScriptTypeErrors = false;

}
else if (Array.isArray(gratsOptions.schemaHeader)) {
if (!gratsOptions.schemaHeader.every(function (segment) { return typeof segment === "string"; })) {
throw new Error("Grats: If the Grats config option `schemaHeader` is an array, it must be an array of strings.");
}
gratsOptions.schemaHeader = gratsOptions.schemaHeader.join("");
}
else if (typeof gratsOptions.schemaHeader !== "string" &&
gratsOptions.schemaHeader !== null) {
throw new Error("Grats: The Grats config option `schemaHeader` must be a string or `null` if provided.");
throw new Error("Grats: The Grats config option `schemaHeader` must be a string, an array of strings, or `null` if provided.");
}

@@ -61,5 +114,11 @@ if (gratsOptions.tsSchemaHeader === undefined) {

}
else if (Array.isArray(gratsOptions.tsSchemaHeader)) {
if (!gratsOptions.tsSchemaHeader.every(function (segment) { return typeof segment === "string"; })) {
throw new Error("Grats: If the Grats config option `tsSchemaHeader` is an array, it must be an array of strings.");
}
gratsOptions.tsSchemaHeader = gratsOptions.tsSchemaHeader.join("");
}
else if (typeof gratsOptions.tsSchemaHeader !== "string" &&
gratsOptions.tsSchemaHeader !== null) {
throw new Error("Grats: The Grats config option `tsSchemaHeader` must be a string or `null` if provided.");
throw new Error("Grats: The Grats config option `tsSchemaHeader` must be a string, an array of strings, or `null` if provided.");
}

@@ -66,0 +125,0 @@ return __assign(__assign({}, options), { raw: __assign(__assign({}, options.raw), { grats: gratsOptions }) });

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

import { ParsedCommandLineGrats } from "./lib";
import { ParsedCommandLineGrats } from "./gratsConfig";
import { ReportableDiagnostics } from "./utils/DiagnosticError";
import { Result } from "./utils/Result";
export { printSDLWithoutDirectives } from "./printSchema";
export { printSDLWithoutMetadata } from "./printSchema";
export * from "./Types";

@@ -6,0 +6,0 @@ export * from "./lib";

@@ -17,9 +17,9 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.getParsedTsConfig = exports.codegen = exports.extract = exports.printSDLWithoutDirectives = void 0;
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, "printSDLWithoutDirectives", { enumerable: true, get: function () { return printSchema_1.printSDLWithoutDirectives; } });
Object.defineProperty(exports, "printSDLWithoutMetadata", { enumerable: true, get: function () { return printSchema_1.printSDLWithoutMetadata; } });
__exportStar(require("./Types"), exports);

@@ -46,4 +46,4 @@ __exportStar(require("./lib"), exports);

}
return (0, Result_1.ok)((0, lib_1.validateGratsOptions)(parsed));
return (0, Result_1.ok)((0, gratsConfig_1.validateGratsOptions)(parsed));
}
exports.getParsedTsConfig = getParsedTsConfig;

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

import { GraphQLSchema } from "graphql";
import { DocumentNode, GraphQLSchema } from "graphql";
import { DiagnosticsWithoutLocationResult, ReportableDiagnostics } from "./utils/DiagnosticError";

@@ -6,8 +6,12 @@ import { Result } from "./utils/Result";

import { ParsedCommandLineGrats } from "./gratsConfig";
export * from "./gratsConfig";
export declare function buildSchemaResult(options: ParsedCommandLineGrats): Result<GraphQLSchema, ReportableDiagnostics>;
export declare function buildSchemaResultWithHost(options: ParsedCommandLineGrats, compilerHost: ts.CompilerHost): Result<GraphQLSchema, ReportableDiagnostics>;
export { initTsPlugin } from "./tsPlugin/initTsPlugin";
export type SchemaAndDoc = {
schema: GraphQLSchema;
doc: DocumentNode;
};
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 extractSchema(options: ParsedCommandLineGrats, program: ts.Program): DiagnosticsWithoutLocationResult<GraphQLSchema>;
export declare function extractSchemaAndDoc(options: ParsedCommandLineGrats, program: ts.Program): DiagnosticsWithoutLocationResult<SchemaAndDoc>;
"use strict";
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __values = (this && this.__values) || function(o) {

@@ -44,3 +30,3 @@ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;

Object.defineProperty(exports, "__esModule", { value: true });
exports.extractSchema = exports.buildSchemaResultWithHost = exports.buildSchemaResult = void 0;
exports.extractSchemaAndDoc = exports.buildSchemaAndDocResultWithHost = exports.buildSchemaAndDocResult = exports.initTsPlugin = void 0;
var graphql_1 = require("graphql");

@@ -63,6 +49,10 @@ var DiagnosticError_1 = require("./utils/DiagnosticError");

var applyDefaultNullability_1 = require("./transforms/applyDefaultNullability");
__exportStar(require("./gratsConfig"), exports);
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

@@ -72,16 +62,16 @@ var compilerHost = ts.createCompilerHost(options.options,

true);
return buildSchemaResultWithHost(options, compilerHost);
return buildSchemaAndDocResultWithHost(options, compilerHost);
}
exports.buildSchemaResult = buildSchemaResult;
function buildSchemaResultWithHost(options, compilerHost) {
exports.buildSchemaAndDocResult = buildSchemaAndDocResult;
function buildSchemaAndDocResultWithHost(options, compilerHost) {
var program = ts.createProgram(options.fileNames, options.options, compilerHost);
return new Result_1.ResultPipe(extractSchema(options, program))
return new Result_1.ResultPipe(extractSchemaAndDoc(options, program))
.mapErr(function (e) { return new DiagnosticError_1.ReportableDiagnostics(compilerHost, e); })
.result();
}
exports.buildSchemaResultWithHost = buildSchemaResultWithHost;
exports.buildSchemaAndDocResultWithHost = buildSchemaAndDocResultWithHost;
/**
* The core transformation pipeline of Grats.
*/
function extractSchema(options, program) {
function extractSchemaAndDoc(options, program) {
return new Result_1.ResultPipe((0, snapshotsFromProgram_1.extractSnapshotsFromProgram)(program, options))

@@ -91,3 +81,3 @@ .map(function (snapshots) { return combineSnapshots(snapshots); })

var typesWithTypename = snapshot.typesWithTypename;
var nullableByDefault = options.raw.grats.nullableByDefault;
var config = options.raw.grats;
var checker = program.getTypeChecker();

@@ -97,3 +87,3 @@ var ctx = TypeContext_1.TypeContext.fromSnapshot(checker, snapshot);

var validationResult = (0, Result_1.concatResults)((0, validateMergedInterfaces_1.validateMergedInterfaces)(checker, snapshot.interfaceDeclarations), (0, validateContextReferences_1.validateContextReferences)(ctx, snapshot.contextReferences));
return (new Result_1.ResultPipe(validationResult)
var docResult = new Result_1.ResultPipe(validationResult)
// Add the metadata directive definitions to definitions

@@ -110,15 +100,26 @@ // found in the snapshot.

.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, nullableByDefault); })
// 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.
// Ensure all subscription fields return an AsyncIterable.
.andThen(function (doc) { return (0, validateAsyncIterable_1.validateAsyncIterable)(doc); })
// Validate the document node against the GraphQL spec.
// Build and validate the schema with regards to the GraphQL spec.
.andThen(function (doc) { return buildSchemaFromDoc(doc); })
// Apply default nullability to fields and arguments, and detect any misuse of
// `@killsParentOnException`.
.andThen(function (doc) { return (0, applyDefaultNullability_1.applyDefaultNullability)(doc, config); })
// 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());

@@ -128,3 +129,3 @@ })

}
exports.extractSchema = extractSchema;
exports.extractSchemaAndDoc = extractSchemaAndDoc;
// Given a SDL AST, build and validate a GraphQLSchema.

@@ -131,0 +132,0 @@ function buildSchemaFromDoc(doc) {

@@ -6,2 +6,3 @@ "use strict";

var Result_1 = require("./utils/Result");
var helpers_1 = require("./utils/helpers");
/**

@@ -22,6 +23,6 @@ * Given an entity name of the format `ParentType` or `ParentType.fieldName`,

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, Result_1.ok)(type.astNode.name.loc);
return (0, Result_1.ok)((0, helpers_1.loc)(type.astNode.name));
}

@@ -37,6 +38,6 @@ if (!(type instanceof graphql_1.GraphQLObjectType ||

}
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, Result_1.ok)(field.astNode.name.loc);
return (0, Result_1.ok)((0, helpers_1.loc)(field.astNode.name));
}

@@ -43,0 +44,0 @@ exports.locate = locate;

import { ConstDirectiveNode, DocumentNode, Location } from "graphql";
import { GratsDefinitionNode } from "./GraphQLConstructor";
export declare const FIELD_NAME_DIRECTIVE = "propertyName";
export declare const EXPORTED_DIRECTIVE = "exported";
export declare const ASYNC_ITERABLE_TYPE_DIRECTIVE = "asyncIterable";
/**
* In most cases we can use directives to annotate constructs
* however, it't not possible to annotate an individual TypeNode.
* Additionally, we can't use sets or maps to "tag" nodes because
* there are places where we immutably update the AST to make changes.
*
* Instead, we cheat and add properties to some nodes. These types use
* interface merging to add our own properties to the AST.
*
* We try to use this approach sparingly.
*/
declare module "graphql" {
interface ListTypeNode {
/**
* Grats metadata: Whether the list type was defined as an AsyncIterable.
* Used to ensure that all fields on `Subscription` return an AsyncIterable.
*/
isAsyncIterable?: boolean;
}
}
export declare const FIELD_METADATA_DIRECTIVE = "metadata";
export declare const FIELD_NAME_ARG = "name";
export declare const TS_MODULE_PATH_ARG = "tsModulePath";
export declare const ARG_COUNT = "argCount";
export declare const ASYNC_ITERABLE_ARG = "asyncIterable";
export declare const KILLS_PARENT_ON_EXCEPTION_DIRECTIVE = "killsParentOnException";

@@ -10,17 +32,8 @@ export declare const METADATA_DIRECTIVE_NAMES: Set<string>;

export declare function addMetadataDirectives(definitions: Array<GratsDefinitionNode>): Array<GratsDefinitionNode>;
export type AsyncIterableTypeMetadata = true;
export type PropertyNameMetadata = {
name: string;
export type FieldMetadata = {
tsModulePath: string | null;
name: string | null;
argCount: number | null;
};
export type ExportedMetadata = {
tsModulePath: string;
exportedFunctionName: string;
argCount: number;
};
export declare function makePropertyNameDirective(loc: Location, propertyName: PropertyNameMetadata): ConstDirectiveNode;
export declare function makeExportedDirective(loc: Location, exported: ExportedMetadata): ConstDirectiveNode;
export declare function makeAsyncIterableDirective(loc: Location): ConstDirectiveNode;
export declare function makeKillsParentOnExceptionDirective(loc: Location): ConstDirectiveNode;
export declare function parseAsyncIterableTypeDirective(directive: ConstDirectiveNode): AsyncIterableTypeMetadata;
export declare function parsePropertyNameDirective(directive: ConstDirectiveNode): PropertyNameMetadata;
export declare function parseExportedDirective(directive: ConstDirectiveNode): ExportedMetadata;
export declare function parseFieldMetadataDirective(directive: ConstDirectiveNode): FieldMetadata;

@@ -28,19 +28,15 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseExportedDirective = exports.parsePropertyNameDirective = exports.parseAsyncIterableTypeDirective = exports.makeKillsParentOnExceptionDirective = exports.makeAsyncIterableDirective = exports.makeExportedDirective = exports.makePropertyNameDirective = exports.addMetadataDirectives = exports.DIRECTIVES_AST = exports.METADATA_DIRECTIVE_NAMES = exports.KILLS_PARENT_ON_EXCEPTION_DIRECTIVE = exports.ASYNC_ITERABLE_TYPE_DIRECTIVE = exports.EXPORTED_DIRECTIVE = exports.FIELD_NAME_DIRECTIVE = void 0;
exports.parseFieldMetadataDirective = exports.makeKillsParentOnExceptionDirective = exports.addMetadataDirectives = exports.DIRECTIVES_AST = exports.METADATA_DIRECTIVE_NAMES = exports.KILLS_PARENT_ON_EXCEPTION_DIRECTIVE = exports.ASYNC_ITERABLE_ARG = exports.ARG_COUNT = exports.TS_MODULE_PATH_ARG = exports.FIELD_NAME_ARG = exports.FIELD_METADATA_DIRECTIVE = void 0;
var graphql_1 = require("graphql");
exports.FIELD_NAME_DIRECTIVE = "propertyName";
var FIELD_NAME_ARG = "name";
exports.EXPORTED_DIRECTIVE = "exported";
var TS_MODULE_PATH_ARG = "tsModulePath";
var ARG_COUNT = "argCount";
var EXPORTED_FUNCTION_NAME_ARG = "functionName";
exports.ASYNC_ITERABLE_TYPE_DIRECTIVE = "asyncIterable";
exports.FIELD_METADATA_DIRECTIVE = "metadata";
exports.FIELD_NAME_ARG = "name";
exports.TS_MODULE_PATH_ARG = "tsModulePath";
exports.ARG_COUNT = "argCount";
exports.ASYNC_ITERABLE_ARG = "asyncIterable";
exports.KILLS_PARENT_ON_EXCEPTION_DIRECTIVE = "killsParentOnException";
exports.METADATA_DIRECTIVE_NAMES = new Set([
exports.FIELD_NAME_DIRECTIVE,
exports.EXPORTED_DIRECTIVE,
exports.ASYNC_ITERABLE_TYPE_DIRECTIVE,
exports.FIELD_METADATA_DIRECTIVE,
exports.KILLS_PARENT_ON_EXCEPTION_DIRECTIVE,
]);
exports.DIRECTIVES_AST = (0, graphql_1.parse)("\n directive @".concat(exports.ASYNC_ITERABLE_TYPE_DIRECTIVE, " on FIELD_DEFINITION\n directive @").concat(exports.FIELD_NAME_DIRECTIVE, "(").concat(FIELD_NAME_ARG, ": String!) on FIELD_DEFINITION\n directive @").concat(exports.EXPORTED_DIRECTIVE, "(\n ").concat(TS_MODULE_PATH_ARG, ": String!,\n ").concat(EXPORTED_FUNCTION_NAME_ARG, ": String!\n ").concat(ARG_COUNT, ": Int!\n ) on FIELD_DEFINITION\n directive @").concat(exports.KILLS_PARENT_ON_EXCEPTION_DIRECTIVE, " on FIELD_DEFINITION\n"));
exports.DIRECTIVES_AST = (0, graphql_1.parse)("\n directive @".concat(exports.FIELD_METADATA_DIRECTIVE, "(\n \"\"\"\n Name of property/method/function. Defaults to field name. For\n function-backed fields, this is the function's export name.\n \"\"\"\n ").concat(exports.FIELD_NAME_ARG, ": String\n \"\"\"\n Path of the TypeScript module to import if the field is a function.\n \"\"\"\n ").concat(exports.TS_MODULE_PATH_ARG, ": String\n \"\"\"\n Number of arguments. No value means property access\n \"\"\"\n ").concat(exports.ARG_COUNT, ": Int\n ) on FIELD_DEFINITION\n directive @").concat(exports.KILLS_PARENT_ON_EXCEPTION_DIRECTIVE, " on FIELD_DEFINITION\n"));
function addMetadataDirectives(definitions) {

@@ -50,33 +46,2 @@ return __spreadArray(__spreadArray([], __read(exports.DIRECTIVES_AST.definitions), false), __read(definitions), false);

exports.addMetadataDirectives = addMetadataDirectives;
function makePropertyNameDirective(loc, propertyName) {
return {
kind: graphql_1.Kind.DIRECTIVE,
loc: loc,
name: { kind: graphql_1.Kind.NAME, loc: loc, value: exports.FIELD_NAME_DIRECTIVE },
arguments: [makeStringArg(loc, FIELD_NAME_ARG, propertyName.name)],
};
}
exports.makePropertyNameDirective = makePropertyNameDirective;
function makeExportedDirective(loc, exported) {
return {
kind: graphql_1.Kind.DIRECTIVE,
loc: loc,
name: { kind: graphql_1.Kind.NAME, loc: loc, value: exports.EXPORTED_DIRECTIVE },
arguments: [
makeStringArg(loc, TS_MODULE_PATH_ARG, exported.tsModulePath),
makeStringArg(loc, EXPORTED_FUNCTION_NAME_ARG, exported.exportedFunctionName),
makeIntArg(loc, ARG_COUNT, exported.argCount),
],
};
}
exports.makeExportedDirective = makeExportedDirective;
function makeAsyncIterableDirective(loc) {
return {
kind: graphql_1.Kind.DIRECTIVE,
loc: loc,
name: { kind: graphql_1.Kind.NAME, loc: loc, value: exports.ASYNC_ITERABLE_TYPE_DIRECTIVE },
arguments: [],
};
}
exports.makeAsyncIterableDirective = makeAsyncIterableDirective;
function makeKillsParentOnExceptionDirective(loc) {

@@ -91,27 +56,13 @@ return {

exports.makeKillsParentOnExceptionDirective = makeKillsParentOnExceptionDirective;
function parseAsyncIterableTypeDirective(directive) {
if (directive.name.value !== exports.ASYNC_ITERABLE_TYPE_DIRECTIVE) {
throw new Error("Expected directive to be ".concat(exports.ASYNC_ITERABLE_TYPE_DIRECTIVE));
function parseFieldMetadataDirective(directive) {
if (directive.name.value !== exports.FIELD_METADATA_DIRECTIVE) {
throw new Error("Expected directive to be ".concat(exports.FIELD_METADATA_DIRECTIVE));
}
return true;
}
exports.parseAsyncIterableTypeDirective = parseAsyncIterableTypeDirective;
function parsePropertyNameDirective(directive) {
if (directive.name.value !== exports.FIELD_NAME_DIRECTIVE) {
throw new Error("Expected directive to be ".concat(exports.FIELD_NAME_DIRECTIVE));
}
return { name: getStringArg(directive, FIELD_NAME_ARG) };
}
exports.parsePropertyNameDirective = parsePropertyNameDirective;
function parseExportedDirective(directive) {
if (directive.name.value !== exports.EXPORTED_DIRECTIVE) {
throw new Error("Expected directive to be ".concat(exports.EXPORTED_DIRECTIVE));
}
return {
tsModulePath: getStringArg(directive, TS_MODULE_PATH_ARG),
exportedFunctionName: getStringArg(directive, EXPORTED_FUNCTION_NAME_ARG),
argCount: getIntArg(directive, ARG_COUNT),
name: getStringArg(directive, exports.FIELD_NAME_ARG),
tsModulePath: getStringArg(directive, exports.TS_MODULE_PATH_ARG),
argCount: getIntArg(directive, exports.ARG_COUNT),
};
}
exports.parseExportedDirective = parseExportedDirective;
exports.parseFieldMetadataDirective = parseFieldMetadataDirective;
function getStringArg(directive, argName) {

@@ -121,3 +72,3 @@ var _a;

if (!arg) {
throw new Error("Expected to find argument ".concat(argName));
return null;
}

@@ -133,3 +84,3 @@ if (arg.value.kind !== graphql_1.Kind.STRING) {

if (!arg) {
throw new Error("Expected to find argument ".concat(argName));
return null;
}

@@ -141,17 +92,1 @@ if (arg.value.kind !== graphql_1.Kind.INT) {

}
function makeStringArg(loc, argName, value) {
return {
kind: graphql_1.Kind.ARGUMENT,
loc: loc,
name: { kind: graphql_1.Kind.NAME, loc: loc, value: argName },
value: { kind: graphql_1.Kind.STRING, loc: loc, value: value },
};
}
function makeIntArg(loc, argName, value) {
return {
kind: graphql_1.Kind.ARGUMENT,
loc: loc,
name: { kind: graphql_1.Kind.NAME, loc: loc, value: argName },
value: { kind: graphql_1.Kind.INT, loc: loc, value: value.toString() },
};
}

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

import { GraphQLSchema } from "graphql";
import { ConfigOptions } from "./lib";
import { DocumentNode, GraphQLSchema } from "graphql";
import { ConfigOptions } from "./gratsConfig";
/**

@@ -8,2 +8,3 @@ * Prints code for a TypeScript module that exports a GraphQLSchema.

export declare function printExecutableSchema(schema: GraphQLSchema, config: ConfigOptions, destination: string): string;
export declare function applyTypeScriptHeader(config: ConfigOptions, code: string): string;
/**

@@ -13,3 +14,4 @@ * Prints SDL, potentially omitting directives depending upon the config.

*/
export declare function printGratsSDL(schema: GraphQLSchema, config: ConfigOptions): string;
export declare function printSDLWithoutDirectives(schema: GraphQLSchema): string;
export declare function printGratsSDL(doc: DocumentNode, config: ConfigOptions): string;
export declare function applySDLHeader(config: ConfigOptions, sdl: string): string;
export declare function printSDLWithoutMetadata(doc: DocumentNode): string;
"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);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.printSDLWithoutDirectives = exports.printGratsSDL = exports.printExecutableSchema = void 0;
exports.printSDLWithoutMetadata = exports.applySDLHeader = exports.printGratsSDL = exports.applyTypeScriptHeader = exports.printExecutableSchema = void 0;
var graphql_1 = require("graphql");

@@ -24,8 +13,9 @@ var codegen_1 = require("./codegen");

var code = (0, codegen_1.codegen)(schema, destination);
if (config.tsSchemaHeader) {
return "".concat(config.tsSchemaHeader, "\n").concat(code);
}
return code;
return applyTypeScriptHeader(config, code);
}
exports.printExecutableSchema = printExecutableSchema;
function applyTypeScriptHeader(config, code) {
return formatHeader(config.tsSchemaHeader, code);
}
exports.applyTypeScriptHeader = applyTypeScriptHeader;
/**

@@ -35,15 +25,33 @@ * Prints SDL, potentially omitting directives depending upon the config.

*/
function printGratsSDL(schema, config) {
var sdl = printSDLWithoutDirectives(schema);
if (config.schemaHeader) {
return "".concat(config.schemaHeader, "\n").concat(sdl);
}
return sdl;
function printGratsSDL(doc, config) {
var sdl = printSDLWithoutMetadata(doc);
return applySDLHeader(config, sdl) + "\n";
}
exports.printGratsSDL = printGratsSDL;
function printSDLWithoutDirectives(schema) {
return (0, graphql_1.printSchema)(new graphql_1.GraphQLSchema(__assign(__assign({}, schema.toConfig()), { directives: schema.getDirectives().filter(function (directive) {
return !metadataDirectives_1.METADATA_DIRECTIVE_NAMES.has(directive.name);
}) })));
function applySDLHeader(config, sdl) {
return formatHeader(config.schemaHeader, sdl);
}
exports.printSDLWithoutDirectives = printSDLWithoutDirectives;
exports.applySDLHeader = applySDLHeader;
function printSDLWithoutMetadata(doc) {
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) {
return graphql_1.specifiedScalarTypes.some(function (scalar) { return scalar.name === t.name.value; })
? null
: t;
},
});
return (0, graphql_1.print)(trimmed);
}
exports.printSDLWithoutMetadata = printSDLWithoutMetadata;
function formatHeader(header, code) {
if (header !== null) {
return "".concat(header, "\n").concat(code);
}
return code;
}

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

var helpers_1 = require("../utils/helpers");
var Extractor_1 = require("../Extractor");
var metadataDirectives_1 = require("../metadataDirectives");
var Extractor_1 = require("../Extractor");
/**

@@ -105,3 +105,3 @@ * Grats allows you to define GraphQL fields on TypeScript interfaces using

var directives = (_b = doc.field.directives) === null || _b === void 0 ? void 0 : _b.filter(function (directive) {
return directive.name.value !== metadataDirectives_1.EXPORTED_DIRECTIVE;
return directive.name.value !== metadataDirectives_1.FIELD_METADATA_DIRECTIVE;
});

@@ -108,0 +108,0 @@ newDocs.push({

import { DocumentNode } from "graphql";
import { DiagnosticsResult } from "../utils/DiagnosticError";
export declare function applyDefaultNullability(doc: DocumentNode, nullableByDefault: boolean): DiagnosticsResult<DocumentNode>;
import { ConfigOptions } from "../gratsConfig";
/**
* Grats has options to make all fields nullable by default to conform to
* GraphQL best practices. This transform applies this option to the schema.
*/
export declare function applyDefaultNullability(doc: DocumentNode, { nullableByDefault, strictSemanticNullability }: ConfigOptions): DiagnosticsResult<DocumentNode>;

@@ -13,2 +13,27 @@ "use strict";

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

@@ -21,36 +46,52 @@ exports.applyDefaultNullability = void 0;

var metadataDirectives_1 = require("../metadataDirectives");
var publicDirectives_1 = require("../publicDirectives");
var GraphQLConstructor_1 = require("../GraphQLConstructor");
function applyDefaultNullability(doc, nullableByDefault) {
var _a;
var helpers_1 = require("../utils/helpers");
/**
* Grats has options to make all fields nullable by default to conform to
* GraphQL best practices. This transform applies this option to the schema.
*/
function applyDefaultNullability(doc, _a) {
var _b;
var nullableByDefault = _a.nullableByDefault, strictSemanticNullability = _a.strictSemanticNullability;
var gql = new GraphQLConstructor_1.GraphQLConstructor();
var errors = [];
var newDoc = (0, graphql_1.visit)(doc, (_a = {},
_a[graphql_1.Kind.FIELD_DEFINITION] = function (t) {
var _a;
var newDoc = (0, graphql_1.visit)(doc, (_b = {},
_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; });
if (killsParent) {
if (killsParent.loc == null) {
throw new Error("Expected killsParent to have a location");
}
// You can only use @killsParentOnException if nullableByDefault is on.
if (!nullableByDefault) {
errors.push((0, DiagnosticError_1.gqlErr)(killsParent.loc, E.killsParentOnExceptionWithWrongConfig()));
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(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)(killsParent.loc, E.killsParentOnExceptionOnNullable()));
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(killsParent), E.killsParentOnExceptionOnNullable()));
}
return t;
// Set the location of the NON_NULL_TYPE wrapper to the location of the
// `@killsParentOnException` directive so that type errors created by graphql-js
// are reported at the correct location.
return __assign(__assign({}, t), { type: __assign(__assign({}, t.type), { loc: killsParent.loc }) });
}
if (nullableByDefault) {
return __assign(__assign({}, t), { type: gql.nullableType(t.type) });
if (nullableByDefault && t.type.kind === graphql_1.Kind.NON_NULL_TYPE) {
var type = gql.nullableType(t.type);
var directives = (_b = t.directives) !== null && _b !== void 0 ? _b : [];
if (strictSemanticNullability) {
var semanticNullability = (0, publicDirectives_1.makeSemanticNonNullDirective)((0, helpers_1.loc)(t.type));
directives = __spreadArray(__spreadArray([], __read(directives), false), [semanticNullability], false);
}
return __assign(__assign({}, t), { directives: directives, type: type });
}
return t;
},
_a));
_b));
if (errors.length > 0) {
return (0, Result_1.err)(errors);
}
if (strictSemanticNullability) {
return (0, Result_1.ok)(__assign(__assign({}, newDoc), { definitions: (0, publicDirectives_1.addSemanticNonNullDirective)(newDoc.definitions) }));
}
return (0, Result_1.ok)(newDoc);
}
exports.applyDefaultNullability = applyDefaultNullability;

@@ -9,2 +9,3 @@ "use strict";

var helpers_1 = require("../utils/helpers");
var TAG_REGEX = /@(gql)|(killsParentOnException)/i;
// Given a ts.Program, extract a set of ExtractionSnapshots from it.

@@ -17,3 +18,3 @@ // In the future this part might be able to be incremental, were we only run extraction

// If the file doesn't contain any GraphQL definitions, skip it.
if (!/@gql/i.test(sourceFile.text)) {
if (!TAG_REGEX.test(sourceFile.text)) {
return false;

@@ -20,0 +21,0 @@ }

@@ -46,2 +46,3 @@ "use strict";

var E = require("./Errors");
var helpers_1 = require("./utils/helpers");
exports.UNRESOLVED_REFERENCE_NAME = "__UNRESOLVED_REFERENCE__";

@@ -151,6 +152,3 @@ /**

if (nameDefinition == null) {
if (unresolved.loc == null) {
throw new Error("Expected namedType to have a location.");
}
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)(unresolved.loc, E.unresolvedTypeReference()));
return (0, Result_1.err)((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(unresolved), E.unresolvedTypeReference()));
}

@@ -157,0 +155,0 @@ return (0, Result_1.ok)(__assign(__assign({}, unresolved), { value: nameDefinition.name.value }));

@@ -19,4 +19,5 @@ import { GraphQLError, Location, Source } from "graphql";

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;

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

Object.defineProperty(exports, "__esModule", { value: true });
exports.graphqlSourceToSourceFile = exports.tsRelated = exports.tsErr = exports.gqlRelated = exports.gqlErr = exports.graphQlErrorToDiagnostic = exports.FAKE_ERROR_CODE = exports.ReportableDiagnostics = void 0;
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");

@@ -149,2 +149,17 @@ var ReportableDiagnostics = /** @class */ (function () {

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

@@ -151,0 +166,0 @@ var start = node.getStart();

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

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

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

@@ -49,1 +49,15 @@ function DefaultMap(getDefault) {

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;
import { DocumentNode } from "graphql";
import { DiagnosticsResult } from "../utils/DiagnosticError";
/**
* Ensure that all fields on `Subscription` return an AsyncIterable, and that no other
* fields do.
* Ensure that all fields on `Subscription` return an AsyncIterable and transform
* the return type of subscription fields to not treat AsyncIterable as as list type.
*/
export declare function validateAsyncIterable(doc: DocumentNode): DiagnosticsResult<DocumentNode>;
"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 };
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;
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
return __assign.apply(this, arguments);
};

@@ -19,6 +19,6 @@ Object.defineProperty(exports, "__esModule", { value: true });

var E = require("../Errors");
var metadataDirectives_1 = require("../metadataDirectives");
var helpers_1 = require("../utils/helpers");
/**
* Ensure that all fields on `Subscription` return an AsyncIterable, and that no other
* fields do.
* Ensure that all fields on `Subscription` return an AsyncIterable and transform
* the return type of subscription fields to not treat AsyncIterable as as list type.
*/

@@ -28,9 +28,28 @@ function validateAsyncIterable(doc) {

var errors = [];
var visitNode = function (t) {
var validateFieldsResult = validateField(t);
if (validateFieldsResult != null) {
errors.push(validateFieldsResult);
var visitNode = {
enter: function (t) {
// Note: We assume the default name is used here. When custom operation types are supported
// we'll need to update this.
if (t.name.value !== "Subscription") {
// Don't visit nodes that aren't the Subscription type.
return false;
}
},
};
var visitSubscriptionField = function (field) {
var inner = innerType(field.type); // Remove any non-null wrapper types
if (inner.kind !== graphql_1.Kind.LIST_TYPE || !inner.isAsyncIterable) {
errors.push((0, DiagnosticError_1.gqlErr)((0, helpers_1.loc)(field.type), E.subscriptionFieldNotAsyncIterable()));
return field;
}
var itemType = inner.type;
// If either field.type or item type is nullable, the field should be nullable
if (isNullable(field.type) || isNullable(itemType)) {
var innerInner = innerType(itemType);
return __assign(__assign({}, field), { type: innerInner });
}
// If _both_ are non-nullable, we will preserve the non-nullability.
return __assign(__assign({}, field), { type: itemType });
};
(0, graphql_1.visit)(doc, (_a = {},
var newDoc = (0, graphql_1.visit)(doc, (_a = {},
_a[graphql_1.Kind.INTERFACE_TYPE_DEFINITION] = visitNode,

@@ -40,2 +59,3 @@ _a[graphql_1.Kind.INTERFACE_TYPE_EXTENSION] = visitNode,

_a[graphql_1.Kind.OBJECT_TYPE_EXTENSION] = visitNode,
_a[graphql_1.Kind.FIELD_DEFINITION] = visitSubscriptionField,
_a));

@@ -45,41 +65,13 @@ if (errors.length > 0) {

}
return (0, Result_1.ok)(doc);
return (0, Result_1.ok)(newDoc);
}
exports.validateAsyncIterable = validateAsyncIterable;
function validateField(t) {
var e_1, _a;
var _b;
if (t.fields == null)
return;
// Note: We assume the default name is used here. When custom operation types are supported
// we'll need to update this.
var isSubscription = t.name.value === "Subscription" &&
(t.kind === graphql_1.Kind.OBJECT_TYPE_DEFINITION ||
t.kind === graphql_1.Kind.OBJECT_TYPE_EXTENSION);
try {
for (var _c = __values(t.fields), _d = _c.next(); !_d.done; _d = _c.next()) {
var field = _d.value;
var asyncDirective = (_b = field.directives) === null || _b === void 0 ? void 0 : _b.find(function (directive) { return directive.name.value === metadataDirectives_1.ASYNC_ITERABLE_TYPE_DIRECTIVE; });
if (isSubscription && asyncDirective == null) {
if (field.type.loc == null) {
throw new Error("Expected field type to have a location.");
}
return (0, DiagnosticError_1.gqlErr)(field.type.loc, E.subscriptionFieldNotAsyncIterable());
}
if (!isSubscription && asyncDirective != null) {
if (asyncDirective.loc == null) {
throw new Error("Expected asyncDirective to have a location.");
}
return (0, DiagnosticError_1.gqlErr)(asyncDirective.loc, // Directive location is the AsyncIterable type.
E.nonSubscriptionFieldAsyncIterable());
}
}
function innerType(type) {
if (type.kind === graphql_1.Kind.NON_NULL_TYPE) {
return innerType(type.type);
}
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; }
}
return type;
}
function isNullable(t) {
return t.kind !== graphql_1.Kind.NON_NULL_TYPE;
}
{
"name": "grats",
"version": "0.0.0-main-03b23474",
"version": "0.0.0-main-055d3f1c",
"main": "dist/src/index.js",

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

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

@@ -40,6 +41,26 @@ "dependencies": {

},
"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",
"build": "rm -rf dist/ && tsc --build",
"format": "prettier . --write",

@@ -46,0 +67,0 @@ "lint": "eslint . && prettier . --check"

@@ -60,1 +60,5 @@ # Grats: Implementation-First GraphQL for TypeScript

- [typegraphql-reflection-poc](https://github.com/MichalLytek/typegraphql-reflection-poc)
## License
Grats is [MIT licensed](./LICENSE).
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