Giter Club home page Giter Club logo

json-graphql-server's Introduction

json-graphql-server

travis (.org) github top language David. dependencies npm github contributors license prs welcome

Get a full fake GraphQL API with zero coding in less than 30 seconds.

Motivation

I'd love to learn GraphQL, but it seems that I first have to read a book about GraphQL Types and Queries, then install a gazillion npm packages.

  • About every developer

Start playing with GraphQL right away with json-graphql-server, a testing and mocking tool for GraphQL. All it takes is a JSON of your data.

Inspired by the excellent json-server.

Example

Follow the guide below starting from scratch, or see the example live on StackBlitz:

Open in StackBlitz

Create a db.js file.

Your data file should export an object where the keys are the entity types. The values should be lists of entities, i.e. arrays of value objects with at least an id key. For instance:

module.exports = {
    posts: [
        { id: 1, title: "Lorem Ipsum", views: 254, user_id: 123 },
        { id: 2, title: "Sic Dolor amet", views: 65, user_id: 456 },
    ],
    users: [
        { id: 123, name: "John Doe" },
        { id: 456, name: "Jane Doe" }
    ],
    comments: [
        { id: 987, post_id: 1, body: "Consectetur adipiscing elit", date: new Date('2017-07-03') },
        { id: 995, post_id: 1, body: "Nam molestie pellentesque dui", date: new Date('2017-08-17') }
    ]
}

Start the GraphQL server on localhost, port 3000.

json-graphql-server db.js

To use a port other than 3000, you can run json-graphql-server db.js --p <your port here> To use a host other than localhost, you can run json-graphql-server db.js -h <your host here> or --host <your host here>

Now you can query your data in graphql. For instance, to issue the following query:

{
    Post(id: 1) {
        id
        title
        views
        User {
            name
        }
        Comments {
            date
            body
        }
    }
}

Go to http://localhost:3000/?query=%7B%20Post%28id%3A%201%29%20%7B%20id%20title%20views%20User%20%7B%20name%20%7D%20Comments%20%7B%20date%20body%20%7D%20%7D%20%7D. You'll get the following result:

{
    "data": {
        "Post": {
            "id": "1",
            "title": "Lorem Ipsum",
            "views": 254,
            "User": {
                "name": "John Doe"
            },
            "Comments": [
                { "date": "2017-07-03T00:00:00.000Z", "body": "Consectetur adipiscing elit" },
                { "date": "2017-08-17T00:00:00.000Z", "body": "Nam molestie pellentesque dui" },
            ]
        }
    }
}

The json-graphql-server accepts queries in GET and POST. Under the hood, it uses the express-graphql module. Please refer to their documentations for details about passing variables, etc.

Note that the server is GraphiQL enabled, so you can query your server using a full-featured graphical user interface, providing autosuggest, history, etc. Just browse http://localhost:3000/ to access it.

GraphiQL client using json-graphql-server

Install

npm install -g json-graphql-server

Generated Types and Queries

Based on your data, json-graphql-server will generate a schema with one type per entity, as well as 3 query types and 3 mutation types. For instance for the Post entity:

type Query {
  Post(id: ID!): Post
  allPosts(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): [Post]
  _allPostsMeta(page: Int, perPage: Int, sortField: String, sortOrder: String, filter: PostFilter): ListMetadata
}
type Mutation {
  createPost(data: String): Post
  createManyPost(data: [{data:String}]): [Post]
  updatePost(data: String): Post
  removePost(id: ID!): Post
}
type Post {
    id: ID!
    title: String!
    views: Int!
    user_id: ID!
    User: User
    Comments: [Comment]
}
type PostFilter {
    q: String
    id: ID
    id_neq: ID
    title: String
    title_neq: String
    views: Int
    views_lt: Int
    views_lte: Int
    views_gt: Int
    views_gte: Int
    views_neq: Int
    user_id: ID    
    user_id_neq: ID
}
type ListMetadata {
    count: Int!
}
scalar Date

By convention, json-graphql-server expects all entities to have an id field that is unique for their type - it's the entity primary key. The type of every field is inferred from the values, so for instance, Post.title is a String!, and Post.views is an Int!. When all entities have a value for a field, json-graphql-server makes the field type non nullable (that's why Post.views type is Int! and not Int).

For every field named *_id, json-graphql-server creates a two-way relationship, to let you fetch related entities from both sides. For instance, the presence of the user_id field in the posts entity leads to the ability to fetch the related User for a Post - and the related Posts for a User.

The all* queries accept parameters to let you sort, paginate, and filter the list of results. You can filter by any field, not just the primary key. For instance, you can get the posts written by user 123. Json-graphql-server also adds a full-text query field named q, and created range filter fields for numeric and date fields. All types (excluding booleans and arrays) get a not equal filter. The detail of all available filters can be seen in the generated *Filter type.

Supported types

