Readonly/computed field directive

Just going to start by saying that I’m relatively new to using graph dbs so may not be thinking in the right mindset

What I’m looking for is some form computer value or the inverse of a hasInverse directive. Essentially, a separate type for responses compared to requests.

I would like to have a type A and B, where A has a field of B’s, but it should not be possible to create a B by adding an A. Instead, B’s should be queriable via A, but not mutable via A.

A basic example:

POST /admin/schema

type Foo {
	id: String! @id @search(by: [exact])
	bar: [Bar]
}

type Bar {
	id: String! @id
	foo: Foo @hasInverse(field: bar)
}

Create a Foo with linked Bar.

POST /graphql

mutation {
  addFoo(input: [
    {
      id: "x"
    }
  ]) { foo { id bar { foo { id } } } }
  
  addBar(input: [
    {
      id: "a"
      foo: { id: "x" }
    }
  ]) { bar { id foo { bar { id } } } }
}

This succeeds in creating a Foo and Bar, but I’d want it to fail or not be possible to create a Bar on Foo as that is a computed field

POST /graphql

mutation {
  addFoo(input: [
    {
      id: "y"
      bar: { id: "b" }
    }
  ]) { foo { id bar { foo { id } } } }
}

My initial thinking would be to use an @custom directive to compute the field or use @auth to disable mutations to Foo.bar. However, it feels like there should be a simpler way to create an inverse readonly relationship

While backend security is currently very basic, this is easily accomplished by the @auth directive.

type Bar  @auth(
    add: { rule:  "{$DENIED: { eq: \"DENIED\" } }"}
) {
	id: String! @id
	foo: Foo @hasInverse(field: bar)
}

You could create a custom mutation if you needed to create B in some way.

J

2 Likes

Thanks, this is what I suspected and gives me a basis to work off. It does feel like it should be possible to encode this far more easily. Either by authenticating fields or having a directive that specifies a readonly edge.

The workaround for creating a custom B is quite laborious as it’s not currently possible to use dql, therefore a call to a remote service to construct the type is required