GithubHelp home page GithubHelp logo

apollographql / persistgraphql Goto Github PK

View Code? Open in Web Editor NEW
425.0 68.0 57.0 146 KB

A build tool for GraphQL projects.

License: MIT License

TypeScript 99.88% JavaScript 0.12%
graphql apollo-client middleware

persistgraphql's Introduction

PersistGraphQL

persistgraphql is a simple build tool that enables query whitelisting and persisted queries for GraphQL projects that use statically analyze-able GraphQL queries.

It scans a code directory and extracts GraphQL query documents from .graphql files. It then assigns these queries ID values/hashes and produces a JSON file which maps from queries to hashes/IDs. This map can then be used by the client and server to perform query whitelisting, query lookups (i.e. client only sends the hash/id, the server just looks up the corresponding query), etc.

The npm package also provides a network interface for Apollo Client that manages the query lookups in persistgraphql/lib/browser. To see how to extract the queries on the server, see the code snippets below.

Installation

For only the CLI tool:

npm install -g persistgraphql

As a dependency (for Apollo Client network interface):

npm install --save persistgraphql

Build Tool Semantics

The build tool binary is called persistgraphql. Running it with no other arguments should give:

Usage: persistgraphql input_file [output file] [--add_typename]

It can be called on a file containing GraphQL query definitions with extension .graphql:

persistgraphql queries.graphql

It can also be called on a directory, which it will step through recursively:

persistgraphql src/

By default, the output will be placed in extracted_queries.json. An output file can be specified as the second argument:

persistgraphql index.ts output.json

Adding Typenames to Extracted Queries

It can also take the --add_typename flag which will apply a query transformation to the query documents, adding the __typename field at every level of the query. You must pass this option if your client code uses this query transformation.

persistgraphql src/ --add_typename

Extracting Queries from TypeScript

To extract GraphQL queries from TypeScript files, use --js --extension=ts.

persistgraphql src/index.js --js --extension=ts

Extracting Queries from JavaScript

It is also possible to extract GraphQL queries from JavaScript files using --extension=js --js.

persistgraphql src/index.js --js --extension=js

Apollo Client Network Interface

This package provides an implementation of an Apollo Client network interface that provides persisted query support. It serves as a drop-in replacement for the standard network interface and uses the query map given by persistgraphql in order to send only query hashes/ids to the serverather than the query document.

This package also provides a way for you to alter any generic NetworkInterface to use persisted queries from a provided query map with the addPersistedQueries(networkInterface: NetworkInterface, queryMap: OutputMap) function. This overrides the query member function of your network interface instance to replace your query with an id based on the query map provided.

See the implementation as well as some documentation for it within src/network_interface/ApolloNetworkInterface.ts.

Server-side

If you use the client network interface provided by this package, you can quickly roll your own middleware to get the GraphQL query instead of the query ID that the network interface sends. Here's an example with Express using the lodash invert method:

import queryMap from ../extracted_queries.json’;
import { invert } from 'lodash';
app.use(
  '/graphql',
  (req, resp, next) => {
    if (config.persistedQueries) {
      const invertedMap = invert(queryMap);
      req.body.query = invertedMap[req.body.id];
    }
    next();
  },
);

Here's an example with a Hapi server extension using the lodash invert method:

import queryMap from ../extracted_queries.json’;
import { invert } from 'lodash';
server.ext('onPreHandler', (req: Request, reply) => {
  if (config.persistedQueries && req.url.path.indexOf('/graphql') >= 0 && req.payload.id) {
    const invertedMap = invert(queryMap);
    req.payload.query = invertedMap[req.payload.id]
  }
  return reply.continue();
});

persistgraphql's People

Contributors

benjie avatar chrisbujok avatar dimitri-koenig avatar dotansimha avatar helfer avatar jlengstorf avatar nnance avatar poincare avatar ramikhalaf avatar ravikiran438 avatar scallygames avatar sepehr500 avatar veeramarni 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  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

persistgraphql's Issues

Latest 0.3.3 release does not install

Installing this package appears to have broken in 50970f7

mdeltito@abc $ mkdir test && cd test && npm init
mdeltito@abc $ npm install --save persistgraphql
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
npm ERR! path /Users/mdeltito/code/test/node_modules/persistgraphql/bin/persistgraphql
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall chmod
npm ERR! enoent ENOENT: no such file or directory, chmod '/Users/mdeltito/code/test/node_modules/persistgraphql/bin/persistgraphql'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent

Allow to output readable format (no AST)

Hi,

I'd like to know if it is possible to extract the queries in a human readable form, instead of minified AST that is supposed to be shared between client and server.

My usecase is that I have graphql fragments everywhere and I use fragments composition, so it would be useful to be able to output the composed version of my queries so that I can play with the queries in a sandbox like Graphiql. Otherwise I have to do this composition manually and maintain it over time.

Here's the kind of output I'd like to have

query ReportEditionSynthesisShowQuery($reportEditionId: ID!) {
    reportEdition: ReportEdition(id: $reportEditionId) {
        id
        startDate
        endDate
        report {
            id
            name
        }
        contributions: answers {
            id
            ...SynthesisItemContribution
        }
        importantTopicContributions: topicAnswers(filter: {important: true}) {
            ...ImportantItemsTopicContribution
        }
        recipients {
            email
        }
    }
}


fragment ImportantItemsTopicContribution on TopicAnswer {
    id
    content
    contribution: answer {
        id
        user {
            id
            firstName
            lastName
            avatar
        }
    }
}

fragment SynthesisItemContribution on Answer {
    answerType
    user {
        ...SynthesisItemHeaderByUser
    }
    topicContributions: topicAnswers {
        ...SynthesisSectionsTopicContribution
    }
}

fragment SynthesisItemHeaderByUser on User {
    ...UserAlt
}

fragment UserAlt on User {
    id
    firstName
    lastName
    pictureUrl: avatar
    job
    color
    email
}


fragment SynthesisSectionsTopicContribution on TopicAnswer {
    topic {
        id,
        name
    }
    content
}

Here is my query defined in HOC (I did not include subcomponents but I can if needed)

const injectSynthesisData = Comp => {
  return graphql(gql`

      query ReportEditionSynthesisShowQuery($reportEditionId: ID!) {
          reportEdition: ReportEdition(id: $reportEditionId) {
              id
              startDate
              endDate
              report {
                  id
                  name
              }
              contributions: answers {
                  id
                  ...SynthesisItemContribution
              }
              importantTopicContributions: topicAnswers(filter: {important: true}) {
                  ...ImportantItemsTopicContribution
              }
              recipients {
                  email
              }
          }
      }
      
      
      ${ImportantItems.fragments.topicContribution}
      ${SynthesisItem.fragments.contribution}

  `,{
    options: (props) => ({
      variables: {
        reportEditionId: props.match.params.reportEditionId
      }
    }),
  })(Comp)
};

Docs about server middleware out of date

The README says "middleware for Express servers in persistgraphql/lib/server", but there's no middleware to be found.
It also says "These will likely be moved to their own packages in the future", which I assume already has happened. Where did they go?

Retain previously persisted queries for a number of subsequent builds[feature request]

One of the things keeping us from using this in our implementation is that existing published client builds would not be supported if a query goes away, or something reorders them. One thought as to how to handle this:

  • scan output file for already defined queries (production build would update this and store it in git).
  • queries in output file not in input scan are marked in some way (separate deprecation file with a count? Alteration to json structure to include a deprecated object which contains the old id?)
  • After fixed number of times going to the deprecation file, the query is removed from the json file, being replaced with a noop query (to block against id reuse)
  • new queries are then added to the end.

Big questions I see are how to handle deprecation data. A separate counts file is one option which could be committed along side the persisted json but stripped automatically from production builds by any tool which does any kind of dead code removal (as it's build tool metadata, not used code). Any query which is not in the current code gets checked/added to that counts file and once it is past x number of builds (which is a command line option) it gets removed.

Another option I see is to add deprecation data in place of the raw id number in the json. This won't affect a client consuming it, though in development perhaps the connection could understand that and emit a warning if a deprecated query is hit. Server side is where this changes the most, as the reversal isn't alone enough as the deprecation information put into the json would alter the key map.

Benefits to the two ways I see of storing deprecation information: Separate file:

  • No changes to APIs
  • Server handling remains really simple as a middleware with no code needed from this package

Same JSON:

  • Easy to implement various runtime checks in development for warnings
  • Server can monitor and log use of a query, allowing dev team to put it back in after build if it's still regularly used
  • Deprecation cutoff could theoretically be handled server side in code rather than in compile configuration.

This tool can only generate 1 query when scan a directory that contains multiple ".graphql" files

I have several ".graphql" files in 1 folder, and use persistgraphql ./src/graphql/ to generate the map json file, but the result is not correct.

P.S. They are valid ".graphql" files with correct syntax and can be used with webpack-graphql-loader.

The graphql files:

wx20180805-235104
graphql.zip

The json output:

{"mutation ($songID: Int, $playlistID: Int) {\n  removeSongFromPlaylist(SongID: $songID, PlaylistID: $playlistID) {\n    ID\n    ClassName\n    LastEdited\n    Created\n    Title\n    Description\n    NumberOfSongs\n  }\n}\n":1}

Server and client sync

It then assigns these queries ID values/hashes and produces a JSON file which maps from queries to hashes/IDs. This map can then be used by the client and server to perform query whitelisting

How server and client sync this map when on client was added new query?
It is not clear in Readme, please add more information.

Promise error catching block needed

Hi there

It took me a while to figure out that using nodemon this nice library/utility throws an 'Maximum call stack size exceeded' error, if you give it a change to do so :-)