Type GraphQL Type Rule Example value
Id GraphQLID name === 'id' || name.substr(name.length - 3) === '_id' 1
Integer GraphQLInt Number.isInteger(value) 12
Numeric GraphQLFloat !isNaN(parseFloat(value)) && isFinite(value) 12.34
Boolean GraphQLBoolean typeof value === 'boolean' false
String GraphQLString typeof value === 'string' 'foo'
Array GraphQLList Array.isArray(value) ['bar'], [12, 34]
Date DateType (custom) value instanceof Date || isISODateString(value) new Date('2016-06-10T15:49:14.236Z'), '2016-06-10T15:49:14.236Z'
Object GraphQLJSON Object.prototype.toString.call(value) === '[object Object]' transport: { service: 'fakemail', auth: { user: '[email protected]', pass: 'f00b@r' } }

GraphQL Usage

Here is how you can use the queries and mutations generated for your data, using Post as an example:

Query / Mutation Result
// get a single entity, by id
{
  Post(id: 1) {
    id
    title
    views
    user_id
  }
}
            
{
  "data": {
    "Post": {
        "id": 1,
        "title": "Lorem Ipsum",
        "views": 254,
        "user_id": 123
    } 
  }
}
            
// include many-to-one relationships
{
  Post(id: 1) {
    title
    User {
        name
    }
  }
}
            
{
  "data": {
    "Post": {
        "title": "Lorem Ipsum",
        "User": {
            "name": "John Doe"
        }
    } 
  }
}
            
// include one-to-many relationships
{
  Post(id: 1) {
    title
    Comments {
        body
    }
  }
}
            
{
  "data": {
    "Post": {
        "title": "Lorem Ipsum",
        "Comments": [
            { "body": "Consectetur adipiscing elit" },
            { "body": "Nam molestie pellentesque dui" },
        ]
    } 
  }
}
            
// get a list of entities for a type
{
  allPosts {
    title
    views
  }
}
            
{
  "data": {
    "allPosts": [
      { "title": "Lorem Ipsum", views: 254 },
      { "title": "Sic Dolor amet", views: 65 }
    ]
  }
}
            
// paginate the results
{
  allPosts(page: 0, perPage: 1) {
    title
    views
  }
}
            
{
  "data": {
    "allPosts": [
      { "title": "Lorem Ipsum", views: 254 },
    ]
  }
}
            
// sort the results by field
{
  allPosts(sortField: "title", sortOrder: "desc") {
    title
    views
  }
}
            
{
  "data": {
    "allPosts": [
      { "title": "Sic Dolor amet", views: 65 }
      { "title": "Lorem Ipsum", views: 254 },
    ]
  }
}
            
// filter the results using the full-text filter
{
  allPosts(filter: { q: "lorem" }) {
    title
    views
  }
}
            
{
  "data": {
    "allPosts": [
      { "title": "Lorem Ipsum", views: 254 },
    ]
  }
}
            
// filter the result using any of the entity fields
{
  allPosts(filter: { views: 254 }) {
    title
    views
  }
}
            
{
  "data": {
    "allPosts": [
      { "title": "Lorem Ipsum", views: 254 },
    ]
  }
}
            
// all fields (except boolean and array) get not equal filters
// -lt, _lte, -gt, and _gte
{
  allPosts(filter: { title_neq: "Lorem Ipsum" }) {
    title
    views
  }
}
            
{
  "data": {
    "allPosts": [
      { "title": "Some Other Title", views: 254 },
    ]
  }
}
            
// number fields get range filters
// -lt, _lte, -gt, and _gte
{
  allPosts(filter: { views_gte: 200 }) {
    title
    views
  }
}
            
{
  "data": {
    "allPosts": [
      { "title": "Lorem Ipsum", views: 254 },
    ]
  }
}
            

Usage with Node

Install the module locally:

npm install --save-dev json-graphql-server

Then use the jsonGraphqlExpress express middleware:

import express from 'express';
import jsonGraphqlExpress from 'json-graphql-server';

const PORT = 3000;
const app = express();
const data = {
    // ... your data
};

app.use('/graphql', jsonGraphqlExpress.default(data));
app.listen(PORT);

Usage in browser with XMLHttpRequest

Useful when using XMLHttpRequest directly or libraries such as axios.

Install with a script tag

Add a script tag referencing the library:

<script src="../lib/json-graphql-server.client.min.js"></script>

It will expose the JsonGraphqlServer as a global object:

<script type="text/javascript">
    window.addEventListener('load', function() {
        const data = [...];

        const server = JsonGraphqlServer({
            data,
            url: 'http://localhost:3000/graphql'
        });

        server.start();

        const xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://localhost:3000/graphql', true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.setRequestHeader('Accept', 'application/json');
        xhr.onerror = function(error) {
            console.error(error);
        }
        xhr.onload = function() {
            const result = JSON.parse(xhr.responseText);
            console.log('data returned:', result);
            alert('Found ' + result.data.allPosts.length + ' posts');
        }
        const body = JSON.stringify({ query: 'query allPosts { allPosts { id } }' });
        xhr.send(body);
    });
