Skip to content
41 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Docs: a workspace knowledge base people and agents write together1/**
2 * Full-text search over pages (D1's FTS5): turning what someone typed into
3 * a safe query, and deciding which spaces a search may look in. Pure.
4 */
5
6/**
7 * A query as FTS5 understands it: each word quoted (so `-`, `:` and
8 * operators are text, never syntax), every word required, the last one a
9 * prefix so results come as you type. Null when nothing searchable is left.
10 */
11export function ftsQuery(text: string): string | null {
12 const words = String(text ?? "")
13 .toLowerCase()
14 .split(/[^\p{L}\p{N}_]+/u)
15 .filter(Boolean)
16 .slice(0, 12);
17 if (!words.length) return null;
18 return words.map((w, i) => `"${w.replace(/"/g, "")}"${i === words.length - 1 ? "*" : ""}`).join(" ");
19}
20
21/**
22 * Which spaces a search looks in: those the reader may read, narrowed to
23 * one space when asked. An empty list means search nothing.
24 */
25export function searchSpaces(readable: string[], only: string | null | undefined): string[] {
26 if (!only) return readable;
27 return readable.includes(only) ? [only] : [];
28}
29
30/** Whether a page belongs under a project filter: it, or its space, is linked to the project. */
31export function inProject(project: string | null | undefined, pageProjects: string[], spaceProjects: string[]): boolean {
32 if (!project) return true;
33 const want = project.toLowerCase();
34 return pageProjects.some((p) => p.toLowerCase() === want) || spaceProjects.some((p) => p.toLowerCase() === want);
35}
36
37/** A project reference as stored: `owner/name`, lowercased; null when it is not one. */
38export function projectRef(value: string): string | null {
39 const s = String(value ?? "").trim().replace(/^\/+|\/+$/g, "").toLowerCase();
40 return /^[a-z0-9][a-z0-9._-]{0,99}\/[a-z0-9._-]{1,100}$/.test(s) ? s : null;
41}