mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-07-14 18:15:56 -04:00
* feat: reorganize API around operation domains
Restructure the oRPC contract from 14 resource-oriented routers to 8
domain-oriented routers for a cleaner public API surface.
- Consolidate 7 watch procedures into unified tracking.watch/unwatch
with scope + ids input (movie, episode, season, series)
- Split dashboard across tracking (stats, history), library
(continueWatching, upcoming), and discover (recommendations)
- Merge explore + search + discover into single discover router
- Absorb integrations into account.integrations
- Merge system.authConfig into system.publicInfo
- Collapse 6 admin setting endpoints into admin.settings.get/update
- Deduplicate platforms.list + explore.watchProviders into
discover.platforms
- Add symmetric unwatchMovie/unwatchSeries core functions
- Rename titles.detail→get, titles.recommendations→similar,
people.detail→get
BREAKING CHANGE: All client API paths have changed. REST paths now
mirror router structure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address review feedback on API reorganization
- Fix updateRating invalidation in native app — was only invalidating
title queries, now calls invalidateTitleQueries() to also refresh
tracking.userInfo (drives the rating UI)
- Make unwatchMovie status revert consistent with unwatchSeries — revert
any non-watchlist status, not just "completed"
- Add sync invariant comment on handleWatch/handleUnwatch loops
- Remove unused queryClient import in native use-title-actions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: updateStatus NOT_FOUND error + rate() invalidation in native
- updateStatus now throws NOT_FOUND when quickAddTitle returns null
(title doesn't exist), instead of silently succeeding
- Add NOT_FOUND error to updateStatus contract definition
- Fix rate() in native title-actions.ts to call invalidateTitleQueries()
instead of only invalidating orpc.titles.key() — mirrors the fix
already applied to the hook-based path in d2ddc0f
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: expand mobile app docs and add Play Store badge
- Add the Google Play badge to the README alongside the App Store badge
- Expand the mobile app docs with the Android/Play Store release details
- Refresh docs site dependencies and related package versions for the updated docs stack
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
37 lines
1.1 KiB
TypeScript
37 lines
1.1 KiB
TypeScript
import { ORPCError } from "@orpc/server";
|
|
|
|
import { AppErrorCode } from "@sofa/api/errors";
|
|
import { fetchFullFilmography, getOrFetchPerson } from "@sofa/core/person";
|
|
import { getDisplayStatusesByTitleIds } from "@sofa/core/tracking";
|
|
|
|
import { os } from "../context";
|
|
import { authed } from "../middleware";
|
|
|
|
export const get = os.people.get.use(authed).handler(async ({ input, context }) => {
|
|
const person = await getOrFetchPerson(input.id);
|
|
if (!person)
|
|
throw new ORPCError("NOT_FOUND", {
|
|
message: "Person not found",
|
|
data: { code: AppErrorCode.PERSON_NOT_FOUND },
|
|
});
|
|
|
|
const allCredits = await fetchFullFilmography(person.id);
|
|
|
|
const start = (input.page - 1) * input.limit;
|
|
const pageCredits = allCredits.slice(start, start + input.limit);
|
|
|
|
const userStatuses = getDisplayStatusesByTitleIds(
|
|
context.user.id,
|
|
pageCredits.map((c) => c.titleId),
|
|
);
|
|
|
|
return {
|
|
person,
|
|
filmography: pageCredits,
|
|
userStatuses,
|
|
page: input.page,
|
|
totalPages: Math.max(1, Math.ceil(allCredits.length / input.limit)),
|
|
totalResults: allCredits.length,
|
|
};
|
|
});
|