@nolgard/webapps-search
v0.1.3
Published
Same-origin, typed search client for Pinecone addons.
Readme
@nolgard/webapps-search
License
Copyright (c) 2026 Johan Lindqvist. Use of material not already licensed requires prior written permission. See LICENSE.txt. Previously granted MIT and third-party rights remain unchanged.
Framework-independent client for Pinecone's public GET /rest-api/v1/search.
No runtime dependencies or API keys. Requires Fetch, URL and AbortController
(modern browsers or Node.js 18+). TypeScript declarations are included.
import { createSearchClient, SearchClientError } from '@nolgard/webapps-search'
const search = createSearchClient({ apiBase: '/pinecone/rest-api/v1/' })
const controller = new AbortController()
try {
const result = await search.search(
{ q: 'education', limit: 20, label_ids: [3], sort: 'relevance' },
{ signal: controller.signal },
)
// Render titles/excerpts as text, never as HTML.
console.log(result.count)
} catch (error) {
if (error instanceof SearchClientError && error.code !== 'aborted') {
// Map the stable code/status to a localized message.
// Do not log queries, metadata values, URLs or response bodies.
console.error(error.code, error.status)
}
}suggest({ q: 'edu', limit: 5 }) uses prefix search and returns distinct,
non-empty result titles (case-insensitive deduplication). Debounce and cancel
requests in the addon; the package deliberately performs no automatic retries.
Automatic suggestion prefixes apply only to plain queries; explicit operators,
wildcards and quoted phrases are transmitted unchanged without an implicit prefix.
SQLite supports wildcard search, pagination, sorting, operators, section filters
and metadata filters. Legacy JSON capabilities remain backend-defined.
Query syntax (SQLite)
- Plain words use AND and match whole indexed words;
+wordexplicitly requires a word (the same AND behavior).-wordexcludes it. "exact phrase"matches adjacent words in order;-"excluded phrase"excludes that phrase. Quotes do not support wildcards or backslash escaping.word*matches words starting withword,*wordmatches words ending with it, and*word*matches words containing it. Combine with+/-, for example+*education* -course*.- Wildcard roots require at least three Unicode letters/digits. Stars inside words, repeated stars, empty phrases and exclusion-only queries are rejected. AND/OR/NOT typed into a query are literal search words, not executable syntax.
- Leading wildcards expand the FTS5 vocabulary with the index's Unicode normalization. At most 256 expanded words across the query are permitted. Overly broad queries return HTTP 400, never silently truncated results. Native trailing prefixes do not need vocabulary expansion.
- Advanced syntax requires SQLite; the legacy JSON backend returns HTTP 400. No new request fields, index rebuild or stored-data migration are required.
getSearchHighlightTerms(query) returns deduplicated lowercase positive words
for display highlighting, excluding -terms, excluded phrases and operators.
It preserves substring highlighting inside compound words. It is not a syntax
validator: the backend validates the complete query. Non-string, invalid Unicode
or more than 200 code points throws SearchClientError (invalid_query).
Contract
search accepts the backend parameter names: q (at most 200 Unicode code
points), limit (1..50), page (1..1000), section_ids/label_ids (at most
50 positive safe integer IDs), label_mode (any/all), include_descendants
and prefix_search (booleans), sort (relevance/title/updated), and
metadata (at most ten { key, operator, value } filters). Operators are
eq, in, gte, lte; in takes 1..20 scalar values. Strings in metadata
filters must not exceed 500 UTF-8 bytes. Unknown request/configuration keys are
rejected, not forwarded.
Results expose only the documented fields in index.d.ts, validate result URLs
as same-origin HTTP(S), and normalize them to absolute URLs. Highlight offsets
are Unicode code points. Text may contain HTML-looking characters; consumers
must use text rendering, never innerHTML or Svelte {@html}. Pagination,
generation and highlights are optional to support the JSON engine.
Security and errors
- API URLs must be same-origin HTTP(S), without user info, query or fragment. Protocol-relative URLs and redirects are rejected.
- Requests use
mode: same-origin,credentials: same-origin,redirect: error,cache: no-storeandreferrerPolicy: no-referrer. Session cookies are managed by the browser; the client never reads cookies or storage and never adds auth headers. Use HTTPS in production. - No API key/token option, global credential lookup, persistent result cache, query logging, telemetry or server diagnostic passthrough.
- Errors expose stable
code, HTTPstatusand numericretryAfter(seconds), never the response body, request URL, exception cause or supplied abort reason. Codes:invalid_options,invalid_query,unsafe_url,invalid_response,request_failed,network_error,timeout,aborted. - A default 10-second timeout covers both Fetch and JSON reading.
timeoutMsaccepts 1..60000. Cancellation uses codeabortedand nameAbortError. - JSON responses are read as bounded UTF-8 streams (maximum 2 MiB). Oversized,
malformed or non-JSON responses fail with
invalid_response. - Backend authorization and public metadata selection remain authoritative: a browser library cannot conceal data that a server already exposes. Never store secrets in searchable public content, metadata, queries or addon config.
apiBaseis recommended for nonstandard installation paths. Otherwise the client detects/pinecone(including nested paths), or uses the site root.searchApiUrlselects an explicit same-origin endpoint. Browser location is used by default; tests/SSR must supplylocationand may supplyfetch.
Development
Run npm test in this directory. Publish with npm publish --access public.
Only the implementation, types and README are included in the npm package.
