Coder Social home page Coder Social logo

graphql's Introduction

Mirage JS

npm version example workflow

A client-side server to develop, test and prototype your JavaScript app.

Documentation

Visit miragejs.com to read the docs.

graphql's People

Contributors

2wheelcoder avatar dependabot[bot] avatar gfmartinez avatar jneurock avatar josemarluedke avatar kdembler avatar oreoz avatar rgaiacs avatar samselikoff 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

Watchers

 avatar  avatar

graphql's Issues

How deal with complex queries?

I'm getting a bunch of errors when I try to use queries with variables.

image

// app/mirage/server.js

import { createServer } from "miragejs"
import { createGraphQLHandler } from "@miragejs/graphql"
import graphQLSchema from "app/gql/schema.gql"

export function makeServer() {
  return createServer({
    routes() {
      const graphQLHandler = createGraphQLHandler(graphQLSchema, this.schema);

      this.post("/graphql", graphQLHandler)
    }
  })
}

// schema

import { gql } from 'glimmer-apollo'

export const graphQLSchema = gql`
  type CurrentAccount {
    id: ID!
    name: String!
    flags: [String]!
    memberships: [Membership]
  }

  type Account {
    id: ID!
    accountType: String!
    isActive: Boolean!
    name: String!
  }

  type CurrentUser {
    id: ID!
    name: String!
    email: String!
    imageUrl: String!
    phone: String!
    isPeekAdmin: Boolean!
    currentAccountRoles: [String]
    accounts: [Account]
  }

  type Membership {
    id: ID!
    name: String!
    membershipVariants: [MembershipVariant!]!
  }

  type MembershipVariant {
    colorHex: String!
    creditsPerTerm: Int!
    description: String!
    externalName: String!
    id: ID!
    imageUrl: String!
    internalName: String!
  }

  type Query {
    currentAccount: CurrentAccount!
    currentUser: CurrentUser!
    memberships(id: ID!): [Membership!]!
  }
 `

// query

query CurrentAccountMembershipVariant($membershipId: ID, $variantId: ID) {
  currentAccount {
    id
    memberships(id: $membershipId) {
      id
      membershipVariants(id: $variantId) {
        id
        internalName
        externalName
        description
        currency
        creditsPerTerm
        imageUrl
        colorHex
        validBetween
        validFor {
          amount
          unit
        }
        creditWindow {
          unit
          amount
        }
      }
    }
  }
}

Could you please give some help here @jneurock I might be missing something?

Example of own resolvers for query / filter involving Union types

I spent a few hours to figure out how to write my own resolver for query / filter involving Union types.

The solution that works for me was something like

let foos = context.mirageSchema.all('foo').models;
for (let foo of foos) {
  foo.__typename = 'Foo';
}

let bars = context.mirageSchema.all('bar').models;
for (let bar of bars) {
  bar.__typename = 'Bar';
}

return [].concat(foos, bars);

Did I miss something in the documentation?

Should I send a pull request adding this use case to the list of examples?

GraphQL Playground

Is it possible to also create a graphql playground? Currently the /graphql url does not return anything.

createGraphQLHandler can't deal with directives

Hi all,

I love this library. It works so well.

I discovered a problem when I use directives in the query. Here is a simple example.

app/gql/schema.gql

type Person {
  id: ID!
  key: String
  firstName: String!
  lastName: String!
}

type Query {
  allPeople: [Person]
}

app/components/person.js

import { createServer } from "app/mirage/server";
import { request } from "graphql-request"

const server = createServer();

server.create("person", { firstName: "Mikael", lastName: "Åkerfeldt" })

export default {
  // ...other component stuff

  personQuery: `
    query Person($id: id) {
      person(id: $id) {
        id
        key @client
        firstName
        lastName
      }
    }
  `,
  getPerson(id) {
    return request("/graphql", this.personQuery, { id })
  }
}

In the production version my Person type does not have the key attribute but I inject it with typePolicies of the ApolloClient at the start of the app.

When I run Mirage with the key @client directive in the query I get the following error

