apollo-client-devtools icon indicating copy to clipboard operation
apollo-client-devtools copied to clipboard

Chrome Apollo Client Extension does not see schema for local state.

Open y-murashka opened this issue 4 years ago • 29 comments

Hi there. Basically i've started doing some pet project and decided not to create a server itself but use local state management for now.

I'm doing the following thing:

const cache = new InMemoryCache();

const client = new ApolloClient({
  cache,
  resolvers,
  typeDefs
});

cache.writeData({
  data: {
    appState: {
      isCollapsed: true,
      __typename: 'AppState'
    }
  },
});
const applicationContainer = document.getElementById('application-root');
const application = (
  <ApolloProvider client={client}>
    <Pages></Pages>>
    </ApolloProvider>
);
ReactDOM.render(application, applicationContainer);

Here is schema:

export const typeDefs = gql`
   type Query {
    appState: AppState
  }

   type AppState {
        isCollapsed: Boolean
    }
`;

And here is resolvers

export const GET_APP_STATE = gql`
  query GetAppState {
    appState @client
  }
`;

export const resolvers = {
  Query:{
    appState: ( _, { cache }) => {
      const { appState } = cache.readQuery({ query: GET_APP_STATE });
      return appState;
    },
  }
};

When i run Apollo Dev tools in chrome i expect to see schema but it's empty. Query works as expected.

image

y-murashka avatar Dec 04 '19 03:12 y-murashka

singing up upon this. apollo local state visualization is a must have in devtools.

dvakatsiienko avatar Feb 20 '20 13:02 dvakatsiienko

+1

ghost avatar Feb 23 '20 13:02 ghost

+2

t-lock avatar Mar 05 '20 11:03 t-lock

without high quality local state management monitoring (and control) this feature doubtfully can be used as mature one in Apollo Client...although containing entire state in a cache sounds good (without Redux for instance), but again a reliable instrument to do so is required

dvakatsiienko avatar Mar 05 '20 12:03 dvakatsiienko

Same here. I am very enthusiastically contemplating using Apollo Client for all data (remote + local) but having the introspection break once I add a local schema is making me seriously reconsider this approach, as it makes dev (especially across a team) more labor intensive. Are you guys contemplating a fix for this?

MichaelDM avatar Mar 25 '20 09:03 MichaelDM

I was testing Apollo Local State management for a REALLY simple usecase:

  • isAuthenticated flag;
  • Application Authorized Endpoints list;

And after tinkering with it for ~3 weeks or so I've decided to delete all local state from Apollo and move it to Redux. And I am happy now. As for now Apollo client local state it not comfortable to work with due to its verbosity and lack of possibility for simple acces and visualization. Although the idea is very cool.

dvakatsiienko avatar Mar 25 '20 09:03 dvakatsiienko

Does anyone have any ideas on how to fix this?

I'm encountering this problem with @apollo/client v3.

I've tried the release-3.0 branch, but it seems to be too far from the release and doesn't work either.

ElForastero avatar Apr 22 '20 06:04 ElForastero

