Skip to content

Commit

Permalink
Merge branch 'master' into gql-import
Browse files Browse the repository at this point in the history
  • Loading branch information
FredyC authored Feb 24, 2019
2 parents c2ebcb9 + 0f480fb commit dd93c7c
Show file tree
Hide file tree
Showing 23 changed files with 267 additions and 113 deletions.
19 changes: 1 addition & 18 deletions docs/plugins/typescript-react-apollo.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,4 @@ Or if you are using `noNamespaces` option:

#### `withSubscriptionHooks` (default value: `false`)

This will cause the codegen to add React **Hooks** even for _Subscriptions_. Since they are not included in the `react-apollo-hooks` package, the option
is separated.

In order to use this flag, you should add a `importUseSubscriptionFrom` option specifying the path (relative to generated file) where the `useSubscription` function and the `SubscriptionHookOptions<T, TVariables>` type may be found.

For example if you have defined `useSubscription` in the `react-apollo-subscriptions.tsx` file, you can use:

```yaml
withHooks: true
withSubscriptionHooks: true
importUseSubscriptionFrom: './react-apollo-subscriptions'
```
> This feature is experimental. You can find an actual implementation [here](https://github.com/Urigo/WhatsApp-Clone-Client-React/blob/master/src/polyfills/react-apollo-hooks.ts) or from [this issue](https://github.com/trojanowski/react-apollo-hooks/pull/37) on `react-apollo-hooks`.

#### `importUseSubscriptionFrom`

See `withSubscriptionHooks`.
This will cause the codegen to add React **Hooks** even for _Subscriptions_.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
"@types/glob": "7.1.1",
"@types/jest": "24.0.6",
"@types/mkdirp": "0.5.2",
"@types/node": "10.12.26",
"@types/node": "10.12.27",
"@types/request": "2.48.1",
"@types/common-tags": "1.8.0",
"@types/graphql": "14.0.7",
"husky": "1.3.1",
"lint-staged": "8.1.4",
"tslint": "5.12.1",
"tslint": "5.13.0",
"typescript": "3.3.3",
"graphql": "14.1.1",
"graphql-tag": "2.10.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function resolveArguments(schema: GraphQLSchema, args: GraphQLArgument[])
const namedType = getNamedType(arg.type);
const indicators = resolveTypeIndicators(namedType);
const directives = getDirectives(schema, arg);
const hasDefaultValue = !!arg.defaultValue;
const hasDefaultValue = arg.defaultValue != null;

debugLog(`[resolveArguments] resolving argument ${arg.name} of type ${type.name}...`);

Expand Down
24 changes: 24 additions & 0 deletions packages/graphql-codegen-core/tests/transform-arguments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,28 @@ describe('resolveArguments', () => {
expect(result[0].isArray).toBeFalsy();
expect(result[0].isRequired).toBeFalsy();
});

it('should resolve correctly when using arguments with default values', () => {
const parsed = parseAndBuildSchema<GraphQLObjectType>(
`
type A {
f1(offset: Int = 0, limit: Int = 50): String
}
`,
'A'
);

const args = parsed.getFields()['f1'].args;
const result = resolveArguments({} as any, args);

expect(result.length).toBe(2);

expect(result[0].name).toBe('offset');
expect(result[0].type).toBe('Int');
expect(result[0].hasDefaultValue).toBe(true);

expect(result[1].name).toBe('limit');
expect(result[1].type).toBe('Int');
expect(result[1].hasDefaultValue).toBe(true);
});
});
2 changes: 2 additions & 0 deletions packages/plugins/flow-documents/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export interface FlowDocumentsPluginConfig {
skipTypename?: boolean;
namingConvention?: string;
typesPrefix?: string;
useFlowExactObjects?: boolean;
useFlowReadOnlyTypes?: boolean;
}

export type ScalarsMap = { [name: string]: string };
Expand Down
26 changes: 17 additions & 9 deletions packages/plugins/flow-documents/src/selection-set-to-object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ export class SelectionSetToObject {
}

const { selections } = this._selectionSet;
const useFlowExactObject: boolean = this._visitorInstance.parsedConfig.useFlowExactObjects;
const useFlowReadOnlyTypes: boolean = this._visitorInstance.parsedConfig.useFlowReadOnlyTypes;

