File size: 8,118 Bytes
6b825ee |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
// @ts-check
import axios, { AxiosResponse, AxiosError } from 'axios';
import { Request, Response } from 'express';
console.log(`[Register Module] src/register.ts file is being evaluated. __dirname is: ${__dirname}`);
interface PastebinResponse {
link: string;
}
interface RegisterClientPayload {
user: string;
pass: string;
email: string;
nickname?: string;
avatar?: string;
bio?: string;
dob?: string;
cover_photo?: string;
country?: string;
timezone?: string;
}
type ExternalApiSignUpPayload = RegisterClientPayload;
interface RegisterApiResponseData {
status: string;
token?: string;
cookies?: string;
avatar?: string;
cover_photo?: string;
message?: string;
}
function isRegisterClientPayload(body: any): body is RegisterClientPayload {
return !!(body && typeof body === 'object' &&
typeof body.user === 'string' && body.user.length > 0 &&
typeof body.pass === 'string' && body.pass.length > 0 &&
typeof body.email === 'string' && body.email.length > 0);
}
function isRegisterApiResponseData(data: any): data is RegisterApiResponseData {
return !!(data && typeof data === 'object' && typeof data.status === 'string');
}
const api = {
async getLink(): Promise<string> {
console.log("[Register API - getLink] Attempting to fetch link...");
try {
const res: AxiosResponse<string | PastebinResponse> = await axios.get('https://pastebin.com/raw/YtqNc7Yi');
const responseData = res.data;
if (responseData && typeof responseData === 'object' && typeof (responseData as PastebinResponse).link === 'string') {
return (responseData as PastebinResponse).link;
} else if (typeof responseData === 'string' && responseData.startsWith('http')) {
return responseData;
}
throw new Error('Invalid or missing link in Pastebin response data.');
} catch (err: unknown) {
const error = err instanceof Error ? err : new Error(String(err));
throw new Error('Failed to get base link.', { cause: error });
}
},
async register(body: ExternalApiSignUpPayload): Promise<RegisterApiResponseData> {
console.log("[Register API - register] Attempting external API signup, payload:", body);
try {
const link: string = await api.getLink();
const res: AxiosResponse<RegisterApiResponseData> = await axios.post(`${link}/signup`, body);
console.log("[Register API - register] Response from external API:", res.data);
return res.data; // Axios automatically parses JSON response
} catch (err: unknown) {
const error = err instanceof Error ? err : new Error(String(err));
if (axios.isAxiosError(error) && error.response) {
console.error("Axios error data:", error.response.data, "Status:", error.response.status);
}
throw new Error('Failed to contact/process signup endpoint.', { cause: error });
}
},
};
interface RegisterRouteParams {
req: Request<any, any, any>; // Body is initially any, refined by type guard
res: Response;
}
interface RegisterExpressRouteModule {
method: "get" | "post" | "put" | "delete" | "patch" | "options" | "head" | "all";
path: string;
install: (params: RegisterRouteParams) => Promise<void> | void;
}
export const modules: RegisterExpressRouteModule[] = [
{
method: 'post',
path: '/register',
install: async ({ req, res }: RegisterRouteParams): Promise<void> => {
console.log(`[Register Route] Handler for ${req.method.toUpperCase()} ${req.path}`);
const rawClientBody: unknown = req.body;
console.log("[Register Route] Raw request body from client:", rawClientBody);
try {
if (isRegisterClientPayload(rawClientBody)) {
const clientData: RegisterClientPayload = rawClientBody; // Type guard refines type
const payloadForExternalApi: ExternalApiSignUpPayload = {
user: clientData.user,
pass: clientData.pass,
email: clientData.email,
};
if (clientData.nickname && clientData.nickname.trim() !== "") payloadForExternalApi.nickname = clientData.nickname;
if (clientData.avatar && clientData.avatar.trim() !== "") payloadForExternalApi.avatar = clientData.avatar;
if (clientData.bio && clientData.bio.trim() !== "") payloadForExternalApi.bio = clientData.bio;
if (clientData.dob && clientData.dob.trim() !== "") payloadForExternalApi.dob = clientData.dob;
if (clientData.cover_photo && clientData.cover_photo.trim() !== "") payloadForExternalApi.cover_photo = clientData.cover_photo;
if (clientData.country && clientData.country.trim() !== "") payloadForExternalApi.country = clientData.country;
if (clientData.timezone && clientData.timezone.trim() !== "") payloadForExternalApi.timezone = clientData.timezone;
const rawApiResult: RegisterApiResponseData = await api.register(payloadForExternalApi);
if (isRegisterApiResponseData(rawApiResult)) { // Guard for external API response structure
const resultFromExternalApi: RegisterApiResponseData = rawApiResult;
if (resultFromExternalApi.status === 'success') {
console.log("[Register Route] External API reported SUCCESS.");
res.json({
success: true,
message: resultFromExternalApi.message || "Registration successful!",
data: resultFromExternalApi
});
} else {
console.warn("[Register Route] External API reported FAILURE. Status:", resultFromExternalApi.status, "Message:", resultFromExternalApi.message);
res.status(400).json({
success: false,
error: resultFromExternalApi.message || "Registration failed at external API."
});
}
} else {
console.error("[Register Route] Unexpected response structure from external API:", rawApiResult);
res.status(500).json({ success: false, error: "Received an unexpected response from the registration service." });
}
} else {
console.warn("[Register Route] Validation failed: req.body does not conform to RegisterClientPayload. Received:", rawClientBody);
res.status(400).json({ success: false, error: 'Invalid registration data: user, pass, and email are required and must be valid non-empty strings.' });
return;
}
} catch (err: unknown) {
const error = err instanceof Error ? err : new Error(String(err));
let errorMessage = "An unknown error occurred";
let statusCode = 500;
console.error(`[Register Route] Overall error:`, error.message, (error as any).cause || error);
const originalError = (error as any).cause || error;
if (axios.isAxiosError(originalError)) {
const axiosError = originalError as AxiosError<any>; // Type assertion
errorMessage = axiosError.message;
statusCode = axiosError.response?.status || 503;
const responseData = axiosError.response?.data;
const specificApiError = responseData?.error || responseData?.message;
if (specificApiError) {
errorMessage = `Reg API Error (${statusCode}): ${specificApiError}`;
} else if (axiosError.response) {
errorMessage = `Reg API Error (${statusCode}): Req failed (status ${statusCode}).`;
} else if (axiosError.request) {
errorMessage = `No response from reg service: ${axiosError.message}`;
}
} else if (originalError instanceof Error) {
errorMessage = originalError.message || String(originalError);
} else {
errorMessage = String(originalError);
}
console.error(`[Register Route] Error to client: ${errorMessage}, Status: ${statusCode}`);
if (!res.headersSent) {
res.status(statusCode).json({ success: false, error: errorMessage });
} else {
console.warn("[Register Route] Headers sent, cannot send error.");
}
}
},
},
];
|