[Module Listing Request]: `Nuxt API SDK`
Description
This module provides a thin wrapper around $fetch and is just a little bit of fun. It provides an "SDK" kinda way to call your server routes in nuxt!
It hooks into the nitro server's scannedHandlers object and generates a template in Nuxt-land so that in userland instead of this:
// example get
await $fetch(`/api/user/${uid}`, { method: 'get' })
// example post
await $fetch(`/api/user`, {
method: 'post',
body: { name: 'Jamie' }
})
You can now do this, with full autocompletion and type-safety:
// example get
await useApi().user.uid(uid).get()
// example post
await useApi().user.post({ body: { name: 'Jamie' } })
To type the body, I've introduced a defineBodyType server util that does nothing but return the type of the body.
I want to try and move to using the built in defineRouteMeta but couldn't figure out a way to extend it. Let me know if there's another way I can type up the request body.
Example usage on a server route:
type Body = Omit<User, 'uid'>
export const body = defineRouteType<Body>()
export default defineEventHandler(async (event) => {
const body = await readBody<Body | undefined>(event)
// etc..
})
I'm not precious about this - it was a reason to dive deeper into modules and Nitro, a bit of practice generating template files dynamically, and the result is kinda fun! 🍭 Maybe someone else will enjoy it too?
I've only tested with Nuxt 4, but I think it should work on v3 too.
Repository
https://github.com/jamiecurnow/nuxt-api-sdk
npm
https://www.npmjs.com/package/nuxt-api-sdk
Nuxt Compatibility
Nuxt 4
BTW, here's a simple version of the generated "sdk" file contents:
import { $fetch as _$fetch, type FetchOptions } from 'ofetch'
import type { InternalApi } from 'nitropack/types'
type GetBody<T> = T extends { body: infer B } ? { body: B } : { body: FetchOptions['body'] }
export const _useApi = (_apiOpts?: { fetch?: typeof _$fetch }) => {
const $fetch = _apiOpts?.fetch || _$fetch
return {
user: {
uid: (uid: string) => ({
get: async (opts?: Omit<FetchOptions, 'method'>): Promise<InternalApi['/api/user/:uid']['get']> => {
return $fetch(`/api/user/${uid}`, { ...(opts || {}), method: 'GET', responseType: 'json' })
}
}),
post: async (
opts?: Omit<FetchOptions, 'method' | 'body'> & GetBody<typeof import('/Users/JCGeek/Documents/Projects/@jamiecurnow/nuxt-api-sdk/playground/server/api/user/index.post.ts')>
): Promise<InternalApi['/api/user']['post']> => {
return $fetch(`/api/user`, { ...(opts || {}), method: 'POST', responseType: 'json' })
}
}
}
}