for (const selection of selections) {
switch (selection.kind) {
Expand All @@ -124,22 +126,28 @@ export class SelectionSetToObject {

const typeName = this._visitorInstance.addTypename || this._queriedForTypename ? this._buildTypeNameField() : null;
const baseFields = this._primitiveFields.length
? `$Pick<${this._visitorInstance.convertName(this._parentSchemaType.name)}, { ${this._primitiveFields
.map(fieldName => `${fieldName}: *`)
.join(', ')} }>`
? `$Pick<${this._visitorInstance.convertName(this._parentSchemaType.name)}, {${
useFlowExactObject ? '|' : ''
} ${this._primitiveFields.map(fieldName => `${useFlowReadOnlyTypes ? '+' : ''}${fieldName}: *`).join(', ')} ${
useFlowExactObject ? '|' : ''
}}>`
: null;
const linksFields = this._linksFields.length
? `{ ${this._linksFields.map(field => `${field.alias || field.name}: ${field.selectionSet}`).join(', ')} }`
? `{${useFlowExactObject ? '|' : ''} ${this._linksFields
.map(field => `${useFlowReadOnlyTypes ? '+' : ''}${field.alias || field.name}: ${field.selectionSet}`)
.join(', ')} ${useFlowExactObject ? '|' : ''}}`
: null;
const aliasBaseFields = this._primitiveAliasedFields.length
? `{ ${this._primitiveAliasedFields
? `{${useFlowExactObject ? '|' : ''} ${this._primitiveAliasedFields
.map(
aliasedField =>
`${aliasedField.alias}: $ElementType<${this._visitorInstance.convertName(
this._parentSchemaType.name
)}, '${aliasedField.fieldName}'>`
`${useFlowReadOnlyTypes ? '+' : ''}${
aliasedField.alias
}: $ElementType<${this._visitorInstance.convertName(this._parentSchemaType.name)}, '${
aliasedField.fieldName
}'>`
)
.join(', ')} }`
.join(', ')} ${useFlowExactObject ? '|' : ''}}`
: null;
const inlineFragments = this.inlineFragmentsString;
const fragmentSpreads = quoteIfNeeded(
Expand Down
16 changes: 12 additions & 4 deletions packages/plugins/flow-documents/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export interface ParsedDocumentsConfig {
addTypename: boolean;
convert: (str: string) => string;
typesPrefix: string;
useFlowExactObjects: boolean;
useFlowReadOnlyTypes: boolean;
}

export class FlowDocumentsVisitor implements BasicFlowVisitor {
Expand All @@ -28,7 +30,9 @@ export class FlowDocumentsVisitor implements BasicFlowVisitor {
addTypename: !pluginConfig.skipTypename,
scalars: { ...DEFAULT_SCALARS, ...(pluginConfig.scalars || {}) },
convert: pluginConfig.namingConvention ? resolveExternalModuleAndFn(pluginConfig.namingConvention) : toPascalCase,
typesPrefix: pluginConfig.typesPrefix || ''
typesPrefix: pluginConfig.typesPrefix || '',
useFlowExactObjects: pluginConfig.useFlowExactObjects || false,
useFlowReadOnlyTypes: pluginConfig.useFlowReadOnlyTypes || false
};
}

Expand All @@ -40,6 +44,10 @@ export class FlowDocumentsVisitor implements BasicFlowVisitor {
return this.convertName(nodeName + 'Fragment');
}

public get parsedConfig(): ParsedDocumentsConfig {
return this._parsedConfig;
}

public get schema(): GraphQLSchema {
return this._schema;
}
Expand All @@ -64,7 +72,7 @@ export class FlowDocumentsVisitor implements BasicFlowVisitor {
const fragmentRootType = this._schema.getType(node.typeCondition.name.value) as GraphQLObjectType;
const selectionSet = new SelectionSetToObject(this, fragmentRootType, node.selectionSet);

return new DeclarationBlock()
return new DeclarationBlock(this._parsedConfig)
.export()
.asKind('type')
.withName(this.getFragmentName(node.name.value))
Expand All @@ -80,15 +88,15 @@ export class FlowDocumentsVisitor implements BasicFlowVisitor {
node.variableDefinitions
);

const operationResult = new DeclarationBlock()
const operationResult = new DeclarationBlock(this._parsedConfig)
.export()
.asKind('type')
.withName(this.convertName(name + pascalCase(node.operation)))
.withContent(selectionSet.string).string;

const operationVariables = !visitedOperationVariables
? null
: new DeclarationBlock()
: new DeclarationBlock(this._parsedConfig)
.export()
.asKind('type')
.withName(this.convertName(name + pascalCase(node.operation) + 'Variables'))
Expand Down
56 changes: 56 additions & 0 deletions packages/plugins/flow-documents/tests/flow-documents.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -660,4 +660,60 @@ describe('Flow Documents Plugin', () => {
validateFlow(result.definitions[0]);
});
});

describe('Output options', () => {
it('Should respect flow option useFlowExactObjects', () => {
const ast = parse(`
query currentUser {
me {
id
username
role
profile {
age
}
}
}
`);
const result = visit(ast, {
leave: new FlowDocumentsVisitor(schema, {
skipTypename: true,
useFlowExactObjects: true
})
});

expect(result.definitions[0]).toBeSimilarStringTo(
`export type CurrentUserQuery = {| me: ?($Pick<User, {| id: *, username: *, role: * |}> & {| profile: ?$Pick<Profile, {| age: * |}> |}) |};`
);

validateFlow(result.definitions[0]);
});

it('Should respect flow option useFlowReadOnlyTypes', () => {
const ast = parse(`
query currentUser {
me {
id
username
role
profile {
age
}
}
}
`);
const result = visit(ast, {
leave: new FlowDocumentsVisitor(schema, {
skipTypename: true,
useFlowReadOnlyTypes: true
})
});

expect(result.definitions[0]).toBeSimilarStringTo(
`export type CurrentUserQuery = { +me: ?($Pick<User, { +id: *, +username: *, +role: * }> & { +profile: ?$Pick<Profile, { +age: * }> }) };`
);

validateFlow(result.definitions[0]);
});
});
});
2 changes: 2 additions & 0 deletions packages/plugins/flow-resolvers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export interface FlowResolversPluginConfig {
scalars?: ScalarsMap;
namingConvention?: string;
typesPrefix?: string;
useFlowExactObjects?: boolean;
useFlowReadOnlyTypes?: boolean;
}

export const plugin: PluginFunction<FlowResolversPluginConfig> = (
Expand Down
20 changes: 12 additions & 8 deletions packages/plugins/flow-resolvers/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@ import {
InputValueDefinitionNode
} from 'graphql/language/ast';
import { FlowResolversPluginConfig } from './index';
import { GraphQLSchema, GraphQLObjectType } from 'graphql';
import { GraphQLSchema, GraphQLObjectType, isOutputType } from 'graphql';

export interface ParsedConfig {
scalars: ScalarsMap;
convert: (str: string) => string;
typesPrefix: string;
contextType: string;
mapping: { [typeName: string]: string };
useFlowExactObjects: boolean;
useFlowReadOnlyTypes: boolean;
}

export class FlowResolversVisitor implements BasicFlowVisitor {
Expand All @@ -44,7 +46,9 @@ export class FlowResolversVisitor implements BasicFlowVisitor {
mapping: pluginConfig.mapping || {},
scalars: { ...DEFAULT_SCALARS, ...(pluginConfig.scalars || {}) },
convert: pluginConfig.namingConvention ? resolveExternalModuleAndFn(pluginConfig.namingConvention) : toPascalCase,
typesPrefix: pluginConfig.typesPrefix || ''
typesPrefix: pluginConfig.typesPrefix || '',
useFlowExactObjects: pluginConfig.useFlowExactObjects || false,
useFlowReadOnlyTypes: pluginConfig.useFlowReadOnlyTypes || false
};
}

Expand All @@ -57,7 +61,7 @@ export class FlowResolversVisitor implements BasicFlowVisitor {
}

public get rootResolver(): string {
return new DeclarationBlock()
return new DeclarationBlock(this._parsedConfig)
.export()
.asKind('interface')
.withName(this.convertName('ResolversRoot'))
Expand Down Expand Up @@ -125,7 +129,7 @@ export class FlowResolversVisitor implements BasicFlowVisitor {
this._parsedConfig.mapping[node.name as any] ||
this._parsedConfig.scalars[node.name as any] ||
this.convertName(node.name);
const block = new DeclarationBlock()
const block = new DeclarationBlock(this._parsedConfig)
.export()
.asKind('interface')
.withName(name, `<Context = ${this._parsedConfig.contextType}, ParentType = ${type}>`)
Expand All @@ -145,7 +149,7 @@ export class FlowResolversVisitor implements BasicFlowVisitor {

this._collectedResolvers[node.name as any] = name;

return new DeclarationBlock()
return new DeclarationBlock(this._parsedConfig)
.export()
.asKind('interface')
.withName(name, `<Context = ${this._parsedConfig.contextType}, ParentType = ${node.name}>`)
Expand All @@ -155,7 +159,7 @@ export class FlowResolversVisitor implements BasicFlowVisitor {
ScalarTypeDefinition = (node: ScalarTypeDefinitionNode): string => {
const baseName = this.convertName(node.name);

return new DeclarationBlock()
return new DeclarationBlock(this._parsedConfig)
.export()
.asKind('interface')
.withName(this.convertName(node.name + 'ScalarConfig'), ` extends GraphQLScalarTypeConfig<${baseName}, any>`)
Expand All @@ -169,7 +173,7 @@ export class FlowResolversVisitor implements BasicFlowVisitor {
? new OperationVariablesToObject<FlowResolversVisitor, InputValueDefinitionNode>(this, node.arguments).string
: '';

return new DeclarationBlock()
return new DeclarationBlock(this._parsedConfig)
.export()
.asKind('type')
.withName(directiveName, '<Result>')
Expand All @@ -192,7 +196,7 @@ export class FlowResolversVisitor implements BasicFlowVisitor {
}
}

return new DeclarationBlock()
return new DeclarationBlock(this._parsedConfig)
.export()
.asKind('interface')
.withName(name, `<Context = ${this._parsedConfig.contextType}, ParentType = ${node.name}>`)
Expand Down
2 changes: 2 additions & 0 deletions packages/plugins/flow/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface FlowPluginConfig {
enumValues?: EnumValuesMap;
namingConvention?: string;
typesPrefix?: string;
useFlowExactObjects?: boolean;
useFlowReadOnlyTypes?: boolean;
}

export const plugin: PluginFunction<FlowPluginConfig> = (
Expand Down
Loading

0 comments on commit dd93c7c

Please sign in to comment.