"message": "Unknown directive @client.",

My current work-around is to create a copy of the query file with the *.e2e.ts extension but I would rather not double-up on these files.

Is there a way to overcome that issue? Maybe with a resolver?

Cheers,

Tom

Expected Iterable, but did not find one for field

When a schema defines a list using an interface, it looks like @miragejs/graphql fails to build the field for the list

interface ItemRead {
  authors: [String!]!
  id: ID!
  title: String!
}

type BookChapterRead implements ItemRead {
  authors: [String!]!
  chapter: Int
  id: ID!
  title: String!
}

type BookRead implements ItemRead {
  authors: [String!]!
  id: ID!
  rating: Int
  title: String!
}

type Query {
  booksRead: [BookRead]
  bookChapterRead: [BookChapterRead]
  itemsRead: [ItemRead]
}

Querying for..

{
  itemsRead {
    id
    title
    authors
  }
}

..fails with..

Expected Iterable, but did not find one for field "Query.itemsRead".

..while querying other fields works fine.

I put together a reproduction in the REPL https://miragejs.com/repl/v2/042996bcd5

TypeError on `returnType` when returning Union from mutations

This is related to a comment made on #52 that was out of context for the issue where it was added to.

We've defined a mutation to work with basic updates on our MembershipInstance model, we defined this schema

const schema = {
  type Membership {
    id: ID!
    name: String!
    membershipInstances(id: ID): [MembershipInstance]
  }

  type MembershipInstance {
    id: ID!
    ...
  }

  type Mutation {
    updateMembershipInstance(input: UpdateMembershipInstanceInput): UpdateMembershipInstanceResponse
  }

  input UpdateMembershipInstanceInput {
    id: ID!
    name: String!
  }

  union UpdateMembershipInstanceResponse = UpdateMembershipInstanceSuccess | Error

  type UpdateMembershipInstanceSuccess {
    membershipInstance: MembershipInstance
  }

  type Error {
    message: String
  }
}

and we have this mutation handler on our resolvers we're passing to createGraphQLHandler(...)

const resolvers = {
    updateMembershipInstance: (parent, args, context, info) => {
      const { mirageServer } = context
      const { id: membershipInstanceId } = args.input
      const membershipInstance = mirageServer.schema.membershipInstance.find(membershipInstanceId)

      if (membershipInstance) {
        membershipInstance.update(args.input)
      }

      const response = new UpdateMembershipInstanceSuccess()
      response.membershipInstance = membershipInstance

      return response
    }
}

export class UpdateMembershipInstanceSuccess {
  get __typename () {
    return 'UpdateMembershipInstanceSuccess'
  }
}

this code, as is, works, but we're wondering if this is the graphql way to do things, specially because we're calling mirage directly to update records, then we're also building a typed response to avoid graphql union errors. What we're discussing with the rest of the team is if this shouldn't have a different handler, deferring the actual data update work to mirage/graphql, we tried this also

const resolvers = {
  updateMembershipInstance: {
    __typename: 'UpdateMembershipInstanceResponse',
    __resolveType: (obj, context, info) => {
      debugger
    },
    resolveType: (obj, context, info) => {
      debugger
    },
    __returnType: () => {
      debugger
    },
    returnType: () => {
      debugger
    }
  },

  UpdateMembershipInstanceResponse: {
    __resolveType: (obj, context, info) => {
      debugger
    },
    resolveType: (obj, context, info) => {
      debugger
    },
    __returnType: () => {
      debugger
    },
    returnType: () => {
      debugger
    }
  },

  updateMembershipInstance: (parent, args, context, info) => {
    const membershipInstance = mirageGraphQLFieldResolver(...arguments)
  
    const response = new UpdateMembershipInstanceSuccess()
    response.membershipInstance = membershipInstance
  
    return response
  }
}

export class UpdateMembershipInstanceSuccess {
  get __typename () {
    return 'UpdateMembershipInstanceSuccess'
  }
}

but this approach fails, with this error

