Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mcollina/fastify-api
A radically simple API routing and method injection plugin for Fastify.
https://github.com/mcollina/fastify-api
fastify fastify-plugin
Last synced: about 1 month ago
JSON representation
A radically simple API routing and method injection plugin for Fastify.
- Host: GitHub
- URL: https://github.com/mcollina/fastify-api
- Owner: mcollina
- Created: 2021-03-15T21:46:22.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-06-16T21:11:15.000Z (8 months ago)
- Last Synced: 2024-12-21T09:39:55.109Z (about 2 months ago)
- Topics: fastify, fastify-plugin
- Language: JavaScript
- Homepage:
- Size: 462 KB
- Stars: 18
- Watchers: 20
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# fastify-api
A **radically simple** API **routing and method injection plugin** for [Fastify](https://fastify.dev).
Uses [`fastify.inject`](https://github.com/fastify/light-my-request) under the hood, with _developer ergonomics_ in mind.
Injects `fastify.api.client` with automatically mapped methods from route definitions. Also injects `fastify.api.meta`, which you can serve and use [`manifetch`](https://github.com/galvez/manifetch) to automatically build an API client for the browser.
## Usage
1. **Original fastify.{method}() with `exposeAs` option, without params:**
```js
fastify.get('/1/method', { exposeAs: 'method' }, (_, reply) => {
reply.send('Hello from /1/method')
})
fastify.get('/invoke/1/method', async (_, reply) => {
const result = await fastify.api.client.method()
reply.send(result)
})
```2. **Original fastify.{method}() with `exposeAs` option, with params:**
```js
fastify.get('/2/method/:id', { exposeAs: 'methodWithParams' }, ({ id }, _, reply) => {
reply.send(`Hello from /2/method/ with id ${id}`)
})
fastify.get('/invoke/2/method', async (req, reply) => {
const result = await fastify.api.client.methodWithParams({ id: 123 })
reply.send(result)
})
```3. **Will automatically create a nested structure too, if needed:**
```js
fastify.get('/3/nested/method/:id', { exposeAs: 'nested.method' }, ({ id }, _, reply) => {
reply.send(`Hello from /3/nested/method/ with id ${id}`)
})
fastify.get('/invoke/3/nested/method', async (req, reply) => {
const result = await fastify.api.client.nested.method({ id: 123 })
reply.send(result)
})
```4. **Modified fastify.api.{method}() setter if the handler is a named function:**
```js
fastify.api.get('/4/method', function methodFromNamedFunction ({ id }, _, reply) {
reply.send(`Hello from /4/method with id ${id}`)
})
fastify.get('/invoke/4/method', async (req, reply) => {
const result = await fastify.api.client.methodFromNamedFunction({ id: 123 })
reply.send(result)
})
```5. **Modified fastify.api(setter) helper to quickly define multiple methods:**
_Makes more sense if the setter function is coming from another file._
```js
fastify.api(({ get }) => ({
topLevelMethod: get('/5/top-level-method/:id', function ({ id }, _, reply) {
reply.send({ id })
}),
nestedMethods: {
method: get('/5/nested-methods/method/:id', ({ id }, _, reply) => {
reply.send({ id })
}),
otherMethod: get('/5/nested-methods/other-method/:id', ({ id }, _, reply) => {
reply.send({ id })
}),
deeplyNestedMethods: {
method: get('/5/nested-methods/deeply-nested-methods/method/:id', ({ id }, _, reply) => {
reply.send({ id })
}),
otherMethod: get('/5/nested-methods/deeply-nested-methods/other-method/:id', ({ id }, _, reply) => {
reply.send({ id })
})
}
}
}))fastify.get('/invoke/5/top-level-method', async (req, reply) => {
const result = await fastify.api.client.topLevelMethod({ id: 123 })
reply.send(result)
})
fastify.get('/invoke/5/nested-methods/method', async (_, reply) => {
const result = await fastify.api.client.nestedMethods.method({ id: 123 })
reply.send(result)
})
fastify.get('/invoke/5/nested-methods/other-method', async (_, reply) => {
const result = await fastify.api.client.nestedMethods.otherMethod({ id: 123 })
reply.send(result)
})
fastify.get('/invoke/5/nested-methods/deeply-nested-methods/method', async (_, reply) => {
const result = await fastify.api.client.nestedMethods.deeplyNestedMethods.method({ id: 123 })
reply.send(result)
})
fastify.get('/invoke/5/nested-methods/deeply-nested-methods/other-method', async (_, reply) => {
const result = await fastify.api.client.nestedMethods.deeplyNestedMethods.otherMethod({ id: 123 })
reply.send(result)
})
```6. **Any API method exposed in fastify.api.client can take options:**
```js
fastify.get('/6/method', { exposeAs: 'methodWithOptions' }, (req, reply) => {
reply.send(`Hello from /6/method/ with query.arg ${
req.query.arg
} and the x-foobar header ${
req.headers['x-foobar']
}`)
})
fastify.get('/invoke/6/method', async (_, reply) => {
const result = await fastify.api.client.methodWithOptions({
query: {
arg: 1
},
headers: {
'x-foobar': 1
}
})
reply.send(result)
})
```## API responses
If you call a route via HTTP, it'll operate normally as if weren't using the plugin. If you use `fastify.api.client.xyz()` to invoke it from another handler, you'll get an object containing `{ json, body, status, headers }` as response. If it's unable to parse a JSON document out of `body`, `json` is undefined.