shoc-frontend-new/src/domain/team-member-invite/api/team-member-invite-api.ts

59 lines
2.2 KiB
TypeScript

/**
* Anonymous invite registration. The invite token travels only in request bodies,
* never in a URL path or query, and the server scopes every call to that token.
*/
import { isHTTPError } from "ky";
import { apiPost } from "@/api/api";
import { API_PATHS } from "@/api/api-paths";
import { handleApiResponse } from "@/api/handle-api-response";
import type { AuthUser } from "@/domain/auth/types/auth-user";
import type {
CompleteRegistrationInput,
TeamMemberInviteDetails,
TeamMemberInviteErrorCode,
} from "@/domain/team-member-invite/types/team-member-invite";
import { getAuthUser, setAuthUser } from "@/lib/auth/auth-storage";
export const teamMemberInviteApi = {
resolve: async (token: string): Promise<TeamMemberInviteDetails> => {
const data = await apiPost<unknown>(API_PATHS.teamMemberInvite.resolve, { token });
return handleApiResponse<TeamMemberInviteDetails>(data);
},
sendCode: async (token: string): Promise<void> => {
await apiPost<unknown>(API_PATHS.teamMemberInvite.sendCode, { token });
},
verifyCode: async ({ token, code }: { token: string; code: string }): Promise<void> => {
await apiPost<unknown>(API_PATHS.teamMemberInvite.verifyCode, { token, code });
},
/** Finishes registration and stores the returned session exactly as login does. */
complete: async (input: CompleteRegistrationInput): Promise<AuthUser> => {
const data = await apiPost<unknown>(API_PATHS.teamMemberInvite.complete, {
token: input.token,
password: input.password,
// An empty value clears the phone the admin entered.
phone: input.phone.trim(),
});
const user = handleApiResponse<AuthUser>(data);
setAuthUser(user);
return getAuthUser() ?? user;
},
};
/** The server's failure code for an invite call, when the response carried one. */
export function inviteErrorCode(error: unknown): TeamMemberInviteErrorCode | null {
if (!isHTTPError(error)) {
return null;
}
const data: unknown = error.data;
if (typeof data === "object" && data !== null && "code" in data) {
const code = (data as { code: unknown }).code;
return typeof code === "string" ? (code as TeamMemberInviteErrorCode) : null;
}
return null;
}