TypeError: Cannot read properties of undefined (reading 'returnType') at mirageGraphQLFieldResolver
{
  "message": "Cannot read properties of undefined (reading 'returnType')",
  "locations": [
    {
      "line": 2,
      "column": 3
    }
  ],
  "path": [
    "updateMembershipInstance"
  ]
}

which makes me thing we're not using mirageGraphQLFieldResolver correctly, but what I find specially confusing is that we also added returnType to our types resolvers, but it seems we're not even hitting those, and we cannot still find which type from our schema this error is originating from

any help or comment would be super welcomed!

FetchError: request to http://localhost/graphql failed, reason: connect ECONNREFUSED 127.0.0.1:80

I'm trying to run a sample from README.md.

Node version: v14.16.0

  • package.json
{
  "devDependencies": {
    "@miragejs/graphql": "^0.1.11",
    "graphql-request": "^3.4.0",
    "miragejs": "^0.1.41"
  }
}
  • test.js
const { createServer } = require("miragejs")
const { createGraphQLHandler } = require("@miragejs/graphql")
const { request } = require("graphql-request")

const graphQLSchema = `
input PersonInput {
  firstName: String
  lastName: String
}

type Mutation {
  createPerson(input: PersonInput!): Person
  updatePerson(id: ID!, input: PersonInput!): Person

  deletePerson(id: ID!): Boolean
}

type Person {
  id: ID!
  firstName: String!
  lastName: String!
}

type Query {
  allPeople: [Person]
  person(id: ID!): Person

  people(firstName: String, lastName: String, sortBy: String): [Person]
}
`

const URL = "http://localhost/graphql"

const server = createServer({
  routes() {
    const graphQLHandler = createGraphQLHandler(graphQLSchema, this.schema);

    this.post(URL, graphQLHandler)
  }
})

server.create("person", { firstName: "Mikael", lastName: "Åkerfeldt" })

const personQuery = `
  query Person($id: id) {
    person(id: $id) {
      id
      firstName
      lastName
    }
  }
`

request(URL, personQuery, { id: "1" }).then(
  console.log,
  console.error,
).finally(
  () => console.log('DONE')
)
  • Execution
$ node test.js 
FetchError: request to http://localhost/graphql failed, reason: connect ECONNREFUSED 127.0.0.1:80
    at ClientRequest.<anonymous> (/home/cel/projects/my/mirage/node_modules/node-fetch/lib/index.js:1461:11)
    at ClientRequest.emit (events.js:315:20)
    at Socket.socketErrorListener (_http_client.js:469:9)
    at Socket.emit (events.js:315:20)
    at emitErrorNT (internal/streams/destroy.js:106:8)
    at emitErrorCloseNT (internal/streams/destroy.js:74:3)
    at processTicksAndRejections (internal/process/task_queues.js:80:21) {
  type: 'system',
  errno: 'ECONNREFUSED',
  code: 'ECONNREFUSED'
}
DONE

model.hasInverseFor is not a function

I have a mutation updateSoftwareSourceCode(input: $input) and the variable input is

{
  "input": {
    "codeRepository": "https://github.com/foo/bar",
    "format": "SCRIPTS",
    "name": "Foo",
    "description": "A method.",
    "categories": [
      "WEB_SCRAPING"
    ],
    "keywords": [
      "Scientific Online Discourse",
      "Science-relatedness",
      "Tweets",
      "NLP"
    ],
    "version": "1.0",
    "downloadUrl": "https://codeload.github.com/foo/bar/zip/refs/heads/main",
    "documentationLink": "https://github.com/foo/bar/blob/main/annotation_framework.pdf",
    "programmingLanguage": "Python",
    "runtimePlatform": "Python 3.8",
    "datasetUsages": [
      {
        "isInput": true,
        "isOutput": false,
        "datasetId": "1"
      }
    ],
    "contributors": [
      {
        "isSubmitter": true,
        "isMaintainer": true,
        "personId": "10"
      }
    ],
    "scholarlyArticle": {
      "title": "foo",
      "doi": "foo/bar",
      "url": "https://dl.acm.org/doi/foo/bar"
    },
    "id": "7"
  }
}