</script>

Use with a bundler (webpack)

npm install json-graphql-server
import JsonGraphqlServer from 'json-graphql-server';

const data = [...];

const server = JsonGraphqlServer({
    data,
    url: 'http://localhost:3000/graphql'
});

server.start();

const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:3000/graphql', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Accept', 'application/json');
xhr.onerror = function(error) {
    console.error(error);
}
xhr.onload = function() {
    const result = JSON.parse(xhr.responseText);
    console.log('data returned:', result);
    alert('Found ' + result.data.allPosts.length + ' posts');
}
const body = JSON.stringify({ query: 'query allPosts { allPosts { id } }' });
xhr.send(body);

Usage in browser with fetch

import fetchMock from 'fetch-mock';
import JsonGraphqlServer from 'json-graphql-server';

const data = [...];
const server = JsonGraphqlServer({ data });

fetchMock.post('http://localhost:3000/graphql', server.getHandler());

fetch({
    url: 'http://localhost:3000/graphql',
    method: 'POST',
    body: JSON.stringify({ query: 'query allPosts { allPosts { id } }' })
})
.then(response => response.json())
.then(json => {
    alert('Found ' + result.data.allPosts.length + ' posts');
})

Adding Authentication, Custom Routes, etc.

json-graphql-server doesn't deal with authentication or custom routes. But you can use your favorite middleware with Express:

import express from 'express';
import jsonGraphqlExpress from 'json-graphql-server';

import OAuthSecurityMiddleWare from './path/to/OAuthSecurityMiddleWare';

const PORT = 3000;
const app = express();
const data = {
    // ... your data
};
app.use(OAuthSecurityMiddleWare());
app.use('/graphql', jsonGraphqlExpress(data));
app.listen(PORT);

Schema Export

You can also use the export jsonSchemaBuilder to get your own copy of the GraphQLSchema:

In node:

import {graphql} from 'graphql';
import {jsonSchemaBuilder} from 'json-graphql-server';

const data = { };
const schema = jsonSchemaBuilder(data);
const query = `[...]`

graphql(schema, query).then(result => {
  console.log(result);
});

Or available in the global scope when running on a client as jsonSchemaBuilder.

Plain Schema

If you want to use another server type instead of the built in graphql express, like apollo-server or etc, you can expose the plain schema to be built into an executable schema (there may be version issues otherwise).

This uses the export getPlainSchema.

import { ApolloServer } from 'apollo-server';
import { makeExecutableSchema } from '@graphql-tools/schema'; // or graphql-tools
import { applyMiddleware } from 'graphql-middleware';
import { getPlainSchema } from 'json-graphql-server';

const data = { };

// Example middlewares
const logInput = async (resolve, root, args, context, info) => {
    console.log(`1. logInput: ${JSON.stringify(args)}`);
    const result = await resolve(root, args, context, info);
    console.log(`5. logInput`);
    return result;
};
const logResult = async (resolve, root, args, context, info) => {
    console.log(`2. logResult`);
    const result = await resolve(root, args, context, info);
    console.log(`4. logResult: ${JSON.stringify(result)}`);
    return result;
};

// Leverage getPlainSchema
const schema = applyMiddleware(
    makeExecutableSchema(getPlainSchema(data)),
    logInput,
    logResult
);
const server = new ApolloServer({
    schema,
});
server.listen({ port: 3000 });

Deployment

Deploy with Heroku or Next.js.

Roadmap

  • CLI options (https, watch, delay, custom schema)
  • Subscriptions
  • Client-side mocking (ร  la FakeRest)

Contributing

Use Prettier formatting and make sure you include unit tests. The project includes a Makefile to automate usual developer tasks:

make install
make build
make test
make watch
make format

To learn more about the contributions to this project, consult the contribution guide.

Maintainers

fzaninotto djhi alexisjanvier
Francois Zaninotto Gildas Garcia Alexis Janvier

License

json-graphql-server is licensed under the MIT Licence, sponsored and supported by marmelab.

json-graphql-server's People

Contributors

akselinurmio avatar alexisjanvier avatar dependabot[bot] avatar djhi avatar fzaninotto avatar kmaschta avatar luwangel avatar mchaffotte avatar minupalaniappan avatar orta avatar pgrimaud avatar pjweisberg avatar qubitpi avatar sehmaschine avatar simon-ouyang-demo avatar sioked avatar slax57 avatar sulco avatar tvthatsme avatar underscore05 avatar vantreeseba 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

json-graphql-server's Issues

'Error in resolver Fastmove.Move\nCannot read property \'find\' of undefined'

Hi,

I was doing a test with this and got the following error:

Error in resolver Fastmove.Move\nCannot read property 'find' of undefined

I am using the following data:

