Coder Social home page Coder Social logo

graphql-tag's Introduction

graphql-tag

npm version Build Status Get on Slack

Helpful utilities for parsing GraphQL queries. Includes:

  • gql A JavaScript template literal tag that parses GraphQL query strings into the standard GraphQL AST.
  • /loader A webpack loader to preprocess queries

graphql-tag uses the reference graphql library under the hood as a peer dependency, so in addition to installing this module, you'll also have to install graphql.

gql

The gql template literal tag can be used to concisely write a GraphQL query that is parsed into a standard GraphQL AST. It is the recommended method for passing queries to Apollo Client. While it is primarily built for Apollo Client, it generates a generic GraphQL AST which can be used by any GraphQL client.

import gql from 'graphql-tag';

const query = gql`
  {
    user(id: 5) {
      firstName
      lastName
    }
  }
`

The above query now contains the following syntax tree.

{
  "kind": "Document",
  "definitions": [
    {
      "kind": "OperationDefinition",
      "operation": "query",
      "name": null,
      "variableDefinitions": null,
      "directives": [],
      "selectionSet": {
        "kind": "SelectionSet",
        "selections": [
          {
            "kind": "Field",
            "alias": null,
            "name": {
              "kind": "Name",
              "value": "user",
              ...
            }
          }
        ]
      }
    }
  ]
}

Fragments

The gql tag can also be used to define reusable fragments, which can easily be added to queries or other fragments.

import gql from 'graphql-tag';

const userFragment = gql`
  fragment User_user on User {
    firstName
    lastName
  }
`

The above userFragment document can be embedded in another document using a template literal placeholder.

const query = gql`
  {
    user(id: 5) {
      ...User_user
    }
  }
  ${userFragment}
`

Note: While it may seem redundant to have to both embed the userFragment variable in the template literal AND spread the ...User_user fragment in the graphQL selection set, this requirement makes static analysis by tools such as eslint-plugin-graphql possible.

Why use this?

GraphQL strings are the right way to write queries in your code, because they can be statically analyzed using tools like eslint-plugin-graphql. However, strings are inconvenient to manipulate, if you are trying to do things like add extra fields, merge multiple queries together, or other interesting stuff.

That's where this package comes in - it lets you write your queries with ES2015 template literals and compile them into an AST with the gql tag.

Caching parse results

This package only has one feature - it caches previous parse results in a simple dictionary. This means that if you call the tag on the same query multiple times, it doesn't waste time parsing it again. It also means you can use === to compare queries to check if they are identical.

Importing graphQL files

To add support for importing .graphql/.gql files, see Webpack loading and preprocessing below.

Given a file MyQuery.graphql

query MyQuery {
  ...
}

If you have configured the webpack graphql-tag/loader, you can import modules containing graphQL queries. The imported value will be the pre-built AST.

import MyQuery from 'query.graphql'

Importing queries by name

You can also import query and fragment documents by name.

query MyQuery1 {
  ...
}

query MyQuery2 {
  ...
}

And in your JavaScript:

import { MyQuery1, MyQuery2 } from 'query.graphql'

Preprocessing queries and fragments

Preprocessing GraphQL queries and fragments into ASTs at build time can greatly improve load times.

Babel preprocessing

GraphQL queries can be compiled at build time using babel-plugin-graphql-tag. Pre-compiling queries decreases script initialization time and reduces bundle sizes by potentially removing the need for graphql-tag at runtime.

TypeScript preprocessing

Try this custom transformer to pre-compile your GraphQL queries in TypeScript: ts-transform-graphql-tag.

React Native and Next.js preprocessing

Preprocessing queries via the webpack loader is not always possible. babel-plugin-import-graphql supports importing graphql files directly into your JavaScript by preprocessing GraphQL queries into ASTs at compile-time.

E.g.:

import myImportedQuery from './productsQuery.graphql'

class ProductsPage extends React.Component {
  ...
}

Webpack loading and preprocessing

Using the included graphql-tag/loader it is possible to maintain query logic that is separate from the rest of your application logic. With the loader configured, imported graphQL files will be converted to AST during the webpack build process.

Example webpack configuration

{
  ...
  loaders: [
    {
      test: /\.(graphql|gql)$/,
      exclude: /node_modules/,
      loader: 'graphql-tag/loader'
    }
  ],
  ...
}

Create React App

Preprocessing GraphQL imports is supported in create-react-app >= v2 using evenchange4/graphql.macro.

For create-react-app < v2, you'll either need to eject or use react-app-rewire-inline-import-graphql-ast.

Testing

Testing environments that don't support Webpack require additional configuration. For Jest use jest-transform-graphql.

Support for fragments

With the webpack loader, you can import fragments by name:

In a file called query.gql:

fragment MyFragment1 on MyType1 {
  ...
}

fragment MyFragment2 on MyType2 {
  ...
}

And in your JavaScript:

import { MyFragment1, MyFragment2 } from 'query.gql'

Note: If your fragment references other fragments, the resulting document will have multiple fragments in it. In this case you must still specify the fragment name when using the fragment. For example, with @apollo/client you would specify the fragmentName option when using the fragment for cache operations.

