apollographql / apollo-client-devtools

Apollo Client browser developer tools.
https://apollographql.com/docs/react/development-testing/developer-tooling/#apollo-client-devtools
MIT License
1.49k stars 165 forks source link

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

Open y-murashka opened 4 years ago

y-murashka commented 4 years ago

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

dvakatsiienko commented 4 years ago

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

ghost commented 4 years ago

+1

t-lock commented 4 years ago

+2

dvakatsiienko commented 4 years ago

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

MichaelDM commented 4 years ago

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?

dvakatsiienko commented 4 years ago

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

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.

ElForastero commented 4 years ago

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.

MichaelDM commented 4 years ago

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?

ElForastero commented 4 years ago

@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 ```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 # in the RSS, 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 ```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, }, }, }); ```
bennypowers commented 4 years ago

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

MichaelDM commented 4 years ago

@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.

ElForastero commented 4 years ago

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

Remownz commented 4 years ago

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
        }
      `,
    });
sandorTuranszky commented 4 years ago

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

MichaelDM commented 4 years ago

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...

bennypowers commented 4 years ago

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

Natas0007 commented 4 years ago

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.

tobiasriemenschneider commented 3 years ago

+1

just-Bri commented 3 years ago

+1

Just had this start happening to me yesterday.

dstockdale commented 3 years ago

+1

vigie commented 3 years ago

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}`);
    }
}
just-Bri commented 3 years ago

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.

hwillson commented 3 years ago

@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!

vigie commented 3 years ago

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.

hwillson commented 3 years ago

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

rektide commented 3 years ago

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

cortopy commented 3 years ago

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

VasiliKubarka commented 2 years ago

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

spigelli commented 2 years ago

Also still seeing this