Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -379,12 +379,16 @@ export type {
IntrospectionEnumValue,
IntrospectionField,
IntrospectionInputObjectType,
IntrospectionInputType,
IntrospectionInputTypeRef,
IntrospectionInputValue,
IntrospectionInterfaceType,
IntrospectionListTypeRef,
IntrospectionNamedTypeRef,
IntrospectionNonNullTypeRef,
IntrospectionObjectType,
IntrospectionOutputType,
IntrospectionOutputTypeRef,
IntrospectionQuery,
IntrospectionScalarType,
IntrospectionSchema,
Expand Down
2 changes: 1 addition & 1 deletion src/jsutils/keyMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import type {ObjMap} from './ObjMap';
*
*/
export default function keyMap<T>(
list: Array<T>,
list: $ReadOnlyArray<T>,
keyFn: (item: T) => string
): ObjMap<T> {
return list.reduce(
Expand Down
2 changes: 1 addition & 1 deletion src/jsutils/keyValMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type {ObjMap} from './ObjMap';
*
*/
export default function keyValMap<T, V>(
list: Array<T>,
list: $ReadOnlyArray<T>,
keyFn: (item: T) => string,
valFn: (item: T) => V
): ObjMap<V> {
Expand Down
19 changes: 12 additions & 7 deletions src/utilities/buildClientSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ import type {
IntrospectionEnumType,
IntrospectionInputObjectType,
IntrospectionTypeRef,
IntrospectionListTypeRef,
IntrospectionNonNullTypeRef,
IntrospectionInputTypeRef,
IntrospectionOutputTypeRef,
IntrospectionNamedTypeRef,
} from './introspectionQuery';


Expand Down Expand Up @@ -120,14 +121,14 @@ export function buildClientSchema(
// preferring cached instances before building new instances.
function getType(typeRef: IntrospectionTypeRef): GraphQLType {
if (typeRef.kind === TypeKind.LIST) {
const itemRef = ((typeRef: any): IntrospectionListTypeRef).ofType;
const itemRef = typeRef.ofType;
if (!itemRef) {
throw new Error('Decorated type deeper than introspection query.');
}
return new GraphQLList(getType(itemRef));
}
if (typeRef.kind === TypeKind.NON_NULL) {
const nullableRef = ((typeRef: any): IntrospectionNonNullTypeRef).ofType;
const nullableRef = typeRef.ofType;
if (!nullableRef) {
throw new Error('Decorated type deeper than introspection query.');
}
Expand Down Expand Up @@ -161,7 +162,7 @@ export function buildClientSchema(
return typeDef;
}

function getInputType(typeRef: IntrospectionTypeRef): GraphQLInputType {
function getInputType(typeRef: IntrospectionInputTypeRef): GraphQLInputType {
const type = getType(typeRef);
invariant(
isInputType(type),
Expand All @@ -170,7 +171,9 @@ export function buildClientSchema(
return type;
}

function getOutputType(typeRef: IntrospectionTypeRef): GraphQLOutputType {
function getOutputType(
typeRef: IntrospectionOutputTypeRef
): GraphQLOutputType {
const type = getType(typeRef);
invariant(
isOutputType(type),
Expand All @@ -179,7 +182,9 @@ export function buildClientSchema(
return type;
}

function getObjectType(typeRef: IntrospectionTypeRef): GraphQLObjectType {
function getObjectType(
typeRef: IntrospectionNamedTypeRef<IntrospectionObjectType>
): GraphQLObjectType {
const type = getType(typeRef);
invariant(
type instanceof GraphQLObjectType,
Expand Down
4 changes: 4 additions & 0 deletions src/utilities/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ export type {
IntrospectionQuery,
IntrospectionSchema,
IntrospectionType,
IntrospectionInputType,
IntrospectionOutputType,
IntrospectionScalarType,
IntrospectionObjectType,
IntrospectionInterfaceType,
IntrospectionUnionType,
IntrospectionEnumType,
IntrospectionInputObjectType,
IntrospectionTypeRef,
IntrospectionInputTypeRef,
IntrospectionOutputTypeRef,
IntrospectionNamedTypeRef,
IntrospectionListTypeRef,
IntrospectionNonNullTypeRef,
Expand Down
245 changes: 144 additions & 101 deletions src/utilities/introspectionQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,17 +104,17 @@ export const introspectionQuery = `
}
`;

export type IntrospectionQuery = {
__schema: IntrospectionSchema
};

export type IntrospectionSchema = {
queryType: IntrospectionNamedTypeRef;
mutationType: ?IntrospectionNamedTypeRef;
subscriptionType: ?IntrospectionNamedTypeRef;
types: Array<IntrospectionType>;
directives: Array<IntrospectionDirective>;
};
export type IntrospectionQuery = {|
+__schema: IntrospectionSchema;
|};

export type IntrospectionSchema = {|
+queryType: IntrospectionNamedTypeRef<IntrospectionObjectType>;
+mutationType: ?IntrospectionNamedTypeRef<IntrospectionObjectType>;
+subscriptionType: ?IntrospectionNamedTypeRef<IntrospectionObjectType>;
+types: $ReadOnlyArray<IntrospectionType>;
+directives: $ReadOnlyArray<IntrospectionDirective>;
|};

export type IntrospectionType =
| IntrospectionScalarType
Expand All @@ -124,95 +124,138 @@ export type IntrospectionType =
| IntrospectionEnumType
| IntrospectionInputObjectType;

export type IntrospectionScalarType = {
kind: 'SCALAR';
name: string;
description: ?string;
};

export type IntrospectionObjectType = {
kind: 'OBJECT';
name: string;
description: ?string;
fields: Array<IntrospectionField>;
interfaces: Array<IntrospectionNamedTypeRef>;
};

export type IntrospectionInterfaceType = {
kind: 'INTERFACE';
name: string;
description: ?string;
fields: Array<IntrospectionField>;
possibleTypes: Array<IntrospectionNamedTypeRef>;
};

export type IntrospectionUnionType = {
kind: 'UNION';
name: string;
description: ?string;
possibleTypes: Array<IntrospectionNamedTypeRef>;
};

export type IntrospectionEnumType = {
kind: 'ENUM';
name: string;
description: ?string;
enumValues: Array<IntrospectionEnumValue>;
};

export type IntrospectionInputObjectType = {
kind: 'INPUT_OBJECT';
name: string;
description: ?string;
inputFields: Array<IntrospectionInputValue>;
};
export type IntrospectionOutputType =
| IntrospectionScalarType
| IntrospectionObjectType
| IntrospectionInterfaceType
| IntrospectionUnionType
| IntrospectionEnumType;

export type IntrospectionInputType =
| IntrospectionScalarType
| IntrospectionEnumType
| IntrospectionInputObjectType;

export type IntrospectionScalarType = {|
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if these types should be exact types since that doesn't actually describe what is returned from the server - all fields are queried on each possible type, so the properties exist and are null.

That might be okay as just a balance between correctness and usability, but we should keep an eye on this in case we need to remove the exact types in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer exact types for now, as it's way easier to pretend fields that are always null don't exist. If we have to add a bunch of null fields, we might want a conversion from IntrospectionType to LinkedType to give us the more-restrictive typing (could also do things like enforce ofType is non-null on List and NonNullable).

Basically, if we need to relax this, then we probably want two different sets of types:

IntrospectionType => things coming over-the-wire in an introspection query. Does not differentiate from Input and Output types, but is a 1:1 data representation.

LinkedType => type system description using reference types that is a validated version of what came down from the wire.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine to keep it exact types for now - just wanted to highlight the disconnect so we're aware in the future

+kind: 'SCALAR';
+name: string;
+description: ?string;
|};

export type IntrospectionObjectType = {|
+kind: 'OBJECT';
+name: string;
+description: ?string;
+fields: $ReadOnlyArray<IntrospectionField>;
+interfaces: $ReadOnlyArray<
IntrospectionNamedTypeRef<IntrospectionInterfaceType>
>;
|};

export type IntrospectionInterfaceType = {|
+kind: 'INTERFACE';
+name: string;
+description: ?string;
+fields: $ReadOnlyArray<IntrospectionField>;
+possibleTypes: $ReadOnlyArray<
IntrospectionNamedTypeRef<IntrospectionObjectType>
>;
|};

export type IntrospectionUnionType = {|
+kind: 'UNION';
+name: string;
+description: ?string;
+possibleTypes: $ReadOnlyArray<
IntrospectionNamedTypeRef<IntrospectionObjectType>
>;
|};

export type IntrospectionEnumType = {|
+kind: 'ENUM';
+name: string;
+description: ?string;
+enumValues: $ReadOnlyArray<IntrospectionEnumValue>;
|};

export type IntrospectionInputObjectType = {|
+kind: 'INPUT_OBJECT';
+name: string;
+description: ?string;
+inputFields: $ReadOnlyArray<IntrospectionInputValue>;
|};

export type IntrospectionListTypeRef<
T: IntrospectionTypeRef = IntrospectionTypeRef
> = {|
+kind: 'LIST';
+ofType?: T;
|};

export type IntrospectionNonNullTypeRef<
T: IntrospectionTypeRef = IntrospectionTypeRef
> = {|
+kind: 'NON_NULL';
+ofType?: T;
|};

export type IntrospectionTypeRef =
| IntrospectionNamedTypeRef
| IntrospectionListTypeRef
| IntrospectionNonNullTypeRef;

export type IntrospectionNamedTypeRef = {
kind: string;
name: string;
};

export type IntrospectionListTypeRef = {
kind: 'LIST';
ofType?: IntrospectionTypeRef;
};

export type IntrospectionNonNullTypeRef = {
kind: 'NON_NULL';
ofType?: IntrospectionTypeRef;
};

export type IntrospectionField = {
name: string;
description: ?string;
args: Array<IntrospectionInputValue>;
type: IntrospectionTypeRef;
isDeprecated: boolean;
deprecationReason: ?string;
};

export type IntrospectionInputValue = {
name: string;
description: ?string;
type: IntrospectionTypeRef;
defaultValue: ?string;
};

export type IntrospectionEnumValue = {
name: string;
description: ?string;
isDeprecated: boolean;
deprecationReason: ?string;
};

export type IntrospectionDirective = {
name: string;
description: ?string;
locations: Array<DirectiveLocationEnum>;
args: Array<IntrospectionInputValue>;
};
| IntrospectionNamedTypeRef<IntrospectionType>
| IntrospectionListTypeRef<IntrospectionTypeRef>
| IntrospectionNonNullTypeRef<
| IntrospectionNamedTypeRef<IntrospectionType>
| IntrospectionListTypeRef<IntrospectionTypeRef>
>;

export type IntrospectionOutputTypeRef =
| IntrospectionNamedTypeRef<IntrospectionOutputType>
| IntrospectionListTypeRef<IntrospectionOutputTypeRef>
| IntrospectionNonNullTypeRef<
| IntrospectionNamedTypeRef<IntrospectionOutputType>
| IntrospectionListTypeRef<IntrospectionOutputTypeRef>
>;

export type IntrospectionInputTypeRef =
| IntrospectionNamedTypeRef<IntrospectionInputType>
| IntrospectionListTypeRef<IntrospectionInputTypeRef>
| IntrospectionNonNullTypeRef<
| IntrospectionNamedTypeRef<IntrospectionInputType>
| IntrospectionListTypeRef<IntrospectionInputTypeRef>
>;

export type IntrospectionNamedTypeRef<
T: IntrospectionType = IntrospectionType
> = {|
+kind: $PropertyType<T, 'kind'>;
+name: string;
|};

export type IntrospectionField = {|
+name: string;
+description: ?string;
+args: $ReadOnlyArray<IntrospectionInputValue>;
+type: IntrospectionOutputTypeRef;
+isDeprecated: boolean;
+deprecationReason: ?string;
|};

export type IntrospectionInputValue = {|
+name: string;
+description: ?string;
+type: IntrospectionInputTypeRef;
+defaultValue: ?string;
|};

export type IntrospectionEnumValue = {|
+name: string;
+description: ?string;
+isDeprecated: boolean;
+deprecationReason: ?string;
|};

export type IntrospectionDirective = {|
+name: string;
+description: ?string;
+locations: $ReadOnlyArray<DirectiveLocationEnum>;
+args: $ReadOnlyArray<IntrospectionInputValue>;
|};