import { Router } from 'express'; import { z } from 'zod'; import * as repo from '../../db/repos/search.js'; import { parsePagination } from '../pagination.js'; import { validate } from '../validate.js'; import { asyncWrap } from '../errors.js'; const KINDS = ['page','ref','source_doc','message']; const querySchema = z.object({ q: z.string().min(1), space_id: z.string().uuid().optional(), kinds: z.string().optional(), limit: z.string().optional(), offset: z.string().optional() }); export const router = Router(); // Hybrid vector + reciprocal-rank-fusion search lands in Plan 3 (see // docs/superpowers/specs/2026-05-31-void-v2-design.md §search). router.get('/', validate({ query: querySchema }), asyncWrap(async (req, res) => { const { limit, offset } = parsePagination(req); const rawKinds = req.validatedQuery.kinds; const kinds = rawKinds ? rawKinds.split(',').map(s => s.trim()).filter(k => KINDS.includes(k)) : null; res.json(await repo.fts({ q: req.validatedQuery.q, space_id: req.validatedQuery.space_id ?? null, kinds, limit, offset })); }) );