feat(20-02): add updateMemberProfile fetcher + AdminMember.isAdmin
- Add isAdmin: boolean to AdminMember interface (after color, before
hasCredential) — feeds the Phase 20 editor toggle initial state (D-02)
- Add updateMemberProfile(memberId, body) fetcher: PATCH /api/admin/members/:id,
credentials:include, redirect:manual, JSON body
- Maps 401/opaqueredirect → SessionExpiredError (existing convention)
- Maps 409/422 → Error('last-admin') sentinel (D-03 last-admin guard)
- Maps other non-ok → generic error
- All 50 tests pass; eslint + prettier + tsc --noEmit exit 0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
18da7e9476
commit
5bcd8180c1
@@ -801,15 +801,13 @@ describe('updateMemberProfile — URL + verb contract (Phase 20, Plan 20-02)', (
|
||||
const { updateMemberProfile, SessionExpiredError } = await import('./client.js');
|
||||
await expect(updateMemberProfile(7, { displayName: 'X' })).rejects.toSatisfy(
|
||||
(e: unknown) =>
|
||||
e instanceof Error &&
|
||||
!(e instanceof SessionExpiredError) &&
|
||||
e.message !== 'last-admin',
|
||||
e instanceof Error && !(e instanceof SessionExpiredError) && e.message !== 'last-admin',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('AdminMember.isAdmin field (Phase 20, Plan 20-02)', () => {
|
||||
it('AdminMember interface has isAdmin: boolean (compile-time type check via runtime shape)', async () => {
|
||||
it('AdminMember interface has isAdmin: boolean (compile-time type check via runtime shape)', () => {
|
||||
// Construct a conforming object — TypeScript will error at compile time if
|
||||
// isAdmin is missing from the AdminMember interface (caught by tsc --noEmit).
|
||||
const member: import('./client.js').AdminMember = {
|
||||
|
||||
Reference in New Issue
Block a user