Mirage GraphQL raises the following error

{
  "errors": [
    {
      "message": "model.hasInverseFor is not a function",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "updateSoftwareSourceCode"
      ]
    }
  ]
}

miragejs/ember-cli-mirage#1216 (comment) indicates that this might be related with

Mirage's ORM expects foreign key names to be *Id or *Ids.

Would be great to know which field raise the error. Is this something that should be submitted upstream?

Help Wanted: TypeScript and Priorities

This issue is an appeal for a little help from contributors

Many months back, I completed a TypeScript rewrite of Mirage GraphQL; however, I haven’t had any luck finding someone to test the alpha/beta releases. I’d prefer some real-world validation before publishing it since the changes are sweeping (to the code, not the functionality).

The lack of interest seemed to indicate to me that the library isn’t being used enough to tackle my TODO list.

TODO List

My current TODO list looks like this:

  1. Release TypeScript version
  2. Make auto-filtering optional and off-by-default (a breaking change but I think very welcome)
  3. Publish the documentation and reduce the size of the README

Since I don't really want to do any of these things unless people find them useful, I’d like some feedback. If I can release the TypeScript version of the library, I’d be happy to move forward with the remaining priorities.

Beta Testing

@rgaiacs, @nomin-sasabuchi, since you both opened recent issues, would you be interested in trying the TypeScript version? It was published to npm at @miragejs/[email protected]. No worries, if you don’t have time or energy for that.

Expose API or hooks for custom resolvers

It would be nice if we could reuse some of the inbuilt logic for pagination, simple field resolving, etc. as a basis for our own custom resolvers. Any chance that some of these functions could be exposed via a public API?

I'm looking to do some more advanced filtering, but in order to do so it appears that I have to implement everything else as well, which turns a seemingly small task into a seemingly big task. Another option might be to expose hooks within the resolver to allow us to e.g. filter a set of objects before pagination is applied, although this might be less robust for other use cases.

Just trying to start a discussion, I'm also willing to help with this if this fits with the goals of the project.

Not directly related to the ask above, but I would also appreciate some more advanced and/or real-world examples of custom resolvers if anyone is willing to contribute any!

How can I update an entry in resolver and trigger an update in watchQuery?

For example I have an entity Book and I need to mock a mutation changeBookName. I am writing something like this:

Mutation: {
        changeBookName(obj, args, context) {
          let book = context.mirageSchema.findBy('Book', {uuid: args.uuid});
          book.update({ name: 'aaaaa' });
          return book;
        },

And I see the response is correct in console but apollo client ignores this change.

I use Ember 3.28.12, "ember-apollo-client": "^4.1.1", and watchQuery under the hood

Thanks.

Add Typescript typings

As the title says, it'd be great to have typings for this library. Seeing Typescript on the rise and in use in many projects (including one I'm working on), it'd make developer experience better.

When updating data, an error occurs if there is a relationship

Prerequisites

Operation has been confirmed for data acquisition, creation, and updating when there is no relationship

Problem

If you request an update for a schema that has the following relationships, the following error will occur. Why?
If I exclude the related property (status: ScheduleState!), it works, so I think it's a problem with the relation.
Do I need to write my own resolver in such a case?

