mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-13 05:16:29 +02:00
ApiClient hardening (data/api.ts):
- onUnauthorized callback wired in _layout.tsx — 401 clears token,
workspace store, TanStack Query cache, replaces nav to /login.
Idempotent via signingOutRef. Mirrors packages/core/api/client.ts
handleUnauthorized.
- X-Request-ID per request (lib/request-id.ts)
- Structured logger: `[api] -> METHOD path (rid)` on start, `[api] <-
STATUS path (rid, duration)` on end. console.error for 5xx,
console.warn for 404, console.log for success.
- Zod parseWithFallback for listIssues + listTimeline (the only two
endpoints with schemas in packages/core/api/schemas.ts today —
matches web's current coverage; new schemas should land on the web
side first and both clients pick them up).
Core export (packages/core/package.json):
- Add `./api/schemas` to exports map so mobile can import the shared
Zod schemas + EMPTY_* fallbacks (pure data, on the mobile sharing
whitelist per CLAUDE.md).
Issue detail v1 (app/(app)/[workspace]/issue/[id].tsx):
- Read issue + infinite-scroll timeline + comment composer
- Stack header shows MUL-XXX once detail loads
- Supporting files: data/queries/issues.ts, data/mutations/issues.ts,
components/issue/{timeline-list,comment-composer,...},
lib/{format-activity,timeline-coalesce,timeline-thread}.ts
- Property edits, reactions, mentions, image lightbox deferred to V2+
apps/mobile/CLAUDE.md — Lessons learned (encode into reflexes):
1. Install/upgrade deps: `pnpm view <pkg> dist-tags` first; `expo
install` for Expo packages, never `pnpm add` blindly
2. New source subdirectory: `git check-ignore -v` to verify against
root .gitignore generic rules (data/, build/, bin/); add !data/
override if matched. Cost a 14-file missing commit before.
3. ApiClient capability list (Zod parse / 401 callback / X-Request-ID
/ structured logger) — all baseline, not polish
4. Visual alignment is baseline, not polish — tab icons, screen titles,
right-column vertical alignment of trailing elements, type-aware
secondary lines (mirror InboxDetailLabel, not raw item.body)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
32 lines
990 B
TypeScript
32 lines
990 B
TypeScript
/**
|
|
* Mobile-owned parseWithFallback. Mirrors packages/core/api/schema.ts —
|
|
* the boundary defense for installed-app schema drift required by root
|
|
* CLAUDE.md "API Response Compatibility" and apps/mobile/CLAUDE.md
|
|
* "Type drift defense".
|
|
*
|
|
* Why we mirror instead of import: keeps mobile fully decoupled and lets
|
|
* us route the warning into mobile's own logger instead of the core
|
|
* schemaLogger singleton. Behavior is identical: safeParse → on success
|
|
* return parsed; on failure log + return fallback (never throw into UI).
|
|
*/
|
|
import { type ZodType } from "zod";
|
|
|
|
export interface ParseOptions {
|
|
endpoint: string;
|
|
}
|
|
|
|
export function parseWithFallback<T>(
|
|
data: unknown,
|
|
schema: ZodType,
|
|
fallback: T,
|
|
opts: ParseOptions,
|
|
): T {
|
|
const result = schema.safeParse(data);
|
|
if (result.success) return result.data as T;
|
|
console.warn(`[api] schema validation failed: ${opts.endpoint}`, {
|
|
issues: result.error.issues,
|
|
received: data,
|
|
});
|
|
return fallback;
|
|
}
|