syntax = "proto3";
package dagger;

option go_package = "./idproto";

// ID represents a GraphQL value of a certain type, constructed by evaluating
// its contained pipeline. In other words, it represents a
// constructor-addressed value, which may be an object, an array, or a scalar
// value.
//
// It may be binary=>base64-encoded to be used as a GraphQL ID value for
// objects. Alternatively it may be stored in a database and referred to via an
// RFC-6920 ni://sha-256;... URI.
message ID {
  // The parent ID, if any.
  ID parent = 1;

  // The GraphQL type of the value.
  Type type = 2;

  // GraphQL field name.
  string field = 3;

  // GraphQL field arguments, always in alphabetical order.
  repeated Argument args = 4;

  // If true, this Selector is not reproducible.
  //
  // TODO: do we need to refer to session/client IDs or anything here? Or is
  // that all internal? Forcing function is whether this is used as an
  // in-memory query cache key. But the query cache might be made per-session
  // or even per-client instead anyway! What buys us the most?
  bool tainted = 5;

  // If true, this Selector may be omitted from the pipeline without changing
  // the ultimate result.
  //
  // This is used to prevent meta-queries like 'pipeline' and 'withFocus' from
  // busting cache keys when desired.
  //
  // It is worth noting that we don't store meta information at this level and
  // continue to force metadata to be set via GraphQL queries. It makes IDs
  // always easy to evaluate.
  bool meta = 6;

  // If the field returns a list, this is the index of the element to select.
  // Note that this defaults to zero, as IDs always refer to
  //
  // Here we're teetering dangerously close to full blown attribute path
  // selection, but we're intentionally limiting ourselves instead to cover
  // only the common case of returning a list of objects. The only case not
  // handled is a nested list. Don't do that; have a type instead.
  int64 nth = 7;

  // A module that must be loaded prior to evaluating this ID.
  //
  // The actual usage of this ID is opaque to the protocol. In Dagger this is
  // the module ID providing the implementation of the field.
  ID module = 8;
}

// A named value passed to a GraphQL field or contained in an input object.
message Argument {
  string name = 1;
  Literal value = 2;
}

// A value passed to an argument or contained in a list.
message Literal {
  oneof value {
    ID id = 1;
    bool null = 2;
    bool bool = 3;
    string enum = 4;
    int64 int = 5;
    double float = 6;
    string string = 7;
    List list = 8;
    Object object = 9;
  }
}

// A list of values.
message List {
  repeated Literal values = 1;
}

// A series of named values.
message Object {
  repeated Argument values = 1;
}

// A GraphQL type.
message Type {
  string namedType = 1;
  Type elem = 2;
  bool nonNull = 3;
}