Warnings

This package will emit a warning if you have multiple fragments of the same name. You can disable this with:

import { disableFragmentWarnings } from 'graphql-tag';

disableFragmentWarnings()

Experimental Fragment Variables

This package exports an experimentalFragmentVariables flag that allows you to use experimental support for parameterized fragments.

You can enable / disable this with:

import { enableExperimentalFragmentVariables, disableExperimentalFragmentVariables } from 'graphql-tag';

Enabling this feature allows you to declare documents of the form.

fragment SomeFragment ($arg: String!) on SomeType {
  someField
}

Resources

You can easily generate and explore a GraphQL AST on astexplorer.net.

graphql-tag's People

Contributors

abernix avatar abhiaiyer91 avatar benjamn avatar czert avatar dependabot[bot] avatar detrohutt avatar gajus avatar greengremlin avatar greenkeeper[bot] avatar heldr avatar helfer avatar hwillson avatar jamiter avatar jnwng avatar michaeldeboey avatar michalkvasnicak avatar mitchiemt11 avatar mquandalle avatar olleolleolle avatar patrickjs avatar phryneas avatar pleunv avatar poincare avatar powerkiki avatar rocwang avatar sachag avatar stonexer avatar svc-secops avatar tmeasday avatar wtgtybhertgeghgtwtg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graphql-tag's Issues

Combine mutations

Hi,

I'm struggling the best way to understand how to do this. There is not much documentation for this lib.

In short i have a dynamic amount of mutations I need to preform in a single operations/call. I was trying to figure out some how i can dynamically build these or concat two qgl mutations together?

Any ideas?

TypeError: Cannot read property 'body' of undefined - Fragment in *.graphql file does't load

You can take a look on example here fokot/GitHunt-React@962e568

import PostedByFragmentFromFile from './PostedByFragment.graphql';
 
 const PostedByFragmentInline = gql`
     fragment PostedByFragment on Entry {
       postedBy {
          html_url
          login
       }
     }
   `;
 
  RepoInfo.fragments = {
    entry: gql`
      fragment RepoInfo on Entry {
          stargazers_count
          open_issues_count
        }
      ...PostedByFragment
      }
    ${PostedByFragmentFromFile}
    `,
  };
  
// ^^^ PostedByFragmentFromFile does not work but PostedByFragmentInline works

If fails with error

result += args[i].loc.source.body;
TypeError: Cannot read property 'body' of undefined

Also botch fragment looks almost the same.

Webpack loader imports fragment multiple times when querying an interface

I'm having an issue where the webpack loader loads the fragment multiple times in certain instances.

This is my setup:

# schema
interface Foo {
  bar: String!
}

type FooBar implements Foo {
  bar: String!
}

type OtherFooBar implements Foo {
  bar: String!
}



# Query.graphql
#import 'FragmentOne.graphql'
#import 'FragmentTwo.graphql'
query Test {
  ...FragmentOne
  ...FragmentTwo
}



# FragmentOne.graphql
#import 'FragmentThree.graphql'

fragment FragmentOne on FooBar {
  ...FragmentThree
}



# FragmentTwo.graphql
#import 'FragmentThree.graphql'

fragment FragmentTwo on OtherFooBar {
  ...FragmentThree
}



# FragmentThree.graphql
fragment FragmentThree on Foo {
  bar
}

Result:

query Test {
  ...FragmentOne
  ...FragmentTwo
}

fragment FragmentOne on FooBar {
  ...FragmentThree
}

fragment FragmentThree on Foo {
  bar
}

fragment FragmentTwo on OtherFooBar {
  ...FragmentThree
}

fragment FragmentThree on Foo {
  bar
}

Expected resultย (with de-duping):

query Test {
  ...FragmentOne
  ...FragmentTwo
}

fragment FragmentOne on FooBar {
  ...FragmentThree
}

fragment FragmentTwo on OtherFooBar {
  ...FragmentThree
}

fragment FragmentThree on Foo {
  bar
}

FragmentThree is being included multiple times which is throwing an error since each fragment is only allowed to be defined once.

Can I add variables through template literal?

I am trying to write a complex mutation with pieces that are dynamically created. I'm wondering:

(a) Is it okay to do something like this with the dynamic creation of mutations,

(b) can I use variables from js directly in my template literals? Or do I need to pass them as graphQL variables? ex:

const createEvent = (existing, event) => gql`
  mutation logEvent {
    createEvent(
      channel: "${event.channel}"
      metadata: ${JSON.stringify(event.metadata)}
      segmentId: "${event.messageId}"
      timestamp: "${event.timestamp}"
      type: ${event.type === 'page' ? 'PAGEVIEW' : 'TRACK'}
      userId: "${event.anonymousId}"
      ${createProjectVersion(existing, event.properties.version)}
      ${createPage(existing, event.context.page)}
      name: "${event.name}"
      ${createIpAddress(existing, event)}
    ) {
      id
    }
  }
`;

