Skip to content

Commit

Permalink
refactor: all TypeComposers for creation now required a second argume…
Browse files Browse the repository at this point in the history
…nt -`schemaComposer`

This helps to simplify code base. Also this is preparation for a new package `graphql-compose-decorator`

BREAKING CHANGE: you cannot import `TypeComposer` and other composers from module. Please use `schemaCompose.createOutputTC()`
  • Loading branch information
nodkz committed Mar 15, 2019
1 parent bc86210 commit aae6d1b
Show file tree
Hide file tree
Showing 38 changed files with 1,449 additions and 1,286 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Expand Up @@ -48,6 +48,7 @@
"$Shape": true,
"$FlowFixMe": true,
"$ReadOnlyArray": true,
"$Keys": true
"$Keys": true,
"$ReadOnly": true
}
}
8 changes: 8 additions & 0 deletions jest.config.js
@@ -0,0 +1,8 @@
module.exports = {
// moduleNameMapper: {
// '^app(.*)$': '<rootDir>/src$1',
// },
moduleFileExtensions: ['js'],
testMatch: ['**/__tests__/**/*-test.(ts|js)'],
roots: ['<rootDir>/src'],
};
5 changes: 0 additions & 5 deletions package.json
Expand Up @@ -69,11 +69,6 @@
"path": "./node_modules/cz-conventional-changelog"
}
},
"jest": {
"roots": [
"<rootDir>/src"
]
},
"scripts": {
"build": "npm run build-cjs && npm run build-mjs && npm run build-esm",
"build-cjs": "rimraf lib && BABEL_ENV=cjs babel src --ignore __tests__,__mocks__ -d lib && COPY_TO_FOLDER=lib npm run build-flow && COPY_TO_FOLDER=lib npm run build-ts",
Expand Down
65 changes: 37 additions & 28 deletions src/EnumTypeComposer.js
Expand Up @@ -12,80 +12,88 @@ import type {
import { defineEnumValues, defineEnumValuesToConfig } from './utils/configToDefine';
import { graphqlVersion } from './utils/graphqlVersion';
import type { TypeAsString } from './TypeMapper';
import type { SchemaComposer } from './SchemaComposer';
import { SchemaComposer } from './SchemaComposer';
import type { Extensions } from './utils/definitions';

export type ComposeEnumTypeConfig = GraphQLEnumTypeConfig & {
+extensions?: Extensions,
};

export type EnumTypeComposerDefinition = TypeAsString | ComposeEnumTypeConfig | GraphQLEnumType;
export type EnumTypeComposerDefinition =
| TypeAsString
| $ReadOnly<ComposeEnumTypeConfig>
| $ReadOnly<GraphQLEnumType>;

export type GraphQLEnumTypeExtended = GraphQLEnumType & {
_gqcExtensions?: Extensions,
};

export class EnumTypeComposer {
gqType: GraphQLEnumTypeExtended;
sc: SchemaComposer<any>;

static schemaComposer: SchemaComposer<any>;

get schemaComposer(): SchemaComposer<any> {
return this.constructor.schemaComposer;
}

static create(typeDef: EnumTypeComposerDefinition): EnumTypeComposer {
const etc = this.createTemp(typeDef);
this.schemaComposer.add(etc);
static create(typeDef: EnumTypeComposerDefinition, sc: SchemaComposer<any>): EnumTypeComposer {
if (!(sc instanceof SchemaComposer)) {
throw new Error(
'You must provide SchemaComposer instance as a second argument for `EnumTypeComposer.create(typeDef, schemaComposer)`'
);
}
const etc = this.createTemp(typeDef, sc);
if (sc) sc.add(etc);
return etc;
}

static createTemp(typeDef: EnumTypeComposerDefinition): EnumTypeComposer {
if (!this.schemaComposer) {
throw new Error('Class<EnumTypeComposer> must be created by a SchemaComposer.');
}
static createTemp(
typeDef: EnumTypeComposerDefinition,
_sc?: SchemaComposer<any>
): EnumTypeComposer {
const sc = _sc || new SchemaComposer();

let ETC;

if (isString(typeDef)) {
const typeName: string = typeDef;
const NAME_RX = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
if (NAME_RX.test(typeName)) {
ETC = new this.schemaComposer.EnumTypeComposer(
ETC = new EnumTypeComposer(
new GraphQLEnumType({
name: typeName,
values: graphqlVersion < 13 ? { _OldGraphqlStubValue_: {} } : {},
})
}),
sc
);
} else {
const type = this.schemaComposer.typeMapper.createType(typeName);
const type = sc.typeMapper.createType(typeName);
if (!(type instanceof GraphQLEnumType)) {
throw new Error(
'You should provide correct GraphQLEnumType type definition.' +
'Eg. `enum MyType { KEY1 KEY2 KEY3 }`'
);
}
ETC = new this.schemaComposer.EnumTypeComposer(type);
ETC = new EnumTypeComposer(type, sc);
}
} else if (typeDef instanceof GraphQLEnumType) {
ETC = new this.schemaComposer.EnumTypeComposer(typeDef);
ETC = new EnumTypeComposer(typeDef, sc);
} else if (isObject(typeDef)) {
const type = new GraphQLEnumType({
...(typeDef: any),
});
ETC = new this.schemaComposer.EnumTypeComposer(type);
ETC.gqType._gqcExtensions = typeDef.extensions || {};
ETC = new EnumTypeComposer(type, sc);
ETC.gqType._gqcExtensions = (typeDef: any).extensions || {};
} else {
throw new Error('You should provide GraphQLEnumTypeConfig or string with enum name or SDL');
}

return ETC;
}

constructor(gqType: GraphQLEnumType) {
if (!this.schemaComposer) {
throw new Error('Class<EnumTypeComposer> can only be created by a SchemaComposer.');
constructor(gqType: GraphQLEnumType, sc: SchemaComposer<any>) {
if (!(sc instanceof SchemaComposer)) {
throw new Error(
'You must provide SchemaComposer instance as a second argument for `new EnumTypeComposer(GraphQLEnumType, SchemaComposer)`'
);
}
this.sc = sc;

if (!(gqType instanceof GraphQLEnumType)) {
throw new Error('EnumTypeComposer accept only GraphQLEnumType in constructor');
Expand Down Expand Up @@ -345,7 +353,7 @@ export class EnumTypeComposer {

setTypeName(name: string): EnumTypeComposer {
this.gqType.name = name;
this.schemaComposer.add(this);
this.sc.add(this);
return this;
}

Expand All @@ -370,11 +378,12 @@ export class EnumTypeComposer {
delete newValues[fieldName].isDeprecated;
});

const cloned = new this.schemaComposer.EnumTypeComposer(
const cloned = new EnumTypeComposer(
new GraphQLEnumType({
name: newTypeName,
values: newValues,
})
}),
this.sc
);

cloned.setDescription(this.getDescription());
Expand Down
73 changes: 40 additions & 33 deletions src/InputTypeComposer.js
Expand Up @@ -17,7 +17,7 @@ import type { Thunk, ObjMap, Extensions } from './utils/definitions';
import { ScalarTypeComposer } from './ScalarTypeComposer';
import { EnumTypeComposer } from './EnumTypeComposer';
import type { TypeAsString } from './TypeMapper';
import type { SchemaComposer } from './SchemaComposer';
import { SchemaComposer } from './SchemaComposer';
import type {
GraphQLInputFieldConfig,
GraphQLInputFieldConfigMap,
Expand Down Expand Up @@ -80,58 +80,60 @@ export type InputTypeComposerDefinition =

export class InputTypeComposer {
gqType: GraphQLInputObjectTypeExtended;
sc: SchemaComposer<any>;

static schemaComposer: SchemaComposer<any>;

get schemaComposer(): SchemaComposer<any> {
return this.constructor.schemaComposer;
}

static create(typeDef: InputTypeComposerDefinition): InputTypeComposer {
const itc = this.createTemp(typeDef);
this.schemaComposer.add(itc);
static create(typeDef: InputTypeComposerDefinition, sc: SchemaComposer<any>): InputTypeComposer {
if (!(sc instanceof SchemaComposer)) {
throw new Error(
'You must provide SchemaComposer instance as a second argument for `InputTypeComposer.create(typeDef, schemaComposer)`'
);
}
const itc = this.createTemp(typeDef, sc);
sc.add(itc);
return itc;
}

static createTemp(typeDef: InputTypeComposerDefinition): InputTypeComposer {
if (!this.schemaComposer) {
throw new Error('Class<InputTypeComposer> must be created by a SchemaComposer.');
}
static createTemp(
typeDef: InputTypeComposerDefinition,
_sc?: SchemaComposer<any>
): InputTypeComposer {
const sc = _sc || new SchemaComposer();

let ITC;

if (isString(typeDef)) {
const typeName: string = typeDef;
const NAME_RX = /^[_a-zA-Z][_a-zA-Z0-9]*$/;
if (NAME_RX.test(typeName)) {
ITC = new this.schemaComposer.InputTypeComposer(
ITC = new InputTypeComposer(
new GraphQLInputObjectType({
name: typeName,
fields: () => ({}),
})
}),
sc
);
} else {
const type = this.schemaComposer.typeMapper.createType(typeName);
const type = sc.typeMapper.createType(typeName);
if (!(type instanceof GraphQLInputObjectType)) {
throw new Error(
'You should provide correct GraphQLInputObjectType type definition.' +
'Eg. `input MyInputType { name: String! }`'
);
}
ITC = new this.schemaComposer.InputTypeComposer(type);
ITC = new InputTypeComposer(type, sc);
}
} else if (typeDef instanceof GraphQLInputObjectType) {
ITC = new this.schemaComposer.InputTypeComposer(typeDef);
ITC = new InputTypeComposer(typeDef, sc);
} else if (isObject(typeDef)) {
const fields = typeDef.fields;
const type = new GraphQLInputObjectType({
name: typeDef.name,
description: typeDef.description,
fields: isFunction(fields)
? () => resolveInputConfigMapAsThunk(this.schemaComposer, (fields(): any), typeDef.name)
? () => resolveInputConfigMapAsThunk(sc, (fields(): any), typeDef.name)
: () => ({}),
});
ITC = new this.schemaComposer.InputTypeComposer(type);
ITC = new InputTypeComposer(type, sc);
if (isObject(typeDef.fields)) ITC.addFields(typeDef.fields);
ITC.gqType._gqcExtensions = typeDef.extensions || {};
} else {
Expand All @@ -143,10 +145,13 @@ export class InputTypeComposer {
return ITC;
}

constructor(gqType: GraphQLInputObjectType) {
if (!this.schemaComposer) {
throw new Error('Class<InputTypeComposer> can only be created by a SchemaComposer.');
constructor(gqType: GraphQLInputObjectType, sc: SchemaComposer<any>) {
if (!(sc instanceof SchemaComposer)) {
throw new Error(
'You must provide SchemaComposer instance as a second argument for `new InputTypeComposer(GraphQLInputType, SchemaComposer)`'
);
}
this.sc = sc;

if (!(gqType instanceof GraphQLInputObjectType)) {
throw new Error('InputTypeComposer accept only GraphQLInputObjectType in constructor');
Expand Down Expand Up @@ -191,12 +196,12 @@ export class InputTypeComposer {
this.gqType._fields = () => {
return defineInputFieldMap(
this.gqType,
resolveInputConfigMapAsThunk(this.schemaComposer, fields, this.getTypeName())
resolveInputConfigMapAsThunk(this.sc, fields, this.getTypeName())
);
};
} else {
(this.gqType: any)._typeConfig.fields = () => {
return resolveInputConfigMapAsThunk(this.schemaComposer, fields, this.getTypeName());
return resolveInputConfigMapAsThunk(this.sc, fields, this.getTypeName());
};
delete this.gqType._fields; // if schema was builded, delete defineFieldMap
}
Expand Down Expand Up @@ -232,8 +237,9 @@ export class InputTypeComposer {
// nested field
let childTC;
if (!this.hasField(name)) {
childTC = this.schemaComposer.InputTypeComposer.createTemp(
`${this.getTypeName()}${upperFirst(name)}`
childTC = InputTypeComposer.createTemp(
`${this.getTypeName()}${upperFirst(name)}`,
this.sc
);
this.setField(name, childTC);
} else {
Expand Down Expand Up @@ -329,7 +335,7 @@ export class InputTypeComposer {
throw new Error(`Type ${this.getTypeName()} does not have field with name '${fieldName}'`);
}

return resolveInputConfigAsThunk(this.schemaComposer, fc, fieldName, this.getTypeName());
return resolveInputConfigAsThunk(this.sc, fc, fieldName, this.getTypeName());
}

getFieldType(fieldName: string): GraphQLInputType {
Expand All @@ -344,7 +350,7 @@ export class InputTypeComposer {
`This field should be InputObjectType, but it has type '${fieldType.constructor.name}'`
);
}
return this.schemaComposer.InputTypeComposer.createTemp(fieldType);
return InputTypeComposer.createTemp(fieldType, this.sc);
}

makeFieldNonNull(fieldNameOrArray: string | Array<string>): InputTypeComposer {
Expand Down Expand Up @@ -404,7 +410,7 @@ export class InputTypeComposer {

setTypeName(name: string): InputTypeComposer {
this.gqType.name = name;
this.schemaComposer.add(this);
this.sc.add(this);
return this;
}

Expand All @@ -428,11 +434,12 @@ export class InputTypeComposer {
newFields[fieldName] = { ...(fc: any) };
});

return new this.schemaComposer.InputTypeComposer(
return new InputTypeComposer(
new GraphQLInputObjectType({
name: newTypeName,
fields: newFields,
})
}),
this.sc
);
}

Expand Down

0 comments on commit aae6d1b

Please sign in to comment.