47 lines
1.2 KiB
TypeScript
47 lines
1.2 KiB
TypeScript
/**
|
|
* Which slugs a category may take. Category slugs live at the URL root (e.g.
|
|
* /music), so they must never collide with the frontend's own routes.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
/**
|
|
* Top-level path segments that already have meaning in the SPA router (see
|
|
* src/App.tsx), plus a few reserved for infrastructure.
|
|
*/
|
|
export const RESERVED_SLUGS: readonly string[] = [
|
|
"~",
|
|
"dumps",
|
|
"users",
|
|
"playlists",
|
|
"search",
|
|
"login",
|
|
"register",
|
|
"notifications",
|
|
"reset-password",
|
|
"manage",
|
|
"api",
|
|
"assets",
|
|
];
|
|
|
|
/**
|
|
* A well-formed category slug: lowercase alphanumerics,
|
|
* hyphen-separated, no leading, trailing or double hyphen.
|
|
*/
|
|
export const CATEGORY_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
|
/** Checks whether `slug` is well-formed (see {@link CATEGORY_SLUG_RE}). */
|
|
export function isValidSlugFormat(slug: string): boolean {
|
|
return CATEGORY_SLUG_RE.test(slug);
|
|
}
|
|
|
|
/** Checks whether `slug` is one of the {@link RESERVED_SLUGS}. */
|
|
export function isReservedSlug(slug: string): boolean {
|
|
return RESERVED_SLUGS.includes(slug);
|
|
}
|
|
|
|
/** Checks whether `slug` is well-formed and not reserved. */
|
|
export function isSlugAvailable(slug: string): boolean {
|
|
return isValidSlugFormat(slug) && !isReservedSlug(slug);
|
|
}
|