const createPage = (existing, page) => {
  if (existing.pages[0]) return `pageId: "${existing.pages[0].id}"`;
  return `
    page: {
      path: "${page.path}",
      url: "${page.url}",
      title: "${page.title}"
    }
  `;
};

here you can see that createPage is dynamically creating either a nested update or a reference to a page. I am seeing an error on metadata that it expected type Json! but got undefined. I'm guessing this is because it is not a graphQL defined variable? Or maybe my JSON isn't parsing correctly. Any help here would be appreciated.

External fragments are not pulled into the query document using the loader.

The fragments are not pulled into the query document using the loader.

Example:

# ContactFragment.gql
fragment Contact on ContactType {
    phone
    email
}
# UserInfo.gql
fragment UserInfo on UserInfoType {
    id
    name
    contact {
        address
        ...Contact
    }
}
# User.gql
query User($email: String) {
  user(email: $email) {
    ...UserInfo
  }
}
# Users.gql
query Users($emails: [String]) {
  users(emails: $emails) {
    ...UserInfo
  }
}
// Both of the following Nodes fail when used with apollo client.
The error is: `Unknown fragment \"UserInfo\".`

const UserQueryNode: DocumentNode = require('graphql-tag/loader!../../graphql/User.gql');
const UsersQueryNode: DocumentNode = require('graphql-tag/loader!../../graphql/Users.gql');

The apollo-codegen handles the above scenario well when generating the schema.ts file.
However, graphql-tag/loader is unable to insert the fragments in this example.

One thing to notice is that graphql-tag/loader works well when the fragments are also located in the same file as the query that is referencing them.

The fragments should be pulled in via the loader, however, that is not the case as per this issue.

So, we need the fragments to be in separate files and apollo-codegen handles them properly when compiling the schema.ts. We just have to ensure that the loader in this module is also properly including them in each query.

=====
Version:
"graphql-tag": "^1.2.4",
node: 6.9.5
os: darwin x64

Maximum call stack size exceeded

I have to use the null as value in mutations. Therefore I cloned the repository and packaged it.

Now in parse.js line 488 in the function parseValueLiteral accepts null as value. But when I use it in the browser i get the error:

