Skip to main content

Server-side APIs

If your plugin requires a server-side API for some complexed computing or private process, Clubs allows it to define that server-side APIs freely using getApiPaths.

getApiPaths

getApiPaths is an asynchronous function that generates API endpoints and returns an array of ClubsApiPath to define API endpoints and their behavior, etc.

Clubs runtime passes 3 arguments to getApiPaths, plugin options, config, and utils. And the return value should be an array of objects with the following values:

RequiredTypeDescription
pathsRequiredarray includes string, RegExp or undefinedPath to determine the URL of the API endpoint.
methodRequired'CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT' or 'PATCH'HTTP method of the API endpoint.
handlerRequiredAPIRouteAsynchronous function compliant with APIRoute type

The returns value

The return value of getApiPaths should be an array of objects with these properties.

paths

If a string /api/+ meta.id + the paths joined with / matches the pathname and method (described in below) in the API request, the handler function will be called as the API endpoint.

/api/ and meta.id are automatically added by Clubs runtime, so you do not need to use them in the paths.

For example, if your plugin has example-plugin as the meta.id and you want to add an API endpoint has /api/example-plugin/vote/create, paths should be the following value:

["vote", "create"]
// This will be => /api/example-plugin/vote/create (/api/{meta.id}/{paths joined with `/`})

If you would like to add the API endpoint as the root pathname = /api/example-plugin/, you can define it as an empty array, or an array containing only undefined, like this:

[]
// OR
[undefined]

// These will be => /api/example-plugin/ (/api/{meta.id}/)
info

// TODO: Add a note about RegExp path

method

Specify the HTTP method that the API endpoint expects. If the paths match but the method mismatch, the API will not be called.

/src/index.ts
const getApiPaths = async () => [
{
method: 'POST',
handler: () => ({ body: '' }),
paths: ['vote', 'create'],
},
]

export default {
getApiPaths,
meta: {
/*...*/
},
}

handler

handler is a function that returns the API response to the request that matches paths and method, and it must be compliant with APIRoute type. The request body, headers, etc. can be accessed via its argument, APIContext.

/src/index.ts
const getApiPaths = async (options) => [
{
handler: async ({ request }) => ({
body: JSON.stringify({ options, body: request.body }),
}),
method: 'POST',
paths: ['vote', 'create'],
},
]

export default {
getApiPaths,
meta: {
/*...*/
},
}

Use plugin options

The 1st argument of getApiPaths is passed an object plugin options, has type ClubsPluginOptions(*). By controlling the return value of getApiPaths with plugin options, you can control the API endpoints.

/src/index.ts
const getApiPaths = async (options) => {
const votes = options.find(({ key }) => key === 'votes')?.value // e.g., [{id: 'a-1', more: value}, {id: 'a-2', more: value}, {id: 'a-3', more: value}]

return votes.map((vote) => ({
handler: async ({ request }) => ({
body: JSON.stringify({ options, body: request.body }),
}),
method: 'PATCH',
paths: ['vote', vote.id, 'edit'],
}))
}

export default {
getApiPaths,
meta: {
/*...*/
},
}
info

The details of the plugin options are found on ClubsPluginOptions.

Use configuration

The 2nd argument of getApiPaths is passed an object config, has type ClubsConfiguration(*). By controlling the return value of getApiPaths with config, you can control the API endpoints.

ClubsConfiguration contains major primitive configuration values such as Clubs name, property token address, chain ID which tokenized it, URL of Json-RPC endpoint, etc.

/src/index.ts
import { JsonRpcProvider } from 'ethers'

const getApiPaths = async (_, config) => {
const { rpcUrl } = config

return [
{
handler: async ({ request }) => {
const prov = new JsonRpcProvider(rpcUrl)
/* Some kind of processing using ethers provider... */
return {
body: JSON.stringify({ success: true }),
}
},
method: 'POST',
paths: ['vote', 'create'],
},
]
}

export default {
getApiPaths,
meta: {
/*...*/
},
}
info

The details of the config are found on ClubsConfiguration.

Use utils

The 3rd argument of getApiPaths is passed an object utils, has type ClubsFactoryUtils(*). ClubsFactoryUtils has a function getPluginConfigById that allows users to retrieve configuration values for other plugins using getPluginConfigById.

/src/index.ts
const getApiPaths = async (_, __, utils) => {
const emojiPlugin = utils.getPluginConfigById('emoji:plugin:id') // Find a config of a plugin that has `meta.id: "emoji:plugin:id"`
const emoji =
emojiPlugin?.options?.find(({ key }) => key === 'emoji')?.value ?? '🦄'

return [
{
handler: async () => ({
body: JSON.stringify({ emoji }),
}),
method: 'GET',
paths: ['emoji'],
},
]
}

export default {
getApiPaths,
meta: {
/*...*/
},
}
info

The details of the utils are found on utils.