Hey guys, Update on my end. I actually figured out it wasn't an error on apollo's side, but on mine. I had a mistake in my typeDefs file. Even though the typeDefs had more complexity than the example of local Management in apolloGraphql example (https://www.apollographql.com/docs/tutorial/local-state/), it worked like a charm. @ElForastero, might you post (and/or double-check) your typeDefs? Perhaps, as I did, you have an issue there?

MichaelDM avatar Apr 22 '20 12:04 MichaelDM

@MichaelDM Which error did you have?

I have defined typeDefs as a regular *.graphql file with client schema. So it is validated by IDE and codegen. I can't see any errors here. I'm starting to suspect, that this is because I don't have any remote endpoints right now. I have only local state and therefore all my schema constists of local queries/mutations and resolvers.

client.schema.graphql
type Source {
  id: ID!
  url: String!
  link: String!
  title: String!
  description: String
  image: String
  color: String
}

input SourceInput {
  url: String!
  link: String!
  title: String!
  description: String
  image: String
  color: String
}

type Feed {
  id: ID!
  # Unique identifier of the feed
  # <guid> in the RSS, <id> in the Atom
  guid: String!
  # External key
  source_id: ID!
  link: String!
  title: String!
  description: String
  content: String
  pubDate: String
  author: String
  image: String
  categories: [String]
  seen: Boolean!
}

input FeedInput {
  guid: String!
  source_id: ID!
  link: String!
  title: String!
  seen: Boolean
  description: String
  content: String
  pubDate: String
  author: String
  image: String
  categories: [String]
}

type Query {
  sources: [Source]!
  feed(sourceID: ID): [Feed]!
}

type Mutation {
  addSource(input: SourceInput!): Source!
  markFeedAsSeen(id: ID!): Feed!
}
client.ts
import { ApolloClient, InMemoryCache } from '@apollo/client';
import { resolvers as sources } from './resolvers/sources';
import { resolvers as feed } from './resolvers/feed';
import typeDefs from './schema.client.graphql';

const cache = new InMemoryCache();

export const client = new ApolloClient({
  cache,
  typeDefs,
  resolvers: {
    Query: {
      ...sources.Query,
      ...feed.Query,
    },
    Mutation: {
      ...sources.Mutation,
      ...feed.Mutation,
    },
  },
});

ElForastero avatar Apr 22 '20 14:04 ElForastero

Same problem, but wasn't solved by adding a backend.

https://spectrum.chat/apollo/apollo-link-state/client-has-typedefs-but-no-docs-in-graphiql~8a80e439-3257-4fce-a666-a1e75c3cec63

bennypowers avatar Apr 23 '20 11:04 bennypowers

@ElForastero here is an idea. I have at minimum the extend keyword: extend type Query { ... } extend type Mutation{ ...} Would have to look over the docs again, but probably need to apply it well to your other Types.

MichaelDM avatar Apr 23 '20 15:04 MichaelDM

@MichaelDM I've tried the extend keyword and nothing was changed.

ElForastero avatar Apr 23 '20 16:04 ElForastero

same here: minimum typeDefs with or without "extend" keyword but no schema documentation inside devtools

this.apolloClient = new ApolloClient({
      defaultOptions: this.defaultOptions,
      cache: this.cache,
      link: ApolloLink.from(links),
      typeDefs: gql`
        extend type FlightIntents {
          type: String
        }

        extend type Query {
          flightIntents: FlightIntents
        }
      `,
    });

Remownz avatar Apr 28 '20 22:04 Remownz

Does not work for me either. Any comments on this from the Apollo team?

sandorTuranszky avatar Apr 29 '20 14:04 sandorTuranszky

What I think looking back was most frustrating for me, was the lack of error messages to help me debug the issues I had.

Unfortunately, @ElForastero , @Remownz , there are no errors that are apparent to my eyes when I read your code snippets.

This said, how I would go about solving this, is going from an implementation that works (even if it's the tutorial example), modifying it bit by bit to get to the complexity that you have today, and see where it breaks in the process. If you find the solution, please post it here because I'm sure others will find it useful!

Off the top of my head, when I did it on my end, I realized I had typos in my schema, like query lowercase, or writing a wrong type (Number) instead of Int...

MichaelDM avatar Apr 30 '20 08:04 MichaelDM

I've gotten to the point where the VS Code extension "Apollo GraphQL" properly loads and executes my client-side schema. I did this by running a code-generation script in a file watcher:

import { mergeTypeDefs } from '@graphql-tools/merge';
import { loadFilesSync } from '@graphql-tools/load-files';
import { writeFileSync } from 'fs';
import { print } from 'graphql';

const types =
  loadFilesSync('./src/**/*.client.schema.graphql');

const merged =
  print(mergeTypeDefs(types)).replace(`schema {
  query: Query
  mutation: Mutation
}`, '');

writeFileSync('./src/apollo/schema/generated.schema.graphql', merged);
// apollo.config.js
/* eslint-env node */
module.exports = {
  client: {
    service: {
      name: 'thing-name',
      localSchemaFile: './server/graphql/graphql.schema.json', // using graphql-codegen
    },
    includes: [
      './src/apollo/schema/generated.schema.graphql', // using above script
      './src/**/*.fragment.graphql',
      './src/**/*.mutation.graphql',
      './src/**/*.query.graphql',
    ],
    excludes: [
      './server/**/*.schema.graphql',
      './src/**/*.client.schema.graphql',
    ],
  },
};
// client.ts
import typeDefs from './schema/generated.schema.graphql'; // using rollup-plugin-graphql or es-dev-server-import-graphql
// ...
console.log(typeDefs) // LGTM, no problems here AFAICT. Uses extend keyword and has some new local types.
const client = new ApolloClient({
  typeDefs,
  // ...
});

So now I get autocomplete in my component graphql files, great!

However, I still don't get GraphiQL working with my client schema, only the server schema via introspection query. The extension does not log any errors to the console, either in the app context, or the extension context.

I get the same results if I use typeDefs or if I use typeDefs.loc.source.body

I can't share the generated schema files publicly, but I'd be happy to DM it to a maintainer if they want to try and repro

bennypowers avatar Jul 10 '20 13:07 bennypowers

Any updates on this issue from Apollo? I'm running the latest Apollo Client v3.1.4 and no typeDefs defined on the client side are shown in Dev Tools Schema tab (DevTools v2.3.1). I've tried with and without the extend keyword in front of type. Server side typeDefs are shown fine. Even when completely disconnecting the server in the config (for testing), no client typeDefs (schema) are shown.

Natas0007 avatar Sep 09 '20 18:09 Natas0007

+1

tobiasriemenschneider avatar Oct 30 '20 06:10 tobiasriemenschneider

+1

Just had this start happening to me yesterday.

just-Bri avatar Oct 30 '20 14:10 just-Bri

+1

dstockdale avatar Oct 30 '20 14:10 dstockdale

This fix works well for me: configure the client to use this "IntrospectionLink". You can get GraphQL Code Generator to generate the introspectionResult for you from your local schema definition.

Tested with devtools v3.0.2, works well:

import { ApolloLink, NextLink, Operation } from '@apollo/client/core';
import { ExecutionResult } from 'graphql';
import Observable from 'zen-observable';

import introspectionResult from './schema-introspection.json';

/**
 * Serves introspection operations. For example, the Apollo Client
 * Chrome Devtool issues an introspection operation when it opens
 * in order to display the schema.
 */
export class IntrospectionLink extends ApolloLink {
    request(operation: Operation, forward?: NextLink) {
        switch (operation.operationName.toLowerCase()) {
            case 'introspectionquery':
                return new Observable<ExecutionResult>((subscriber) => {
                    subscriber.next({
                        data: introspectionResult,
                    });
                    subscriber.complete();
                });
        }

        if (forward) {
            return forward(operation);
        }

        throw new Error(`Unable to handle operation ${operation.operationName}`);
    }
}

vigie avatar Mar 19 '21 05:03 vigie

I think the extension has recently updated, the UI is quite different. I can now see all current page queries/mutation in the tabs as intended, as well as my schema etc.

I believe I couldn't see them before because we were on a beta version of Apollo that was not supported by the extension yet.

just-Bri avatar Mar 19 '21 13:03 just-Bri

@reifnotreef yes, we just launched 3.0 which includes the new UI you've noticed, but is also a full re-write behind the scenes to put a better foundation in place for future growth. Glad to hear it's working - thanks!

hwillson avatar Mar 19 '21 14:03 hwillson

Yes, really enjoying the update, thanks @hwillson and team! But note, it does not fix the subject of this issue - showing local only schemas. My above workaround will get you there in the meantime.

vigie avatar Mar 19 '21 18:03 vigie

For sure, thanks @vigie - we'll dig into this shortly.

hwillson avatar Mar 19 '21 18:03 hwillson

I mistook this for a thread on seeing reactive variables. There is a feature request for that at: https://github.com/apollographql/apollo-client-devtools/discussions/391

rektide avatar May 20 '21 20:05 rektide

I'm using 3.0.5 in chromium and it's broken for me. I'm only following the tutorial for local state

This is my local schema

extend type RootQuery {
    isLoggedIn: Boolean!
  }

If I use the @client directive, it tells me that's not right

image

If I don't have the directive and select "Load from cache" I still get the data though image

So it seems like an issue with devTools, not with apollo client. The cache tab also shows that the cache is empty, even though it's not

cortopy avatar Jul 12 '21 11:07 cortopy

hello @hwillson, can you please tell when support of local schema will be fixed(added) for dev tools? I've tested latest version of development example with @apollo/client: "3.3.20" and Apollo Client Devtools 4.0.0

In client app example I've noticed that you even do not try to use local typedefs, saved property for Color type is not described in graphql types.

if to add typeDefs property to Apollo Client constructor then nothing will change in types description of apollo-client-devtools

export const clientTypeDefs = gql`
  extend type Color {
    saved: Boolean!
  }
`;

const client = new ApolloClient({
  cache: new InMemoryCache({
    typePolicies: {
      Color: {
        keyFields: ["hex"],
        fields: {
          saved: {
            read(_, { readField }) {
              const hex = readField("hex");
              const favoritedColors = readField("favoritedColors", makeReference("ROOT_QUERY"));
              return favoritedColors.some(colorRef => {
                return hex === readField("hex", colorRef);
              });
            }
          },
        }
      }
    },
  }),
  typeDefs: [clientTypeDefs],
  uri: 'http://localhost:4000',
});

However this property used in example and exists in apollo cache

image

VasiliKubarka avatar Oct 21 '21 12:10 VasiliKubarka

Also still seeing this

spigelli avatar Jan 25 '22 23:01 spigelli