From fa1d946e6da51318e762bdb5cbf9bc357d5edcd3 Mon Sep 17 00:00:00 2001 From: izumin5210 Date: Mon, 13 Sep 2021 11:20:58 +0900 Subject: [PATCH 1/2] Update documents --- README.md | 19 ++++++++--- src/maskWithFragment.ts | 72 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3f61bfe..6e644b3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![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 @@ -47,6 +47,8 @@ const _GET_GREETING = gql` // ... +// Use typed document node generated by `@graphql-codegen/typed-document-node` (RECOMMENDED). +// Alternatively, you can use the document node defined by `graphql-tag`. const [data] = useQuery(GetPostDocument, { variables: { postId: "123" } }); const header = maskWithFragment(PostHeaderFragmentDoc, data.postById); @@ -63,10 +65,19 @@ const header = maskWithFragment(PostHeaderFragmentDoc, 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 +``` diff --git a/src/maskWithFragment.ts b/src/maskWithFragment.ts index b0a1afd..2840600 100644 --- a/src/maskWithFragment.ts +++ b/src/maskWithFragment.ts @@ -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(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, TData extends TFilteredData = TFilteredData >(doc: DocumentNode | TypedDocumentNode, 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` if you specify a type parameter. + * const header = maskWithFragment(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`. + * const header = maskWithFragment(PostHeaderFragmentDoc, data); + * ``` + */ export function maskWithFragment< TFilteredData extends Record, TData extends TFilteredData = TFilteredData From fa39966785b18f20d607159cd76b24dbc2ed2e3c Mon Sep 17 00:00:00 2001 From: izumin5210 Date: Mon, 13 Sep 2021 11:24:41 +0900 Subject: [PATCH 2/2] Update README --- README.md | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 6e644b3..9b90304 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Mask GraphQL query result with Fragment ([graphql-anywhere](https://www.npmjs.co ```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` @@ -22,35 +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... } } `; -// ... - -// Use typed document node generated by `@graphql-codegen/typed-document-node` (RECOMMENDED). -// Alternatively, you can use the document node defined by `graphql-tag`. 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", @@ -61,6 +46,9 @@ 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