module.exports = {
    pokemon: [
        { id: 1, name: "BULBASAUR", stats: {baseStamina: 128, baseAttack: 118, baseDefense: 111} },
        { id: 4, name: "CHARMANDER", stats: {baseStamina: 118, baseAttack: 116, baseDefense: 93} },
        { id: 7, name: "SQUIRTLE", stats: {baseStamina: 127, baseAttack: 94, baseDefense: 121} }
    ],
    types: [
        { id: 701, pokemon_id: 1, type: "POKEMON_TYPE_GRASS" },
        { id: 702, pokemon_id: 1, type: "POKEMON_TYPE_POISON" },
        { id: 703, pokemon_id: 4, type: "POKEMON_TYPE_FIRE" },
        { id: 704, pokemon_id: 7, type: "POKEMON_TYPE_WATER" }
    ],
    fastmoves: [
        { id: 801, pokemon_id: 1, move_id: 601 },
        { id: 802, pokemon_id: 1, move_id: 602 },
        { id: 803, pokemon_id: 4, move_id: 607 },
        { id: 804, pokemon_id: 4, move_id: 608 },
        { id: 805, pokemon_id: 7, move_id: 612 },
        { id: 806, pokemon_id: 7, move_id: 602 }
    ],
    chargemoves: [
        { id: 901, pokemon_id: 1, move_id: 603 },
        { id: 902, pokemon_id: 1, move_id: 604 },
        { id: 903, pokemon_id: 1, move_id: 605 },
        { id: 904, pokemon_id: 4, move_id: 609 },
        { id: 905, pokemon_id: 4, move_id: 610 },
        { id: 906, pokemon_id: 4, move_id: 611 },
        { id: 907, pokemon_id: 7, move_id: 613 },
        { id: 908, pokemon_id: 7, move_id: 614 },
        { id: 909, pokemon_id: 7, move_id: 615 }
    ],
    move: [
        { id: 601, name: "VINE_WHIP_FAST", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 602, name: "TACKLE_FAST", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 603, name: "SLUDGE_BOMB", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 604, name: "SEED_BOMB", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 605, name: "POWER_WHIP", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 607, name: "EMBER_FAST", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 608, name: "SCRATCH_FAST", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 609, name: "FLAME_CHARGE", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 610, name: "FLAME_BURST", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 611, name: "FLAMETHROWER", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 612, name: "BUBBLE_FAST", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 613, name: "AQUA_JET", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 614, name: "AQUA_TAIL", pvp: { power: 10 }, gym: { power: 10 } },
        { id: 615, name: "WATER_PULSE", pvp: { power: 10 }, gym: { power: 10 } },
    ]
}

issuing the following query produces the error:

{
    allPokemons (page: 0, perPage:2) {
        name
        stats 
        Types {
          type
        }
        Fastmoves {
          Move {
            name
          }
        } 
        Chargemoves {
          id
        }
    }
}

Not here that in Chargemoves i am just getting the id and that works, but in Fastmoves i am going 2 levels deep to Move and there i get the error.

Is this not supported? Or am i doing something wrong?

Support CORS

This simple server is a great way for mocking GraphQL APIs while developing the front-end. Thank you!
I have an issue with React Apollo because it seems that json-graphql-server doesn't support CORS (error 405 on OPTION call).

Do you have any plan to support it?

Thank you,
Matteo

Does not generate "ID"

Hello,
json-server can generate an ID when creating an entity, the json-graphql-server do this too?

Fragments in nested JSON Array

Hey,
Is it possible to work with something like this (in screenshot) ?
It would be very nice to categories and cluster objects.
Itยดs a nested array in the JSON Array. If i do it with jsonGraphqlExpress.default(data), iยดm just be able to get the data from the whole nested array.
It would be so nice, if you can help me!
Thank you
Best regards
Marcel
Bildschirmfoto 2021-08-25 um 10 54 44

Bildschirmfoto 2021-08-25 um 10 50 09

Update mutation fails after first execution

After installing the plain json-graphql-server module and attempting to run the example, I'm seeing an issue with mutations. It seems that the first time we perform any mutation for an entity by id it's successful, but any time we attempt to perform the mutation for the same entity with the sam id again it is unsuccessful. It returns null and doesn't update the the value in the database.

Steps to recreate:

  1. Copy the file from the example in the docs into db.js https://github.com/marmelab/json-graphql-server#example
module.exports = {
    posts: [
        { id: 1, title: "Lorem Ipsum", views: 254, user_id: 123 },
        { id: 2, title: "Sic Dolor amet", views: 65, user_id: 456 },
    ],
    users: [
        { id: 123, name: "John Doe" },
        { id: 456, name: "Jane Doe" }
    ],
    comments: [
        { id: 987, post_id: 1, body: "Consectetur adipiscing elit", date: new Date('2017-07-03') },
        { id: 995, post_id: 1, body: "Nam molestie pellentesque dui", date: new Date('2017-08-17') }
    ]
}
  1. Start the server: json-graphql-server db.js

  2. Execute a mutation against a post - Should succeed and return the appropriate value

