docs: add media-types single-source-of-truth rule to CLAUDE.md
Document that media-type detection lives in App\Enums\Media\Type (backend) and resources/js/lib/mediaType.ts (frontend), the three types (image/video/document), the type→mime→extension precedence, the MediaType union on every media interface, and acceptAttribute() for upload accepts.
This commit is contained in:
parent
a8bed34d17
commit
e6826d499f
1 changed files with 10 additions and 0 deletions
10
CLAUDE.md
10
CLAUDE.md
|
|
@ -291,6 +291,16 @@ ## Per-Platform Post Meta (`PostPlatform.meta`)
|
|||
- Required-on-publish (meta a platform needs to publish, e.g. Discord `channel_id`) also lives there: `addRequiredOnPublishErrors()` for request-driven flows (web/API update `withValidator`), `assertStoredPostPublishable()` for flows that publish stored state without resubmitting platforms (MCP `PublishPostTool`). Add new required-meta rules to `requiredMetaViolation()`, not inline.
|
||||
- When adding a new platform's meta field, add it (and any publish requirement) to `PostPlatformMetaRules` ONLY, and cover it in `tests/Feature/Api/PostApiPlatformMetaTest.php` + `tests/Feature/Mcp/PostPlatformMetaToolTest.php`.
|
||||
|
||||
## Media Types (image / video / document)
|
||||
|
||||
- A media item is one of exactly three types: **image**, **video**, **document** (PDF). There is no standalone "audio" media type (audio exists only as a video voiceover input).
|
||||
- Media-type detection lives in ONE place per side — NEVER hand-write `type === 'image'`, `mime_type === 'application/pdf'`, `mime.startsWith('video/')`, or extension checks inline.
|
||||
- Backend: `App\Enums\Media\Type` — `classify()`, `fromMime()`, `fromExtension()`, `isGif()`, plus the `allowedMimeTypes()` / `extensions()` allow-lists. Use these, never a raw MIME/extension comparison.
|
||||
- Frontend: `resources/js/lib/mediaType.ts` — the mirror of the backend enum: the `MediaType` union, `classify()`, `fromMimeType()` (for a browser `File.type`), `fromExtension()`, `isImage()`/`isVideo()`/`isDocument()`/`isGif()`. `@/composables/useMedia` re-exports `isImageMedia`/`isVideoMedia`/`isDocumentMedia` aliases for legacy call sites.
|
||||
- Detection trusts the explicit `type` first, then the MIME, then the filename extension — so an item with only a MIME (e.g. AI/Unsplash/Giphy media without a `type`) still classifies correctly. A bare `item.type === 'image'` (with a `v-else` video) silently mis-renders those.
|
||||
- The `type` field on every media-ish interface is the `MediaType` union, never `string` — `MediaItem`, and any sibling picked/asset/saved shape (`PickedMedia`, `AssetMedia`, `SavedMedia`, etc.).
|
||||
- The upload `accept` attribute for "everything we allow" comes from `acceptAttribute()` (frontend) / `Media\Type::allowedMimeTypes()` (backend) — never a hardcoded MIME list. Per-capability `accept` builders driven by content-type rules (e.g. `image/*,video/*`) are fine; those aren't detection.
|
||||
|
||||
## Pest / Feature Tests
|
||||
|
||||
- ALWAYS use named routes via the `route()` helper in feature tests. NEVER hardcode URL strings like `'/posts/ai/create'`.
|
||||
|
|
|
|||
Loading…
Reference in a new issue