Comparing version 0.6.2 to 0.7.0-alpha.1
@@ -437,10 +437,4 @@ "use strict"; | ||
if (fieldOptions.resolve) { | ||
if (typeof fieldOptions.property !== "undefined") { | ||
console.warn("Both resolve and property should not be supplied, property will be ignored"); | ||
} | ||
resolver = fieldOptions.resolve; | ||
} | ||
else if (fieldOptions.property) { | ||
resolver = utils_1.propertyFieldResolver(fieldOptions.property); | ||
} | ||
if (typeof fieldOptions.default !== "undefined") { | ||
@@ -447,0 +441,0 @@ resolver = withDefaultValue(resolver, fieldOptions.default); |
@@ -31,23 +31,23 @@ import * as Types from "./types"; | ||
*/ | ||
id<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
id<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add an Int field type to the object schema. | ||
*/ | ||
int<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
int<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add a Float field type to the object schema. | ||
*/ | ||
float<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
float<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add a String field type to the object schema. | ||
*/ | ||
string<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
string<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add a Boolean field type to the object schema. | ||
*/ | ||
boolean<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
boolean<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Adds a new field to the object type | ||
*/ | ||
field<FieldName extends string>(name: FieldName, type: Types.AllOutputTypes<GenTypes> | Types.BaseScalars, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
field<FieldName extends string>(name: FieldName, type: Types.AllOutputTypes<GenTypes> | Types.BaseScalars, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
@@ -69,4 +69,4 @@ * Declare that an object type implements a particular interface, | ||
/** | ||
* Used to modify a field already defined on an interface or | ||
* abstract type. | ||
* Used to modify a field already defined on an interface or mixed-in | ||
* from another type. | ||
* | ||
@@ -185,23 +185,23 @@ * At this point the type will not change, but the resolver, | ||
*/ | ||
id<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
id<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add an Int field type to the object schema. | ||
*/ | ||
int<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
int<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add a Float field type to the object schema. | ||
*/ | ||
float<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
float<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add a String field type to the object schema. | ||
*/ | ||
string<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
string<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Add a Boolean field type to the object schema. | ||
*/ | ||
boolean<FieldName extends string>(name: FieldName, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
boolean<FieldName extends string>(name: FieldName, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
* Adds a new field to the object type | ||
*/ | ||
field<FieldName extends string>(name: FieldName, type: Types.AllOutputTypes<GenTypes> | Types.BaseScalars, options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
field<FieldName extends string>(name: FieldName, type: Types.AllOutputTypes<GenTypes> | Types.BaseScalars, ...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName>): void; | ||
/** | ||
@@ -208,0 +208,0 @@ * Adds a description to the `GraphQLInterfaceType` |
110
dist/core.js
@@ -45,4 +45,8 @@ "use strict"; | ||
*/ | ||
ObjectTypeDef.prototype.id = function (name, options) { | ||
this.field(name, "ID", options); | ||
ObjectTypeDef.prototype.id = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "ID"].concat(opts)); | ||
}; | ||
@@ -52,4 +56,8 @@ /** | ||
*/ | ||
ObjectTypeDef.prototype.int = function (name, options) { | ||
this.field(name, "Int", options); | ||
ObjectTypeDef.prototype.int = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "Int"].concat(opts)); | ||
}; | ||
@@ -59,4 +67,8 @@ /** | ||
*/ | ||
ObjectTypeDef.prototype.float = function (name, options) { | ||
this.field(name, "Float", options); | ||
ObjectTypeDef.prototype.float = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "Float"].concat(opts)); | ||
}; | ||
@@ -66,4 +78,8 @@ /** | ||
*/ | ||
ObjectTypeDef.prototype.string = function (name, options) { | ||
this.field(name, "String", options); | ||
ObjectTypeDef.prototype.string = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "String"].concat(opts)); | ||
}; | ||
@@ -73,4 +89,8 @@ /** | ||
*/ | ||
ObjectTypeDef.prototype.boolean = function (name, options) { | ||
this.field(name, "Boolean", options); | ||
ObjectTypeDef.prototype.boolean = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "Boolean"].concat(opts)); | ||
}; | ||
@@ -80,3 +100,14 @@ /** | ||
*/ | ||
ObjectTypeDef.prototype.field = function (name, type, options) { | ||
ObjectTypeDef.prototype.field = function (name, type) { | ||
var opts = []; | ||
for (var _i = 2; _i < arguments.length; _i++) { | ||
opts[_i - 2] = arguments[_i]; | ||
} | ||
var options = {}; | ||
if (typeof opts[0] === "function") { | ||
options.resolve = opts[0]; | ||
} | ||
else { | ||
options = tslib_1.__assign({}, opts[0]); | ||
} | ||
this.typeConfig.fields.push({ | ||
@@ -115,4 +146,4 @@ item: Types.NodeType.FIELD, | ||
/** | ||
* Used to modify a field already defined on an interface or | ||
* abstract type. | ||
* Used to modify a field already defined on an interface or mixed-in | ||
* from another type. | ||
* | ||
@@ -332,4 +363,8 @@ * At this point the type will not change, but the resolver, | ||
*/ | ||
InterfaceTypeDef.prototype.id = function (name, options) { | ||
this.field(name, "ID", options); | ||
InterfaceTypeDef.prototype.id = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "ID"].concat(opts)); | ||
}; | ||
@@ -339,4 +374,8 @@ /** | ||
*/ | ||
InterfaceTypeDef.prototype.int = function (name, options) { | ||
this.field(name, "Int", options); | ||
InterfaceTypeDef.prototype.int = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "Int"].concat(opts)); | ||
}; | ||
@@ -346,4 +385,8 @@ /** | ||
*/ | ||
InterfaceTypeDef.prototype.float = function (name, options) { | ||
this.field(name, "Float", options); | ||
InterfaceTypeDef.prototype.float = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "Float"].concat(opts)); | ||
}; | ||
@@ -353,4 +396,8 @@ /** | ||
*/ | ||
InterfaceTypeDef.prototype.string = function (name, options) { | ||
this.field(name, "String", options); | ||
InterfaceTypeDef.prototype.string = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "String"].concat(opts)); | ||
}; | ||
@@ -360,4 +407,8 @@ /** | ||
*/ | ||
InterfaceTypeDef.prototype.boolean = function (name, options) { | ||
this.field(name, "Boolean", options); | ||
InterfaceTypeDef.prototype.boolean = function (name) { | ||
var opts = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
opts[_i - 1] = arguments[_i]; | ||
} | ||
this.field.apply(this, [name, "Boolean"].concat(opts)); | ||
}; | ||
@@ -367,3 +418,14 @@ /** | ||
*/ | ||
InterfaceTypeDef.prototype.field = function (name, type, options) { | ||
InterfaceTypeDef.prototype.field = function (name, type) { | ||
var opts = []; | ||
for (var _i = 2; _i < arguments.length; _i++) { | ||
opts[_i - 2] = arguments[_i]; | ||
} | ||
var options = {}; | ||
if (typeof opts[0] === "function") { | ||
options.resolve = opts[0]; | ||
} | ||
else { | ||
options = tslib_1.__assign({}, opts[0]); | ||
} | ||
this.typeConfig.fields.push({ | ||
@@ -370,0 +432,0 @@ item: Types.NodeType.FIELD, |
@@ -7,2 +7,26 @@ import { DirectiveTypeDef, EnumTypeDef, InputObjectTypeDef, InterfaceTypeDef, ObjectTypeDef, UnionTypeDef, WrappedType } from "./core"; | ||
* | ||
* ``` | ||
* const User = objectType('User', (t) => { | ||
* t.int('id', { description: 'Id of the user' }) | ||
* t.string('fullName', { description: 'Full name of the user' }) | ||
* t.field('status', 'StatusEnum'); | ||
* t.field('posts', 'Post', { | ||
* list: true, | ||
* resolve(root, args, ctx) { | ||
* return ctx.getUser(root.id).posts() | ||
* } | ||
* }) | ||
* }); | ||
* | ||
* const Post = objectType('Post', (t) => { | ||
* t.int('id') | ||
* t.string('title') | ||
* }) | ||
* | ||
* const StatusEnum = enumType('StatusEnum', { | ||
* ACTIVE: 1, | ||
* DISABLED: 2 | ||
* }); | ||
* ``` | ||
* | ||
* @see https://graphql.github.io/learn/schema/#object-types-and-fields | ||
@@ -9,0 +33,0 @@ */ |
@@ -11,2 +11,26 @@ "use strict"; | ||
* | ||
* ``` | ||
* const User = objectType('User', (t) => { | ||
* t.int('id', { description: 'Id of the user' }) | ||
* t.string('fullName', { description: 'Full name of the user' }) | ||
* t.field('status', 'StatusEnum'); | ||
* t.field('posts', 'Post', { | ||
* list: true, | ||
* resolve(root, args, ctx) { | ||
* return ctx.getUser(root.id).posts() | ||
* } | ||
* }) | ||
* }); | ||
* | ||
* const Post = objectType('Post', (t) => { | ||
* t.int('id') | ||
* t.string('title') | ||
* }) | ||
* | ||
* const StatusEnum = enumType('StatusEnum', { | ||
* ACTIVE: 1, | ||
* DISABLED: 2 | ||
* }); | ||
* ``` | ||
* | ||
* @see https://graphql.github.io/learn/schema/#object-types-and-fields | ||
@@ -13,0 +37,0 @@ */ |
@@ -44,7 +44,5 @@ import { DirectiveLocationEnum, GraphQLNamedType, GraphQLSchema, GraphQLObjectType } from "graphql"; | ||
hasDefaultResolver(typeName: string): boolean; | ||
hasPropertyResolver(type: GraphQLObjectType, fieldName: string): boolean; | ||
hasDefaultValue(type: GraphQLObjectType, fieldName: string): boolean; | ||
isFieldModified(typeName: string, fieldName: string): boolean; | ||
isInterfaceField(type: GraphQLObjectType, fieldName: string): boolean; | ||
getPropertyResolver(type: GraphQLObjectType, fieldName: string): string | undefined; | ||
addScalar(config: Types.ScalarOpts): void; | ||
@@ -51,0 +49,0 @@ addInterfaceType(config: Types.InterfaceTypeConfig): void; |
@@ -82,10 +82,2 @@ "use strict"; | ||
}; | ||
Metadata.prototype.hasPropertyResolver = function (type, fieldName) { | ||
if (this.isInterfaceField(type, fieldName)) { | ||
// | ||
} | ||
return Boolean(this.objectFieldMeta[type.name] && | ||
this.objectFieldMeta[type.name][fieldName] && | ||
this.objectFieldMeta[type.name][fieldName].property); | ||
}; | ||
Metadata.prototype.hasDefaultValue = function (type, fieldName) { | ||
@@ -103,7 +95,2 @@ return Boolean(this.objectFieldMeta[type.name] && | ||
}; | ||
// Type Genreation Helpers: | ||
Metadata.prototype.getPropertyResolver = function (type, fieldName) { | ||
return (this.objectFieldMeta[type.name] && | ||
this.objectFieldMeta[type.name][fieldName].property); | ||
}; | ||
// Schema construction helpers: | ||
@@ -110,0 +97,0 @@ Metadata.prototype.addScalar = function (config) { |
@@ -77,3 +77,8 @@ "use strict"; | ||
}; | ||
typeRootTypeName = function (typeName) { return suffixed(typeName, "RootType"); }; | ||
typeRootTypeName = function (typeName) { | ||
if (isEntryType(typeName)) { | ||
return "{}"; | ||
} | ||
return suffixed(typeName, "RootType"); | ||
}; | ||
fieldResolverName = function (typeName, fieldName) { | ||
@@ -177,8 +182,8 @@ return suffixed(typeName, fieldName, "Resolver"); | ||
: "?:"; | ||
if (metadata.hasPropertyResolver(type, field.name)) { | ||
return "" + metadata.getPropertyResolver(type, field.name) + colon; | ||
} | ||
return "" + field.name + colon; | ||
}; | ||
makeRootType = function (type) { | ||
if (isEntryType(type.name)) { | ||
return; | ||
} | ||
if (backingTypeMap[type.name]) { | ||
@@ -361,2 +366,7 @@ allTypeStrings.push("export type " + typeRootTypeName(type.name) + " = " + backingTypeMap[type.name] + ";"); | ||
exports.buildTypeDefinitions = buildTypeDefinitions; | ||
function isEntryType(typeName) { | ||
return (typeName === "Query" || | ||
typeName === "Mutation" || | ||
typeName === "Subscription"); | ||
} | ||
var stringify = function (v) { return JSON.stringify(v); }; | ||
@@ -363,0 +373,0 @@ function stringifyTypeFieldMapping(tsInterfaceName, obj) { |
@@ -89,4 +89,3 @@ import { GraphQLFieldResolver, GraphQLScalarTypeConfig, GraphQLNamedType, GraphQLIsTypeOfFn, GraphQLResolveInfo, DirectiveLocationEnum, GraphQLDirective, GraphQLSchema } from "graphql"; | ||
/** | ||
* The description of the field, as defined in the GraphQL | ||
* object definition | ||
* The description of the field, as defined in the GraphQL object definition | ||
*/ | ||
@@ -149,3 +148,6 @@ description?: string; | ||
export declare type OutputFieldArgs = Record<string, ArgDefinition>; | ||
export interface OutputFieldOpts<GenTypes = any, TypeName = any, FieldName = any> extends FieldOpts { | ||
/** | ||
* All non-resolver output field options | ||
*/ | ||
export interface CommonOutputOpts extends FieldOpts { | ||
/** | ||
@@ -155,10 +157,26 @@ * Any arguments defined | ||
args?: OutputFieldArgs; | ||
} | ||
export interface OutputFieldOpts<GenTypes = any, TypeName = any, FieldName = any> extends CommonOutputOpts { | ||
/** | ||
* Property to use to resolve the field. If resolve is specified, this field is ignored. | ||
* Resolver for the output field | ||
*/ | ||
property?: Extract<keyof RootValue<GenTypes, TypeName>, string>; | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
/** | ||
* Default value for the field, if none is returned. | ||
*/ | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
export declare type OutputFieldResolver<GenTypes, TypeName, FieldName> = (root: RootValue<GenTypes, TypeName>, args: ArgsValue<GenTypes, TypeName, FieldName>, context: ContextValue<GenTypes>, info: GraphQLResolveInfo) => MaybePromise<ResultValue<GenTypes, TypeName, FieldName>>; | ||
/** | ||
* All properties that can be changed about a field | ||
*/ | ||
export declare type ModifyFieldOpts<GenTypes, TypeName, FieldName> = { | ||
/** | ||
* The description of the field, as defined in the GraphQL object definition. | ||
*/ | ||
description?: string; | ||
/** | ||
* Resolver for the output field | ||
*/ | ||
resolve?: (root: RootValue<GenTypes, TypeName>, args: ArgsValue<GenTypes, TypeName, FieldName>, context: ContextValue<GenTypes>, info: GraphQLResolveInfo) => MaybePromise<ResultValue<GenTypes, TypeName, FieldName>>; | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
/** | ||
@@ -168,6 +186,3 @@ * Default value for the field, if none is returned. | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
export interface AbstractFieldOpts<GenTypes, FieldName> extends FieldOpts { | ||
} | ||
export declare type ModifyFieldOpts<GenTypes, TypeName, FieldName> = Omit<OutputFieldOpts<GenTypes, TypeName, FieldName>, "args" | "list" | "listItemNullable" | "nullable">; | ||
}; | ||
export interface InputFieldOpts<GenTypes = any, TypeName = any> extends FieldOpts { | ||
@@ -183,3 +198,3 @@ /** | ||
/** | ||
* Set a value for the input | ||
* Set a default value for the input type | ||
*/ | ||
@@ -501,6 +516,6 @@ default?: InputValue<GenTypes, TypeName>; | ||
} | ||
export declare type TypeResolver<GenTypes, TypeName> = (root: RootValue<GenTypes, TypeName>, context: ContextValue<GenTypes>, info: GraphQLResolveInfo) => MaybePromise<Maybe<InterfaceMembers<GenTypes, TypeName>>>; | ||
/** | ||
* Generated type helpers: | ||
*/ | ||
export declare type TypeResolver<GenTypes, TypeName> = (root: RootValue<GenTypes, TypeName>, context: ContextValue<GenTypes>, info: GraphQLResolveInfo) => MaybePromise<Maybe<InterfaceMembers<GenTypes, TypeName>>>; | ||
declare type GenTypesShapeKeys = "context" | "argTypes" | "backingTypes" | "returnTypes" | "enums" | "objects" | "interfaces" | "unions" | "scalars" | "inputObjects" | "allInputTypes" | "allOutputTypes"; | ||
@@ -524,2 +539,3 @@ /** | ||
export declare type RootValue<GenTypes, TypeName> = GenTypes extends GenTypesShape ? TypeName extends keyof GenTypes["backingTypes"] ? GenTypes["backingTypes"][TypeName] : any : never; | ||
export declare type RootValueField<GenTypes, TypeName, FieldName> = FieldName extends keyof RootValue<GenTypes, TypeName> ? RootValue<GenTypes, TypeName>[FieldName] : never; | ||
export declare type ArgsValue<GenTypes, TypeName, FieldName> = GenTypes extends GenTypesShape ? TypeName extends keyof GenTypes["argTypes"] ? FieldName extends keyof GenTypes["argTypes"][TypeName] ? GenTypes["argTypes"][TypeName][FieldName] : any : {} : never; | ||
@@ -533,3 +549,27 @@ export declare type ResultValue<GenTypes, TypeName, FieldName> = GenTypes extends GenTypesShape ? TypeName extends keyof GenTypes["returnTypes"] ? FieldName extends keyof GenTypes["returnTypes"][TypeName] ? GenTypes["returnTypes"][TypeName][FieldName] : any : any : never; | ||
}; | ||
export declare type RootTypeMap = Record<string, string | ImportedType | undefined>; | ||
export declare type ConditionalOutputFieldOpts<GenTypes = any, TypeName = any, FieldName = any> = FieldName extends keyof RootValue<GenTypes, TypeName> ? RootValueField<GenTypes, TypeName, FieldName> extends ResultValue<GenTypes, TypeName, FieldName> ? OptionalOutputOpts<GenTypes, TypeName, FieldName> : Extract<RootValueField<GenTypes, TypeName, FieldName>, null> extends null ? OptionalOutputOpts<GenTypes, TypeName, FieldName> : RequiredOutputOpts<GenTypes, TypeName, FieldName> : RequiredOutputOpts<GenTypes, TypeName, FieldName>; | ||
export declare type OptionalOutputOpts<GenTypes, TypeName, FieldName> = [] | [OptionalResolverOutputFieldOpts<GenTypes, TypeName, FieldName>] | [OutputFieldResolver<GenTypes, TypeName, FieldName>]; | ||
export declare type RequiredOutputOpts<GenTypes, TypeName, FieldName> = [NeedsResolverOutputFieldOpts<GenTypes, TypeName, FieldName>] | [OutputFieldResolver<GenTypes, TypeName, FieldName>]; | ||
export interface OutputWithDefaultOpts<GenTypes, TypeName, FieldName> extends CommonOutputOpts { | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
default: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
export interface OutputWithResolveOpts<GenTypes, TypeName, FieldName> extends CommonOutputOpts { | ||
resolve: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
/** | ||
* The "Needs Resolver" output field opts means that the resolver cannot | ||
* be fulfilled by the "backing value" alone, and therefore needs either | ||
* a valid resolver or a "root value". | ||
*/ | ||
export declare type NeedsResolverOutputFieldOpts<GenTypes, TypeName, FieldName> = OutputWithDefaultOpts<GenTypes, TypeName, FieldName> | OutputWithResolveOpts<GenTypes, TypeName, FieldName>; | ||
/** | ||
* If we already have the correct value for the field from the root type, | ||
* then we can provide a resolver or a default value, but we don't have to. | ||
*/ | ||
export interface OptionalResolverOutputFieldOpts<GenTypes, TypeName, FieldName> extends CommonOutputOpts { | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
export {}; |
@@ -1,2 +0,2 @@ | ||
import { GraphQLFieldResolver, GraphQLObjectType, GraphQLInterfaceType } from "graphql"; | ||
import { GraphQLObjectType, GraphQLInterfaceType } from "graphql"; | ||
import * as Types from "./types"; | ||
@@ -9,11 +9,2 @@ export declare function log(msg: string): void; | ||
/** | ||
* If a resolve function is not given, then a default resolve behavior is used | ||
* which takes the property of the source object of the same name as the field | ||
* and returns it as the result, or if it's a function, returns the result | ||
* of calling that function while passing along args and context value. | ||
*/ | ||
export declare const propertyFieldResolver: (key: string) => GraphQLFieldResolver<any, any, { | ||
[argName: string]: any; | ||
}>; | ||
/** | ||
* | ||
@@ -20,0 +11,0 @@ * Copied from graphql-js: |
@@ -30,21 +30,2 @@ "use strict"; | ||
}; | ||
/** | ||
* If a resolve function is not given, then a default resolve behavior is used | ||
* which takes the property of the source object of the same name as the field | ||
* and returns it as the result, or if it's a function, returns the result | ||
* of calling that function while passing along args and context value. | ||
*/ | ||
exports.propertyFieldResolver = function (key) { | ||
return function (source, args, contextValue, info) { | ||
// ensure source is a value for which property access is acceptable. | ||
if (typeof source === "object" || typeof source === "function") { | ||
// TODO: Maybe warn here if key doesn't exist on source? | ||
var property = source[key]; | ||
if (typeof property === "function") { | ||
return source[key](args, contextValue, info); | ||
} | ||
return property; | ||
} | ||
}; | ||
}; | ||
// ---------------------------- | ||
@@ -51,0 +32,0 @@ /** |
{ | ||
"name": "nexus", | ||
"version": "0.6.2", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"version": "0.7.0-alpha.1", | ||
"main": "dist", | ||
"types": "src", | ||
"license": "MIT", | ||
@@ -7,0 +7,0 @@ "description": "Scalable, strongly typed GraphQL schema development", |
## GraphQL Nexus | ||
**(Still actively WIP, any feedback appreciated!)** | ||
``` | ||
yarn add nexus # or npm install nexus | ||
``` | ||
**(Still under construction, check [#1](https://github.com/graphql-nexus/nexus/issues/1) for the TODO List!)** | ||
Simple, strongly typed GraphQL schema construction for TypeScript/JavaScript | ||
@@ -15,10 +19,6 @@ | ||
Build them manually (for now) | ||
[graphql-nexus.com](https://graphql-nexus.com) | ||
``` | ||
yarn run website | ||
``` | ||
### License | ||
MIT |
@@ -49,3 +49,3 @@ import { | ||
import * as Types from "./types"; | ||
import { propertyFieldResolver, suggestionList, objValues } from "./utils"; | ||
import { suggestionList, objValues } from "./utils"; | ||
import { isObject } from "util"; | ||
@@ -635,10 +635,3 @@ | ||
if (fieldOptions.resolve) { | ||
if (typeof fieldOptions.property !== "undefined") { | ||
console.warn( | ||
`Both resolve and property should not be supplied, property will be ignored` | ||
); | ||
} | ||
resolver = fieldOptions.resolve; | ||
} else if (fieldOptions.property) { | ||
resolver = propertyFieldResolver(fieldOptions.property); | ||
} | ||
@@ -645,0 +638,0 @@ if (typeof fieldOptions.default !== "undefined") { |
@@ -72,5 +72,5 @@ import * as Types from "./types"; | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "ID", options); | ||
this.field(name, "ID", ...opts); | ||
} | ||
@@ -83,5 +83,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "Int", options); | ||
this.field(name, "Int", ...opts); | ||
} | ||
@@ -94,5 +94,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "Float", options); | ||
this.field(name, "Float", ...opts); | ||
} | ||
@@ -105,5 +105,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "String", options); | ||
this.field(name, "String", ...opts); | ||
} | ||
@@ -116,5 +116,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "Boolean", options); | ||
this.field(name, "Boolean", ...opts); | ||
} | ||
@@ -128,4 +128,10 @@ | ||
type: Types.AllOutputTypes<GenTypes> | Types.BaseScalars, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
let options: Types.OutputFieldOpts<GenTypes, TypeName, any> = {}; | ||
if (typeof opts[0] === "function") { | ||
options.resolve = opts[0]; | ||
} else { | ||
options = { ...opts[0] }; | ||
} | ||
this.typeConfig.fields.push({ | ||
@@ -166,4 +172,4 @@ item: Types.NodeType.FIELD, | ||
/** | ||
* Used to modify a field already defined on an interface or | ||
* abstract type. | ||
* Used to modify a field already defined on an interface or mixed-in | ||
* from another type. | ||
* | ||
@@ -427,5 +433,5 @@ * At this point the type will not change, but the resolver, | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "ID", options); | ||
this.field(name, "ID", ...opts); | ||
} | ||
@@ -438,5 +444,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "Int", options); | ||
this.field(name, "Int", ...opts); | ||
} | ||
@@ -449,5 +455,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "Float", options); | ||
this.field(name, "Float", ...opts); | ||
} | ||
@@ -460,5 +466,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "String", options); | ||
this.field(name, "String", ...opts); | ||
} | ||
@@ -471,5 +477,5 @@ | ||
name: FieldName, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
this.field(name, "Boolean", options); | ||
this.field(name, "Boolean", ...opts); | ||
} | ||
@@ -483,4 +489,10 @@ | ||
type: Types.AllOutputTypes<GenTypes> | Types.BaseScalars, | ||
options?: Types.OutputFieldOpts<GenTypes, TypeName, FieldName> | ||
...opts: Types.ConditionalOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
) { | ||
let options: Types.OutputFieldOpts<GenTypes, TypeName, any> = {}; | ||
if (typeof opts[0] === "function") { | ||
options.resolve = opts[0]; | ||
} else { | ||
options = { ...opts[0] }; | ||
} | ||
this.typeConfig.fields.push({ | ||
@@ -487,0 +499,0 @@ item: Types.NodeType.FIELD, |
@@ -18,2 +18,26 @@ import { assertValidName, GraphQLScalarType } from "graphql"; | ||
* | ||
* ``` | ||
* const User = objectType('User', (t) => { | ||
* t.int('id', { description: 'Id of the user' }) | ||
* t.string('fullName', { description: 'Full name of the user' }) | ||
* t.field('status', 'StatusEnum'); | ||
* t.field('posts', 'Post', { | ||
* list: true, | ||
* resolve(root, args, ctx) { | ||
* return ctx.getUser(root.id).posts() | ||
* } | ||
* }) | ||
* }); | ||
* | ||
* const Post = objectType('Post', (t) => { | ||
* t.int('id') | ||
* t.string('title') | ||
* }) | ||
* | ||
* const StatusEnum = enumType('StatusEnum', { | ||
* ACTIVE: 1, | ||
* DISABLED: 2 | ||
* }); | ||
* ``` | ||
* | ||
* @see https://graphql.github.io/learn/schema/#object-types-and-fields | ||
@@ -20,0 +44,0 @@ */ |
@@ -127,13 +127,2 @@ import { | ||
hasPropertyResolver(type: GraphQLObjectType, fieldName: string) { | ||
if (this.isInterfaceField(type, fieldName)) { | ||
// | ||
} | ||
return Boolean( | ||
this.objectFieldMeta[type.name] && | ||
this.objectFieldMeta[type.name][fieldName] && | ||
this.objectFieldMeta[type.name][fieldName].property | ||
); | ||
} | ||
hasDefaultValue(type: GraphQLObjectType, fieldName: string) { | ||
@@ -160,11 +149,2 @@ return Boolean( | ||
// Type Genreation Helpers: | ||
getPropertyResolver(type: GraphQLObjectType, fieldName: string) { | ||
return ( | ||
this.objectFieldMeta[type.name] && | ||
this.objectFieldMeta[type.name][fieldName].property | ||
); | ||
} | ||
// Schema construction helpers: | ||
@@ -171,0 +151,0 @@ |
@@ -119,3 +119,8 @@ import { | ||
}; | ||
const typeRootTypeName = (typeName: string) => suffixed(typeName, "RootType"); | ||
const typeRootTypeName = (typeName: string) => { | ||
if (isEntryType(typeName)) { | ||
return "{}"; | ||
} | ||
return suffixed(typeName, "RootType"); | ||
}; | ||
const fieldResolverName = (typeName: string, fieldName: string) => | ||
@@ -242,5 +247,2 @@ suffixed(typeName, fieldName, "Resolver"); | ||
: "?:"; | ||
if (metadata.hasPropertyResolver(type, field.name)) { | ||
return `${metadata.getPropertyResolver(type, field.name)}${colon}`; | ||
} | ||
return `${field.name}${colon}`; | ||
@@ -250,2 +252,5 @@ }; | ||
const makeRootType = (type: GraphQLObjectType) => { | ||
if (isEntryType(type.name)) { | ||
return; | ||
} | ||
if (backingTypeMap[type.name]) { | ||
@@ -537,2 +542,10 @@ allTypeStrings.push( | ||
function isEntryType(typeName: string) { | ||
return ( | ||
typeName === "Query" || | ||
typeName === "Mutation" || | ||
typeName === "Subscription" | ||
); | ||
} | ||
const stringify = (v: any) => JSON.stringify(v); | ||
@@ -539,0 +552,0 @@ |
154
src/types.ts
@@ -132,4 +132,3 @@ import { | ||
/** | ||
* The description of the field, as defined in the GraphQL | ||
* object definition | ||
* The description of the field, as defined in the GraphQL object definition | ||
*/ | ||
@@ -201,2 +200,12 @@ description?: string; | ||
/** | ||
* All non-resolver output field options | ||
*/ | ||
export interface CommonOutputOpts extends FieldOpts { | ||
/** | ||
* Any arguments defined | ||
*/ | ||
args?: OutputFieldArgs; | ||
} | ||
export interface OutputFieldOpts< | ||
@@ -206,12 +215,12 @@ GenTypes = any, | ||
FieldName = any | ||
> extends FieldOpts { | ||
> extends CommonOutputOpts { | ||
/** | ||
* Any arguments defined | ||
* Resolver for the output field | ||
*/ | ||
args?: OutputFieldArgs; | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
/** | ||
* Property to use to resolve the field. If resolve is specified, this field is ignored. | ||
* Default value for the field, if none is returned. | ||
*/ | ||
property?: Extract<keyof RootValue<GenTypes, TypeName>, string>; | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
@@ -221,19 +230,24 @@ // /** | ||
// */ | ||
// subscribe?: ( | ||
// root: RootValue<GenTypes, TypeName>, | ||
// args: ArgsValue<GenTypes, TypeName, FieldName>, | ||
// context: ContextValue<GenTypes>, | ||
// info: GraphQLResolveInfo | ||
// ) => ResultValue<GenTypes, TypeName, FieldName>; | ||
// subscribe?: OutputFieldResolver<GenTypes, TypeName, FieldName> | ||
} | ||
export type OutputFieldResolver<GenTypes, TypeName, FieldName> = ( | ||
root: RootValue<GenTypes, TypeName>, | ||
args: ArgsValue<GenTypes, TypeName, FieldName>, | ||
context: ContextValue<GenTypes>, | ||
info: GraphQLResolveInfo | ||
) => MaybePromise<ResultValue<GenTypes, TypeName, FieldName>>; | ||
/** | ||
* All properties that can be changed about a field | ||
*/ | ||
export type ModifyFieldOpts<GenTypes, TypeName, FieldName> = { | ||
/** | ||
* The description of the field, as defined in the GraphQL object definition. | ||
*/ | ||
description?: string; | ||
/** | ||
* Resolver for the output field | ||
*/ | ||
resolve?: ( | ||
root: RootValue<GenTypes, TypeName>, | ||
args: ArgsValue<GenTypes, TypeName, FieldName>, | ||
context: ContextValue<GenTypes>, | ||
info: GraphQLResolveInfo | ||
) => MaybePromise<ResultValue<GenTypes, TypeName, FieldName>>; | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
/** | ||
@@ -243,11 +257,4 @@ * Default value for the field, if none is returned. | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
}; | ||
export interface AbstractFieldOpts<GenTypes, FieldName> extends FieldOpts {} | ||
export type ModifyFieldOpts<GenTypes, TypeName, FieldName> = Omit< | ||
OutputFieldOpts<GenTypes, TypeName, FieldName>, | ||
"args" | "list" | "listItemNullable" | "nullable" | ||
>; | ||
export interface InputFieldOpts<GenTypes = any, TypeName = any> | ||
@@ -264,3 +271,3 @@ extends FieldOpts { | ||
/** | ||
* Set a value for the input | ||
* Set a default value for the input type | ||
*/ | ||
@@ -639,6 +646,2 @@ default?: InputValue<GenTypes, TypeName>; | ||
/** | ||
* Generated type helpers: | ||
*/ | ||
export type TypeResolver<GenTypes, TypeName> = ( | ||
@@ -650,2 +653,6 @@ root: RootValue<GenTypes, TypeName>, | ||
/** | ||
* Generated type helpers: | ||
*/ | ||
type GenTypesShapeKeys = | ||
@@ -748,2 +755,10 @@ | "context" | ||
export type RootValueField< | ||
GenTypes, | ||
TypeName, | ||
FieldName | ||
> = FieldName extends keyof RootValue<GenTypes, TypeName> | ||
? RootValue<GenTypes, TypeName>[FieldName] | ||
: never; | ||
export type ArgsValue< | ||
@@ -791,2 +806,73 @@ GenTypes, | ||
export type RootTypeMap = Record<string, string | ImportedType | undefined>; | ||
// ----- | ||
// Conditional Output Field Options | ||
// | ||
// Possibly the trickiest part of the typings, we conditionally | ||
// determine whether the resolvers are required for the field, based on | ||
// the field name and value of the root type associated with that field (if any). | ||
// | ||
// If the field is required, it must either have a resolver as a function, or | ||
// an object with either a "resolver" or a "default" field. If it's not required, | ||
// any of those can exist but they're not required. | ||
// ----- | ||
// - If the field actually exists in the "root value" | ||
// - If the value of the root field is the expected type, and the field isn't nullable | ||
// - Then the resolver is optional | ||
// - Else if it's the wrong type, then we need a resolver / default for this field | ||
// - Else field doesn't even exist in the root type, we need a resolver | ||
export type ConditionalOutputFieldOpts< | ||
GenTypes = any, | ||
TypeName = any, | ||
FieldName = any | ||
> = FieldName extends keyof RootValue<GenTypes, TypeName> | ||
? RootValueField<GenTypes, TypeName, FieldName> extends ResultValue< | ||
GenTypes, | ||
TypeName, | ||
FieldName | ||
> | ||
? OptionalOutputOpts<GenTypes, TypeName, FieldName> | ||
: Extract<RootValueField<GenTypes, TypeName, FieldName>, null> extends null | ||
? OptionalOutputOpts<GenTypes, TypeName, FieldName> | ||
: RequiredOutputOpts<GenTypes, TypeName, FieldName> | ||
: RequiredOutputOpts<GenTypes, TypeName, FieldName>; | ||
export type OptionalOutputOpts<GenTypes, TypeName, FieldName> = | ||
| [] | ||
| [OptionalResolverOutputFieldOpts<GenTypes, TypeName, FieldName>] | ||
| [OutputFieldResolver<GenTypes, TypeName, FieldName>]; | ||
export type RequiredOutputOpts<GenTypes, TypeName, FieldName> = | ||
| [NeedsResolverOutputFieldOpts<GenTypes, TypeName, FieldName>] | ||
| [OutputFieldResolver<GenTypes, TypeName, FieldName>]; | ||
export interface OutputWithDefaultOpts<GenTypes, TypeName, FieldName> | ||
extends CommonOutputOpts { | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
default: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
export interface OutputWithResolveOpts<GenTypes, TypeName, FieldName> | ||
extends CommonOutputOpts { | ||
resolve: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} | ||
/** | ||
* The "Needs Resolver" output field opts means that the resolver cannot | ||
* be fulfilled by the "backing value" alone, and therefore needs either | ||
* a valid resolver or a "root value". | ||
*/ | ||
export type NeedsResolverOutputFieldOpts<GenTypes, TypeName, FieldName> = | ||
| OutputWithDefaultOpts<GenTypes, TypeName, FieldName> | ||
| OutputWithResolveOpts<GenTypes, TypeName, FieldName>; | ||
/** | ||
* If we already have the correct value for the field from the root type, | ||
* then we can provide a resolver or a default value, but we don't have to. | ||
*/ | ||
export interface OptionalResolverOutputFieldOpts<GenTypes, TypeName, FieldName> | ||
extends CommonOutputOpts { | ||
resolve?: OutputFieldResolver<GenTypes, TypeName, FieldName>; | ||
default?: MaybeThunk<ResultValue<GenTypes, TypeName, FieldName>>; | ||
} |
@@ -1,8 +0,2 @@ | ||
import { | ||
GraphQLFieldResolver, | ||
GraphQLObjectType, | ||
GraphQLInterfaceType, | ||
GraphQLUnionType, | ||
isUnionType, | ||
} from "graphql"; | ||
import { GraphQLObjectType, GraphQLInterfaceType } from "graphql"; | ||
import path from "path"; | ||
@@ -47,24 +41,2 @@ import * as Types from "./types"; | ||
/** | ||
* If a resolve function is not given, then a default resolve behavior is used | ||
* which takes the property of the source object of the same name as the field | ||
* and returns it as the result, or if it's a function, returns the result | ||
* of calling that function while passing along args and context value. | ||
*/ | ||
export const propertyFieldResolver = ( | ||
key: string | ||
): GraphQLFieldResolver<any, any> => { | ||
return function(source, args, contextValue, info) { | ||
// ensure source is a value for which property access is acceptable. | ||
if (typeof source === "object" || typeof source === "function") { | ||
// TODO: Maybe warn here if key doesn't exist on source? | ||
const property = source[key]; | ||
if (typeof property === "function") { | ||
return source[key](args, contextValue, info); | ||
} | ||
return property; | ||
} | ||
}; | ||
}; | ||
// ---------------------------- | ||
@@ -71,0 +43,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
533646
8106
0
57