Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for object type helpers used by Relay #5

Closed
wants to merge 13 commits into from
Closed
11 changes: 11 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
browser: false,
moduleFileExtensions: ['js', 'ts'],
roots: ['<rootDir>/src'],
testRegex: '/__tests__/[^.]+-test.ts$',
transform: {
'\\.ts$': 'ts-jest'
},
testEnvironment: 'node',
watchman: false
};
38 changes: 12 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,39 +32,25 @@
"build"
],
"scripts": {
"preversion": "npm run ci",
"prepublish": "npm run build",
"lint": "tslint 'src/**/*.ts'",
"preversion": "yarn ci",
"prepublish": "yarn build",
"lint": "tslint --project tsconfig.json",
"test": "jest",
"test-watch": "jest --watch",
"ci": "npm run lint && npm run test",
"build": "rm -rf build && tsc"
"ci": "yarn lint && yarn test",
"build": "rm -rf build && tsc --pretty"
},
"peerDependencies": {
"graphql": ">=0.6.0 <1.0.0"
},
"devDependencies": {
"@types/graphql": "^0.8.2",
"@types/jest": "^16.0.1",
"@types/node": "^6.0.52",
"graphql": "^0.8.2",
"jest": "^19.0.2",
"tslint": "^4.5.1",
"@types/graphql": "^0.11.7",
"@types/jest": "^22.0.1",
"@types/node": "^9.3.0",
"graphql": "^0.12.3",
"jest": "^22.0.4",
"ts-jest": "^22.0.1",
"tslint": "^5.8.0",
"typescript": "^2.2.1"
},
"jest": {
"roots": [
"<rootDir>/src"
],
"moduleFileExtensions": [
"js",
"ts"
],
"transform": {
".ts": "<rootDir>/resources/jest-ts-transform.js"
},
"testRegex": "/__tests__/[^.]+-test.ts$",
"browser": false,
"testEnvironment": "node"
}
}
12 changes: 0 additions & 12 deletions resources/jest-ts-transform.js

This file was deleted.

2 changes: 1 addition & 1 deletion src/__tests__/fixtures/wrap-fixture.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GraphQLInputType, GraphQLOutputType, GraphQLInputObjectType, GraphQLObjectType, GraphQLEnumType } from 'graphql';
import { GraphQLInputType, GraphQLOutputType, GraphQLInputObjectType, GraphQLObjectType, GraphQLEnumType } from 'graphql/type';
import { StrongInputType, StrongOutputType, wrapWeakType } from '../../index';

const anyType: any = null;
Expand Down
2 changes: 1 addition & 1 deletion src/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ implements StrongInputOutputType<TValue> {
}

