Files
suaveplan/packages/api-stack/api/api-plugin-search/src/schemas/schemas.md
2026-05-27 23:29:53 +01:00

4.2 KiB

schemas/schemas

(no submodules)

Purpose

The schemas module owns the public Zod surface of @suaveplan/api-plugin-search. Every HTTP route in the package validates its request body, path params, or query string against one of these schemas before invoking the service layer, and every response shape is declared here so @hono/zod-openapi can publish a typed /openapi.json document without per-route duplication. Inferred types are exported in parallel so direct programmatic consumers (e.g. another plugin building on top of the search service) can construct payloads with full type safety.

Features

  • Thirteen schemas covering the full upstream search surface — queries, hits, facets, sort orders, index status enums, index field declarations, document indexing, bulk indexing, suggest queries, and every response shape.
  • Two const-object enums (SearchSortOrder, IndexStatus) so consumers can branch on string literals without re-typing them.
  • Sensible defaults at the boundary (sort: "relevance", limit: 20, offset: 0, highlight: false, highlightTag: "mark", analyzer: "standard", weight: 1, facet: false) so consumers only pass the fields they care about.
  • Hard upper bounds on every numeric and string field — query capped at 1000 chars, index names at 128 chars, limit ≤ 200, bulk docs ≤ 1000 — keeping the HTTP surface within sane resource budgets.
  • Inferred TypeScript types exported alongside each schema so call sites can type-check payloads at compile time without z.infer boilerplate.

Usage: Basic

import {
    SearchQuerySchema,
    type SearchQuery,
} from "@suaveplan/api-plugin-search";

const parsed = SearchQuerySchema.safeParse({
    query: "hello world",
    index: "posts",
});
if (parsed.success) {
    const q: SearchQuery = parsed.data;
    // q.sort === "relevance" by default, q.limit === 20, ...
}

Usage: Advanced

Compose the schemas with @hono/zod-openapi to publish typed routes:

import { createRoute } from "@hono/zod-openapi";
import {
    SearchQuerySchema,
    SearchResultSchema,
} from "@suaveplan/api-plugin-search";

export const searchRoute = createRoute({
    method: "post",
    path: "/query",
    request: {
        body: {
            content: { "application/json": { schema: SearchQuerySchema } },
        },
    },
    responses: {
        200: {
            description: "Search results",
            content: { "application/json": { schema: SearchResultSchema } },
        },
    },
});

API Reference

Symbol Shape
SearchSortOrder const object + type union — "relevance", "date_asc", "date_desc", "alpha_asc", "alpha_desc"
IndexStatus const object + type union — "active", "building", "error"
SearchQuerySchema / SearchQuery request body for POST /query
SearchHitSchema / SearchHit one hit returned by search()
FacetValueSchema / FacetValue { value, count }
FacetSchema / Facet { field, values: FacetValue[] }
SearchResultSchema / SearchResult response shape of POST /query
IndexFieldSchema / IndexField per-field config in CreateIndex
CreateIndexSchema / CreateIndex request body for POST /indexes
IndexInfoSchema / IndexInfo response shape of GET /indexes/:name
IndexListQuerySchema / IndexListQuery query string for GET /indexes
IndexDocumentSchema / IndexDocument request body for indexing
BulkIndexSchema / BulkIndex request body for bulk indexing
SuggestQuerySchema / SuggestQuery request body for POST /suggest
SuggestionSchema / Suggestion one entry in SuggestResult.suggestions
SuggestResultSchema / SuggestResult response shape of POST /suggest

Implementation Notes

All numeric fields use z.coerce.number() so query-string values ("20") parse correctly. z.record(z.string(), z.unknown()) is used for free-form document fields and filter maps. The createdAt field on IndexInfoSchema accepts both ISO-string and Date so the schema can validate both the service-internal shape and the serialized-over-HTTP shape.