End to End React with Prisma 2

Start at the beginning and work your way through this project. The code for each step as well as the finished project can be found in the Github repository.


    15. Add queries, mutations and fragments

    Objective: Add all the query and mutations files that our frontend will need.

    Now that we know we have our backend in a good place, let's go ahead and create all of the queries and mutations that the backend will support. An important thing we will utilize to prevent code duplication is fragments. We actually have been using these for all of our testing, so hopefully they will look familiar. The essence of a fragment is that it will store all of the fields we want to return for a particular model type.

    Click to download the graphQL folder

    Let's look at this FeedTagFragment. It is of type FeedTag and we are saving it to the variable FEED_TAG_FRAGMENT.

    If we go down to FEED_FRAGMENT we see that we can inject in the FEED_TAG_FRAGMENT at the end of the fragment and use it within the FEED_FRAGMENT by using the pattern ...FeedTagFragment. This should kind of feel like the destructuring that we see with javascript and we are able to add all of these fragments together by using template strings template string example ${with-variables-injected-at-the-places-we-need-them}.

    utils/api/graphql/fragments.ts

    ts

    import { gql } from '@apollo/client'
    export const FEED_TAG_FRAGMENT = gql`
    fragment FeedTagFragment on FeedTag {
    id
    name
    }
    `
    export const BUNDLE_TAG_FRAGMENT = gql`
    fragment BundleTagFragment on BundleTag {
    id
    name
    }
    `
    export const AUTHOR_FRAGMENT = gql`
    fragment AuthorFragment on User {
    id
    auth0
    picture
    nickname
    }
    `
    export const LIKE_FRAGMENT = gql`
    fragment LikeFragment on Like {
    id
    name
    }
    `
    export const FEED_FRAGMENT = gql`
    fragment FeedFragment on Feed {
    id
    name
    url
    likes {
    ...AuthorFragment
    }
    tags {
    ...FeedTagFragment
    }
    author {
    ...AuthorFragment
    }
    }
    ${FEED_TAG_FRAGMENT}
    ${AUTHOR_FRAGMENT}
    `
    export const BUNDLE_FRAGMENT = gql`
    fragment BundleFragment on Bundle {
    id
    name
    description
    tags {
    ...BundleTagFragment
    }
    author {
    ...AuthorFragment
    }
    likes {
    ...AuthorFragment
    }
    }
    ${BUNDLE_TAG_FRAGMENT}
    ${AUTHOR_FRAGMENT}
    `
    export const SAVED_ARTICLE_FRAGMENT = gql`
    fragment SavedArticleFragment on SavedArticle {
    id
    contents
    url
    author {
    ...AuthorFragment
    }
    feed {
    ...FeedFragment
    }
    }
    ${AUTHOR_FRAGMENT}
    ${FEED_FRAGMENT}
    `

    We go through all of the different models for these fragments and we export them all as fragments so we can use them in our queries and mutations. Let's tackle the queries first.

    We can import all of these fragments that we just made at the top of our file. Let's take the bundles query. You can see that we use the BundleFragment to get all of our bundle fields, but when we want to get the nested feeds we need to load that FeedFragment inside the feeds return object. The actual fragments we import as template string variables at the bottom of the query.

    utils/api/graphql/queries.ts

    ts

    import { gql } from '@apollo/client'
    import {
    BUNDLE_FRAGMENT,
    BUNDLE_TAG_FRAGMENT,
    FEED_FRAGMENT,
    FEED_TAG_FRAGMENT,
    SAVED_ARTICLE_FRAGMENT,
    } from './fragments'
    export const BUNDLES_QUERY = gql`
    query {
    bundles {
    ...BundleFragment
    feeds {
    ...FeedFragment
    }
    }
    }
    ${BUNDLE_FRAGMENT}
    ${FEED_FRAGMENT}
    `
    export const FEEDS_QUERY = gql`
    query {
    feeds {
    ...FeedFragment
    bundles {
    ...BundleFragment
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const FIND_FEEDS_QUERY = gql`
    query findFeedsQuery($data: FindFeedsInput) {
    findFeeds(data: $data) {
    ...FeedFragment
    bundles {
    ...BundleFragment
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const FEED_QUERY = gql`
    query feedQuery($data: FeedInput) {
    feed(data: $data) {
    ...FeedFragment
    bundles {
    ...BundleFragment
    feeds {
    ...FeedFragment
    }
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const BUNDLE_QUERY = gql`
    query bundleQuery($data: BundleInput) {
    bundle(data: $data) {
    ...BundleFragment
    feeds {
    ...FeedFragment
    bundles {
    ...BundleFragment
    }
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const FIND_FEED_TAGS_QUERY = gql`
    query findFeedTagsQuery($data: FindFeedTagsInput) {
    findFeedTags(data: $data) {
    ...FeedTagFragment
    }
    }
    ${FEED_TAG_FRAGMENT}
    `
    export const FIND_BUNDLE_TAGS_QUERY = gql`
    query findBundleTagsQuery($data: FindBundleTagsInput) {
    findBundleTags(data: $data) {
    ...BundleTagFragment
    }
    }
    ${BUNDLE_TAG_FRAGMENT}
    `
    export const SAVED_ARTICLES_QUERY = gql`
    query savedArticlesQuery {
    savedArticles {
    ...SavedArticleFragment
    }
    }
    ${SAVED_ARTICLE_FRAGMENT}
    `
    export const SAVED_ARTICLE_QUERY = gql`
    query savedArticleQuery($data: SavedArticleInput) {
    savedArticle(data: $data) {
    ...SavedArticleFragment
    }
    }
    ${SAVED_ARTICLE_FRAGMENT}
    `

    Finally, let's add the mutations. Nothing too surprising here

    utils/api/graphql/mutations.ts

    ts

    import { gql } from '@apollo/client'
    import {
    BUNDLE_FRAGMENT,
    FEED_FRAGMENT,
    SAVED_ARTICLE_FRAGMENT,
    } from './fragments'
    export const LIKE_BUNDLE_MUTATION = gql`
    mutation likeBundleMutation($data: LikeBundleInput) {
    likeBundle(data: $data) {
    ...BundleFragment
    feeds {
    ...FeedFragment
    }
    }
    }
    ${BUNDLE_FRAGMENT}
    ${FEED_FRAGMENT}
    `
    export const LIKE_FEED_MUTATION = gql`
    mutation likeFeedMutation($data: LikeFeedInput) {
    likeFeed(data: $data) {
    ...FeedFragment
    bundles {
    ...BundleFragment
    }
    }
    }
    ${BUNDLE_FRAGMENT}
    ${FEED_FRAGMENT}
    `
    export const CREATE_BUNDLE_MUTATION = gql`
    mutation createBundleMutation($data: BundleCreateInput) {
    createBundle(data: $data) {
    ...BundleFragment
    feeds {
    ...FeedFragment
    bundles {
    ...BundleFragment
    }
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const UPDATE_BUNDLE_MUTATION = gql`
    mutation updateBundleMutation($data: BundleUpdateInput) {
    updateBundle(data: $data) {
    ...BundleFragment
    feeds {
    ...FeedFragment
    bundles {
    ...BundleFragment
    }
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const CREATE_FEED_MUTATION = gql`
    mutation createFeedMutation($data: FeedCreateInput) {
    createFeed(data: $data) {
    ...FeedFragment
    bundles {
    ...BundleFragment
    feeds {
    ...FeedFragment
    }
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const UPDATE_FEED_MUTATION = gql`
    mutation updateFeedMutation($data: FeedUpdateInput) {
    updateFeed(data: $data) {
    ...FeedFragment
    bundles {
    ...BundleFragment
    feeds {
    ...FeedFragment
    }
    }
    }
    }
    ${FEED_FRAGMENT}
    ${BUNDLE_FRAGMENT}
    `
    export const CREATE_SAVED_ARTICLE_MUTATION = gql`
    mutation createSavedArticleMutation($data: SavedArticleCreateInput) {
    createSavedArticle(data: $data) {
    ...SavedArticleFragment
    }
    }
    ${SAVED_ARTICLE_FRAGMENT}
    `
    export const DELETE_BUNDLE_MUTATION = gql`
    mutation deleteBundleMutation($data: BundleInput) {
    deleteBundle(data: $data) {
    id
    }
    }
    `
    export const DELETE_FEED_MUTATION = gql`
    mutation deleteFeedMutation($data: FeedInput) {
    deleteFeed(data: $data) {
    id
    }
    }
    `
    export const DELETE_SAVED_ARTICLE_MUTATION = gql`
    mutation deleteSavedArticleMutation($data: DeleteSavedArticleInput) {
    deleteSavedArticle(data: $data) {
    id
    url
    }
    }
    `