Error: Cannot return null for non-nullable field Schedule.status.: {"response":{"errors":[{"message":"Cannot return null for non-nullable field Schedule.status.","locations":[{"line":11,"column":5}],"path":["updateSchedule","status"]}],"data":{"updateSchedule":null},

Code

//schema
type Mutation {
  updateSchedule(id: ID!,params: UpdateScheduleInput): Schedule
}

type Schedule {
  id: ID!
  startAt: DateTime
  endAt: DateTime
  status: ScheduleState!
}

type ScheduleState {
  id: ID!
  name: String!
}


input UpdateScheduleInput {
  id: ID!
  startAt: DateTime
  endAt: DateTime
  statusId: ID
}

//query
export const updateSchedule = gql`
  mutation updateSchedule($id: ID!, $params: UpdateScheduleInput) {
    updateSchedule(id: $id, params: $params) {
      id
      startAt
      endAt
      status {
        id
        name
      }
    }
  }
`

Tried

By the way, I tried the following resolver, but it didn't work

import {
  createGraphQLHandler,
  mirageGraphQLFieldResolver,
} from '@miragejs/graphql'
import { createServer } from 'miragejs'

import schema from './generated-mock-schema'

export default createServer({
  seeds(server) {
    const status0 = server.create('ScheduleState', {
      id: '0',
      name: 'making',
    })
    const status1 = server.create('ScheduleState', {
      id: '1',
      name: 'confirm',
    })
    server.create('Schedule', {
      id: '1',
      startAt: '2023-12-01 11:05:09',
      endAt: '2023-12-01 13:05:09',
      status: status0,
    })
    server.create('Schedule', {
      id: '2',
      startAt: '2023-12-01 13:05:09',
      endAt: '2023-12-01 15:05:09',
      status: status1,
    })
  },
  routes() {
    const resolvers = {
      Mutation: {
        updateSchedule(obj, args, context, info) {
          const { params } = args

          const schedules = context.mirageSchema.db.schedules.find(args.id)
          const statusData = context.mirageSchema.db.scheduleStates.find(
            schedules.statusId
          )
          const records = {
            ...schedules,
           status: statusData,
            ...params,
          }
          return context.mirageSchema.db.schedules.update(args.id, records)
        },
      },
    }
    this.post(
      import.meta.env.VITE_SCHEDULE_API_URL,
      // @ts-ignore
      createGraphQLHandler(schema, this.schema, { resolvers })
    )
  },
})

[QUESTION] Does this plugin works for testing?

Hello, I was trying to set MirageJS in a React Native App, for development it works great, but I could not figure out how to make it works on test files.
Is this plugin designed only for development? On my small test example my query never finishes the load state
image

Support for object union types

Hey there and thanks for the awesome library!

I'm running into a problem trying to use a schema with a union type. Consider the following schema:

type Orange {
  id: ID!
  weight: Float!
}

type Apple {
  id: ID!
  radius: Float!
}

union Fruit = Orange | Apple

type Basket {
  id: ID!
  fruit: Fruit!
}

type Query {
  basket: Basket!
}

I'm trying to run a following query against it:

query GetBasket {
  basket {
    id
    fruit {
      ... on Orange {
        id
        weight
      }
      ... on Apple {
        id
        radius
      }
    }
  }
}

However, when executing it, I run into an error: Abstract type "Fruit" must resolve to an Object type at runtime for field "Basket.fruit" with value [{ id: "appleID", radius: 5, __typename: "Apple" }], received "undefined". Either the "Fruit" type should provide a "resolveType" function or each possible type should provide an "isTypeOf" function.

As can be seen in the error message, the object contains __typename field so I'd expect the server to be able to determine the type.

I'm not sure whether that's an issue with the library or me using GraphQL incorrectly but I've tried everything that came to my mind.

README incorrect?

Is the README correct?

npm i miragejs @miragejs/graphql.

import { createGraphQLHandler } from 'miragejs-graphql'

Module not found: Error: Can't resolve 'miragejs-graphql'?

Handle Custom scalar type like Date

Hi I have a graphql schema, where I have a custom scalar type defined. How do we handle serialization and deserialization of custom scalar type.

How to respond with a server error?

Hey folks 👋 I'm struggling with responding with a server error. I use the typical mirage way. Say, I want to simulate 502s and test Apollo's retry mechanism, so under some fake conditions I return this for a query:

return new Response(502);

But what I get returned instead is wrapped in GraphQL error. It looks like miragejs/graphql (or something internally) treats my response with 502 as a regular response and complains that the data is not returned properly:

image

Is it possible that miragejs/graphql is not aware that it should "re-throw" (pass) the error? Could someone give me pointers on where I should look to fill the gap?

Missing CommonJS distribution

Really excited about this package, unfortunately I have been unable to get it to work in my Next.js app because it is distributed as ES2015 modules instead of CommonJS. Since many developers are not transpiling their node_modules folders I believe its best practice to distribute a CommonJS format so that it works in a typical Node environment without any additional work by the user. The miragejs package has an example of offering both. If you look at their package.json it lists:

"main": "dist/mirage-cjs.js",
"module": "dist/mirage-esm.js",

The error I get is:

import { createGraphQLHandler } from "./lib/handler";
       ^

SyntaxError: Unexpected token {

I took a shot at trying to transpile this using my Next.js babel settings, but wound up with this error:
TypeError: Cannot destructure property context of 'undefined' or 'null'.

Thanks for the hard work here! Can't wait to try it out.

Mocking Subscriptions/ Subscriptions in Resolver

Any suggestions on how to handle mocking Subscriptions? I'm thinking through a way to do it using the graphql-subscriptions in tandem with mock-socket libraries, but it might be a little heavy.

Mirage: You called server.create(<model_name>) but no model or factory was found

Hi @jneurock , on the following example I have 2 entities that are connected HouseListing and HouseListingMedia, when I try to create an instance of HouseListingMedia I get the following error: You called server.create('houseListingMedia') but no model or factory was found..

I've tried changing the capitalization but it has no effect. houseListingMediaObject is the content that I've tried to create the instance of HouseListingMedia. When I run console.log on the server variable I can see that houseListingMedia is a recognized model. Why I'm getting this error?

I saw on unit testing that first I need to create the "child" entity, in this case HouseListingMedia and use the server.create return to create the "father", in this case HouseListing. When i try to createa a HouseListing without creating a HouseListingMedia it works, but I want to make this relationship work.

I've tried adding an ID field to HouseListingMedia but is does not seem to be the cause. This behavior is the same for both testing and development

This is a fragment of my schema

type HouseListingMedia {
    isPublic: Boolean!
    displayOrder: Int!
    propertyId: String!
    photoUrl: String
    thumbnailUrl: String
}

type HouseListing {
    id: ID!
    images: [HouseListingMedia]
    ...
}

Console.log on server

image

Sub fields returning null

Having an issue returning sub fields.. Not sure If there is something I need to add to resolvers, but have attempted that as well with no luck. Name returns fine, but null is coming back for any fields inside location. Even though the data exists in the same format. Am i missing something?

type Query {
    findPeople(
        personId: [String!]
    ): [Person]
}

type Person {
    location: Location
    name: String
}

type Location {
    city: String
}

How to reproduce NOT_FOUND error with context.mirageSchema.findBy()

Hi,

I have a custom resolver (like https://github.com/miragejs/graphql?tab=readme-ov-file#example-deleting-a-person). For a minimal example, consider that the database table person is empty and the result of

const person = context.mirageSchema.db.people.find(1)

is person be null. How do I create a NOT_FOUND error? Currently, Mirage JS GraphQL will return null but no error.

I would appreciate any help to reproduce the follow query to GitHub GraphQL API

Screenshot 2024-04-17 at 16-14-56 Explorer - GitHub Docs

Errors on schema with interfaces

Given a schema with interfaces:

type Account {
  id: ID
  profile: ProfileData!
} 

interface Profile {
  email: String
  phone: String
}

type ProfileData {
  personal: PersonalProfile
  business: BusinessProfile
}

type PersonalProfile implements Profile {
  firstName: String!
  lastName: String!
  email: String
  phone: String
}

type BusinessProfile implements Profile {
  name: String!
  type: BusinessTypes
  email: String
  phone: String
}

@miragejs/graphql gets confused when trying to create Models. The attempts to create a ProfileData record using server.create('profileData') gives an error indicating there is no model nor factory available for it. In addition, a Profile model is created when there should be none since it is an interface.

RelationShip

Hello, how to get all tickets ?

seed: server.schema.listTickets.create({ total: 1, tickets: server.schema.tickets.all() });

query: getTickets(limit: Float, init: Float, userEmail: String!): ListTicket

type ListTicket {
  total: Int!
  tickets: [Ticket!]!
}

type Ticket {
  id: String!
  status: String
  category: String
  subject: String
  url: String
}

Response: Cannot return null for non-nullable field Query.getTickets.

The built-in union type resolver doesn't consider parent records

When resolving all types except for union types, the library looks for field values on the parent object, if it's passed in to the resolver. This means resolving fields with a union type only works at the upper most query level or just coincidentally.

The union type resolver needs to be updated to consider the optional parent object.

Make the auto-filtering feature an off-by-default option?

To maintain compatibility with the design of ember-cli-mirage-graphql (the Ember-specific library that came before this), Mirage GraphQL automatically filters records by variables when auto-resolving. I think this behavior is probably surprising to most and I'm not sure if it's actually useful.

Example of the behavior being useful:

query Products($size: String) {
  products(size: $size) {
    id
    name
    size
  }
}

The query is called with a $size variable having the value "XL" and only records that match are returned from Mirage's database.


Example of the behavior being painful (forcing a query to be manually resolved):

query Products($limit: Int) {
  products(limit: $limit) {
    id
    name
  }
}

The query is called with a $limit variable having the value 10 and Mirage GraphQL tries to auto-resolve this by filtering for products having a "limit" field with a value of 10. Since "limit" isn't a field, no records are returned.


I'd like to gather some feedback on whether or not to change this behavior and make it off-by-default. I could add a handler creation option to enable this for anyone who does find this behavior useful.

Automatic limit

Hi!

I'm using this library in my project (amazing idea and implementation, btw) and I would like to now if it is possible to enable some "smart" args at a given query.

For example, I have the following schema (automatically generated from NestJS):

# ------------------------------------------------------
# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY)
# ------------------------------------------------------

type ProgressReport {
  id: Int!
  valuePrevious: Float
  valueNew: Float!
  comment: String
  createdAt: DateTime!
  keyResult: KeyResult!
  user: User!
}

"""
A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format.
"""
scalar DateTime

type Team {
  id: Int!
  name: String!
  createdAt: DateTime!
  updatedAt: DateTime!
  keyResults: [KeyResult!]!
  company: Company!
  users: [User!]!
}

type User {
  id: Int!
  authzSub: String!
  role: String
  picture: String
  createdAt: DateTime!
  updatedAt: DateTime!
  keyResults: [KeyResult!]!
  progressReports: [ProgressReport!]!
  confidenceReports: [ConfidenceReport!]!
  teams: [Team!]!
}

type ConfidenceReport {
  id: Int!
  valuePrevious: Float
  valueNew: Float!
  comment: String
  createdAt: DateTime!
  keyResult: KeyResult!
  user: User!
}

type KeyResult {
  id: Int!
  title: String!
  description: String
  initialValue: Int!
  goal: Int!
  format: String!
  createdAt: DateTime!
  updatedAt: DateTime!
  owner: User!
  objective: Objective!
  team: Team!
  progressReports(limit: Int): [ProgressReport!]!
  confidenceReports(limit: Int): [ConfidenceReport!]!
}

type Objective {
  id: Int!
  title: String!
  createdAt: DateTime!
  updatedAt: DateTime!
  keyResults: [KeyResult!]!
  cycle: Cycle!
}

type Cycle {
  id: Int!
  dateStart: DateTime!
  dateEnd: DateTime!
  createdAt: DateTime!
  updatedAt: DateTime!
  company: Company!
  objectives: [Objective!]!
}

type Company {
  id: Int!
  name: String!
  createdAt: DateTime!
  updatedAt: DateTime!
  teams: [Team!]!
  cycles: [Cycle!]!
}

type KeyResultView {
  id: Int!
  title: String
  binding: String
  rank: [Int!]!
  keyResults: [KeyResult!]!
  createdAt: DateTime!
  updatedAt: DateTime!
  user: User!
}

type Query {
  company(id: Int!): Company!
  confidenceReport(id: Int!): ConfidenceReport!
  cycle(id: Int!): Cycle!
  keyResult(id: Int!): KeyResult!
  keyResultView(binding: KeyResultViewBinding, id: Int): KeyResultView!
  objective(id: Int!): Objective!
  progressReport(id: Int!): ProgressReport!
  team(id: Int!): Team!
  user(id: Int!): User!
}

"""Each binding represents a given view in our applications"""
enum KeyResultViewBinding {
  MINE
}

type Mutation {
  updateRank(rank: [Int!]!, id: Int!): KeyResultView!
  createKeyResultView(binding: KeyResultViewBinding, title: String, rank: [Int!]!): KeyResultView!
  createProgressReport(comment: String, keyResultID: Int!, value: Int!): ProgressReport!
}

If you check the progressReport field at KeyResult type, it has a limit argument. NestJS (my GraphQL backend) uses that argument to limit the amount of retuned data if a value is provided (if the value is 0, it would return every recorded entity).

I've noticed that, in my MirageJS setup, if I provide a limit argument it simply wont return any value. If I understood correctly, it uses the limit and tries to fetch a given ProgressReport with limit=1 (which would return always empty, since ProgressReport does not have a limit option.

There are any way to enable this? I would not like to rewrite my schema just for MirageJS. My current development process is good, since I can simply copy the NestJS auto-generated schema directly to MirageJS.

ApolloError: Cannot read property 'type' of undefined

Hi @jneurock, I'm getting this error while trying to execute a query that does not include any "type" property. When I inspect the ApolloError object does not give any valuable information about the error location. I've got no errors while trying to seed this "Contacts" Entity, however, the MirageJS query does not work properly. Could it be some conflict of dependencies? I'm using:

"@miragejs/graphql": "^0.1.13",
"graphql": "^16.6.0",
"@apollo/client": "^3.7.4",

Apollo Client Error object

image

Query that throws this error

query clients($take: Int) {
    contacts(take: $take) {
        edges {
            id
            firstName
            lastName
            location
            photoUrl
        }
        pageInfo {
            totalCount
        }
    }
}

Server.ts queries - I'm not using automatic query handling, because of intermediary pagination types involved (edges and pageInfo). The console.log call inside the contacts query does not get triggered, I've only gotten the error. I'm assuming that this custom resolver is not working, however, the listings query works fine

        Query: {
          listings: () => ({
            edges: this.schema.all('Listing'),
            pageInfo: {
              currentPage: 0,
              itemCount: 200,
              hasNextPage: false,
              hasPreviousPage: false,
              perPage: 200,
              pageCount: 1,
            },
            contacts: () => {
              console.log('>>>>> Contact query');
              return {
                edges: this.schema.all('Contact'),
                pageInfo: {
                  totalCount: 100,
                },
              };
            },
          }),
        },

Resolver Ignores Subfield Values

First of all, thanks for the great library!

I was using it to mock results from a search query but I encountered what looks like a bug.

To give some context, the query that I'm trying to mock takes in a string, here is what my schema looks like:

type Dog {
// ... dogfields
}

type Cat {
//... cat fields
}
union Animal = Cat | Dog

type SearchResult {
item: Animal!
rank: Int!
}

type Query {
search(str: String!): [SearchResult!]!
}

Whatever I return as item from the search resolver, Mirage just ignores it and returns the first Animal in the database.

I've put together an example repo here: https://github.com/Gamaranto/miragegraphqlbug
In the example repo, I return null as item in the search resolver, but the first animal in the db is returned anyway.

Thanks in advance for the help!

Associated records are not filtered by query arguments

When fetching records at the root query level, we use query arguments to filter records from Mirage's database, by default. This is done via Mirage's API. That said, when we resolve associated records we don't consider query arguments.

Pretty much all resolvers need to be updated to properly filter associated records on parent objects.

Possible to mix in custom resolvers?

Loving this package so far and all the automatic crud mutations you get out of the box. Amazing job!

Aside from the basic crud mutations, i do have some mutations that need custom logic (password reset, signup activation etc). Is this possible and if so, how do I go about accessing the mirage db from within them resolvers?

Thanks!

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.