49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
/**
|
|
* Checks which slugs a category may take. A category's feed lives at the URL
|
|
* root (`/music`), so its slug must not shadow another top-level route. The
|
|
* category service runs these checks when a category is created or renamed.
|
|
*
|
|
* @module
|
|
*/
|
|
|
|
/**
|
|
* Lists the top-level path segments a category slug may not take. They are
|
|
* the SPA's own routes (`src/App.tsx`); `api`, `ws`, `assets` and
|
|
* `emojibase`, which the server answers before the SPA; and `manage`, a
|
|
* former route whose old links may still be about. Keep it in step with the
|
|
* route table and the build's top-level folders.
|
|
*/
|
|
export const RESERVED_SLUGS: readonly string[] = [
|
|
"~",
|
|
"dumps",
|
|
"users",
|
|
"playlists",
|
|
"search",
|
|
"login",
|
|
"register",
|
|
"notifications",
|
|
"reset-password",
|
|
"unsubscribe",
|
|
"manage",
|
|
"api",
|
|
"ws",
|
|
"assets",
|
|
"emojibase",
|
|
];
|
|
|
|
/**
|
|
* Matches a well-formed category slug, made of lowercase letters and digits
|
|
* joined by single hyphens.
|
|
*/
|
|
export const CATEGORY_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
|
/** Checks whether `slug` matches {@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);
|
|
}
|