I'll attach a PR to this.

Thx
Best
Dimitri

Support babel compiled AST.

I use babel-plugin-graphql-tag to compile my queries, this is used mainly so I can use aliases when importing GraphQL files. However this doesn't work with the build tool as it appears fragments are not being imported.

It would be helpful to be able to crawl precompiled AST JS so that crawling can be done on resolved documents (prevent having to bootstrap babel).

For instance, something like:

# Build persisted queries across babel compiled GraphQL.
persist-grapqhl ./lib/grapqhl --ast --extension=js
  • has-reproduction
  • feature
  • blocking
  • good first issue

Provide a webpack plugin [feature request]

It would be really nice if this tool would be available as a webpack plugin as well.

Graphql-tag has a loader module that it offers which I use extensively. I would love to have as an automatic part of my build a similar function with persisted queries.

I have a couple of theories about how this might function, they start out pretty much the same.

  1. Similar to extract text plugin with remove:false, offers a loader which is functionally a "pass through" but stores the results of previous loaders to use in the plugin
  2. Plugin emits a persisted query json that is parallel to emitted bundles. Plugin is aware of multiple bundles (through compiler information) to ensure that parallel ones have different ids.

Option 1 ends here. Option 2 goes one step further and does something like DefinePlugin to replace some kind of defined import with a json loader which has the json inlined.

Extracting from JS fails with "unhandled promise rejection"

I’m getting an error I’m not sure how to start debugging when trying to run persistgraphql on gql-tagged queries in a project:

$ persistgraphql src/client/containers/Test.js --add_typename
Using the add-typename query transformer.
(node:26286) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): GraphQLError: Syntax Error GraphQL (1:1) Unexpected <EOF>

1:
   ^

(node:26286) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I stripped down the file to make sure it wasn’t something else in my code:

import { gql } from 'react-apollo';

const QueryOne = gql`
  query TestQuery($id: String) {
    test(id: $id) {
      id
      name
    }
  }
`;

export default {
  QueryOne,
};

After looking through the tests, I believe this should work, so I’m not sure how or where this is failing. If this is a bug and not an issue with how I'm using it, I'm happy to contribute — just need a pointer to how I might start debugging.

Thanks!

How should we namespace open source queryTransformers?

First off, let me say thanks for the awesome codebase and toolkit! I am using it with Apollo 2.x now and am really enjoying the lighter network footprint!
To help others work with apollo-link-state and persistgraphql, I have a small queryTransformer which strips any fields with the @client directive, and I'd like to share it for others to use. Is there a repo naming pattern I should aim for, or anything like that?

ex: persistgraphql-query-transform-trim-client-fields

Thanks again!

Silently removing duplicate query names

Current behavior
When defining two queries with the same operation name, only the last one is kept. All other versions are removed.

Expected behavior
Two options:

  • Keep all versions
      • they have different content, thus being different queries that should get their own id each
      • no technical problem as the different strings take different indices on the object
      • convenient
      • can cause misinterpretations when doing performance analysis etc.
  • Throw error if duplicates names exist
      • prevents error
      • forbidding theoretically allowed syntax

Minimal reproduction
Run persistgraphql on

// bar.graphql
query foo {
    foo
    {
        bar
        foobar
    }
}

// baz.graphql
query foo {
    faz
    {
        baz
        fazbaz
    }
}

// result {"query foo {\n  faz {\n    baz\n    fazbaz\n  }\n}\n":1}

Minimal demo

git clone -b duplicate-operation-names https://github.com/
Aides359/persistgraphql
cd persistgraphql
npm install
npm run compile
npm start