/**
* The nullable sstrong GraphQL enum type object.
* The nullable strong GraphQL enum type object.
*/
class StrongNullableEnumType<TValue>
extends GraphQLEnumType
Expand Down
12 changes: 7 additions & 5 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ export type StrongInterfaceFieldMap = {

/**
* The configuration object to be used when creating interface types. It
* requires `resolveType` and `fields`.
* requires `fields`.
*/
export type StrongInterfaceTypeConfig<TValue, TFieldMap extends StrongInterfaceFieldMap> = {
readonly name: string,
readonly description?: string | undefined,
readonly resolveType: (value: TValue) => StrongObjectType<TValue, never>,
readonly resolveType?: (value: TValue) => StrongObjectType<TValue, never>,
readonly fields: StrongInterfaceFieldMapConfig<TFieldMap>,
};

Expand Down Expand Up @@ -135,12 +135,14 @@ implements StrongOutputType<TValue | null | undefined> {
super({
name: config.name,
description: config.description,
resolveType: value => config.resolveType(value).ofType,
resolveType: typeof config.resolveType === 'function'
? value => config.resolveType!(value).ofType
: undefined,
// Compute our fields from the fields map we were provided in the config.
// The format we define in our config is pretty similar to the format
// GraphQL.js expects.
fields: (): GraphQLFieldConfigMap<TValue, never> => {
const weakFields: GraphQLFieldConfigMap<TValue, never> = {};
fields: (): GraphQLFieldConfigMap<TValue, any> => {
const weakFields: GraphQLFieldConfigMap<TValue, any> = {};
for (const fieldName of Object.keys(config.fields)) {
const fieldConfig = config.fields[fieldName];
weakFields[fieldName] = {
Expand Down
90 changes: 67 additions & 23 deletions src/list.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GraphQLList, GraphQLNonNull } from 'graphql';
import { StrongInputType, StrongOutputType, StrongInputOutputType } from './type';
import { StrongInputType, StrongInputOutputType, StrongOutputType } from './type';

/**
* Creates a strong list type where the inner type is whatever GraphQL strong
Expand All @@ -8,26 +8,70 @@ import { StrongInputType, StrongOutputType, StrongInputOutputType } from './type
export function createListType<TValue>(type: StrongInputOutputType<TValue>): StrongInputOutputType<Array<TValue>>;
export function createListType<TValue>(type: StrongInputType<TValue>): StrongInputType<Array<TValue>>;
export function createListType<TValue>(type: StrongOutputType<TValue>): StrongOutputType<Array<TValue>>;
export function createListType<TValue>(type: StrongInputOutputType<TValue>): StrongInputOutputType<Array<TValue>> {
const nullableListType: StrongInputOutputType<Array<TValue> | null | undefined> = {
_strongType: true,
_strongInputType: true,
_strongOutputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLList(type.getWeakType()),
getWeakInputType: () => new GraphQLList(type.getWeakInputType()),
getWeakOutputType: () => new GraphQLList(type.getWeakOutputType()),
nullable: () => nullableListType,
};
const listType: StrongInputOutputType<Array<TValue>> = {
_strongType: true,
_strongInputType: true,
_strongOutputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLNonNull(new GraphQLList(type.getWeakType())),
getWeakInputType: () => new GraphQLNonNull(new GraphQLList(type.getWeakInputType())),
getWeakOutputType: () => new GraphQLNonNull(new GraphQLList(type.getWeakOutputType())),
nullable: () => nullableListType,
};
return listType;
export function createListType<TValue>(type: any): any { // NB: Only the overload types are considered by the compiler
if (type._strongInputType && type._strongOutputType) {
const nullableListType: StrongInputOutputType<Array<TValue> | null | undefined> = {
_strongType: true,
_strongInputType: true,
_strongOutputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLList(type.getWeakType()),
getWeakInputType: () => new GraphQLList(type.getWeakInputType()),
getWeakOutputType: () => new GraphQLList(type.getWeakOutputType()),
nullable: () => nullableListType,
};

const listType: StrongInputOutputType<Array<TValue>> = {
_strongType: true,
_strongInputType: true,
_strongOutputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLNonNull(new GraphQLList(type.getWeakType())),
getWeakInputType: () => new GraphQLNonNull(new GraphQLList(type.getWeakInputType())),
getWeakOutputType: () => new GraphQLNonNull(new GraphQLList(type.getWeakOutputType())),
nullable: () => nullableListType,
};

return listType;
} else if (type._strongInputType) {
const nullableListType: StrongInputType<Array<TValue> | null | undefined> = {
_strongType: true,
_strongInputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLList(type.getWeakType()),
getWeakInputType: () => new GraphQLList(type.getWeakInputType()),
nullable: () => nullableListType,
};

const listType: StrongInputType<Array<TValue>> = {
_strongType: true,
_strongInputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLNonNull(new GraphQLList(type.getWeakType())),
getWeakInputType: () => new GraphQLNonNull(new GraphQLList(type.getWeakInputType())),
nullable: () => nullableListType,
};

return listType;
} else if (type._strongOutputType) {
const nullableListType: StrongOutputType<Array<TValue> | null | undefined> = {
_strongType: true,
_strongOutputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLList(type.getWeakType()),
getWeakOutputType: () => new GraphQLList(type.getWeakOutputType()),
nullable: () => nullableListType,
};

const listType: StrongOutputType<Array<TValue>> = {
_strongType: true,
_strongOutputType: true,
_strongValue: undefined as any,
getWeakType: () => new GraphQLNonNull(new GraphQLList(type.getWeakType())),
getWeakOutputType: () => new GraphQLNonNull(new GraphQLList(type.getWeakOutputType())),
nullable: () => nullableListType,
};

return listType;
}
}
15 changes: 8 additions & 7 deletions src/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function createObjectType<TValue, TContext>(config: StrongObjectTypeConfi
export type StrongObjectTypeConfig<TValue, TContext> = {
readonly name: string,
readonly description?: string | undefined,
readonly isTypeOf?: (value: TValue | any, context: TContext) => boolean;
};

/**
Expand Down Expand Up @@ -102,8 +103,8 @@ implements StrongOutputType<TValue> {
* The field created will have a nullable type. To get a non-null field type
* use `fieldNonNull`.
*/
public field<TFieldValue>(config: StrongFieldConfigWithoutArgs<TValue, TContext, TFieldValue | null | undefined>): StrongObjectType<TValue, TContext>
public field<TFieldValue, TArgs>(config: StrongFieldConfigWithArgs<TValue, TArgs, TContext, TFieldValue | null | undefined>): StrongObjectType<TValue, TContext>
public field<TFieldValue>(config: StrongFieldConfigWithoutArgs<TValue, TContext, TFieldValue | null | undefined>): StrongObjectType<TValue, TContext>;
public field<TFieldValue, TArgs>(config: StrongFieldConfigWithArgs<TValue, TArgs, TContext, TFieldValue | null | undefined>): StrongObjectType<TValue, TContext>;
public field<TFieldValue, TArgs>(config: StrongFieldConfig<TValue, TArgs, TContext, TFieldValue | null | undefined>): StrongObjectType<TValue, TContext> {
return new StrongObjectType(this.ofType._field(config));
}
Expand All @@ -112,8 +113,8 @@ implements StrongOutputType<TValue> {
* Returns a new strong GraphQL object type with a new field. This function
* does not mutate the type it was called on.
*/
public fieldNonNull<TFieldValue>(config: StrongFieldConfigWithoutArgs<TValue, TContext, TFieldValue>): StrongObjectType<TValue, TContext>
public fieldNonNull<TFieldValue, TArgs>(config: StrongFieldConfigWithArgs<TValue, TArgs, TContext, TFieldValue>): StrongObjectType<TValue, TContext>
public fieldNonNull<TFieldValue>(config: StrongFieldConfigWithoutArgs<TValue, TContext, TFieldValue>): StrongObjectType<TValue, TContext>;
public fieldNonNull<TFieldValue, TArgs>(config: StrongFieldConfigWithArgs<TValue, TArgs, TContext, TFieldValue>): StrongObjectType<TValue, TContext>;
public fieldNonNull<TFieldValue, TArgs>(config: StrongFieldConfig<TValue, TArgs, TContext, TFieldValue>): StrongObjectType<TValue, TContext> {
return new StrongObjectType(this.ofType._fieldNonNull(config));
}
Expand Down Expand Up @@ -180,12 +181,12 @@ implements StrongOutputType<TValue | null | undefined> {

private readonly _strongConfig: StrongObjectTypeConfig<TValue, TContext>;
private readonly _strongInterfaces: Array<StrongInterfaceType<TValue, {}>>;
private readonly _strongFieldConfigs: Array<StrongFieldConfig<TValue, {}, TContext, any>>;
private readonly _strongFieldConfigs: Array<StrongFieldConfig<TValue, any, TContext, any>>;

constructor(
config: StrongObjectTypeConfig<TValue, TContext>,
interfaces: Array<StrongInterfaceType<TValue, {}>>,
fieldConfigs: Array<StrongFieldConfig<TValue, {}, TContext, any>>,
fieldConfigs: Array<StrongFieldConfig<TValue, any, TContext, any>>,
) {
super({
name: config.name,
Expand Down Expand Up @@ -294,7 +295,7 @@ implements StrongOutputType<TValue | null | undefined> {
const fieldConfigMap = interfaceType._getFieldConfigMap();
// Create all of the object fields from our interface fields and the
// implementation argument.
const fieldConfigs = Object.keys(fieldConfigMap).map<StrongFieldConfig<TValue, {}, TContext, {}>>(fieldName => {
const fieldConfigs = Object.keys(fieldConfigMap).map<StrongFieldConfig<TValue, any, TContext, {}>>(fieldName => {
// Make sure that this interface field name has not already been taken.
this._assertUniqueFieldName(fieldName);
// Get what we will need to create this field.
Expand Down
2 changes: 1 addition & 1 deletion src/scalar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ implements StrongInputOutputType<TInternalValue> {
}

/**
* The nullable sstrong GraphQL scalar type object.
* The nullable strong GraphQL scalar type object.
*/
class StrongNullableScalarType<TInternalValue, TExternalValue>
extends GraphQLScalarType
Expand Down
2 changes: 1 addition & 1 deletion src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ extends GraphQLSchema {
].filter(Boolean);

rootTypes.forEach(rootType => {
const fields = rootType.getFields();
const fields = rootType!.getFields();

for (const fieldName of Object.keys(fields)) {
const resolver = fields[fieldName].resolve || defaultFieldResolver;
Expand Down
15 changes: 9 additions & 6 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
{
"compilerOptions": {
"outDir": "build",
"rootDir": "src",
"target": "es6",
"module": "commonjs",
"allowSyntheticDefaultImports": true,
"alwaysStrict": true,
"newLine": "LF",
"declaration": true,
"forceConsistentCasingInFileNames": true,
"lib": ["es6", "dom", "esnext"],
"module": "commonjs",
"newLine": "LF",
"noFallthroughCasesInSwitch": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"strictNullChecks": true
"outDir": "build",
"rootDir": "src",
"strict": true,
"strictNullChecks": true,
"target": "es6",
},
"exclude": [
"node_modules",
Expand Down
3 changes: 1 addition & 2 deletions tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@
"no-shadowed-variable": true,
"no-unsafe-finally": true,
"no-unused-expression": true,
"no-unused-new": true,
"no-use-before-declare": true,
"no-use-before-declare": false,
"no-var-keyword": true,
"radix": true,
"restrict-plus-operands": false,
Expand Down
Loading