Skip to content

Commit

Permalink
Use ac3 as default for fragment matcher plugin, and a few more AC3 fi…
Browse files Browse the repository at this point in the history
…xes (#4979)

* use ac3 as default for fragment matcher plugin

* fixes for apollo-client helpers plugin
updated docs and config schema
updated examples
  • Loading branch information
dotansimha authored Oct 26, 2020
1 parent 13f8a5b commit 5e792ff
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/afraid-cooks-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-codegen/typescript-apollo-client-helpers': minor
---

Added `requireKeyFields` and `requirePoliciesForAllTypes` to allow more flexibility with the output
11 changes: 11 additions & 0 deletions .changeset/shaggy-bobcats-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@graphql-codegen/fragment-matcher': major
---

**BREAKING CHANGE:** Change the default Apollo-Client version to be "3".

If you are upgrading from v1 of this plugin, and you are using apollo-client v2, please make sure to add to your config:

```yaml
apolloClientVersion: 2
```
4 changes: 2 additions & 2 deletions packages/plugins/other/fragment-matcher/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export interface FragmentMatcherConfig {
module?: 'commonjs' | 'es2015';
/**
* @description Compatible only with TS/TSX/JS/JSX extensions, allow you to generate output based on your Apollo-Client version. Valid values are: `2`, `3`.
* @default 2
* @default 3
*
* @exampleMarkdown
* ```yml
Expand Down Expand Up @@ -100,7 +100,7 @@ export const plugin: PluginFunction = async (
const config: Required<FragmentMatcherConfig> = {
module: 'es2015',
federation: false,
apolloClientVersion: 2,
apolloClientVersion: 3,
useExplicitTyping: false,
...pluginConfig,
};
Expand Down
26 changes: 21 additions & 5 deletions packages/plugins/other/fragment-matcher/tests/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ describe('Fragment Matcher Plugin', () => {
const content = await plugin(
schema,
[],
{},
{
apolloClientVersion: 2,
},
{
outputFile: 'foo.json',
}
Expand All @@ -118,15 +120,19 @@ describe('Fragment Matcher Plugin', () => {
const jsContent = await plugin(
schema,
[],
{},
{
apolloClientVersion: 2,
},
{
outputFile: 'foo.js',
}
);
const jsxContent = await plugin(
schema,
[],
{},
{
apolloClientVersion: 2,
},
{
outputFile: 'foo.jsx',
}
Expand All @@ -144,6 +150,7 @@ describe('Fragment Matcher Plugin', () => {
schema,
[],
{
apolloClientVersion: 2,
module: 'commonjs',
},
{
Expand All @@ -154,6 +161,7 @@ describe('Fragment Matcher Plugin', () => {
schema,
[],
{
apolloClientVersion: 2,
module: 'commonjs',
},
{
Expand All @@ -174,15 +182,19 @@ describe('Fragment Matcher Plugin', () => {
const tsContent = await plugin(
schema,
[],
{},
{
apolloClientVersion: 2,
},
{
outputFile: 'foo.ts',
}
);
const tsxContent = await plugin(
schema,
[],
{},
{
apolloClientVersion: 2,
},
{
outputFile: 'foo.tsx',
}
Expand Down Expand Up @@ -278,6 +290,7 @@ describe('Fragment Matcher Plugin', () => {
schema,
[],
{
apolloClientVersion: 2,
useExplicitTyping: true,
},
{
Expand All @@ -288,6 +301,7 @@ describe('Fragment Matcher Plugin', () => {
schema,
[],
{
apolloClientVersion: 2,
useExplicitTyping: true,
},
{
Expand Down Expand Up @@ -372,6 +386,7 @@ describe('Fragment Matcher Plugin', () => {
],
config: {
federation: true,
apolloClientVersion: 2,
},
pluginMap: {
'fragment-matcher': {
Expand Down Expand Up @@ -418,6 +433,7 @@ describe('Fragment Matcher Plugin', () => {
},
],
config: {
apolloClientVersion: 2,
federation: true,
},
pluginMap: {
Expand Down
16 changes: 16 additions & 0 deletions packages/plugins/typescript/apollo-client-helpers/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,20 @@ export type ApolloClientHelpersConfig = {
* ```
*/
useTypeImports?: boolean;
/**
* @name requireKeyFields
* @type boolean
* @default false
* @description Remove optional sign from all `keyFields` fields.
*
*/
requireKeyFields?: boolean;
/**
* @name requirePoliciesForAllTypes
* @type boolean
* @default false
* @description Remove optional sign from all generated keys of the root TypePolicy.
*
*/
requirePoliciesForAllTypes?: boolean;
};
18 changes: 15 additions & 3 deletions packages/plugins/typescript/apollo-client-helpers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ ${fieldsNames.map(fieldName => `\t${fieldName}?: FieldPolicy<any> | FieldReadFun
return {
...prev,
[typeName]: `{
\t\tkeyFields?: false | ${keySpecifierVarName} | (() => undefined | ${keySpecifierVarName}),
\t\tkeyFields${
config.requireKeyFields ? '' : '?'
}: false | ${keySpecifierVarName} | (() => undefined | ${keySpecifierVarName}),
\t\tqueryType?: true,
\t\tmutationType?: true,
\t\tsubscriptionType?: true,
Expand All @@ -58,8 +60,18 @@ ${fieldsNames.map(fieldName => `\t${fieldName}?: FieldPolicy<any> | FieldReadFun
return prev;
}, {} as Record<string, string>);

const rootTypes = [
schema.getQueryType()?.name,
schema.getMutationType()?.name,
schema.getSubscriptionType()?.name,
].filter(Boolean);

const rootContent = `export type TypedTypePolicies = TypePolicies & {${Object.keys(typedTypePolicies)
.map(typeName => `\n\t${typeName}?: ${typedTypePolicies[typeName]}`)
.map(typeName => {
const nonOptional = config.requirePoliciesForAllTypes && !rootTypes.includes(typeName);
return `\n\t${typeName}${nonOptional ? '' : '?'}: ${typedTypePolicies[typeName]}`;
})
.join(',')}\n};`;

return {
Expand All @@ -79,6 +91,6 @@ export const validate: PluginValidateFn<ApolloClientHelpersConfig> = async (
outputFile: string
) => {
if (extname(outputFile) !== '.ts' && extname(outputFile) !== '.tsx') {
throw new Error(`Plugin "typed-document-node" requires extension to be ".ts" or ".tsx"!`);
throw new Error(`Plugin "apollo-client-helpers" requires extension to be ".ts" or ".tsx"!`);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,61 @@ export type TypedTypePolicies = TypePolicies & {
}
};"
`;
exports[`apollo-client-helpers Should output typePolicies object with requireKeyFields: true 1`] = `
"import { FieldPolicy, FieldReadFunction, TypePolicies } from '@apollo/client/cache';
export type QueryKeySpecifier = ('user' | QueryKeySpecifier)[];
export type QueryFieldPolicy = {
user?: FieldPolicy<any> | FieldReadFunction<any>
};
export type UserKeySpecifier = ('id' | 'name' | UserKeySpecifier)[];
export type UserFieldPolicy = {
id?: FieldPolicy<any> | FieldReadFunction<any>,
name?: FieldPolicy<any> | FieldReadFunction<any>
};
export type TypedTypePolicies = TypePolicies & {
Query?: {
keyFields: false | QueryKeySpecifier | (() => undefined | QueryKeySpecifier),
queryType?: true,
mutationType?: true,
subscriptionType?: true,
fields?: QueryFieldPolicy,
},
User?: {
keyFields: false | UserKeySpecifier | (() => undefined | UserKeySpecifier),
queryType?: true,
mutationType?: true,
subscriptionType?: true,
fields?: UserFieldPolicy,
}
};"
`;
exports[`apollo-client-helpers Should output typePolicies object with requirePoliciesForAllTypes: true 1`] = `
"import { FieldPolicy, FieldReadFunction, TypePolicies } from '@apollo/client/cache';
export type QueryKeySpecifier = ('user' | QueryKeySpecifier)[];
export type QueryFieldPolicy = {
user?: FieldPolicy<any> | FieldReadFunction<any>
};
export type UserKeySpecifier = ('id' | 'name' | UserKeySpecifier)[];
export type UserFieldPolicy = {
id?: FieldPolicy<any> | FieldReadFunction<any>,
name?: FieldPolicy<any> | FieldReadFunction<any>
};
export type TypedTypePolicies = TypePolicies & {
Query?: {
keyFields?: false | QueryKeySpecifier | (() => undefined | QueryKeySpecifier),
queryType?: true,
mutationType?: true,
subscriptionType?: true,
fields?: QueryFieldPolicy,
},
User: {
keyFields?: false | UserKeySpecifier | (() => undefined | UserKeySpecifier),
queryType?: true,
mutationType?: true,
subscriptionType?: true,
fields?: UserFieldPolicy,
}
};"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,44 @@ describe('apollo-client-helpers', () => {
const result = mergeOutputs([await plugin(schema, [], {})]);
expect(result).toMatchSnapshot();
});

it('Should output typePolicies object with requireKeyFields: true', async () => {
const schema = buildSchema(/* GraphQL */ `
type Query {
user: User!
}
type User {
id: ID!
name: String!
}
`);
const result = mergeOutputs([
await plugin(schema, [], {
requireKeyFields: true,
}),
]);
expect(result).toContain(`keyFields:`);
expect(result).not.toContain(`keyFields?:`);
expect(result).toMatchSnapshot();
});

it('Should output typePolicies object with requirePoliciesForAllTypes: true', async () => {
const schema = buildSchema(/* GraphQL */ `
type Query {
user: User!
}
type User {
id: ID!
name: String!
}
`);
const result = mergeOutputs([
await plugin(schema, [], {
requirePoliciesForAllTypes: true,
}),
]);
expect(result).toContain(`User:`);
expect(result).toContain(`Query?:`);
expect(result).toMatchSnapshot();
});
});
2 changes: 1 addition & 1 deletion website/docs/generated-config/fragment-matcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ path/to/file.json:
### `apolloClientVersion`

type: `number (values: 2, 3)`
default: `2`
default: `3`

Compatible only with TS/TSX/JS/JSX extensions, allow you to generate output based on your Apollo-Client version. Valid values are: `2`, `3`.

Expand Down
16 changes: 16 additions & 0 deletions website/docs/generated-config/typescript-apollo-client-helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,19 @@ default: `false`

Will use `import type {}` rather than `import {}` when importing only types. This gives
compatibility with TypeScript's "importsNotUsedAsValues": "error" option


### `requireKeyFields`

type: `boolean`
default: `false`

Remove optional sign from all `keyFields` fields.


### `requirePoliciesForAllTypes`

type: `boolean`
default: `false`

Remove optional sign from all generated keys of the root TypePolicy.
9 changes: 5 additions & 4 deletions website/docs/plugins/fragment-matcher.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,23 @@ title: Fragment Matcher

## Usage with Apollo Client 3

If you are using Apollo Client 3, you need to specify the `apolloClientVersion: 3` configuration, and then use it in your Apollo cache instance:
If you are using Apollo Client 3, update your codegen config accordingly, and then use it in your Apollo cache instance:

```typescript
import { InMemoryCache } from '@apollo/client';

// generated by Fragment Matcher plugin
import { possibleTypes } from '../introspection-result';
import generatedIntrospection from '../introspection-result';

const cache = new InMemoryCache({ possibleTypes });
const cache = new InMemoryCache({ possibleTypes: generatedIntrospection.possibleTypes });
```

> [Read more about fragment matcher and its usage on Apollo Client](https://www.apollographql.com/docs/react/data/fragments/#defining-possibletypes-manually)

## Usage with Apollo Client 2

If you are using version 2 of Apollo-Client, you need to specify the `apolloClientVersion: 2` configuration, and then use it like that:

```typescript
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';

Expand Down
12 changes: 11 additions & 1 deletion website/static/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@
"type": "boolean",
"default": false,
"description": "Will use `import type {}` rather than `import {}` when importing only types. This gives\ncompatibility with TypeScript's \"importsNotUsedAsValues\": \"error\" option"
},
"requireKeyFields": {
"type": "boolean",
"default": false,
"description": "Remove optional sign from all `keyFields` fields."
},
"requirePoliciesForAllTypes": {
"type": "boolean",
"default": false,
"description": "Remove optional sign from all generated keys of the root TypePolicy."
}
}
},
Expand Down Expand Up @@ -2667,7 +2677,7 @@
},
"apolloClientVersion": {
"description": "Compatible only with TS/TSX/JS/JSX extensions, allow you to generate output based on your Apollo-Client version. Valid values are: `2`, `3`.",
"default": 2,
"default": 3,
"enum": [2, 3],
"type": "number"
},
Expand Down

0 comments on commit 5e792ff

Please sign in to comment.