How to handle active clients during re-deploys?

Hi, thanks for sharing this repo! Looks like lots of good work.

I've been doing some thinking about persisted queries as well (but not much doing). I'm curious how you'd handle this situation:

  • Many clients are out "in the wild" with persisted query IDs
  • You refactor the application, changing the data requirements and the graphql queries
  • You redeploy the application which now has new queries and new query IDs

For example, let's say you start with a .graphql file like

query getThing($id: ID!) {
  get(id: $id) {
    name
  }
}

And you run persistgraphql which generates a query map:

{"query getThing($id: ID!) {\n  get(id: $id) {\n    name\n  }\n}\n":1}

Then, later, you refactor the query:

  query getThing($id: ID!) {
    get(id: $id) {
-     name
+     title
    }
  }

And again, persistgraphql to get a map:

{"query getThing($id: ID!) {\n  get(id: $id) {\n    title\n  }\n}\n":1}

But now, ID 1 points at a new query, which may cause some clients to break! How should we avoid that?

The only thing I can think of is: never change or remove a persisted query until you're sure no outstanding clients depend on it. Instead of changing queries, always add new ones. Do we have any other tools to help in this case?

Sorting of fragments in getQueryDocumentKey incorrect

I am having issues with multiple, nested fragments where the query string produced by getQueryDocumentKey doesn't match the run-time query. The mismatch lies in the sorting of the fragments.

This is the query that is sent:

query routeQuery($path: String!) {
  routeByPath(path: $path) {
    object {
      ...BasicPageFragment
      __typename
    }
    __typename
  }
}

fragment BasicPageFragment on NodeBasicPage {
  lead: fieldPageLead
  title: entityLabel
  content: fieldPageContent {
    ...PageContentFragment
    __typename
  }
  __typename
}

fragment PageContentFragment on Paragraph {
  id
  ...CopyTextFragment
  ...AccordionFragment
  __typename
}

fragment CopyTextFragment on ParagraphCopytext {
  text: fieldParaText
  __typename
}

fragment AccordionFragment on ParagraphAccordion {
  container: fieldAccordionContainer {
    ... on ParagraphAccordionItem {
      id
      title: fieldParaTitle
      subtitle: fieldParaSubtitle
      content: fieldParaContent {
        id
        ...CopyTextFragment
        __typename
      }
      __typename
    }
    __typename
  }
  __typename
}

And this is the query from the queryMap:

query routeQuery($path: String!) {
  routeByPath(path: $path) {
    object {
      ...BasicPageFragment
      __typename
    }
    __typename
  }
}

fragment AccordionFragment on ParagraphAccordion {
  container: fieldAccordionContainer {
    ... on ParagraphAccordionItem {
      id
      title: fieldParaTitle
      subtitle: fieldParaSubtitle
      content: fieldParaContent {
        id
        ...CopyTextFragment
        __typename
      }
      __typename
    }
    __typename
  }
  __typename
}

fragment CopyTextFragment on ParagraphCopytext {
  text: fieldParaText
  __typename
}

fragment PageContentFragment on Paragraph {
  id
  ...CopyTextFragment
  ...AccordionFragment
  __typename
}

fragment BasicPageFragment on NodeBasicPage {
  lead: fieldPageLead
  title: entityLabel
  content: fieldPageContent {
    ...PageContentFragment
    __typename
  }
  __typename
}

date for new release

We are having build issues in our project due to downloading @types/mocha by this library as it conflicts with @types\jest. The following PR should fix it, but we don't see newer package version after that fix. Can you please release a new version ASAP?

#23

Apollo Link Support

I would like to be able to use persistgraphql with Apollo link. Is there a way to currently do this? Can it be a feature?

Unhandled promise rejection

I'm having this issue when trying to execute:

(node:28632) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): 

GraphQLError: Syntax Error GraphQL (1:1) Unexpected <EOF>

1:
   ^

I'm using extractgql": "^0.2.1" with [email protected] and graphql 0.9.0 on Mac OS

Align persistgraphql output file format with proposed apollo-codegen operation ID mapping file

In a recent PR to apollo-codegen, a mechanism for generating unique operation IDs was introduced. In addition, it introduced a generated output file that maps between these IDs and the corresponding operation text, for use in registering operations with a server for persistence and whitelisting. The rationale for not simply using persistgraphql is contained in the PR description.

