Files
cameleer-saas/ui/sign-in/src/experience-api.ts

64 lines
2.0 KiB
TypeScript
Raw Normal View History

const BASE = '/api/experience';
async function request(method: string, path: string, body?: unknown): Promise<Response> {
const res = await fetch(`${BASE}${path}`, {
method,
headers: body ? { 'Content-Type': 'application/json' } : undefined,
body: body ? JSON.stringify(body) : undefined,
credentials: 'same-origin',
});
return res;
}
export async function initInteraction(): Promise<void> {
const res = await request('PUT', '', { interactionEvent: 'SignIn' });
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.message || `Failed to initialize sign-in (${res.status})`);
}
}
export async function verifyPassword(
username: string,
password: string
): Promise<string> {
const res = await request('POST', '/verification/password', {
identifier: { type: 'username', value: username },
password,
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
if (res.status === 422) {
throw new Error('Invalid username or password');
}
throw new Error(err.message || `Authentication failed (${res.status})`);
}
const data = await res.json();
return data.verificationId;
}
export async function identifyUser(verificationId: string): Promise<void> {
const res = await request('POST', '/identification', { verificationId });
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.message || `Identification failed (${res.status})`);
}
}
export async function submitInteraction(): Promise<string> {
const res = await request('POST', '/submit');
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.message || `Submit failed (${res.status})`);
}
const data = await res.json();
return data.redirectTo;
}
export async function signIn(username: string, password: string): Promise<string> {
await initInteraction();
const verificationId = await verifyPassword(username, password);
await identifyUser(verificationId);
return submitInteraction();
}