@freshcells/apollo-link-field-keep
    Preparing search index...

    @freshcells/apollo-link-field-keep

    semantic-release GitHub license badge npm codecov

    EXPERIMENTAL

    Similar to @include and @skip, but allows bypassing certain parts of the query completely before sending it to the server

    API Documentation

    • Feature toggling
    • Federated schemas

    Available from the npm package registry with

    yarn add @freshcells/apollo-link-field-keep
    
    npm install @freshcells/apollo-link-field-keep
    
        import KeepLink from '@freshcells/apollo-link-field-keep'

    // ...

    const keepLink = new KeepLink()

    // if you want to use ifFeature conditions, add also the following line, otherwise skip it:
    keepLink.enabledFeatures = ['feature1']

    const apolloClient = new ApolloClient({
    link: from([
    keepLink,
    // .. other links
    ]),
    })

    You can then use the @keep directive as:

    query someQuery($argValue: String! $shouldKeep: Boolean!) {
        someOther {
            subFieldOther(someArg: $argValue) {
                subSubFieldOther
            }
        }
        field(someArg: $argValue) @keep(if: $shouldKeep) {
            subFieldA
            subFieldB
        }
    }
    

    If $shouldKeep in this example is false, it will remove the whole field query including arguments. It will also clean up all variables that might be used (if not used by other fields).

    If you have a query that is used in multiple components and needs to include a certain field everywhere, you can use ifFeature instead of if as:

    query someQuery($argValue: String!) {
        someOther {
            subFieldOther(someArg: $argValue) {
                subSubFieldOther
            }
        }
        field(someArg: $argValue) @keep(ifFeature: "feature1") {
            subFieldA
            subFieldB
        }
    }
    

    It will work exactly the same way as $shouldKeep in the previous example. With this approach you just save time as you do not need to pass the same variables to all query use cases.

    It is also possible to combine if and ifFeature:

    query someQuery($argValue: String! $shouldKeep: Boolean!) {
        someOther {
            subFieldOther(someArg: $argValue) {
                subSubFieldOther
            }
        }
        field(someArg: $argValue) @keep(if: $shouldKeep ifFeature: "feature1") {
            subFieldA
            subFieldB
        }
    }
    

    In this case the fields will only be included if both $shouldKeep is true and feature1 is enabled.

    To prevent Apollo Cache issues, it will fill the field with null when returned from the server.

    Using apollo-link-field-keep with persisted queries, is possible, but requires some pre-processing, before you can send it to the backend.

    Warning

    Only the static version @keep(ifFeature: "name") works, because it can be statically inferred on both client and server. Please do not use @keep(if: $someVariable) with persistent queries, as variables won't be transferred to the server side and cannot be analyzed.

    The library exposes the function removeIgnoreSetsFromDocument to remove any @keep directives. Make sure you still have KeepLink in your pipeline (so it can handle the null values properly)

    import {removeIgnoreSetsFromDocument} from '@freshcells/apollo-link-field-keep'
    import {
    getDefaultValues,
    removeConnectionDirectiveFromDocument,
    } from 'apollo-utilities'
    import {parse, print} from 'graphql/index'

    export const removeClientDirectives = <T extends Record<string, unknown>>(
    query: string,
    variables: T,
    featureList: string[]
    ) => {
    const parsedQuery = parse(query)
    // we have to restore the default variables, as they might have been removed by the keepLink before sending them to the server.
    const defaults = getDefaultValues(
    parsedQuery.definitions.find((d) => d.kind === 'OperationDefinition')
    )
    const nextQuery = removeIgnoreSetsFromDocument(
    removeConnectionDirectiveFromDocument(parsedQuery),
    {...defaults, ...variables},
    featureList
    )
    return print(nextQuery.modifiedDoc)
    }