Skip to content
39 linesCodeBlameRaw
1/**
2 * Inviting someone into a workspace from People: who was typed, and what
3 * to search for as they type. Search finds people by username or name and
4 * shows only what a profile shows (a username, a name, an avatar), never an
5 * email address. No Workers or React imports, so it can be tested under Node.
6 */
7
8/** Where the invite form asks for people as someone types (routes/people-json.ts). */
9export const PEOPLE_SEARCH_PATH = "/-/people.json";
10
11/** The longest query the search takes. */
12const MAX_QUERY = 80;
13
14/** Whether `text` reads as an email address rather than a username. */
15export function looksLikeEmail(text: string): boolean {
16 const at = text.trim().indexOf("@");
17 return at > 0;
18}
19
20/**
21 * What to search for as someone types `text`: the text without a leading
22 * `@`, or null for nothing to search (empty, or an email address, which is
23 * never looked up).
24 */
25export function peopleQuery(text: string): string | null {
26 const trimmed = text.trim();
27 if (!trimmed || looksLikeEmail(trimmed)) return null;
28 const query = trimmed.replace(/^@+/, "").slice(0, MAX_QUERY);
29 return query ? query : null;
30}
31
32/** Who the invite form names: an email address, or a username. Null for nothing. */
33export function inviteTarget(text: string): { email: string } | { username: string } | null {
34 const trimmed = text.trim();
35 if (!trimmed) return null;
36 if (looksLikeEmail(trimmed)) return { email: trimmed };
37 const username = trimmed.replace(/^@+/, "").toLowerCase();
38 return username ? { username } : null;
39}