4.0.0 • Published 7 months ago

@lokalise/fastify-api-contracts v4.0.0

Weekly downloads
-
License
Apache-2.0
Repository
github
Last release
7 months ago

API contract support for fastify

This package adds support for generating fastify routes using universal API contracts, created with @lokalise/api-contracts

This module requires fastify-type-provider-zod type provider to work and is ESM-only.

Usage

Basic usage pattern:

import { buildFastifyNoPayloadRoute, buildFastifyPayloadRoute, injectPost, injectGet } from '@lokalise/fastify-api-contracts'

import { buildGetRoute, buildPayloadRoute } from '@lokalise/api-contracts'
import {
    type ZodTypeProvider,
    serializerCompiler,
    validatorCompiler,
} from 'fastify-type-provider-zod'

const getContract = buildGetRoute({
    successResponseBodySchema: RESPONSE_BODY_SCHEMA,
    requestPathParamsSchema: REQUEST_PATH_PARAMS_SCHEMA,
    requestQuerySchema: REQUEST_QUERY_SCHEMA,
    requestHeaderSchema: REQUEST_HEADER_SCHEMA,
    pathResolver: (pathParams) => `/users/${pathParams.userId}`,
})

const postContract = buildPayloadRoute({
    method: 'post', // can also be 'patch' or 'post'
    successResponseBodySchema: RESPONSE_BODY_SCHEMA,
    requestBodySchema: REQUEST_BODY_SCHEMA,
    pathResolver: () => '/',
})

const getRoute = buildFastifyNoPayloadRoute(getContract, (req) => {
    // req.query, req.params and req.headers represent fields from the contract
}, (contractMetadata) => {
    // Optionally, use this callback to dynamically add extra Fastify route options (like config, preHandler, etc.) using contract metadata.
})

const postRoute = buildFastifyPayloadRoute(postContract, (req) => {
    // req.body, req.query, req.params and req.headers represent fields from the contract
}, (contractMetadata) => {
    // Optionally, use this callback to dynamically add extra Fastify route options (like config, preHandler, etc.) using contract metadata.
})

const app = fastify({
    // app params
})

app.setValidatorCompiler(validatorCompiler)
app.setSerializerCompiler(serializerCompiler)

app.withTypeProvider<ZodTypeProvider>().route(getRoute)
app.withTypeProvider<ZodTypeProvider>().route(postRoute)

await app.ready()

// used in tests, you can use '@lokalise/frontend-http-client' in production code
const postResponse = await injectPost(app, contract, {
    pathParams: { userId: '1'},
    body: { id: '2' },
    headers: { authorization: 'some-value'} // can be passed directly
})

// used in tests, you can use '@lokalise/frontend-http-client' in production code
const getResponse = await injectGet(app, contract, {
    pathParams: { userId: '1' },
    headers: async () => { authorization: 'some-value'} // headers producing function (sync or async) can be passed as well
})

In case you prefer to separate handler definition from route definition, you can use functions buildFastifyNoPayloadRouteHandler (for GET and DELETE handlers) and buildFastifyPayloadRouteHandler (for PUT, POST and PATCH handlers):

import { 
    buildFastifyPayloadRoute, 
    buildFastifyPayloadRouteHandler 
} from '@lokalise/fastify-api-contracts'
import { buildPayloadRoute } from '@lokalise/api-contracts'

const contract = buildPayloadRoute({
    method: 'post',
    requestBodySchema: REQUEST_BODY_SCHEMA,
    successResponseBodySchema: BODY_SCHEMA,
    requestPathParamsSchema: PATH_PARAMS_SCHEMA,
    pathResolver: (pathParams) => `/users/${pathParams.userId}`,
})

const handler = buildFastifyPayloadRouteHandler(contract,
    async (req, reply) => {
        // handler definition here, req and reply will be correctly typed based on the contract
    }
)

const routes = [
    buildFastifyPayloadRoute(contract, handler),
]

Accessing the contract

In case you need some of the contract data within your lifecycle hook or a handler, it is exposed as a part of a route config, and can be accessed like this:

const route = buildFastifyNoPayloadRoute(contract, (req) => {
    const { apiContract } = req.routeOptions.config
})
4.0.0

7 months ago

2.2.0

8 months ago

2.1.2

8 months ago

2.1.1

8 months ago

2.1.0

9 months ago

2.0.2

9 months ago

2.0.1

9 months ago

2.0.0

9 months ago

1.4.4

9 months ago

1.4.3

10 months ago

1.4.2

10 months ago

1.4.1

10 months ago

1.4.0

10 months ago

1.3.0

10 months ago

1.2.0

10 months ago

1.1.3

10 months ago

1.1.2

10 months ago

1.1.1

10 months ago

1.1.0

10 months ago