Guide: accessing metadata
Overview
Papupata allows you to declare, call and implement APIs. Sometimes you need to do something slightly different though and need access to information about the API. This guide helps you with that.Table of contents
To begin with
It might be helpful fairly solid understanding of what papupata API declarations look like.
In the examples presented in this guide, the following API declaration is assumed to be in the scope:
const complexAPI = API.declarePostAPI('/update/:id', routeOptions)
.params({id: String})
.query({author: String, notifyWatchers: Boolean}})
.optionalQuery({timestamp: String})
.body<{ name: string}>()
.response<{status: string }>()
URLs and methods
The most basic things, path and method as specified when declared the API can be accessed directly from the api object.
const {method, path} = complexAPI
// method: post
// path: /update/:id
The path might not be quite what you need though. Perhaps you want a full URL, with path and possibly query parameters already in place. This can be done with the getURL method. Do note that the method requires baseURL to be configured.
API.updateConfig({
baseURL: 'https://www.example.com'
})
console.log(complexAPI.getURL({id: '123'}))
// https://www.example.com/update/123
console.log(complexAPI.getURL({id: '123', author: 'Bob'}))
// https://www.example.com/update/123?author=Bob
Path and query parameters
The names and types of path and query parameters are accessible from the apiUrlParameters property of the api.
const {(params, query, optionalQuery, boolQuery)} = api.apiUrlParameters
Types
This is where things get a little bit more interesting. You can't just export types from and object in typescript, but that's what an API is. Papupata uses a workaround for this problem which looks odd at first, but you get used to it quickly enough. That is, the api exports values that as far as typescript is concerned match the various types used by papupata, allowing the use of typeof operator to access the actual type.
Response
Let's start with the type of the response.
const ApiResponseType = typeof complexApi.ResponseType
In situations where the type of the response returned by the implementation is different from the one observed by the client, ServerResponseType indicates the type the server is expected to return. If unspecified by the declaration, this is the same as responseType.
type ApiResponseTypeOnClient = typeof complexApi.ResponseType
type ApiResponseTypeOnServer = typeof complexApi.ServerResponseType
Body
The body for the request follows the same pattern in the opposite direction, with BodyType being the one observed by the server and CallBodyType being the one used for API calls.
type BodyTypeOnClient = typeof complexApi.CallBodyType
type BodyTypeOnServer = typeof complexApi.BodyType
Request
The papupata request is an express request, possibly modified with your own fields as provided on the API declaration, but more importantly it has explicit types for params, query and body. You can access the request type for a specific API using its RequestType property.
type RequestType = typeof complexApi.RequestType
This can be especially useful when you want to use a named function as the implementation for an API.
Implementation
You can get access to the current implementation and its middleware from the API. The primary use for this is for unit testing, but a clever individual can undoubtedly come up with other uses as well.
const {implementation, implementationMiddleware} = complexApi