Description
I'm working on implementing a Node interface for OneGraph. Each of our underlying APIs implements its own node interface, so we have GitHubNode
, SalesforceNode
, IntercomNode
, etc.
To implement the resolver for the OneGraphNode
, I just need to determine which service the nodeId
is for, then utilize the existing machinery for resolving a node.
It would look something like:
field(
"node",
~args=Arg.[arg("oneGraphId", ~typ=non_null(guid))],
~typ=oneGraphNodeInterface,
~resolve=(resolveInfo, (), id) =>
switch (decodeNodeId(id)) {
| Ok({service, serviceNodeId}) =>
switch (service) {
| `GitHub => resolveGitHubNode(serviceNodeId) |> gitHubNodeToOneGraphNode
| `Salesforce => resolveSalesforceNode(serviceNodeId) |> salesforceNodeToOneGraphNode
}
}
);
It would be really handy if I had a way to convert from the underlying service's node interface to the OneGraph node interface.
Would you be open to a new inherit_types
function that copied all the types from one interface to another and created a function to coerce from one interface to another?
It would look like:
let inherit_types :
'a 'b.
('ctx, 'a) abstract_typ ->
('ctx, 'b) abstract_typ ->
('ctx, 'a) abstract_value -> ('ctx, 'b) abstract_value =
fun from_abstract_typ to_abstract_typ ->
match (from_abstract_typ, to_abstract_typ) with
| (Abstract from_typ), (Abstract to_typ) ->
to_typ.types <- List.concat [from_typ.types; to_typ.types];
List.iter (fun o ->
match o with
| AnyTyp (Object o) -> o.abstracts := to_typ :: !(o.abstracts)
| _ -> invalid_arg "Types for Abstract type must be objects"
) to_typ.types;
fun (AbstractValue (from_typ, src)) -> (AbstractValue (from_typ, src))
| _ -> invalid_arg "Arguments must both be Interface/Union"
With that function, I could easily construct gitHubNodeToOneGraphNode
and salesforceNodeToOneGraphNode
above by doing:
let gitHubNodeToOneGraphNode = Schema.inherit_types(gitHubNode, oneGraphNodeInterface);
let salesforceNodeToOneGraphNode = Schema.inherit_types(salesforceNode, oneGraphNodeInterface);