Skip to content

Commit

Permalink
feature: add early warning for undefined refs to simplify debugging o…
Browse files Browse the repository at this point in the history
…f circular import issues
  • Loading branch information
hayes committed Jul 4, 2021
1 parent 675f6a2 commit 095b68b
Show file tree
Hide file tree
Showing 26 changed files with 180 additions and 130 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ new ApolloServer({
- ## [Smart Subscriptions](https://giraphql.com/plugins/smart-subscriptions)
Make any part of your graph subscribable to get live updates as your data changes.
- ## [Errors](https://giraphql.com/plugins/errors.md)
A plugin for easily including error types in your GraphQL schema and hooking up error types to resolvers.
A plugin for easily including error types in your GraphQL schema and hooking up error types to
resolvers.
37 changes: 20 additions & 17 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ route: /

## GiraphQL - A plugin based GraphQL schema builder for typescript

GiraphQL makes writing graphql schemas in typescript easy, fast and enjoyable. The core of GiraphQL adds 0 overhead at runtime, and has `graphql` as its only dependency.
GiraphQL makes writing graphql schemas in typescript easy, fast and enjoyable. The core of GiraphQL
adds 0 overhead at runtime, and has `graphql` as its only dependency.

By leaning heavily on typescripts ability to infer types, GiraphQL is the most type-safe way of writing GraphQL schemas in typescript/node while requiring very few manual type definitions and no code generation.
By leaning heavily on typescripts ability to infer types, GiraphQL is the most type-safe way of
writing GraphQL schemas in typescript/node while requiring very few manual type definitions and no
code generation.

GiraphQL has a unique and powerful plugin system that makes every plugin feel like its features are built into the core library. Plugins can extend almost any part of the API by adding new options or methods that can take full advantage of GiraphQLs type system.
GiraphQL has a unique and powerful plugin system that makes every plugin feel like its features are
built into the core library. Plugins can extend almost any part of the API by adding new options or
methods that can take full advantage of GiraphQLs type system.

## Hello, World

Expand Down Expand Up @@ -39,47 +44,45 @@ new ApolloServer({

## Plugins that make GiraphQL even better

* \*\*\*\*[**Scope Auth**](plugins/scope-auth.md)\*\*\*\*
- \*\*\*\*[**Scope Auth**](plugins/scope-auth.md)\*\*\*\*

Add global, type level, or field level authorization checks to your schema

* \*\*\*\*[**Validation**](plugins/validation.md)\*\*\*\*
- \*\*\*\*[**Validation**](plugins/validation.md)\*\*\*\*

Validating your inputs and arguments

* \*\*\*\*[**Dataloader**](plugins/dataloader.md)\*\*\*\*
- \*\*\*\*[**Dataloader**](plugins/dataloader.md)\*\*\*\*

Quickly define data-loaders for your types and fields to avoid n+1 queries.

* \*\*\*\*[**Relay**](plugins/relay.md)\*\*\*\*
- \*\*\*\*[**Relay**](plugins/relay.md)\*\*\*\*

Easy to use builder methods for defining relay style nodes and connections, and helpful utilities

for cursor based pagination.

* \*\*\*\*[**Simple Objects**](plugins/simple-objects.md)\*\*\*\*
- \*\*\*\*[**Simple Objects**](plugins/simple-objects.md)\*\*\*\*

Define simple object types without resolvers or manual type definitions.

* \*\*\*\*[**Mocks**](plugins/mocks.md)\*\*\*\*
- \*\*\*\*[**Mocks**](plugins/mocks.md)\*\*\*\*

Add mock resolver for easier testing

* \*\*\*\*[**Sub-Graph**](plugins/sub-graph.md)\*\*\*\*
- \*\*\*\*[**Sub-Graph**](plugins/sub-graph.md)\*\*\*\*

Build multiple subsets of your graph to easily share code between internal and external APIs.

* \*\*\*\*[**Directives**](plugins/directives.md)\*\*\*\*
- \*\*\*\*[**Directives**](plugins/directives.md)\*\*\*\*

Integrate with existing schema graphql directives in a type-safe way.

* \*\*\*\*[**Smart Subscriptions**](plugins/smart-subscriptions.md)\*\*\*\*
- \*\*\*\*[**Smart Subscriptions**](plugins/smart-subscriptions.md)\*\*\*\*

Make any part of your graph subscribable to get live updates as your data changes.

* \*\*\*\*[**Errors**](plugins/errors.md)\*\*\*\*

A plugin for easily including error types in your GraphQL schema and hooking up error types to resolvers.


- \*\*\*\*[**Errors**](plugins/errors.md)\*\*\*\*

A plugin for easily including error types in your GraphQL schema and hooking up error types to
resolvers.
79 changes: 39 additions & 40 deletions docs/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
# Table of contents

* [Overview](README.md)
* [Guide](guide/README.md)
* [Object Types](guide/objects.md)
* [SchemaBuilder](guide/schema-builder.md)
* [Fields](guide/fields.md)
* [Args](guide/args.md)
* [Context object](guide/context.md)
* [Input Objects](guide/inputs.md)
* [Enums](guide/enums.md)
* [Scalars](guide/scalars.md)
* [Interfaces](guide/interfaces.md)
* [Unions](guide/unions.md)
* [Using Plugins](guide/using-plugins.md)
* [App layout](guide/app-layout.md)
* [Patterns](guide/patterns.md)
* [Printing Schema](guide/printing-schemas.md)
* [Changing Default Nullability](guide/changing-default-nullability.md)
* [Writing Plugins](guide/writing-plugins.md)
* [Deno](guide/deno.md)
* [Troubleshooting](guide/troubleshooting.md)
* [Plugins](plugins/README.md)
* [Auth](plugins/scope-auth.md)
* [Dataloader](plugins/dataloader.md)
* [Directives](plugins/directives.md)
* [Errors](plugins/errors.md)
* [Mocks](plugins/mocks.md)
* [Relay](plugins/relay.md)
* [Simple Objects](plugins/simple-objects.md)
* [Smart Subscriptions](plugins/smart-subscriptions.md)
* [SubGraph](plugins/sub-graph.md)
* [Validation](plugins/validation.md)
* [API](api/README.md)
* [SchemaBuilder](api/schema-builder.md)
* [FieldBuilder](api/field-builder.md)
* [ArgBuilder](api/arg-builder.md)
* [InputFieldBuilder](api/input-field-builder.md)
* [Design](design.md)
* [Migrations](migrations/README.md)
* [v2.0](migrations/2.0.md)

- [Overview](README.md)
- [Guide](guide/README.md)
- [Object Types](guide/objects.md)
- [SchemaBuilder](guide/schema-builder.md)
- [Fields](guide/fields.md)
- [Args](guide/args.md)
- [Context object](guide/context.md)
- [Input Objects](guide/inputs.md)
- [Enums](guide/enums.md)
- [Scalars](guide/scalars.md)
- [Interfaces](guide/interfaces.md)
- [Unions](guide/unions.md)
- [Using Plugins](guide/using-plugins.md)
- [App layout](guide/app-layout.md)
- [Patterns](guide/patterns.md)
- [Printing Schema](guide/printing-schemas.md)
- [Changing Default Nullability](guide/changing-default-nullability.md)
- [Writing Plugins](guide/writing-plugins.md)
- [Deno](guide/deno.md)
- [Troubleshooting](guide/troubleshooting.md)
- [Plugins](plugins/README.md)
- [Auth](plugins/scope-auth.md)
- [Dataloader](plugins/dataloader.md)
- [Directives](plugins/directives.md)
- [Errors](plugins/errors.md)
- [Mocks](plugins/mocks.md)
- [Relay](plugins/relay.md)
- [Simple Objects](plugins/simple-objects.md)
- [Smart Subscriptions](plugins/smart-subscriptions.md)
- [SubGraph](plugins/sub-graph.md)
- [Validation](plugins/validation.md)
- [API](api/README.md)
- [SchemaBuilder](api/schema-builder.md)
- [FieldBuilder](api/field-builder.md)
- [ArgBuilder](api/arg-builder.md)
- [InputFieldBuilder](api/input-field-builder.md)
- [Design](design.md)
- [Migrations](migrations/README.md)
- [v2.0](migrations/2.0.md)
26 changes: 13 additions & 13 deletions docs/plugins/README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
# Plugins

* \*\*\*\*[**Scope Auth**](scope-auth.md)\*\*\*\*
- \*\*\*\*[**Scope Auth**](scope-auth.md)\*\*\*\*

Add global, type level, or field level authorization checks to your schema

* \*\*\*\*[**Validation**](validation.md)\*\*\*\*
- \*\*\*\*[**Validation**](validation.md)\*\*\*\*

Validating your inputs and arguments

* \*\*\*\*[**Dataloader**](dataloader.md)\*\*\*\*
- \*\*\*\*[**Dataloader**](dataloader.md)\*\*\*\*

Quickly define data-loaders for your types and fields to avoid n+1 queries.

* \*\*\*\*[**Relay**](relay.md)\*\*\*\*
* Easy to use builder methods for defining relay style nodes and connections, and helpful utilities
- \*\*\*\*[**Relay**](relay.md)\*\*\*\*
- Easy to use builder methods for defining relay style nodes and connections, and helpful utilities

for cursor based pagination.

* \*\*\*\*[**Simple Objects**](simple-objects.md)\*\*\*\*
- \*\*\*\*[**Simple Objects**](simple-objects.md)\*\*\*\*

Define simple object types without resolvers or manual type definitions.

* \*\*\*\*[**Mocks**](mocks.md)\*\*\*\*
- \*\*\*\*[**Mocks**](mocks.md)\*\*\*\*

Add mock resolver for easier testing

* \*\*\*\*[**Sub-Graph**](sub-graph.md)\*\*\*\*
- \*\*\*\*[**Sub-Graph**](sub-graph.md)\*\*\*\*

Build multiple subsets of your graph to easily share code between internal and external APIs.

* \*\*\*\*[**Directives**](directives.md)\*\*\*\*
- \*\*\*\*[**Directives**](directives.md)\*\*\*\*

Integrate with existing schema graphql directives in a type-safe way.

* \*\*\*\*[**Smart Subscriptions**](smart-subscriptions.md)\*\*\*\*
- \*\*\*\*[**Smart Subscriptions**](smart-subscriptions.md)\*\*\*\*

Make any part of your graph subscribable to get live updates as your data changes.

* \*\*\*\*[**Errors**](errors.md)\*\*\*\*

A plugin for easily including error types in your GraphQL schema and hooking up error types to resolvers.
- \*\*\*\*[**Errors**](errors.md)\*\*\*\*

A plugin for easily including error types in your GraphQL schema and hooking up error types to
resolvers.
4 changes: 2 additions & 2 deletions docs/plugins/dataloader.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ This plugin makes it easy to add fields and types that are loaded through a data

### Install

To use the dataloader plugin you will need to install both the `dataloader` package and the
giraphql dataloader plugin:
To use the dataloader plugin you will need to install both the `dataloader` package and the giraphql
dataloader plugin:

```bash
yarn add dataloader @giraphql/plugin-dataloader
Expand Down
6 changes: 3 additions & 3 deletions docs/plugins/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ menu: Plugins

# Errors Plugin

A plugin for easily including error types in your GraphQL schema and hooking up error types to resolvers
A plugin for easily including error types in your GraphQL schema and hooking up error types to
resolvers

## Usage

Expand Down Expand Up @@ -213,7 +214,6 @@ Once your plugins are set up, you can define types for a ZodError, the same way
other error type. Below is a simple example of how this can be done, but the specifics of how you
structure your error types are left up to you.


```typescript
// Util for flattening zod errors into something easier to represent in your Schema.
function flattenErrors(
Expand Down Expand Up @@ -301,4 +301,4 @@ query {
}
}
}
```
```
4 changes: 2 additions & 2 deletions docs/plugins/relay.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,9 @@ const ThingsConnection = builder.connectionObject(
type: SomeThing,
name: 'ThingsConnection',
},
{
{
// Edge options (optional)
name: 'ThingsEdge' // defaults to Appending `Edge` to the Connection name
name: 'ThingsEdge', // defaults to Appending `Edge` to the Connection name
},
);

Expand Down
14 changes: 13 additions & 1 deletion packages/core/src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
SubscriptionFieldsShape,
SubscriptionFieldThunk,
} from './types';
import { normalizeEnumValues, valuesFromEnum } from './utils';
import { normalizeEnumValues, valuesFromEnum, verifyRef } from './utils';
import {
BaseEnum,
EnumParam,
Expand Down Expand Up @@ -122,6 +122,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
options: ObjectTypeOptions<Types, Param, ParentShape<Types, Param>, Interfaces>,
fields?: ObjectFieldsShape<Types, ParentShape<Types, Param>>,
) {
verifyRef(param);
const name =
typeof param === 'string'
? param
Expand Down Expand Up @@ -173,6 +174,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
ref: Type,
fields: ObjectFieldsShape<Types, ParentShape<Types, Type>>,
) {
verifyRef(ref);
this.configStore.onTypeConfig(ref, ({ name }) => {
this.configStore.addFields(ref, () => fields(new ObjectFieldBuilder(name, this)));
});
Expand All @@ -183,6 +185,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
fieldName: string,
field: ObjectFieldThunk<Types, ParentShape<Types, Type>>,
) {
verifyRef(ref);
this.configStore.onTypeConfig(ref, ({ name }) => {
this.configStore.addFields(ref, () => ({
[fieldName]: field(new ObjectFieldBuilder(name, this)),
Expand Down Expand Up @@ -302,6 +305,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
options: InterfaceTypeOptions<Types, Param, ParentShape<Types, Param>, Interfaces>,
fields?: InterfaceFieldsShape<Types, ParentShape<Types, Param>>,
) {
verifyRef(param);
const name =
typeof param === 'string'
? param
Expand Down Expand Up @@ -346,6 +350,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
ref: Type,
fields: InterfaceFieldsShape<Types, ParentShape<Types, Type>>,
) {
verifyRef(ref);
this.configStore.onTypeConfig(ref, ({ name }) => {
this.configStore.addFields(ref, () => fields(new InterfaceFieldBuilder(name, this)));
});
Expand All @@ -356,6 +361,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
fieldName: string,
field: InterfaceFieldThunk<Types, ParentShape<Types, Type>>,
) {
verifyRef(ref);
this.configStore.onTypeConfig(ref, ({ name }) => {
this.configStore.addFields(ref, () => ({
[fieldName]: field(new InterfaceFieldBuilder(name, this)),
Expand All @@ -369,6 +375,10 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
) {
const ref = new UnionRef<OutputShape<Types, Member>, ParentShape<Types, Member>>(name);

options.types.forEach((type) => {
verifyRef(type);
});

const config: GiraphQLUnionTypeConfig = {
kind: 'Union',
graphqlKind: 'Union',
Expand All @@ -388,6 +398,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
param: Param,
options: EnumTypeOptions<Types, Param, Values>,
) {
verifyRef(param);
const name = typeof param === 'string' ? param : (options as { name: string }).name;
const ref = new EnumRef<
Param extends BaseEnum ? ValuesFromEnum<Param> : ShapeFromEnumValues<Types, Values>
Expand Down Expand Up @@ -473,6 +484,7 @@ export default class SchemaBuilder<Types extends SchemaTypes> {
param: Param,
options: GiraphQLSchemaTypes.InputObjectTypeOptions<Types, Fields>,
): InputObjectRef<InputShapeFromFields<Fields>> {
verifyRef(param);
const name = typeof param === 'string' ? param : (param as { name: string }).name;

const ref = (
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/fieldUtils/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default class BaseFieldUtil<Types extends SchemaTypes, ParentShape, Kind

return {
kind: this.kind as never,
graphqlKind: this.graphqlKind as GiraphQLSchemaTypes.GiraphQLKindToGraphQLType[FieldKind],
graphqlKind: this.graphqlKind,
parentType: this.typename,
name,
args,
Expand Down
18 changes: 10 additions & 8 deletions packages/core/src/types/builder-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,16 @@ export type EnumValueConfigMap<Types extends SchemaTypes> = Record<
GiraphQLSchemaTypes.EnumValueConfig<Types>
>;

export type ShapeFromEnumValues<Types extends SchemaTypes, Values extends EnumValues<Types>> =
Values extends readonly string[]
? Values[number]
: Values extends EnumValueConfigMap<Types>
? {
[K in keyof Values]: Values[K]['value'] extends number | string ? Values[K]['value'] : K;
}[keyof Values]
: never;
export type ShapeFromEnumValues<
Types extends SchemaTypes,
Values extends EnumValues<Types>,
> = Values extends readonly string[]
? Values[number]
: Values extends EnumValueConfigMap<Types>
? {
[K in keyof Values]: Values[K]['value'] extends number | string ? Values[K]['value'] : K;
}[keyof Values]
: never;

export type ObjectFieldsShape<Types extends SchemaTypes, Shape> = (
t: GiraphQLSchemaTypes.ObjectFieldBuilder<Types, Shape>,
Expand Down
Loading

0 comments on commit 095b68b

Please sign in to comment.