This proposed output file differs from persistgraphql's output in a few important ways:

  1. It uses operation hashes as the IDs, rather than an incrementing counter.
  2. It uses the ID as the mapping’s key, rather than its value.
  3. It maps to a JSON object that itself contains the operation source (text) and its name.

As pointed out by @martijnwalraven, there are good reasons to align the approaches taken by apollo-codegen and persistgraphql:

One area in particular where I think standardization would be helpful is in the generated mapping file. Ideally, these mapping files would be supported by different servers and tools in the same way the extracted_queries.json file that persistgraphql generates is currently supported by Scaphold for example.

So I'm not saying we should stick to what persistgraphql currently does, but I'd at least like us to synchronize the changes (like switching to hashes or changing the mapping format).

There is an existing issue on persistgraphql that addresses difference point 1. I think switching to operation hashes is the right approach.

What I’d like to propose here is that, to address difference points 2 and 3, persistgraphql adopt the approach proposed in the apollo-codegen PR. The PR lays out an argument for this approach, which I’ll recap here:

  • It seems like (for the server at least) the mapping from ID —> operation text is more useful than the reverse, suggesting that ID should be the key.
  • Typically, keys are short unique identifiers, and they map to values that contain more information, not less, again suggesting that ID should be the key.
  • We already have two pieces of information in each value (operation name and text), which our servers are prepared to consume at registration time. You can imagine other fields coming in the future: perhaps comments describing the operations, for display in a dashboard listing all persisted operations. This suggests that the value in the mapping should be a JSON object that can be extended in the future without breaking parsing older fields.

No .json file generated when crawling directory.

I'm not getting a .json file pointing it to a directory, like so:
$ persistgraphql client/src

When I point it to a file it seams to work fine. Am I missing something here?

Thanks for the all the amazing work contributed to the graphql community!

Add / enable Travis CI

Currently there is no automatic testing for PRs and commits. We should add Trabis CI to test against the different Node.js releases and catch breaking builds.

Register query manually

Why just not register them manually?

Client team can make a request to backend team to register a new query, in this case backend team will be able to improve performance of SQL queries.

Add License

Hi, would it be possible for you to add a license file to this repo?
I saw that in the package.json it's described as MIT.

Thanks for the lib!

Relax dependency requirements

I'm using this tool just to extract queries from JS files, and it does that great, but the strict dependcy requirements cause it to load a version of graphql that doesn't support the Interface1 & Interface2 SDL syntax, and also it brings in a dated version of Apollo too. I'm using Yarn's resolutions to push the requirements of:

    "apollo-client": "^1.1"
    "graphql": ">=0.9.4 <0.11"

up to:

    "apollo-client": "2.3.5",
    "graphql": "0.13.2"

and for my use case, it seems to work fine.

Extract gql extraction into another package

The GQL extraction provided in persistgraphql is pretty great. I'm hoping to use it to add support for javascript source files within apollo-codegen (apollographql/apollo-tooling#25) or similar projects and having the gql extraction stuff available as a separate package would make that much easier. It that something that sounds reasonable?

can't install on Windows

chmod?

npm install --save persistgraphql
npm ERR! path E:\apollo-universal-starter-kit\node_modules\persistgraphql\bin\persistgraphql
npm ERR! code ENOENT
npm ERR! errno -4058
npm ERR! syscall chmod
npm ERR! enoent ENOENT: no such file or directory, chmod 'E:\apollo-universal-starter-kit\node_modules\persistgraphql\bin\persistgraphql'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent

[BUG] template strings within attributes not parsed correctly

Hi

example query:

// works via variables
query MoviesByName($name : String!) {
   movies(name: $name) { ... }
}

// works with static value
query MoviesByName() {
   movies(name: 'StarWars') { ... }
}

// does not work via template string
const name: string = 'StarWars';

query MoviesByName() {
   movies(name: ${name}) { ... }
}

all queries work on default POST request using apollo. after running persistgraphql you'll receive an error, that no value was passed to the name attribute on the 3rd example.

currently you can "workaround" it by using variables, but in some cases it would be great to just pass a variable via template string literals.

package version
apollo client 2.2.2
persistgraphql 0.3.11

thanks for the great tool 👍

Support glob syntax [feature request]

persistgraphql "/(!node_modules)/*.graphql" output.json

It feels like the above should work. Otherwise persistgraphql needs to be run multiple times for each desired directory, with the results being composed later.

[BUG] persistgraphql serializes *differently* from apollo client, breaking the whitelist

persistgraphql's serialization always puts fragments at the bottom, whereas apollo-client matches the source. So if you have a query like

