feat: release design system engine, studio and component contracts

This commit is contained in:
Clintchiz committed 2026-10-19 13:09:03 +05:30
1 parent ff1065fb27
commit 3943b946d6
693 files changed
+175546 -3894

No files matched your search

+21 -9
View File
@@ -132,6 +132,7 @@ export interface AuthEngine {
beginMfaOtp(
mfaToken: string,
method: "email-otp" | "sms-otp",
options?: { resend?: boolean },
): Promise<{ id: string; expiresAt: number } | undefined>;
completeMfa(input: {
rememberDevice?: boolean;
@@ -1711,7 +1712,7 @@ export function createAuthEngine(options: AuthEngineOptions): AuthEngine {
return { ok: true, user: publicUser(user), session };
},
async beginMfaOtp(mfaToken, method) {
async beginMfaOtp(mfaToken, method, request = {}) {
const token = await inspectToken(mfaToken, "login-mfa");
if (!token) return undefined;
const user = await store.findUserById(token.userId);
@@ -1724,12 +1725,18 @@ export function createAuthEngine(options: AuthEngineOptions): AuthEngine {
const previousId = token.metadata?.[key];
if (typeof previousId === "string") {
const previous = await store.findOtp(previousId);
if (previous && !previous.usedAt && previous.expiresAt > now())
return { id: previous.id, expiresAt: previous.expiresAt };
if (request.resend && previous && now() - previous.createdAt < 60_000) return undefined;
if (previous && !previous.usedAt && previous.expiresAt > now()) {
if (!request.resend) return { id: previous.id, expiresAt: previous.expiresAt };
}
}
const challenge = await issueOtp(token.userId, method, undefined, "mfa");
token.metadata = { ...token.metadata, [key]: challenge.id };
await store.updateToken(token);
if (request.resend && typeof previousId === "string") {
const previous = await store.findOtp(previousId);
if (previous && !previous.usedAt) await store.updateOtp({ ...previous, usedAt: now() });
}
return challenge;
} catch {
return undefined;
@@ -2081,12 +2088,17 @@ export function createAuthEngine(options: AuthEngineOptions): AuthEngine {
const verification = verificationUnavailable(user);
if (verification) return verification;
account = await engine.linkOAuth(user.id, providerName, normalizedProfile, tokens);
const providerVerifiesDevice = verifiedEmail &&
options.verifiedOAuthDeviceProviders?.some((name) => normalizedOAuthProvider(name) === providerName);
const deviceCheck = providerVerifiesDevice ? undefined : await newDeviceRequirement(user, {
...sessionInput,
oauthProvider: providerName,
});
const providerVerifiesDevice =
verifiedEmail &&
options.verifiedOAuthDeviceProviders?.some(
(name) => normalizedOAuthProvider(name) === providerName,
);
const deviceCheck = providerVerifiesDevice
? undefined
: await newDeviceRequirement(user, {
...sessionInput,
oauthProvider: providerName,
});
if (deviceCheck) return deviceCheck;
if (await hasMfa(user.id)) {
const methods = await availableMfaMethods(user.id);
+12 -3
View File
@@ -505,10 +505,19 @@ export function createAuthHttpHandlers(options: AuthHttpOptions) {
if (!validation.ok) return validation.response;
const input = validation.value;
const method = text(input.method) === "sms-otp" ? "sms-otp" : "email-otp";
const challenge = await engine.beginMfaOtp(text(input.mfaToken), method);
const challenge = await engine.beginMfaOtp(text(input.mfaToken), method, {
resend: input.resend === true,
});
return challenge
? json({ ok: true, ...challenge })
: json({ ok: false, error: "MFA transaction is invalid or expired" }, 400);
? json({ ok: true, ...challenge, retryAfter: 60 })
: json(
{
ok: false,
error:
"Unable to request a code. Wait 60 seconds before retrying, or sign in again if this request has expired.",
},
400,
);
},
async completeMfa(ctx: Context): Promise<Response> {
+1
View File
@@ -148,6 +148,7 @@ export const otpSchema = v.object({
});
export const mfaOtpRequestSchema = v.object({
resend: v.boolean().optional(),
mfaToken: v
.string()
.required("MFA transaction is missing")