mutation {
  updatePost(id:"1", title:"Foo bar", views: 200, user_id:"123") {
    id
  }
}
# returns: 
#{
#  "data": {
#    "updatePost": {
#      "id": "2"
#    }
#  }
#}
  1. Attempt the exact same mutation again
mutation {
  updatePost(id:"1", title:"Foo bar", views: 200, user_id:"123") {
    id
  }
}
# returns: 
#{
#  "data": {
#    "updatePost": null
#  }
#}

Thanks!

Nested JSON - One-to-Many / Many-to-Many Relationship

Great project! This seems very useful for developing the schema from a JSON. I have an appropriately labeled JSON file that is 3 levels deep, each with a unique ID. Right now it does not appear that the parser identifies properties further than the 2nd level. Everything past that point is listed as type "JSON" and pulls as a group.

For example, in the below request it does not recognize everything below "Class" as having unique queriable properties. You can only query the JSON chunk

{
  "School": [ {
    "id": 1,
    "name": "blah",
    "Class": [ {
         "id": 101,
         "Student": [ {
              "id": 501,
              "propertyA": "test"
         }]
     }]
  }]
}
{
  School(id: 1) {
    Class
  }
}

I would like to request only "propertyA" or other properties of the appropriate level while preserving the hierarchical relationship.

TypeError: jsonGraphqlExpress is not a function

Regardless of wether I use Node require or ES6 import with node --experimental-modules server.mjs I keep getting the error TypeError: jsonGraphqlExpress is not a function when setting up a Node server. Any ideas on how to resolve this?

I am able to run the json-graphql-server globally though, and I must say it's awesome. You all are doing great work. Keep it up.

Extracting Schema?

Hi,

Is there someway to extract the schema that json-graphql-server has created when you run json-graphql-server data.js ?

[Question] Map 'id' to something else.

Hello,

According to the docs : "By convention, json-graphql-server expects all entities to have an id field".
Unfortunately this is not my case, how can I inform json-graphql-server to use another field instead of 'id'?

Thanks,
Alessio

Cannot extend type "Workhsop" because it does not exist in the existing schema.

What you were expecting:

Starts a graphql server

What happened instead:

a [GraphQLError]: Cannot extend type "Workhsop" because it does not exist in the existing schema.

Steps to reproduce:

Create your own data instead of using the example data in the README