RangeError: Maximum call stack size exceeded
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:77:19)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)
    at stripLoc (https://localhost:9000/lib/graphql-tag/browser.js:105:26)

To use Graphql-tag in the browser I used browserify (browserify index.js --standalone graphqlTag -o=browser.js).

In my file line 77 is:function stripLoc (doc, removeLocAtThisLevel) {.

Line 105 is

if (valueType === '[object Object]' || valueType === '[object Array]') {
     doc[keys[key]] = stripLoc(value, true);
}

in function stripLoc.

v1.3 and v2.0

wanted to write down what i'll be prepping in the next few days for posterity so people aren't waiting unnecessarily for their issues to get resolved.

there's a couple of issues with the upcoming minor / major versions of graphql-tag, in particular, we want to move graphql-js to be an external dependency and no longer bundled within graphql-tag. however, this is a fairly major change since it will

  1. introduce a new, potentially larger set of dependencies from graphql
  2. removes two previously exported values from the graphql printer and parse (print and parse, respectively) that others may depend on (in particular, apollo-client, react-apollo, and angular-apollo

however, upgrading the bundled version of graphql within graphql-tag is important since it resolves issues that were resolved upstream like #47. we also want to make sure we're deprecating the fields we're removing from the graphql-tag module.

thus, here's what's coming in v1.3 and v2.0:

v1.3

v1.3 will contain a bundled version of graphql@^0.9.0, as well as deprecation notices for both print and parse.

  • this will resolve #47 for those who want to stay with the bundled version of graphql

v2.0

v2.0 will contain the changes currently in master to move from using the bundled version of graphql to establishing graphql as a peerDependency. we'll also remove the previously mentioned exports

  • this will resolve #49

v1.3 is straightforward and will get done earlier rather than later, and v2.0 may take a little bit of testing to make sure it doesn't bloat our upstream clients (i'll start with a beta release of 2.0 and see how it interacts with apollo-client)

/cc @stubailo and @helfer

EDIT: if you're using one of the deprecated exports, you should use graphql/language/parser and graphql/language/printer moving forward (graphql-tag will be using those too in v2.0)

Weird webpack loader caching issue

I successfully refactored my setup to import the GraphQL types from a seperatetypes.graphql file using the webpack loader. At first this worked fine.

For some reason, when I change the contents of the imported file to add more types, etc. and webpack rebuilds, it seems to import a cached version of the old contents. This results in errors because the resolvers and everything else is out of sync with the types.

If I rename the filename to types2.graphql and update the import to import types from './types2.graphql', it pulls in the new contents fine. Renaming back results in the original errors.

Using the latest versions of graphql-tag and webpack v2.

Until this is resolved I will have to refactor back to using template literals and drop the loader.

Feature request: import fragments by reference

It would be very convenient if I could reference a fragment by value inline. An example:

const myFragment = gql`
fragment MyFragment on Widget {
  name
  gizmo { id }
}
`;

const myQuery = gql`
query MyQuery {
  id
  widgets {
    ...${myFragment}
  }
}
`

Which of course would result in this query:

query MyQuery {
  id
  widgets {
    ...MyFragment
  }
}
fragment MyFragment on Widget {
  name
  gizmo { id }
}

Compare to the current standard:

const myQuery = gql`
query MyQuery {
  widgets {
    id
    ...MyFragment
  }
}
${myFragment}

Note that I have to include the fragment in two different places by two different names. Combined with the fact that fragments are usually in different files, this adds quite a bit of unnecessary friction and uncertainty to referencing a fragment.

[loader] Add "use strict" or document node 6 requirement

I get the following error when using the loader in webpack 2 with node 4.6.1:

Module build failed: SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode

This can be fixed by adding "use strict"; to the top of loader.js or switching to node 6. I'm not sure if you want to add strict mode or document the requirement.

webpack fragment composition from a component perspective

This is just a question.

I'm coming from a year's worth of work on a large Relay project. I'm currently exploring Apollo and when I encountered the GraphQL webpack loader, my first thoughts are that it looks great! I see that fragment composition is a new feature to the loader, so perhaps my question is not yet implemented or just the API is not quite solidified yet, etc. Maybe also the workflow is not quite the same as Relay.

With the webpack loader, I have initially been just writing large queries for each of my URL routes. Essentially, I have some "page view" components that all have their own GraphQL query. All data is fetched at that component and passed down to children as props where needed.

As my project is growing, I was going to begin delegating data requirements out to smaller components via fragments. Each component would just define a fragment that requests the needed fields - "the Relay way". Because I've got my GraphQL queries in their own files and webpack goes ahead and compiles them, I appear to lose the ability to compose child fragments into these parent queries, though.

I see that the recently added feature would allow me to #import fragments from within the GraphQL query file, and compose right there, but this is not the same as composing via your tree of child components. This current #import approach requires me to create X number of known parent queries that know which fragments to compose in right then at compile time. Correct?

In the end, I'd still just end up with a specific "master query" for each URL route that composes in whatever fragments I determine I need before-hand, which makes me wonder why even use fragments with this approach? I'd lose the somewhat dynamic composition of the Relay way, with fragments in components and their parents composing them in, right?

Webpack loader fragment auto-resolution

Regarding #import "my-fragment.gql" (#33) vs auto-resolving/loading fragments from the project where necessary. Bringing this in from a discussion from Twitter/Gist.

Suggestion: Instead of manually #importing files to load fragments for a query/mutation, rather have the webpack loader automatically include them by auto-discovering them in the project.


@armstrjare says:

If the fragments are stored in different parts of file tree, it's a pain to have to manually import them and maintain imports if refactoring etc.

#import '../../contacts/contact.fragment.gql'

Considering:

  1. Code generation via apollo-codegen assumes all fragments and queries are uniquely named
  2. Adding custom preprocessers makes things apollo-specific
  3. This adds extra developer overhead to splitting fragments into multiple files

Why doesn't the loader operate in the following way:

// webpack settings
graphqlLoader {
  // Define any paths/globs where the loader should try and resolve fragments from if they are used without being defined inline in the query files.
  resolvePaths: ['app/**/*.gql']
}

Loader semantics:

  1. Import passes through the loader
  2. Loader reads the file, and parses the query.
  3. Walks the query to see if there need to be any fragment imports that aren't defined inline
  4. If there are any unresolved Fragments, walk the resolvePaths, loading & parsing docs, to build up map of all defined fragments across the app. (Can cache this so don't need to repeat it on subsequent requires)
  5. Insert the just the additional fragments needed for the query into the parsed document structure.
  6. Return the document structure.

To me this:

  1. Eliminates the need for #import preprocessor (IMO this adds redundant complexity to the syntax, and extra managing of import paths etc., and it's non-standard)
  2. Keeps each loaded query minimal - each required file will only be the exact data needed for the query.

Thoughts?


@stubailo responds:

Does this require somehow computing file paths from the fragment names? Or is there a way to do it without that?

As a side note though if explicit imports are a good idea for JavaScript code why not for GraphQL queries as well? Both (1) and (2) apply to JS code just as much, and historically people have always chosen explicit importing over global namespaces.


@armstrjare responds:

Does this require somehow computing file paths from the fragment names? Or is there a way to do it without that?

Not at all - the loader would need to load and parse all resolved graphql files in the project, to determine what "fragments" are available to be used in the application. Only the extension/matcher is relevant - the rest of the info is purely based on the GQL in the file.

As a side note though if explicit imports are a good idea for JavaScript code why not for GraphQL queries as well? Both (1) and (2) apply to JS code just as much, and historically people have always chosen explicit importing over global namespaces.

Well, afaik this is because of the semantics of JS modules being isolated in scope and adding them on top of the existing JS runtime. Are explicit imports for all tokens needed because of this, rather than "we're going to do it this way in order to have explicit imports"?

If there was some form of "method missing" on the global scope (a la Ruby) then I wonder if autoloading would implemented along the lines of, say, how Rails does it?

With GQL we also have the benefit of it not being a programming language, but a data structure/definition. So we're not really comparing apples with apples. I'm not sure the same expectations apply?

There are some downsides of doing implicit fragment resolution though, but I think they outweigh the benefits:

  1. Fragments would be required to be uniquely named - or have some semantics on overloading

Are people even naming different fragments with the same name? As above, all the code-generation tools I've seen assume that all fragments are uniquely named. Is a reasonable constraint? Noting there is no concept of a GraphQL module or scope in the spec (?), and in GraphQL itself all Types are expected to be uniquely named.

  1. Need to load all GQL files in order to determine which fragments are available to be used.
    I'm not sure this is really an issue as a) files are generally pretty small; b) parsing is pretty fast; c) it can be loaded once for the first require() and then cached for future requires

const keyword causing errors with IE <= 10

The parseDocument function uses the const keyword, which causes issues with browsers that don't currently support it, e.g. IE <= 10.

I can get around it by using babel-loader for the graphql-tag package, but I want to say the ideal would be to resolve this at the package level.

function parseDocument(doc) {
  if (cache[doc]) {
    return cache[doc];
  }

  const parsed = parse(doc);

  if (!parsed || parsed.kind !== 'Document') {
    throw new Error('Not a valid GraphQL document.');
  }

  cache[doc] = parsed;

  return parsed;
}

Nested fragments

Hi,

I wanted to nest a fragment in another fragment.
Just like this. https://learngraphql.com/basics/fragments/4
Is this possible with this package? It seems it is not working with my project which is on top of one of the starters I'm using, which depends on this package.
Or maybe a upcoming feature?

I tried to search all the issues here and couldn't find a similar discussion.

Oh I'm using v2.0.0

Publish as UMD

I want to use graphql-tag inside a React Native web player, but when I include it using https://unpkg.com/[email protected], I get the error message

parse is not a function

I suspect it comes from this function call and it seems that this CommonJS import is not working in the browser.

According to the unpkg documentation, we would need to publish a UMD version of graphql-tag to npm to make that work. Unfortunately I couldn't find more information on how to create a UMD version of a module.

Here's the steps needed as per the unpkg documentation:

  • Add the umd (or dist) directory to your .gitignore file
  • Add the umd directory to your files array in package.json
  • Use a build script to generate your UMD build in the umd directory when you publish

An in-range update of mocha is breaking the build ๐Ÿšจ

Version 3.4.1 of mocha just got published.

Branch Build failing ๐Ÿšจ
Dependency mocha
Current Version 3.4.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As mocha is โ€œonlyโ€ a devDependency of this project it might not break production or downstream projects, but โ€œonlyโ€ your build or test tools โ€“ preventing new deploys or publishes.

I recommend you give this issue a high priority. Iโ€™m sure you can resolve this ๐Ÿ’ช

Status Details
  • โŒ continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Release Notes Ohai CRLF...

Fixed a publishing mishap with git's autocrlf settings.

Commits

The new version differs by 3 commits0.

false

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot ๐ŸŒด

Add typescript definitions

For now, in some use cases, TS (in atom) warns: Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'string'. for using gql like this:

gql` ... `

Ensure unique fragment names

Because we aren't going to be relying on createFragment anymore, how do we ensure that a created GraphQL document doesn't have duplicate fragment names that are actually different fragments?

createFragment did this by validating that any fragments with the same name are actually identical. We could reproduce that here.

Which license?

Hi,

under which license is graphql-tag released?

Thanks,
Fabian

The webpack loader doesn't work, does it ?

I have included in my loaders list:

  {
    test: /\.(graphql|gql)$/,
    exclude: /node_modules/,
    loader: 'graphql-tag/loader'
  },

And then I import my query like this

import myquery from '../../graphql/myquery.gql'

I know that the loader parses the .gql file, because when the query is misspelled, I get an error.
However in my code I get a plain text string:

console.log(myquery)

data:application/octet-stream;base64,dmFyIGRvYyA9IHsia2luZCI6IkRvY3VtZW50IiwiZGVmaW5pdGlvbnMiOlt7ImtpbmQiOiJPcGVyYXRpb25EZWZpbml0aW9uIiwib3BlcmF0aW9uIjoicXVlcnkiLCJuYW1lIjp7ImtpbmQiOiJOYW1lIiwidmFsdWUiOiJmdWxsUHJvcGVydHkifSwidmFyaWFibGVEZWZpbml0aW9ucyI6W3sia2luZCI6IlZhcmlhYmxlRGVmaW5pdGlvbiIsInZhcmlhYmxlIjp7ImtpbmQiOiJWYXJpYWJsZSIsIm5hbWUiOnsia2luZCI6Ik5hbWUiLCJ2YWx1ZSI6ImlkIn19LCJ0eXBlIjp7ImtpbmQiOiJOb25OdWxsVHlwZSIsInR5cGUiOnsia2luZCI6Ik5hbWVkVHlwZSIsIm5hbWUiOnsia2luZCI6Ik5hbWUiLCJ2YWx1ZSI6IklEIn19fSwiZGVmY [...]

Does it work on your side? I'm on [email protected] and I'm using babel too (don't know if this is related or not).

Passing array of fragments in query fails

Passing array of fragments to query fails, e.g.:

query SomeQuery {
  field {
     someRuntimeGeneratedFieldsOnFragments
  }
}
${arrayOfFragments}

with error

Syntax Error GraphQL (25:1) Unexpected [

24: }
25: [object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
    ^
26: 

It is working as expected when using createFragments + fragments option in apollo-client, which is being deprecated in next version.

graphql-tag/loader fails in Webpack 2

In Webpack 2, this config:

module: {
  loaders: [
    // GraphQL .gql parser
    {
      test: /\.gql$/,
      exclude: /node_modules/,
      loader: 'graphql-tag/loader',
    },
  ],
},

... yields:

/Users/leebenson/dev/repo/front/node_modules/webpack-config/dist/Config.js:101
throw _iteratorError;
^
TypeError: Cannot read property 'plugins' of undefined
at Config.rootClientJs (/Users/leebenson/dev/repo/front/webpack/dev.js:12:5)
at /Users/leebenson/dev/repo/front/node_modules/webpack-config/src/ConfigExtendCommand.js:80:50
at Array.forEach (native)
at /Users/leebenson/dev/repo/front/node_modules/webpack-config/src/ConfigExtendCommand.js:79:28
at /Users/leebenson/dev/repo/front/node_modules/webpack-config/src/ConfigExtendCommand.js:74:50
at Array.forEach (native)
at ConfigExtendCommand.execute (/Users/leebenson/dev/repo/front/node_modules/webpack-config/src/ConfigExtendCommand.js:70:27)
at executeCommand (/Users/leebenson/dev/repo/front/node_modules/webpack-config/src/Config.js:48:17)
at Config.extend (/Users/leebenson/dev/repo/front/node_modules/webpack-config/src/Config.js:225:16)
at Object. (/Users/leebenson/dev/repo/front/webpack/dev.js:10:29)
at Module._compile (module.js:570:32)
at loader (/Users/leebenson/dev/repo/front/node_modules/babel-register/lib/node.js:144:5)
at Object.require.extensions.(anonymous function) as .js (/Users/leebenson/dev/repo/front/node_modules/babel-register/lib/node.js:154:7)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)

Fragment definitions within a graphql document ought to be unique.

This is a rehash of apollo-client#906, introduced again because the new fragment interpolation pattern doesn't go through the addFragmentsToDocument method that we fixed in apollo-client#913 to remove duplicate fragments.

While a recent change in graphql-tag no longer "warns" when duplicate fragments are in a document, we should probably strip the duplicate fragment from the document altogether in either graphql-tag or apollo-client since this will through errors when getting parsed on the server. Optionally we could consider stripping duplicate fragment definitions from the document altogether; although in the aforementioned commit, @tmeasday says

Note that we are simply checking fragment strings for equality, not ensuring that fragment definitions within the larger graphql document have exact equality. We could do the above, but it'd be quite a bit more complicated, and I'm not sure if there's much benefit. AFAICT the main reason for wanting that before was exactly this functionality.

Steps to Reproduce

Interpolating multiple fragments into the same document generates an invalid GraphQL document:

query {
   ...SomeFragment
}
${SomeFragment}
${SomeFragment}

generates a document like

query {
  ...SomeFragment
}
fragment SomeFragment on SomeResource {
  field
}
fragment SomeFragment on SomeResource {
  field
}

which is invalid (and a server may choke on an invalid GraphQL doc).

I filed this here instead of in apollo-client as the related commit I mentioned above asks why there'd be a benefit to de-duplicating fragments within the document, but this happens more often when the same fragment gets interpolated into the same document twice from different places in the query, not necessarily that the fragment itself is already defined in the document.

Babel plugin for graphql-tag

I was thinking that a babel plugin could be a useful addition to graphql-tag. It would be of the same scope and capabilities of the webpack loader, simply parsing queries into an AST ahead of time, but allowing the queries to reside in the .js file. No ideas yet on how to handle referenced fragments, but the implementation should be simple for queries and mutations that don't require that capability.

Prior work

babel-plugin-graphql is similar in scope, but works differently. Can't share much code other than the boilerplate.
babel-relay-plugin is far more complex and actually validates the query against the schema. This capability is annulled by eslint-plugin-graphql

Implementation

I haven't written a babel plugin before, but after messing around in astexplorer.net for a little bit, it wouldn't be too hard. Plan would be to traverse the AST and look for tagged template literals that are identified with gql. Then the contents of the literal would be passed through graphql-tag's gql. The resulting object would then be recursively traversed converting it's properties to the corresponding babel node.

What are some thoughts on this idea and approach?

Move Webpack Loader to its own repository

I've been working on the included webpack loader to add support for @import directives and am thinking that it could be worth moving the loader to its own repository. Beyond @import support I have some ideas for adding options and using the loader as a tool to incorporate persisted queries and custom scalars. As the loader becomes more complex and feature-rich, it could be worth moving to its own repository.

About output as `request body`

I'm not sure can it convert

const mutation = `mutation {
    add(title: "foo") {
      id
      title
    }
}`

to request body

{"query":"mutation {\n  add(title: \"bar\") {\n    id\n    title\n  }\n}\n","variables":null}

Is that doable by this tool or I need other tools?

Thanks

Module build failed: GraphQLError

I couldn't understand the error , I added graphq-tag to parse the .graphql in webpack config file as shown below

      test: /\.(graphql|gql)$/,
      exclude: /node_modules/,
      loader: 'graphql-tag/loader',
    }
ERROR in ./src/modules/goin_users/client/graphql_queries/user_graphql_queries.graphql
[2] Module build failed: GraphQLError
[2]     at syntaxError (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/bundledParser.js:1349:16)
[2]     at unexpected (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/bundledParser.js:1043:34)
[2]     at parseDefinition (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/bundledParser.js:206:10)
[2]     at parseDocument (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/bundledParser.js:160:23)
[2]     at parse (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/bundledParser.js:97:11)
[2]     at parseDocument (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/index.js:125:16)
[2]     at gql (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/index.js:158:10)
[2]     at Object.module.exports (/home/sairam/Downloads/goin/goin/node_modules/graphql-tag/loader.js:27:18)

Support Field Descriptors

I received the following report concerning Field Descriptors: Swydo/meteor-graphql#4


Consider the example:

test.graphql:

#import './channel.graphql'
#import './user.graphql'

# test type description
type Query {
  # test field description
  channels: [Channel],
  # test field description
  user: User,
}

GraphiQL shows "No Description" for all types and fields. Do I need to do some sort of configuration to get the descriptions to show up?


I would have expected the descriptions to be there because the loader in this packages uses the graphql-js parser, which is aware of the comments as descriptors since this commit: graphql/graphql-js@331dc77

It's possible to manually add this feature by using the getDescription function and applying it when parsing the document before stripLoc is applied.

The question is, why is this necessary and not available by default?

I could make a PR showing a working version of this. Al that is needed is using the getDescription funciton:

var parser = require('graphql/language/parser');
var buildASTSchema = require('graphql/utilities/buildASTSchema');

var parse = parser.parse;
var getDescription = buildASTSchema.getDescription;

// ...

function stripLoc(doc, removeLocAtThisLevel) {
  // ...

  if (!doc.description) {
    var description = getDescription(doc);

    if (description) {
      doc.description = description;
    }
  }

  // ...
}

Let me know if I'm overlooking something here.

graphql-tag/loader with webpack hot load

   
    ERROR in ./src/components/role/projects.graphql
    Module parse failed: /Users/hezhiqiang/webpack2/src/components/role/projects.graphql Unexpected token (1:6)
    You may need an appropriate loader to handle this file type.
    | query RoleIndex {
    |   roles {
    |     id
     @ ./src/components/role/RoleIndex.js 21:0-49
     @ ./src/App.js
     @ ./src/index.js
     @ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server babel-polyfill react-hot-loader/patch ./src/index

Compile time no errors, but when modify a module that include the .graphql file, the error raised.

Webpack version: 2.4.1

Is it possible to import types inside graphql files?

I was trying to find the best way to modularize my app by splitting my schema file.

I was thinking that the #import decorator from graphql-tag/loader was simply concatenating files, but it looks like it works with fragments only?

Or is there a way to import types inside .graphql files?

How could I make something like this work?

Author.graphql

type Author {
    id: Int! # the ! means that every author object _must_ have an id
    firstName: String
    lastName: String
    posts: [Post] # the list of Posts by this author
}

Schema.graphql

#import "./Author.graphql"

type Post {
    id: Int!
    title: String
    author: Author
    votes: Int
}
# the schema allows the following query:
type Query {
    posts: [Post]
    author(id: Int!): Author
}
# this schema allows the following mutation:
type Mutation {
    upvotePost (
        postId: Int!
    ): Post
}

at the moment it fails with error:

mamluk@mamluk-X1:~/Projects/volcano/ServerQL$ node dist/bundle.js
/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:18651
      throw new Error('Type "' + typeName + '" not found in document.');
      ^

Error: Type "Author" not found in document.
    at typeDefNamed (/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:18651:13)
    at produceType (/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:18621:19)
    at produceOutputType (/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:18630:46)
    at /home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:18703:15
    at /home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:9237:31
    at Array.reduce (native)
    at keyValMap (/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:9236:15)
    at makeFieldDefMap (/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:18699:36)
    at fields (/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:18690:16)
    at resolveThunk (/home/mamluk/Projects/volcano/ServerQL/dist/bundle.js:280:40)

Typescript: import fail: Cannot find module 'query.gql'

This is a reopen of #42 .

Nothing has changed, it's just that the presence of a workaround is not a fix.

As described before, attempts to import a graphql module result in Cannot find module.... Using require instead of import, eg:

const query = require('gql/Query.gql');

works fine... up to a point. Somewhere, the Apollo graphql decorator performs a deep copy of the query The query DocumentNode returned above includes a default element that has itself as a property. As a result, the deep copy blows out with a soft stack overflow. So the full workaround is:

const query = require('gql/Query.gql'); delete query['default']

It's possible that the default problem is dependent on the tsconfig.json setting:

"allowSyntheticDefaultImports": true

I need it for other reasons, and was unable to easily test with it turned off.

Can't load .graphql files with webpack loader : Cannot read property 'filter' of undefined

Hi,
I am having errors when using webpack loader to load .graphql files :

Uncaught TypeError: Cannot read property 'filter' of undefined
    at Object.parser (parser.js:12)

When debugging, i saw that for some calls to parser function, document is just a base64 string representation and not a valid object.

var fragments = document.definitions.filter(function (x) { return x.kind === 'FragmentDefinition'; });

split('/n') does not work on Windows

The loader fails to process fragments correctly on Windows because split('\n') does not work there. Modifying it to use split('\n\r') works, however. So, you need to determine the correct newline/carriagereturn characters in a platform independent way.

Unexpected name "null" when null is provided to an arguments

I have a use case where i'm trying to get root nodes of a tree represented in a relational database - i've used GraphQL to wrap around Sequelize.

To achieved this, I want to pass "null" as an argument to my GraphQL server as part of the query - according to the GraphQL spec null parameter values are allowed (http://facebook.github.io/graphql/#sec-Null-Value). However, graphql-tag seems to throw the following error when parsing the query:

Syntax Error GraphQL (2:25) Unexpected Name "null"
1: query {
2: taxon(parentId: null) {
^
3: id,

I have a workaround for this issue - but just wondered whether it was intended functionality?

Thanks,

Alan

2.0 Broken Imports

After upgrading to 2.0 I started getting this error

ERROR in ./~/react-apollo/lib/browser.js
Module not found: Error: [CaseSensitivePathsPlugin] `/src/node_modules/graphql-tag/index.js` does not match the corresponding path on disk - File does not exist.
 @ ./~/react-apollo/lib/browser.js 13:20-42

This import happens in any file that imports this package.

[Feature request] Allow converting from schema to query syntax

Hi guys,
I've been using graphql-tag in production for a few weeks and it's great ! With the webpack loader, it becomes very neat. Lately, I've found that I spent too much time rewriting(copy-pasting) stuff from GraphiQl in order to build my .graphql files.

So it would save me a lot of time if I could have a tool to automatically generate .graph files against a graphql schema in .json (introspection query). I search a lot, but it seems to me that for now, no such things exists.
Don't know if it fits the scope of this package, but it def be a nice addition to the toolbox. You guys have any idea if it exist yet ? or maybe some advice to help me build such a tool ?

Thanks.

Typescript 2.0.6 breaks gdl definition

In Visual Code 1.7.1, using Typescript 2.0.6, we get back the error reported in #1 : Argument of type 'TemplateStringsArray' is not assignable to parameter of type 'string[]'.

The correct definition in index.d.ts seems to be :
export default function gql(literals: TemplateStringsArray, ...placeholders: Array): Document;

Breaking change in 0.1.17?

I was using graphql-tag 0.1.16 along apollo-client 0.5.0, then updated to 0.1.17 and 0.5.6 respectively, which introduced the following TypeError: Cannot read property 'kind' of undefined raised from graphql-tag on GraphQL mutations.

This is what my mutation looks like:

  apollo.mutate({
      mutation: gql`
        mutation {
          newEntry(input: {
            name: "${entry.name}",
            description: "${entry.description}"
          }) {
            entryInfo {
              name,
              description
            }
          }
        }
      `
    });

Though I'm really new to GraphQL so I'm afraid I can't get what kind could refer to :/

Stop bundling GraphQL js

Now that the bundling errors have been fixed we should remove the bundled code from this repo again and test that it still works in react native.

Typescript error: cannot find module 'graphql-tag/printer'

I am building an angular2 app and I am getting the following errors when I build:

TypeScript error: /Users/scott/Documents/showcase/client/node_modules/apollo-client/index.d.ts(3,23): Error TS2307: Cannot find module 'graphql-tag/printer'.
TypeScript error: /Users/scott/Documents/showcase/client/node_modules/apollo-client/middleware.d.ts(4,14): Error TS2304: Cannot find name 'RequestInit'.
TypeScript error: /Users/scott/Documents/showcase/client/node_modules/apollo-client/networkInterface.d.ts(25,12): Error TS2304: Cannot find name 'RequestInit'.
TypeScript error: /Users/scott/Documents/showcase/client/node_modules/apollo-client/networkInterface.d.ts(31,14): Error TS2304: Cannot find name 'RequestInit'.
TypeScript error: /Users/scott/Documents/showcase/client/node_modules/apollo-client/networkInterface.d.ts(35,68): Error TS2304: Cannot find name 'RequestInit'.

Does anyone have any suggestions? Should I just downgrade graphql-tag until typescript support is better?

V2 causes error in angular-cli

After updating to version 2, I got this error in angular-cli:

hashingcrypto.js:74
  this._handle.update(data, encoding);
               ^

TypeError: Data must be a string or a buffer

If I rollback to version 1.3.2 it works fine.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.