src/issue-search-state.tsTypeScript
@@ -0,0 +1,33 @@
1+
export type IssueStatus = "open" | "closed" | "all";2+
3+
export interface IssueSearchState {4+
query: string;5+
status: IssueStatus;6+
page: number;7+
}8+
9+
function readPage(value: string | null): number {10+
const page = Number(value);11+
return Number.isInteger(page) && page > 0 ? page : 1;12+
}13+
14+
function readStatus(value: string | null): IssueStatus {15+
return value === "closed" || value === "all" ? value : "open";16+
}17+
18+
export function readIssueSearchState(url: URL): IssueSearchState {19+
return {20+
query: url.searchParams.get("q") ?? "",21+
status: readStatus(url.searchParams.get("status")),22+
page: readPage(url.searchParams.get("page")),23+
};24+
}25+
26+
export function buildIssueSearchUrl(baseUrl: URL, state: IssueSearchState): string {27+
const search = new URLSearchParams();28+
if (state.query) search.set("q", state.query);29+
search.set("status", state.status);30+
search.set("page", String(state.page));31+
32+
return `${baseUrl.pathname}?${search.toString()}`;33+
}