Stores the categories and which dumps and playlists belong to them, a set of categories for each CategoryKind. The category routes manage and list them, the dump and playlist services file each dump or playlist they write under its categories, and every service that lists dumps or playlists fills in their categoryIds and filters them by category with categoryJoin.

Functions

f
assertCategoriesExist(
kind: CategoryKind,
categoryIds: string[]
): void

Checks that every id in categoryIds names a category of kind, so that a dump is never filed under a playlist category, nor the other way round. The dump and playlist services run it before they write a row or store an uploaded file, so a bad id fails the request before anything is written.

f
attachCategoryIds(
kind: CategoryKind,
items: { id: string; categoryIds?: string[]; }[]
): void

Sets categoryIds on each of items, dumps or playlists as kind says, in place, in one query. Their rows don't carry them, so every service that returns dumps or playlists calls this first.

f
categoryJoin(
kind: CategoryKind,
alias: string,
categoryId?: string
): [string, string[]]

Returns the join that keeps only the rows of alias, a dump or playlist as kind says, filed under categoryId, with its parameters, or nothing without one. A query puts the join after its FROM and the parameters before its own.

f
createCategory(req: CreateCategoryRequest): Category

Creates a category, for POST /api/categories. The name is stored trimmed, and the position defaults to 0. Every client is told to fetch the categories again, as after the two writes below.

f
deleteCategory(id: string): void

Deletes category id, for DELETE /api/categories/:id. Its dumps or playlists stay, and lose it from their categoryIds.

f
getCategoryBySlug(
kind: CategoryKind,
slug: string
): Category

Returns the category of kind at slug, for listDumpsByCategory and the list of every public playlist.

f
getCategoryIdBySlug(
kind: CategoryKind,
slug: string
): string | undefined

Returns the id of the category of kind at slug, or undefined when there is none.

f
listCategories(): Category[]

Returns every category, of both kinds, by kind, position then slug, for GET /api/categories.

f
listDumpsByCategory(
slug: string,
page: number,
limit: number,
requestingUserId?: string
): Page<Dump>

Returns a page of the dumps in the dump category at slug, newest first, for GET /api/dumps?category=. Private dumps are left out, except requestingUserId's own.

f
resolveCategoryFilter(
kind: CategoryKind,
params: URLSearchParams,
name?: string
): string | "missing" | undefined

Returns the id of the category of kind whose slug the name parameter of params, ?category= by default, gives, undefined without one, or "missing" when it names none, so that the list comes back empty rather than unfiltered. The users routes filter a profile's lists with it, and the search route its results.

f
setCategories(
kind: CategoryKind,
id: string,
categoryIds: string[]
): void

Replaces the categories of the dump or playlist id, as kind says, with categoryIds, duplicates dropped. An empty list takes it out of every category. Called inside the dump or playlist service's transaction, it joins that one.

f
updateCategory(
id: string,
req: UpdateCategoryRequest
): Category

Applies req to category id, for PUT /api/categories/:id, and returns the category as it now is. Fields req leaves out keep their value.