Postgres 전문 검색 기반 사이트 검색: 언어별 어간, 접두어 일치, 안전한 스니펫, 오타 대응
코드파일 8개컨텍스트약 511토큰검사 통과
설치
$
genpm add @core/search포함 내용
- src/lib/search/에 소스 코드, 파일 8개. (13.2kB)
- src/lib/search/AGENTS.md에 AI 규칙, 그리고 IDE 규칙 파일.
- @core/contracts, @core/db, @core/jobs을(를) 자동으로 해결합니다.
README
이 패키지에는 README가 없습니다.
약 511토큰→ src/lib/search/AGENTS.md→ .cursor/rules/genpm-core-search.mdc
이것이 AI가 src/lib/search에서 작업할 때 읽는 내용 그대로입니다. 그 외에는 컨텍스트에 아무것도 추가되지 않습니다.
@core/search — rules for AI agents
Purpose
Site search on Postgres full-text search: one search_documents table fed by any SearchSource (@core/contracts),
weighted title/body vectors with the stemmer of each document's language, prefix matching for search-as-you-type,
snippets returned as plain parts (never HTML) and, if the pg_trgm extension exists, a typo-tolerant fallback on
titles. No external engine, no semantic search.
Map
index.ts— public API:search,registerSearchSource,reindex,indexDocument,removeDocument,reindexJob.search.ts— indexing and querying.schema.ts— table and GIN index.adapters/hono.ts—searchRoutes().adapters/next.ts—searchRoute(GET).
Integration
- Generate and apply migrations (see
src/lib/db/AGENTS.md). Optional typo tolerance: runcreate extension if not exists pg_trgm;once (available on Neon, Supabase, RDS). - Register sources in the project file
src/genpm/search.ts, imported at startup:registerSearchSource(contentSearchSource('pages', { path: ({ slug }) =>/${slug}})). - Build the index once and then daily:
await reindexJob.enqueue({})andschedule('search.reindex', '0 3 * * *')(@core/jobs). - Query:
const { hits } = await search(q, { locale }), or mountsearchRoutes()/searchRouteat/api/search. - Render snippets by mapping parts:
hit.snippet.map(p => p.match ? <mark>{p.text}</mark> : p.text). - Verify: index a document and find it by the first letters of a word in its title.
Conventions
- Sources yield plain text bodies (strip Markdown/HTML first, e.g. with
toPlainTextof @core/rich-text). - Pass
localewhen you know it: the query uses that language's stemmer and the GIN index. - Only index published, public content; private data never goes into
search_documents.
Don't
- Don't build SQL from the query string;
search()already sanitizes it to words. - Don't render snippets with
dangerouslySetInnerHTML. - Don't call
reindex()inside a request: use the job.
# @core/search — rules for AI agents
## Purpose
Site search on Postgres full-text search: one `search_documents` table fed by any `SearchSource` (@core/contracts),
weighted title/body vectors with the stemmer of each document's language, prefix matching for search-as-you-type,
snippets returned as plain parts (never HTML) and, if the `pg_trgm` extension exists, a typo-tolerant fallback on
titles. No external engine, no semantic search.
## Map
- `index.ts` — public API: `search`, `registerSearchSource`, `reindex`, `indexDocument`, `removeDocument`, `reindexJob`.
- `search.ts` — indexing and querying. `schema.ts` — table and GIN index.
- `adapters/hono.ts` — `searchRoutes()`. `adapters/next.ts` — `searchRoute` (GET).
## Integration
1. Generate and apply migrations (see `src/lib/db/AGENTS.md`). Optional typo tolerance: run
`create extension if not exists pg_trgm;` once (available on Neon, Supabase, RDS).
2. Register sources in the project file `src/genpm/search.ts`, imported at startup:
`registerSearchSource(contentSearchSource('pages', { path: ({ slug }) => `/${slug}` }))`.
3. Build the index once and then daily: `await reindexJob.enqueue({})` and `schedule('search.reindex', '0 3 * * *')` (@core/jobs).
4. Query: `const { hits } = await search(q, { locale })`, or mount `searchRoutes()` / `searchRoute` at `/api/search`.
5. Render snippets by mapping parts: `hit.snippet.map(p => p.match ? <mark>{p.text}</mark> : p.text)`.
6. Verify: index a document and find it by the first letters of a word in its title.
## Conventions
- Sources yield plain text bodies (strip Markdown/HTML first, e.g. with `toPlainText` of @core/rich-text).
- Pass `locale` when you know it: the query uses that language's stemmer and the GIN index.
- Only index published, public content; private data never goes into `search_documents`.
## Don't
- Don't build SQL from the query string; `search()` already sanitizes it to words.
- Don't render snippets with `dangerouslySetInnerHTML`.
- Don't call `reindex()` inside a request: use the job.
.genpmignore 적용 후 주입될 정확한 트리입니다. 고정 대상:
// @core/search — API pública. Importa desde aquí; endpoint en adapters/hono.ts y adapters/next.ts.
export { reindexJob } from './jobs.ts';
export { type SearchRow, searchDocuments } from './schema.ts';
export {
clearSearchSources,
indexDocument,
queryWords,
registerSearchSource,
reindex,
removeDocument,
resetSearchCache,
type SearchHit,
type SearchOptions,
type SnippetPart,
search,
textConfig,
} from './search.ts';
이 패키지는 MCP 서버를 선언하지 않습니다.
| 버전 | 커밋 | 게시일 | 검사 |
|---|---|---|---|
| 1.0.0 | ae66128 | 6시간 전 | 검사 통과 |
- npm
- zod ^4.0.0
- 제안됨
- GenPM은 npm 명령을 제안하고, 동의한 경우에만 실행합니다.
- 사용하는 패키지 (1)
- @core/kit-cms ^1.0.0
- 검사
- 검사 통과 · 문제 0건
- 커밋
- v1.0.0 → ae6612826aed11b87040adc5f891b5bf6e858c58 · 가져온 뒤 검증됨
- 스크립트
- 없음. GenPM은 패키지 코드를 절대 실행하지 않습니다.
- 라이선스
- MIT
- 품질
- 100/100
- 인정된 라이선스충족
- AGENTS.md에 목적 설명충족
- AGENTS.md에 통합 단계충족
- AGENTS.md에 규칙 또는 금지 사항충족
- 테스트 포함충족
- 보안 검사 통과충족
- 최근 6개월 내 게시충족
- 인증된 게시자충족
- 요약과 키워드충족
- 신고
- 문제가 있나요?