mswjs / data

Data modeling and relation library for testing JavaScript applications.
https://npm.im/@mswjs/data
MIT License
827 stars 52 forks source link

fix(executeQuery): support circular references when updating entities #163

Closed olivierwilkinson closed 2 years ago

olivierwilkinson commented 3 years ago

closes #139

When passing an object with circular references to update the executeQuery function fails: it passes the query object to JSON.stringify which throws a "cyclic object value" exception.

Circular references are created when a bi-directional relationship is made. For example:

const db = factory({
  user: {
    id: primaryKey(String),
    posts: manyOf('post'),
  },
  post: {
    id: primaryKey(String),
    author: oneOf('user')
  },
});

const author = db.user.create({ id: 'user-1' })
const post = db.post.create({ id: 'post-1', author })
const nextAuthor = db.user.update({
  where: { id: { equals: author.id } },
  data: { posts: [post] },
})

If an entity that has been set up this way is passed to update it fails because of the above:

db.post.update({
  where: { id: { equals: 'a-different-post' } },
  data: { author: nextAuthor },
});

As @tinleym talked about in #139, to mock some GraphQL responses these relationships need to be traversed in both directions. This makes these bi-directional setups required to properly mock those resolvers.

This PR adds tests for creating / using bi-directional relationships and fixes the error thrown by executeQuery by adding a safeStringify util that is used in place of JSON.stringify.

The safeStringify util replaces any circular references with a string representation instead. It's more or less a knock off of the one from the MDN docs, but it also inserts some information about the entity it's replaced to keep the logs useful.

The stringified version of nextAuthor that would produced by safeStringify is:

{ "id": "user-1", "posts": [{ "id": "post-1", "author": "Entity(type: user, id: user-1)" }] }
kettanaito commented 3 years ago

Hey, @olivierwilkinson! Thank you for tackling this one. I remember I was looking into this issue myself, need to dig up my old notes to see what I came up with. Your changes will certainly be useful.

olivierwilkinson commented 3 years ago

Hey, @olivierwilkinson! Thank you for tackling this one.

I remember I was looking into this issue myself, need to dig up my old notes to see what I came up with. Your changes will certainly be useful.

No worries at all 😁

I'd hit up against this one myself not too long ago so had an idea what the problem was. Feel free to chop and change to your hearts content! 👌

kettanaito commented 2 years ago

Note to myself: keep notes referencable. Now to understand where exactly I've tackled this months ago...

kettanaito commented 2 years ago

Thank you for working on this, @olivierwilkinson. Your changes are fantastic.

I highly value your contributions! Could you please reach out to me on Twitter? I'd like to compensate you for your time working on the library and discuss if we could collaborate more. Thanks.

github-actions[bot] commented 2 years ago

:tada: This PR is included in version 0.9.1 :tada:

The release is available on:

Your semantic-release bot :package::rocket:

olivierwilkinson commented 2 years ago

Thank you for working on this, @olivierwilkinson. Your changes are fantastic.

I highly value your contributions! Could you please reach out to me on Twitter? I'd like to compensate you for your time working on the library and discuss if we could collaborate more. Thanks.

@kettanaito thank you for your kind words! I would love to collaborate more and will send you a message now. My Twitter handle is olivierwilkins2 😁