| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- /**
- * Frontend route helpers for internal navigation.
- *
- * Why this file exists:
- * - Keep route building consistent across the UI (no stringly-typed URLs scattered everywhere).
- * - Central place to adjust URL structure if we ever need it.
- * - Easy to test in pure Node (no DOM / no Next runtime required).
- *
- * Notes:
- * - We encode dynamic segments defensively via encodeURIComponent.
- * - We validate inputs early to catch mistakes during development.
- */
- /**
- * Ensure a dynamic route segment is a non-empty string.
- *
- * @param {string} name - Human readable segment name for error messages.
- * @param {unknown} value - The segment value.
- * @returns {string} Trimmed segment.
- */
- function requireSegment(name, value) {
- if (typeof value !== "string") {
- throw new Error(`Route segment "${name}" must be a string`);
- }
- const trimmed = value.trim();
- if (!trimmed) {
- throw new Error(`Route segment "${name}" must not be empty`);
- }
- return trimmed;
- }
- /**
- * Encode a segment for safe usage in URLs.
- *
- * @param {string} name
- * @param {unknown} value
- * @returns {string}
- */
- function encodeSegment(name, value) {
- return encodeURIComponent(requireSegment(name, value));
- }
- /**
- * Build an absolute path from named segments.
- *
- * @param {Array<{ name: string, value: unknown }>} parts
- * @returns {string}
- */
- function buildPath(parts) {
- const encoded = parts.map((p) => encodeSegment(p.name, p.value));
- return `/${encoded.join("/")}`;
- }
- /**
- * /
- */
- export function homePath() {
- return "/";
- }
- /**
- * /login
- */
- export function loginPath() {
- return "/login";
- }
- /**
- * /:branch
- *
- * @param {string} branch
- */
- export function branchPath(branch) {
- return buildPath([{ name: "branch", value: branch }]);
- }
- /**
- * /:branch/:year
- *
- * @param {string} branch
- * @param {string} year
- */
- export function yearPath(branch, year) {
- return buildPath([
- { name: "branch", value: branch },
- { name: "year", value: year },
- ]);
- }
- /**
- * /:branch/:year/:month
- *
- * @param {string} branch
- * @param {string} year
- * @param {string} month
- */
- export function monthPath(branch, year, month) {
- return buildPath([
- { name: "branch", value: branch },
- { name: "year", value: year },
- { name: "month", value: month },
- ]);
- }
- /**
- * /:branch/:year/:month/:day
- *
- * @param {string} branch
- * @param {string} year
- * @param {string} month
- * @param {string} day
- */
- export function dayPath(branch, year, month, day) {
- return buildPath([
- { name: "branch", value: branch },
- { name: "year", value: year },
- { name: "month", value: month },
- { name: "day", value: day },
- ]);
- }
- /**
- * /:branch/search
- *
- * @param {string} branch
- */
- export function searchPath(branch) {
- return buildPath([
- { name: "branch", value: branch },
- { name: "search", value: "search" },
- ]);
- }
|