module.exports = {
  workshops: [
    {
      id: 1,
      name: "Conversation",
      description:
        "El alumno se expresa oralmente utilizando las funciones comunicativas y vocabulario adquirido, mejorar la fluidez, y perder el temor a hablar.",
    },
    {
      id: 2,
      name: "TOEFL Preparation",
      description:
        "Ayuda a desarrollar habilidades para el examen de certificaciรณn, a partir del dominio ya adquirido del idioma. Duracion: 1 mes.",
    }
  options: [
    {
      id: 1,
      teacher: "alondra",
      time: "13:00 - 14:00",
      day: "lunes",
      workshop_id: 1,
    },
    {
      id: 2,
      teacher: "gonzalo",
      time: "14:00 - 15:00",
      day: "lunes",
      workshop_id: 1,
    },
    {
      id: 11,
      teacher: "carlos",
      time: "12:00 - 13:00",
      day: "lunes",
      workshop_id: 2,
    },
  ],
};

Related code:

npx json-graphql-server db.js

Other information:

Environment

  • Last version that did not exhibit the issue (if applicable):
  • Browser:

How to perform multiple create mutations in the same query?

Typically INSERT operations in a variety of query languages allow multiple records to be inserted at the same time. I would expect that this would be done here with variables taking the form of an array:

[
{"id":101,"name":"TV","price":200},
{"id":102,"name":"Boat","price":300}
...
]

This is clearly not working - but I'm not even sure if it's a feature that I misuse, or a feature that is absent. Or if there is some workaround to avoid firing multiple requests for multiple record insertions.

Create mutation does not require ID, but CreateMany mutation does

Recent versions of the server removed the need to specifiy IDs, making them auto-incremented just like in JSON Server.

However this works as expected only in the simple Create mutation.

The CreateMany mutations still return an error if IDs are not provided! Strangely enough, if they are provided they are ignored and the auto-increment works! But they have to be provided, even if they are ignored.

This was noticed on v. 2.2.3 (for some reason 2.3.0 does not work at all, I don't know if the issue was later solved).

Usage in browser with ApolloClient

Hey marmelab, thx very much for open-sourcing json-graphql-server - it's been fantastic to get a my prototype GraphQL server running in a few mins.

Quick question - is there any way to get json-graphql-server working with Apollo and React with only the browser? Using the CLI to create a "backend" server works fine with ApolloClient, axios, and XMLHttpRequest. Using the in-browser option works fine with only axios and XMLHttpRequest.

I believe this is because the json-graphql-server uses xhr-mock to intercept XHR requests but Apollo uses some fetch variant instead.

I saw there was some code in src/createApolloClient.js that is related to creating an ApolloClient. Although it is successfully creating an ApolloClient for me to use, it does not seem to interact at all with the resolvers that json-graphql-server sets up. The example Post(id: 1) query just returns null with this client.

I think my options are either to better understand how to use src/createApolloClient.js, modify ApolloClient to use XHR requests, change xhr-mock to mock fetches, or to bite the bullet and create a server. What direction would you recommend?

Edit - made a CodeSandbox to illustrate the problem - https://codesandbox.io/s/sleepy-shadow-9tjmd - best viewed here with console open and scrolled to top - https://9tjmd.codesandbox.io/

Readme: Filter example wrong?

This example:

{
  allPosts(views: 254) {
    title
    views
  }
}

Should probably be:

{
  allPosts(filter: {views: 254}) {
    title
    views
  }
}

Right? At least that's how I've got it to work on my query:

{
  League (id: "switzerland") {
    Waypoints {
      lat
      lng
      radius
      points
      minAltitude
      name
      Type {
        name
      }
      description
    }
  }
  allFlights(
    sortField: "score", 
    sortOrder: "DESC", 
    page: 0, 
    perPage: 10, 
    filter: { date: "2018-07-03" }
  ) {
    date
    score
    User {
      name
    }
  }
}

TypeError: Object.values is not a function

Sorry but I'm not exactly sure how I am supposed to run this.

I've run npm install -g json-graphql-server

I've cloned this repo locally using git clone https://github.com/marmelab/json-graphql-server.gitthen I ran yarn install inside the directory.

Now when I run json-graphql-server data.jsinside the example folder I get the error below.
I have tried to create my own db.js file using the example in the readme as well, giving the same result.

/usr/local/lib/node_modules/json-graphql-server/src/introspection/getSchemaFromData.js:174
    const schemaExtension = Object.values(typesByName).reduce((ext, type) => {
                                   ^

TypeError: Object.values is not a function
    at module.exportDefault.data (/usr/local/lib/node_modules/json-graphql-server/src/introspection/getSchemaFromData.js:174:36)
    at module.exportDefault.data (/usr/local/lib/node_modules/json-graphql-server/src/schemaBuilder.js:8:31)
    at Object.module.exportDefault.data [as jsonGraphqlExpress] (/usr/local/lib/node_modules/json-graphql-server/src/jsonGraphqlExpress.js:50:17)
    at Object.<anonymous> (/usr/local/lib/node_modules/json-graphql-server/bin/json-graphql-server.js:17:32)
    at Module._compile (module.js:570:32)
    at Object.Module._extensions..js (module.js:579:10)
    at Module.load (module.js:487:32)
    at tryModuleLoad (module.js:446:12)
    at Function.Module._load (module.js:438:3)
    at Module.runMain (module.js:604:10)```


Custom port parameter `-p` doesn't work as expected

What you were expecting:
The custom port parameter should be the one defined in the README, -p.

What happened instead:
This parameter has no effect:

$ json-graphql-server db.js -p :3001
GraphQL server running with your data at http://localhost:3000/

Looking at the code, I noticed the change was added in fd05e9e, and the accepted parameter format is --p.

Steps to reproduce:
Try to run the server with the -p parameter with a port different to 3000.

Related code:
Commit that introduced the custom port feature: fd05e9e

Other information:
PR with my suggested changes to add support to -p in addition to --p: #86

Serve the GraphiQL UI

Although currently "the server is GraphiQL enabled", to use it appears to require standing up GraphiQL separately (perhaps via the electron app that is linked) and then pointing at this server.

Feature request:

Optionally (controlled by a switch) serve the GraphiQL UI from json-graphql-server.

Multiline function arguments with trailing comma - SyntaxError: Unexpected token )

When I use a global install of "json-graphql-server" has it, I encounter an error because of trailing commas in multiline function arguments.

My version of Node is the following: v7.1.0. According to this thread, trailing comma support will be enabled by default in V8.

For the moment, I'm able to use the server with this command.

node --harmony_trailing_commas /usr/lib/node_modules/json-graphql-server/bin/json-graphql-server.js

Maybe we should remove them and adapt prettier rules (trailingComma) according to that ?

Anyway, thanks for this awesome work ! ๐Ÿ‘

filtering not null

is something like that possible:

{
  allAuthors (filter: {posts_not: null}) {
    name
  }
}

thank you!

New release is overdue

While several features and fixes have been added over the last year they have not been released as a new version.

It would be really nice if you could simply publish the current master. (maybe you can tag it as [next] if you don't wan't to publish as stable/[latest])

I am mostly looking for the export schema feature which was added about 5 months ago.

Thank you for your help.

Why not Input Types?

I need to understand why using the db.js example file from Readme it doesn't generate the input PostInput or input UserInput or input CommentInput.

Example:

I think it is better to use something like this:

createPost(id: ID!, input: PostInput!): Post

instead of what is now generated:

createPost(id: ID!, title: String!, views: Int!, user_id: ID!): Post.

Am I wrong? I'm still learning... I'm asking for hints. Thanks.

t is not a function

when i first run the project in 2.3.0 the server logged t(...) is not a function, i downgraded for 2.2.3 and worked just fine. So keep an eye on that new version

Is there a way to save the mutations to the db.js file?

Apologies for question here, wasn't clear from "contributing guidelines" what the alternative was

I was expecting that changes/mutation to the database would be updated in db.js, any suggestion on how to make that happen. The changes are all in the InMemoryCache,but there are no updated in the file

Custom Query

Do we have any way to create custom query that cannot generate? Such as Login

See the schema it generates

Hi, thanks for the project! Is it possible to see the schema it generates other than in the GraphiQL docs?

Support many-to-many relationships

It seems that I can't do this right now:

module.exports = {
    posts: [
        { id: 1, title: "Lorem Ipsum", views: 254, user_id: [123, 456] },
        { id: 2, title: "Sic Dolor amet", views: 65, user_id: [456, 457] },
    ],
    users: [
        { id: 123, name: "John Doe" },
        { id: 456, name: "Jane Doe" },
        { id: 457, name: "Xavier" }
    ],
    comments: [
        { id: 987, post_id: 1, body: "Consectetur adipiscing elit", date: new Date('2017-07-03') },
        { id: 995, post_id: 1, body: "Nam molestie pellentesque dui", date: new Date('2017-08-17') }
    ]
}

Is this not supported? or maybe there's a different way of doing it?

p.s.: this would be something like a combined authorship post. This is not my actual use case though, but close enough to show the problem and with a little change of the provided example.

p.s. 2: great tool, keep it up :)

jsonGraphqlExpress is undefined

jsonGraphqlExpress is not present in node bundle in npm

import { jsonGraphqlExpress } from 'json-graphql-server';
console.log(jsonGraphqlExpress); // undefined

Specified port not being used

Running json-graphql-server db.js --p 4000 does not open the server in a different port. The port remains at 3000.

How to access in browser data after mutation?

I am using the "in browser" feature with fetchMock and would like to get the transformed data back out of the "server" after running a mutation. Is this possible?

For instance my json starts as:

{"things":[{"id":1,"name":"Thing 1"}]}

And I run the mutation:

mutation { createThing ("name": "Thing 2") { id name }

I get the right response back and can query it as expected.

I wonder if there is a way to somehow get the updated JSON from the server object after the mutation.

Execution fails with error and return code 1

What you were expecting:
To run the server

What happened instead:
I get the following error:

/path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:1
TypeError: e.reduce is not a function
    at A (/path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:95:1352841)
    at P (/path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:95:1353043)
    at /path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:95:1354046
    at Array.map (<anonymous>)
    at /path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:95:1353965
    at V (/path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:95:1354096)
    at Z (/path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:95:1361152)
    at t.default (/path-to-project/node_modules/json-graphql-server/lib/json-graphql-server.node.min.js:95:1361270)
    at Object.<anonymous> (/path-to-project/src/__mocks__/serve.js:8:21)
    at Generator.next (<anonymous>)
error Command failed with exit code 1.

Steps to reproduce:
Install the package then try to run it with a simple structure like the following...

module.exports = {
  store: {
    name: 'some store',
    id: '123'
  }
};

and it will fail.

Other information:

Environment
OS: Ubuntu 18.04
Node version: 14.15.3
Yarn version: 1.22.10
Npm Version: 6.14.7 (I installed the package with yarn, execution fails with both yarn and npm)

Why db.js?

Why not just point to a JSON file(s) like json-server?

Firing a mutation does not update db.json

When I fire off a mutation like createPost, the action seems succeed but the changes only seem to be served from memory. db.json does not get updated. Isn't this contrary to expected behaviour?

Deploy to Heroku fails with npm ERR! missing script: start

Hi Guys,
I've tried to deploy the json-graphql-server to Heroku, but, I'm still not able to do do.

I'm getting npm ERR! missing script: start

Can you please guide me on the correct way to configure the Heroku Procfile or package.json to properly getting the server running on Heroku?

Thanks a lot.

Schema fails at getRelatedType if table name and foreign key

Schema fails at getRelatedType if table name and foreign key.

Suppose you have table name m_oraganization and primary key id
and then you have foreign key organization_id in m_discount_type

at name conversion
exports.getRelatedType = fieldName =>
getTypeFromKey(fieldName.substr(0, fieldName.length - 3));
substr strips down last three and we get Organization which actually doesn't exist.

UnhandledPromiseRejectionWarning: Error: Unknown type "Organization". Did you mean "MOrganization", "MRelation", or "MOrganizationFilter"?

Please suggest any other logic to handle related type names. Thanks !

POC: Integration with Hasura GraphQL Engine

I have put together a proof of concept for integrating this with Hasura GraphQL Engine at hasura/json-data-import.

It is simply a node script right now. I can make a PR with the integration if someone can give me a thumbs up :-)

Current spec:

  1. Only int, float, text and boolean are supported. All fields are nullable.
  2. Data types are inferred from the data. Therefore, if null is provided as data for a field, it is assumed to be text.
  3. Every table must have an integer primary key called id.
  4. If any table has a key something_id, it is assumed a foreign key to a the column id of table somethings if it exists . If somethings does not exist, something_id is assumed to be a normal column.
  5. All foreign keys are converted to relationships.

Any feedback would be appreciated :-)

delete last record instead of given `id`

What you were expecting:

When I submit a remove... mutation with an id of an existing record, this record will be deleted.

What happened instead:

The last record was deleted.

Steps to reproduce:

  • install json-graphql-server package with npm/yarn: yarn add json-graphql-server

    will instal last version in npm registry 2.1.3.

  • create a simple db.js
  • query to list all record
  • mutation to remove one record, different than the last one

Related code:

# db.js

module.exports = {
  users: [
    {
      id: "asdf",
      name: "John Smith",
      email: "[email protected]"
    },
    {
      id: "qwer",
      name: "John Smith",
      email: "[email protected]"
    },
    {
      id: "zxcv",
      name: "John Smith",
      email: "[email protected]"
    }
  ]
};
# list all users
query {
  allUsers {
    id
    name
  }
}
#remove 2nd user
mutation {
  removeUser(id: "qwer")
}

Other information:

Screen Shot 2019-09-06 at 13 04 19

Screen Shot 2019-09-06 at 13 04 37

Screen Shot 2019-09-06 at 13 04 53

Environment

[email protected]

macOS 10.13.6
node 10.16.0
yarn 1.17.3

Error while deleting: Boolean cannot represent a non boolean value

What you were expecting:

The response should be boolean while deleting.

What happened instead:

The server is returning the object instead.

Steps to reproduce:

Related code:

insert short code snippets here

Other information:

Environment

  • Last version that did not exhibit the issue (if applicable):
  • Browser:

e.reduce is not a function

Running the following snipet of code gives me the error TypeError: e.reduce is not a function

import express from 'express';
import jsonGraphqlExpress from 'json-graphql-server';
import { Users } from '../../db';

const PORT = 3000;
beforeAll(() => {
  console.log(jsonGraphqlExpress);
  const app = express();
  app.use('/graphql', jsonGraphqlExpress(Users));
  app.listen(PORT);
});

while the db.ts contains the following:

import * as bip39 from 'bip39';
import { internet, random } from 'faker';

interface IUser {
  id: number;
  email: string;
  username: string;
  avatar: string;
  passphrase: string;
  pp: string;
  token: string;
}
const users: IUser[] = [];

/**
 * hexaDecimal
 *
 * @method faker.random.hexaDecimal
 * @param {number} count defaults to 1
 */
function hexaDecimal(count: number) {
  if (typeof count === 'undefined') {
    count = 1;
  }

  let wholeString = '';
  for ( let i = 0; i < count; i++ ) {
    // tslint:disable-next-line:max-line-length
    wholeString += random.arrayElement(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F']);
  }

  return '0x' + wholeString;
}

for (let index = 0; index < 100; index += 1) {
  const user = {
    id: index,
    email: internet.email(),
    username: internet.userName(),
    avatar: internet.avatar(),
    passphrase: bip39.generateMnemonic(),
    pp: hexaDecimal(64),
    token: random.uuid(),
  };

  users.push(user);
}

export const Users = users;

Create Mutation

What is the best way to perform a "Create" mutation.
Seems that if I have an entity "values", I have a mutation available called "createValue", but for some reason it requires an id (ID!), but why would a create mutation require an ID. Shouldn't this id be auto-generated?

Dynamic content?

I've searched through issues and pull requests and haven't seen this question yet.

Is there a way for json-graphql-server to handle dynamic data passed in from the user?

My idea is to have the user input the JSON which thereafter becomes queryable via graphql.

Update mutation returns null and doesn't update anything

This is my query and variables:

updatewing

I previously added that wing with a create mutation, that works nicely. This is my original data for wings:

wings: [
        { id: 'ozone-zeno', model: 'Zeno', brand: 'Ozone', certification: 'D' },
        { id: 'nova-mentor-3', model: 'Mentor 3', brand: 'Nova', certification: 'B' }
],

Not accepting post body

I noticed the only way the api responds correctly is if you have the query in the url params. It's supposed to work just by passing the query in the body. Notice specifically the Referrer field below in the response. Unless I'm missing something, from what I can tell by looking at graphql-request, you shouldn't have to specify this in the query params.

Works

image

Does not work

image

Treat date string as date type

The json file cannot define a date type and the date string is just treated as string.

For example:

{"posts": [
   {
       "id": "test",
       "postTime": "2022-01-01T00:00:00Z"
   }
]}

the schema is

[id]: [ID]
[postTime]: [String]

It will be great if the schema generated like this

[id]: [ID]
[postTime]: [Date]

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.