fragment Y on Z {
  # etc
}
query x {
  # etc, uses fragment Y
}

then whitelisting is broken 😬😬😬 because persistgraphql rearranges the text.

You can work around it by putting the fragment after in the source, but it's a weird inconsistency that just cost me a couple hours' work trying to debug.

Module not found

Hello,

I installed this package today, but when I tried to run it, I got the following error:

    at Function.Module._resolveFilename (module.js:470:15)
    at Function.Module._load (module.js:418:25)
    at Module.require (module.js:498:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/ex0ns/.nvm/versions/node/v7.5.0/lib/node_modules/persistgraphql/bin/persistgraphql:4:1)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)

Indeed, lib/src/index.js is missing, it seems that it should be binary.js, could you please take a look.

ex0ns

Hapi17 Example

Hey All-

Has anyone moved to Hapi17 and used this library?

Im getting a wonky error with sending GETs....even though I do have a query string that looks like -

http://localhost:8000/graphql?hash=1

The error is-

{
    "statusCode": 400,
    "error": "Bad Request",
    "message": "Must provide query string."
}

An example of the code I converted to looks like -

server.ext('onPreHandler', (request, h) => {
            console.log(request.url.path)
            if (request.url.path.indexOf('/graphql') >= 0) {
                const { hash = '' } = request.query
                if (!hash) {
                    return h.continue
                }

                request.query = `query events {
                    events{ 
                        eventuuid
                        storyId
                    }
                }   
                `
      
                return h.continue
            }
            return h.continue
        });

Mixing .graphql files with tagged template literals

Working on a project that uses primarily the gql tagged template literal for defining queries, but .graphql|.gql files for defining fragments.

Currently persistgraphql seems to be an either-or proposition. If you pass in the --js --extension=js arguments, the fragments aren't in the docMap, and as a result the following throws

extractFromAST

export function isOperationDefinition(defn: DefinitionNode): defn is OperationDefinitionNode {
  return (defn.kind === 'OperationDefinition');
}

Trace:

TypeError: Cannot read property 'kind' of undefined
    at isOperationDefinition (/Users/mergebandit/dev/super-top-secret-but-totes-badass-project/node_modules/persistgraphql/lib/src/extractFromAST.js:5:17)
    at Array.filter (<anonymous>)
    at Object.getOperationDefinitions (/Users/mergebandit/dev/super-top-secret-but-totes-badass-project/node_modules/persistgraphql/lib/src/extractFromAST.js:46:28)
    at ExtractGQL.createMapFromDocument (/Users/mergebandit/dev/super-top-secret-but-totes-badass-project/node_modules/persistgraphql/lib/src/ExtractGQL.js:70:49)
    at /Users/mergebandit/dev/super-top-secret-but-totes-badass-project/node_modules/persistgraphql/lib/src/ExtractGQL.js:99:26
    at Array.map (<anonymous>)
    at ExtractGQL.createOutputMapFromString (/Users/mergebandit/dev/super-top-secret-but-totes-badass-project/node_modules/persistgraphql/lib/src/ExtractGQL.js:95:46)
    at /Users/mergebandit/dev/super-top-secret-but-totes-badass-project/node_modules/persistgraphql/lib/src/ExtractGQL.js:132:31
    at <anonymous>

Seems to me that, if you choose the .js argument, it should still be able to extract .graphql files and merge them into the output document mapping.

Lost type information with addPersistedQueries

Extending on #3 when using other NetworkInterfaces this type information is lost after calling this function.

As the function expects a parameter of type NetworkInterface and returns this parameter after Object.assign the inferred type is NetworkInterface & { query: Promise<ExecutionResult> }.
Thus all type information of the networkInterface extending NetworkInterface is lost.

Example

const networkInterface = addPersistedQueries(
    createNetworkInterface({
        uri: '/graphql',
    }), // creates HTTPNetworkInterface
    persistedQueries,
);
networkInterface.use(/* some middleware */);

Expectation

Above code should work, since .use() is defined on HTTPNetworkInterface.

Actual result

Throws with Property 'use' does not exist on type 'NetworkInterface & { query: (request: Request) => Promise<ExecutionResult>; }'.

Solution

The solution could look somewhat like this:

export function addPersistedQueries<T extends NetworkInterface>
  (networkInterface: T, queryMap: OutputMap) {
    let __interfaceType: T; // I think this is necessary for Generic to work correctly
   // [...]
}

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.