Further develop (and document) how the GraphQL API can help import data from an external site to the WordPress site
leoloso opened this issue · comments
The GraphQL API has a few features that make it easy to access the data from an external endpoint, manipulate it, and inject it into some other field or mutation, allowing a single GraphQL query to perform complex operations. For instance, it allows importing posts/users/categories/tags/etc from another site (whether it is WordPress or not) into the WordPress site, without the need to write custom resolvers!.
The procedure could be something like this:
- A field
rearrangeJSONObjectProperties($input: JSONObject, $fromToPropertyPaths: JSONObject)
can manipulate the entries in an input, renaming the keys into the desired output - Via the "Resolved Field Variable Reference" feature, the output of the previous field can be accessed as an input into another field/mutation
- Using the "Multiple Query Execution" feature we can export a
JSONObject
that is treated as the expected input type for some mutation (eg:PostInput
,UserInput
, etc) - In the subsequent query, check if the data already exists
- If not, create it
For instance, this (potential) query accesses user data from an external REST endpoint, checks if the user exists on the local site and, if not, it creates it:
query ExportUserData
{
externalData: restData(url: "https://some-other-site.com/rest/users")
userData: rearrangeJSONObjectProperties(
# Using "Resolved Field Variable Reference" to access some resolved value as an input to another field
input: $externalData,
fromToPropertyPaths: {
"user.name": "name",
"user.email": "email"
}
)
# Using "Multiple Query Execution" to export a value
@export(as: "userInput")
extract(object: $userData, path: "email")
@export(as: "userEmail")
}
query CheckUserExists($userEmail: String)
@dependsOn(operation: "ExportUserData")
{
userExists(userEmail: $userEmail) @export(as: "doesUserExist")
}
mutation CreateUser($doesUserExist: Boolean, $userInput: UserInput)
@dependsOn(operation: "CheckUserExists")
@execute(if: $doesUserExist)
{
createUser(input: $userInput) {
id
name
email
}
}
Notice how $userInput
is exported as a JSONObject
, but is then treated as a UserInput
in the following mutation. That casting of the type should already work.
Directives @dependsOn
and @execute
do not currently exist, but they can be implemented once "operation directives" are supported (currently they are not).
If the external endpoint is REST, a single rest
field to get its data may be sufficient. If it is GraphQL, then using a new CPT called ExternalEndpoint
might be better as to specify the GraphQL query:
query ExportUserData
{
externalData: externalEndpointData(cptSlug: "some-graphql-external-endpoint-for-client")
# ...
}
Done