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 —
querycapped 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.inferboilerplate.
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.