Skip to content

Commit

Permalink
Merge pull request #9 from izumin5210/izumin5210/doc
Browse files Browse the repository at this point in the history
Update documents
  • Loading branch information
izumin5210 committed Sep 13, 2021
2 parents 6845814 + fa39966 commit 27a8c70
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 21 deletions.
41 changes: 20 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
[![npm](https://img.shields.io/npm/v/graphql-fragment-mask)](https://www.npmjs.com/package/graphql-fragment-mask)
[![LICENSE](https://img.shields.io/github/license/izumin5210/graphql-fragment-mask)](./LICENSE)

Mask GraphQL query result with Fragment with [TypedDocumentNode](https://the-guild.dev/blog/typed-document-node) ([graphql-anywhere](https://www.npmjs.com/package/graphql-anywhere) alternative)
Mask GraphQL query result with Fragment ([graphql-anywhere](https://www.npmjs.com/package/graphql-anywhere) alternative).

## Usage

```ts
import gql from "graphql-tag";
// Import generated types and generated `TypedDocumentNode` objects of the fragment.
import { PostHeaderFragmentDoc, GetPostDocument } from "./__generated__/Post.generated";

const _POST_HEADER = gql`
Expand All @@ -22,33 +23,19 @@ const _POST_HEADER = gql`
}
`;

const _POST_DETAIL = gql`
fragment PostDetail on Post {
id
title
body
author {
id
username
fullName
avatarUrl
}
}
`;

const _GET_GREETING = gql`
query GetPost($postId: !String) {
postById(postId: $postId) {
...PostHeader
...PostDetail
// and more fields...
}
}
`;

// ...

const [data] = useQuery(GetPostDocument, { variables: { postId: "123" } });


// Use typed document node generated by `@graphql-codegen/typed-document-node` (RECOMMENDED).
const header = maskWithFragment(PostHeaderFragmentDoc, data.postById);
// {
// __typename: "Post",
Expand All @@ -59,14 +46,26 @@ const header = maskWithFragment(PostHeaderFragmentDoc, data.postById);
// avatarUrl: "https://example.com/users/izumin5210/avatar",
// }
// }

// Alternatively, you can use the document node defined by `graphql-tag`.
// const header = maskWithFragment(_POST_HEADER, data.postById);
```

## Dependencies

Install this library with [graphql-js](https://github.com/graphql/graphql-js/) and [graphql-typed-document-node](https://github.com/dotansimha/graphql-typed-document-node):
Install this library with [graphql-js](https://github.com/graphql/graphql-js/).

```
yarn add graphql @graphql-typed-document-node/core graphql-fragment-mask
yarn add graphql graphql-fragment-mask
```

And setup [graphql-code-generator](https://www.graphql-code-generator.com) with [TypedDocumentNode plugin](https://www.graphql-code-generator.com/docs/plugins/typed-document-node) (please refer [TypedDocumentNode's instruction](https://github.com/dotansimha/graphql-typed-document-node#how-to-use)).
If you want to use it with `TypedDocumentNode`, setup [TypedDocumentNode plugin](https://www.graphql-code-generator.com/docs/plugins/typed-document-node) with [graphql-code-generator](https://www.graphql-code-generator.com) (RECOMMENDED, please refer [TypedDocumentNode's instruction](https://github.com/dotansimha/graphql-typed-document-node#how-to-use)).

```
yarn add --dev \
@graphql-codegen/cli \
@graphql-codegen/typescript \
@graphql-codegen/typescript-operations \
@graphql-codegen/typed-document-node
yarn add @graphql-typed-document-node/core
```
72 changes: 72 additions & 0 deletions src/maskWithFragment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,82 @@ import { TypedDocumentNode } from "@graphql-typed-document-node/core";
import { FragmentDefinitionNode, DocumentNode, InlineFragmentNode } from "graphql";
import deepMerge from "deepmerge";

/**
* Masks the input object to the shape of the fragment.
*
* @returns A copy of the input object masked by the fragment.
*
* @example
* ```ts
* import gql from "graphql-tag";
* import { PostHeaderFragment } from "./__generated__/Post.generated";
*
* const POST_HEADER = gql`
* fragment PostHeader on Post {
* title
* author { fullName, avatarUrl }
* }
* `;
*
* // The type of `header` is `PostHeaderFragment` if you specify a type parameter.
* const header = maskWithFragment<PostHeaderFragment>(POST_HEADER, data);
* ```
*
* @example
* ```ts
* import { PostHeaderFragmentDoc } from "./__generated__/Post.generated";
*
* const _POST_HEADER = gql`
* fragment PostHeader on Post {
* title
* author { fullName, avatarUrl }
* }
* `;
*
* // The type of `header` is inferred to `PostHeaderFragment`.
* const header = maskWithFragment(PostHeaderFragmentDoc, data);
* ```
*/
export function maskWithFragment<
TFilteredData extends Record<string, unknown>,
TData extends TFilteredData = TFilteredData
>(doc: DocumentNode | TypedDocumentNode<TFilteredData, any>, input: TData): TFilteredData;
/**
* Masks objects contained in the input array to the shape of the fragment.
*
* @returns the array contains copies of objects masked by the fragment.
*
* @example
* ```ts
* import gql from "graphql-tag";
* import { PostHeaderFragment } from "./__generated__/Post.generated";
*
* const POST_HEADER = gql`
* fragment PostHeader on Post {
* title
* author { fullName, avatarUrl }
* }
* `;
*
* // The type of `header` is `ReadonlyArray<PostHeaderFragment>` if you specify a type parameter.
* const header = maskWithFragment<PostHeaderFragment>(POST_HEADER, data);
* ```
*
* @example
* ```ts
* import { PostHeaderFragmentDoc } from "./__generated__/Post.generated";
*
* const _POST_HEADER = gql`
* fragment PostHeader on Post {
* title
* author { fullName, avatarUrl }
* }
* `;
*
* // The type of `header` is inferred to `ReadonlyArray<PostHeaderFragment>`.
* const header = maskWithFragment(PostHeaderFragmentDoc, data);
* ```
*/
export function maskWithFragment<
TFilteredData extends Record<string, unknown>,
TData extends TFilteredData = TFilteredData
Expand Down

0 comments on commit 27a8c70

Please sign in to comment.