From 798de7947a1e103b3182edbd6121c45fa47e6382 Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Sun, 8 Feb 2026 11:27:39 -0500 Subject: [PATCH] docs: update media item bruno docs with normalization info Update Update Media Item.bru to document normalization behavior: - Note that tags and contributors are auto-normalized (same as Create) - Document response includes updated search fields Relates to Tags & Contributors Migration documentation updates --- bruno/media-items/Create Media Item.bru | 163 ++++++++++-------- bruno/media-items/Update Media Item.bru | 9 +- .../api/media-items/get_media_item.md | 11 +- .../api/media-items/list_media_items.md | 11 +- .../api/media-items/search_media_items.md | 9 +- .../api/media-items/update_media_item.md | 24 ++- 6 files changed, 134 insertions(+), 93 deletions(-) diff --git a/bruno/media-items/Create Media Item.bru b/bruno/media-items/Create Media Item.bru index e1e961e..ad12331 100644 --- a/bruno/media-items/Create Media Item.bru +++ b/bruno/media-items/Create Media Item.bru @@ -14,29 +14,29 @@ headers { Content-Type: application/json } -body:json { - "library_id": "{{library_id}}", - "title": "New Media Item", - "author": "Author Name", - "isbn": "978-0123456789", - "description": "Description of the media item", - "cover_image_path": "/path/to/cover.jpg", - "series": "Series Name", - "series_number": 1, - "tags": ["fiction", "adventure"], - "asin": "B08XYZ123", - "date_published": "2023-01-15", - "publisher": "Publisher Name", - "contributors": ["Contributor Name"], - "language": "en", - "edition": "First Edition", - "page_count": 350, - "genre": "Science Fiction", - "copyright_year": 2023, - "goodreads_id": "123456", - "openlibrary_id": "OL123456M", - "google_books_id": "GB123456" -} + body:json { + "library_id": "{{library_id}}", + "title": "New Media Item", + "author": "Author Name", + "isbn": "978-0123456789", + "description": "Description of the media item", + "cover_image_path": "/path/to/cover.jpg", + "series": "Series Name", + "series_number": 1, + "tags": ["science fiction", "ACME CORP.", "non-fiction"], + "asin": "B08XYZ123", + "date_published": "2023-01-15", + "publisher": "Publisher Name", + "contributors": ["O'Reilly Media", "acme corp"], + "language": "en", + "edition": "First Edition", + "page_count": 350, + "genre": "Science Fiction", + "copyright_year": 2023, + "goodreads_id": "123456", + "openlibrary_id": "OL123456M", + "google_books_id": "GB123456" + } tests { test_create_media_item_success(status, headers, body) { @@ -73,53 +73,70 @@ settings { timeout: 0 } -docs { - ## Create Media Item - - Creates a new media item in a library with full metadata. - - **Method:** POST - - **Endpoint:** /api/media-items - - **Authentication:** Required (Bearer token, admin only) - - **Request Body:** - - `library_id` (string, required): Library UUID - - `title` (string, required): Media item title - - `author` (string, optional): Author name - - `isbn` (string, optional): ISBN number - - `description` (string, optional): Description - - `cover_image_path` (string, optional): Path to cover image - - `series` (string, optional): Series name - - `series_number` (integer, optional): Number in series - - `tags` (array of string, optional): Tags or categories - - `asin` (string, optional): Amazon ASIN - - `date_published` (string, optional): Publication date - - `publisher` (string, optional): Publisher name - - `contributors` (array of string, optional): List of contributors - - `language` (string, optional): Language code (ISO 639-1) - - `edition` (string, optional): Edition information - - `page_count` (integer, optional): Total page count - - `genre` (string, optional): Genre classification - - `copyright_year` (integer, optional): Copyright year - - `goodreads_id` (string, optional): Goodreads identifier - - `openlibrary_id` (string, optional): Open Library identifier - - `google_books_id` (string, optional): Google Books identifier - - **Response:** Created media item object - - All fields above plus system-generated fields - - **Status Codes:** - - 201: Media item created successfully - - 400: Invalid request data - - 401: Unauthorized - - 403: Forbidden (admin access required) - - 404: Library not found - - 500: Internal server error - - **Examples:** - - Create media item: `POST /api/media-items` - - **Note:** Admin access required - only users with admin role can create media items. -} \ No newline at end of file + docs { + ## Create Media Item + + Creates a new media item in a library with full metadata. + + **Method:** POST + + **Endpoint:** /api/media-items + + **Authentication:** Required (Bearer token, admin only) + + **Request Body:** + - `library_id` (string, required): Library UUID + - `title` (string, required): Media item title + - `author` (string, optional): Author name + - `isbn` (string, optional): ISBN number + - `description` (string, optional): Description + - `cover_image_path` (string, optional): Path to cover image + - `series` (string, optional): Series name + - `series_number` (integer, optional): Number in series + - `tags` (array of string, optional): Tags or categories (auto-normalized) (automatically normalized) + - `asin` (string, optional): Amazon ASIN + - `date_published` (string, optional): Publication date + - `publisher` (string, optional): Publisher name + - `contributors` (array of string, optional): List of contributors (auto-normalized) (automatically normalized) + - `language` (string, optional): Language code (ISO 639-1) + - `edition` (string, optional): Edition information + - `page_count` (integer, optional): Total page count + - `genre` (string, optional): Genre classification + - `copyright_year` (integer, optional): Copyright year + - `goodreads_id` (string, optional): Goodreads identifier + - `openlibrary_id` (string, optional): Open Library identifier + - `google_books_id` (string, optional): Google Books identifier + + **Response:** Created media item object + - All fields above plus: + - `tags_search` (array): Normalized for search (lowercase, no punctuation) + - `contributors_search` (array): Normalized for search (lowercase, no punctuation) + + **Normalization Behavior:** + + Tags are automatically normalized: + - Trim whitespace + - Titlecased (preserves hyphenation: "non-fiction" → "Non-Fiction") + - Case-insensitive deduplication (keeps version with punctuation if exists) + - Example: `["science fiction", "SCIENCE-FICTION"]` → `["Science-Fiction"]` + + Contributors are automatically normalized: + - Trim whitespace + - Preserve original casing (CAPSLOCK companies, Title Case, etc.) + - Preserve punctuation for display + - Case-insensitive deduplication (keeps version with punctuation if exists) + - Example: `["acme corp", "ACME CORP.", "acme corp"]` → `["ACME CORP."]` + + **Status Codes:** + - 201: Media item created successfully + - 400: Invalid request data + - 401: Unauthorized + - 403: Forbidden (admin access required) + - 404: Library not found + - 500: Internal server error + + **Examples:** + - Create media item: `POST /api/media-items` + + **Note:** Admin access required - only users with admin role can create media items. + } \ No newline at end of file diff --git a/bruno/media-items/Update Media Item.bru b/bruno/media-items/Update Media Item.bru index d5a41a3..3ef6fa8 100644 --- a/bruno/media-items/Update Media Item.bru +++ b/bruno/media-items/Update Media Item.bru @@ -85,9 +85,12 @@ docs { **Path Parameters:** - `id` (string): Media item UUID - **Request Body:** All media item fields (same as Create) - - **Response:** Updated media item object + **Request Body:** All media item fields (same as Create) + - Tags and contributors are auto-normalized (see Create Media Item docs) + + **Response:** Updated media item object + - Includes normalized `tags` and `contributors` fields + - Includes updated `tags_search` and `contributors_search` fields **Status Codes:** - 200: Media item updated successfully diff --git a/docs/developer/api/media-items/get_media_item.md b/docs/developer/api/media-items/get_media_item.md index 140a731..11ddbd9 100644 --- a/docs/developer/api/media-items/get_media_item.md +++ b/docs/developer/api/media-items/get_media_item.md @@ -37,10 +37,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... "file_size": 1024000, "mime_type": "application/epub+zip", "cover_image_path": "/path/to/cover.jpg", - "series": "Series Name", - "series_number": 1, - "tags": "sci-fi, space opera", - "language": "en", + "series": "Series Name", + "series_number": 1, + "tags": ["sci-fi", "space opera"], + "tags_search": ["sci fi", "space opera"], + "contributors": ["Author Name", "ACME CORP."], + "contributors_search": ["author name", "acme corp"], + "language": "en", "page_count": 350, "genre": "Science Fiction", "copyright_year": 2023, diff --git a/docs/developer/api/media-items/list_media_items.md b/docs/developer/api/media-items/list_media_items.md index 2e1c752..29050e5 100644 --- a/docs/developer/api/media-items/list_media_items.md +++ b/docs/developer/api/media-items/list_media_items.md @@ -41,10 +41,13 @@ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... "file_size": 1024000, "mime_type": "application/epub+zip", "cover_image_path": "/path/to/cover.jpg", - "series": "Series Name", - "series_number": 1, - "tags": "sci-fi, space opera", - "language": "en", + "series": "Series Name", + "series_number": 1, + "tags": ["sci-fi", "space opera"], + "tags_search": ["sci fi", "space opera"], + "contributors": ["Author Name", "ACME CORP."], + "contributors_search": ["author name", "acme corp"], + "language": "en", "page_count": 350, "genre": "Science Fiction", "copyright_year": 2023, diff --git a/docs/developer/api/media-items/search_media_items.md b/docs/developer/api/media-items/search_media_items.md index 0de5d18..98f0709 100644 --- a/docs/developer/api/media-items/search_media_items.md +++ b/docs/developer/api/media-items/search_media_items.md @@ -1,6 +1,13 @@ # Search Media Items -Search for media items by title, author, or description. +Search for media items by title, author, series, tags, or contributors. + +**Note:** Search is case-insensitive and punctuation-agnostic. The search query is matched against normalized tags_search and contributors_search fields, allowing users to find matches regardless of casing or punctuation. + +Examples: +- Search "acme corp" finds items with "ACME CORP." or "Acme Corp" +- Search "oreilly" finds items with "O'Reilly Media" or "OReilly Media" +- Search "science fiction" finds items with "Science-Fiction" or "science-fiction" **Endpoint**: `GET /api/media-items/search` **Auth**: Required diff --git a/docs/developer/api/media-items/update_media_item.md b/docs/developer/api/media-items/update_media_item.md index b2536e7..1c8ae47 100644 --- a/docs/developer/api/media-items/update_media_item.md +++ b/docs/developer/api/media-items/update_media_item.md @@ -12,15 +12,23 @@ Update media item metadata (Admin only). |-----------|------|-----------|-------------| | media_id | string | Yes | Media item UUID | -## Request Body + ## Request Body -| Field | Type | Required | Description | -|--------|------|-----------|-------------| -| title | string | No | Updated title | -| author | string | No | Updated author | -| description | string | No | Updated description | -| series | string | No | Series name | -| series_number | integer | No | Number in series | + | Field | Type | Required | Description | + |--------|------|-----------|-------------| + | title | string | No | Updated title | + | author | string | No | Updated author | + | description | string | No | Updated description | + | series | string | No | Series name | + | series_number | integer | No | Number in series | + | tags | array of string | No | Updated tags (auto-normalized) | + | contributors | array of string | No | Updated contributors (auto-normalized) | + + **Tag/Contributor Normalization:** + - Tags are titlecased and deduplicated (case-insensitive) + - Contributors preserve original casing and punctuation + - Punctuation-preferred deduplication (keeps "ACME CORP." over "acme corp") + - Search fields auto-generated for case-insensitive search ### Example Request