/** * 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); }