Skip to main content

REST

Metatype also allows you to consume your API in the same way you would consume regular REST APIs. It is as easy as calling a function: g.rest(..).

Here is a basic overview of how it looks like:

typegraph("example", (g) => {
// ..
g.expose({
getUsers: ..,
}, pub);

g.rest(`
query users($name: String, $rows: Integer) {
getUsers(name: $name, option: { maxRows: $rows } ) {
name
}
}
`);
// ..
});

General rule

query_type endpoint_name($param1: T1, $param2: T2, ..) {
exposed(..) {
f1
f2 ..
}
}

There is no rule in what type of query you should do most of the time as everything is up to you, however the type of query you set will define how your endpoint should be used.

In other words, depending on what query_type (query or mutation), $param1, $param2, .. will be defined from the request parameters (GET) or the request body (POST).

  • query: Perform a GET at {TYPEGATE_URL}/{TG_NAME} /rest/endpoint_name?param1=..&param2=..
  • mutation: Perform a POST at {TYPEGATE_URL}/{TG_NAME} /rest/endpoint_name with Content-Type set as application/json
{
"param1": ..,
"param2": ..,
..
}

In the example above, for a local instance, the endpoint might look like: http://localhost:7890/example/rest/users?name=Bob&rows=10

Dynamic queries

This enables/disables all non-static queries, i.e. queries whose output or side effects depend on certain parameters.

By default, dynamic is always on.

typegraph({ name: "my-typegraph", dynamic: false }, (g) => {
// ..
});

Auto-generated docs

In any case, you can always check the auto-generated documentation of the available endpoints, parameters, output shapes.

You can browse it at {TYPEGATE_URL}/{TG_NAME}/rest.

OpenAPI clients

In some cases, as your typegraph gets more complicated, you may want to automate the step of writing clients and focus on the actual logic of your application instead.

The OpenAPI spec will be available at {TYPEGATE_URL}/{TG_NAME}/rest/__schema, which is very useful considering that there are already a number of tools that enable you to create clients from an existing OpenAPI specification file.

Once you download the specification file for your API, it should look like something like this:

// {TYPEGATE_URL}/my_awesome_typegraph/rest/__schema
{
"openapi": "3.0.3",
"info": {
"title": "my_awesome_typegraph",
"license": {
"name": "MIT"
},
"description": "Rest endpoints for typegraph \"my_awesome_typegraph\"",
"version": "1.0.0"
},
"servers": [{ "url": "http://localhost:7890" }],
"paths": {
// typing each path manually on a custom client can be very tedious as your API grows
"/my_awesome_typegraph/rest/get_post": {
"get": {
"summary": "Perform get_post",
"operationId": "get_my_awesome_typegraph_get_post",
"responses": { ... }, // you will have various types per response status
"parameters": [ ... ]
}
},
"/my_awesome_typegraph/rest/get_post_id": { ... },
"/my_awesome_typegraph/rest/read_post": { ... }
},
"components": { ... }
}

Here are some of the most used generators:

To keep our setup simple, let us look at @openapitools/openapi-generator-cli, which is just a wrapper around openapi-generator and will download the appropriate dependencies for you.

First, install the cli globally

npm i -g @openapitools/openapi-generator-cli

In this example, let's generate a simple fetch client, you can refer to their official documentation for other generators.

openapi-generator-cli generate \
-i http://localhost:7890/my_awesome_typegraph/rest/__schema \
-g typescript-fetch \
-o my-client \
--skip-validate-spec

This will generate a fetch-based typescript project.

.
+-- apis
¦ +-- DefaultApi.ts
¦ +-- index.ts
+-- models
¦ +-- Either10.ts
¦ +-- ErrorExtensions.ts
¦ ...
¦ +-- GetMyAwesomeTypegraphGetIdentity200Response.ts
¦ +-- Post.ts
¦ +-- User.ts
¦ +-- index.ts
+-- runtime.ts
+-- index.ts