Skip to content

OpenAPI and Validation

OpenAPI and validation are part of the normal authoring path, not a bolt-on.

Package-owned routes can declare request and response metadata directly.

import { z } from 'zod';
import { definePackage, domain, route } from '@lastshotlabs/slingshot';
const postParams = z.object({ id: z.string() });
const postResponse = z.object({ id: z.string(), title: z.string() });
export const blogPackage = definePackage({
name: 'blog',
domains: [
domain({
name: 'posts',
basePath: '/posts',
routes: [
route.get({
path: '/:id',
request: { params: postParams },
responses: {
200: { description: 'Post', schema: postResponse },
},
handler: ({ params, respond }) => respond.json({ id: params.id, title: 'Hello' }),
}),
],
}),
],
});

That metadata drives both runtime validation and generated docs.

Use modelSchemas when you want shared schema sources preloaded before route discovery.

app.config.ts (excerpt)
import { defineApp } from '@lastshotlabs/slingshot';
export default defineApp({
modelSchemas: new URL('./schemas', import.meta.url).pathname,
});

This is especially useful when routes reference named schemas defined outside the route file.

By default, Slingshot generates:

  • /openapi.json
  • /docs

With versioning enabled, each version gets its own docs and spec output.

Use the top-level validation config when you want to standardize error formatting instead of letting every route invent its own error shape.

Entity-generated routes are not exempt from this model. Generated CRUD routes, named operations, route overrides, and extra routes all participate in validation and OpenAPI generation.