113 lines
3.9 KiB
TypeScript
113 lines
3.9 KiB
TypeScript
|
|
/**
|
||
|
|
* Get Started Domain - Contract
|
||
|
|
*
|
||
|
|
* Types and constants for the unified "Get Started" flow that handles:
|
||
|
|
* - Email verification (OTP)
|
||
|
|
* - Account status detection
|
||
|
|
* - Quick eligibility check
|
||
|
|
* - Account completion for SF-only accounts
|
||
|
|
*/
|
||
|
|
|
||
|
|
import type { z } from "zod";
|
||
|
|
|
||
|
|
import type {
|
||
|
|
sendVerificationCodeRequestSchema,
|
||
|
|
sendVerificationCodeResponseSchema,
|
||
|
|
verifyCodeRequestSchema,
|
||
|
|
verifyCodeResponseSchema,
|
||
|
|
quickEligibilityRequestSchema,
|
||
|
|
quickEligibilityResponseSchema,
|
||
|
|
completeAccountRequestSchema,
|
||
|
|
maybeLaterRequestSchema,
|
||
|
|
maybeLaterResponseSchema,
|
||
|
|
getStartedSessionSchema,
|
||
|
|
} from "./schema.js";
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Constants
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Account status after email verification
|
||
|
|
* Determines which flow the user should follow
|
||
|
|
*/
|
||
|
|
export const ACCOUNT_STATUS = {
|
||
|
|
/** User has a portal account - redirect to login */
|
||
|
|
PORTAL_EXISTS: "portal_exists",
|
||
|
|
/** User has WHMCS account but no portal - migrate flow */
|
||
|
|
WHMCS_UNMAPPED: "whmcs_unmapped",
|
||
|
|
/** User has SF account but no WHMCS/portal - complete account flow */
|
||
|
|
SF_UNMAPPED: "sf_unmapped",
|
||
|
|
/** No account exists - full signup flow */
|
||
|
|
NEW_CUSTOMER: "new_customer",
|
||
|
|
} as const;
|
||
|
|
|
||
|
|
export type AccountStatus = (typeof ACCOUNT_STATUS)[keyof typeof ACCOUNT_STATUS];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* OTP verification error codes
|
||
|
|
*/
|
||
|
|
export const OTP_ERROR_CODE = {
|
||
|
|
/** Code has expired */
|
||
|
|
EXPIRED: "otp_expired",
|
||
|
|
/** Invalid code entered */
|
||
|
|
INVALID: "otp_invalid",
|
||
|
|
/** Too many failed attempts */
|
||
|
|
MAX_ATTEMPTS: "otp_max_attempts",
|
||
|
|
/** Rate limit exceeded for sending codes */
|
||
|
|
RATE_LIMITED: "otp_rate_limited",
|
||
|
|
} as const;
|
||
|
|
|
||
|
|
export type OtpErrorCode = (typeof OTP_ERROR_CODE)[keyof typeof OTP_ERROR_CODE];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get Started flow error codes
|
||
|
|
*/
|
||
|
|
export const GET_STARTED_ERROR_CODE = {
|
||
|
|
/** Session token is invalid or expired */
|
||
|
|
INVALID_SESSION: "invalid_session",
|
||
|
|
/** Email not verified yet */
|
||
|
|
EMAIL_NOT_VERIFIED: "email_not_verified",
|
||
|
|
/** SF account creation failed */
|
||
|
|
SF_CREATION_FAILED: "sf_creation_failed",
|
||
|
|
/** WHMCS account creation failed */
|
||
|
|
WHMCS_CREATION_FAILED: "whmcs_creation_failed",
|
||
|
|
} as const;
|
||
|
|
|
||
|
|
export type GetStartedErrorCode =
|
||
|
|
(typeof GET_STARTED_ERROR_CODE)[keyof typeof GET_STARTED_ERROR_CODE];
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Request Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type SendVerificationCodeRequest = z.infer<typeof sendVerificationCodeRequestSchema>;
|
||
|
|
export type VerifyCodeRequest = z.infer<typeof verifyCodeRequestSchema>;
|
||
|
|
export type QuickEligibilityRequest = z.infer<typeof quickEligibilityRequestSchema>;
|
||
|
|
export type CompleteAccountRequest = z.infer<typeof completeAccountRequestSchema>;
|
||
|
|
export type MaybeLaterRequest = z.infer<typeof maybeLaterRequestSchema>;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Response Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type SendVerificationCodeResponse = z.infer<typeof sendVerificationCodeResponseSchema>;
|
||
|
|
export type VerifyCodeResponse = z.infer<typeof verifyCodeResponseSchema>;
|
||
|
|
export type QuickEligibilityResponse = z.infer<typeof quickEligibilityResponseSchema>;
|
||
|
|
export type MaybeLaterResponse = z.infer<typeof maybeLaterResponseSchema>;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Session Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export type GetStartedSession = z.infer<typeof getStartedSessionSchema>;
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// Error Types
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export interface GetStartedError {
|
||
|
|
code: OtpErrorCode | GetStartedErrorCode;
|
||
|
|
message: string;
|
||
|
|
}
|