chore(auth): add debug logging to guest login flow

Add console.log instrumentation across the guest login pipeline (auth-machine, authRepository, authApi) to trace request lifecycle and surface Zod parsing failures with detailed issue info. Useful for diagnosing lastMessageAt schema mismatches.
This commit is contained in:
2026-06-12 16:21:21 +08:00
parent 4c9fd23b4f
commit 7bc21c1864
3 changed files with 59 additions and 1 deletions
+15
View File
@@ -123,16 +123,31 @@ export class AuthRepository implements IAuthRepository {
* 成功后写 guest token + deviceId + userId。 * 成功后写 guest token + deviceId + userId。
*/ */
async guestLogin(deviceId: string): Promise<Result<GuestLoginResponse>> { async guestLogin(deviceId: string): Promise<Result<GuestLoginResponse>> {
console.log("[AuthRepository.guestLogin] API call START", {
deviceIdLength: deviceId.length,
deviceIdPrefix: deviceId.slice(0, 8),
});
return Result.wrap(async () => { return Result.wrap(async () => {
const response = await this.api.guestLogin( const response = await this.api.guestLogin(
GuestLoginRequest.from({ deviceId }), GuestLoginRequest.from({ deviceId }),
); );
console.log("[AuthRepository.guestLogin] API call SUCCESS (Zod parsed)", {
hasToken: !!response.token,
hasUser: !!response.user,
userLastMessageAt: response.user?.lastMessageAt,
});
await this.storage.setGuestToken(response.token); await this.storage.setGuestToken(response.token);
await this.storage.setDeviceId(deviceId); await this.storage.setDeviceId(deviceId);
if (response.userId) { if (response.userId) {
await this.userStorage.setUserId(response.userId); await this.userStorage.setUserId(response.userId);
} }
return response; return response;
}).catch((e) => {
console.error("[AuthRepository.guestLogin] API call FAILED", {
errorName: e?.name,
errorMessage: e?.message,
});
return Result.err(e);
}); });
} }
+25 -1
View File
@@ -4,6 +4,8 @@
* 认证相关接口 * 认证相关接口
* 原始 Dart: lib/data/services/api/auth_api_client.dart * 原始 Dart: lib/data/services/api/auth_api_client.dart
*/ */
import { z } from "zod";
import { httpClient } from "./http_client"; import { httpClient } from "./http_client";
import { ApiPath } from "./api_path"; import { ApiPath } from "./api_path";
import { ApiEnvelope, unwrap } from "./response_helper"; import { ApiEnvelope, unwrap } from "./response_helper";
@@ -117,7 +119,29 @@ export class AuthApi {
method: "POST", method: "POST",
body: body.toJson(), body: body.toJson(),
}); });
return GuestLoginResponse.fromJson(unwrap(env) as Record<string, unknown>); console.log("[AuthApi.guestLogin] raw envelope from backend", env);
const unwrapped = unwrap(env) as Record<string, unknown>;
const userObj = unwrapped.user as { lastMessageAt?: unknown } | undefined;
console.log("[AuthApi.guestLogin] unwrapped data (pre-parse)", {
hasUser: "user" in unwrapped,
userKeys: userObj && typeof userObj === "object" ? Object.keys(userObj) : null,
lastMessageAt: userObj?.lastMessageAt,
lastMessageAtType: typeof userObj?.lastMessageAt,
});
try {
return GuestLoginResponse.fromJson(unwrapped);
} catch (e) {
if (e instanceof z.ZodError) {
console.error("[AuthApi.guestLogin] ZodError parsing response", {
issueCount: e.issues.length,
firstIssue: e.issues[0],
allPaths: e.issues.map((i) => i.path),
});
} else {
console.error("[AuthApi.guestLogin] unexpected error", e);
}
throw e;
}
} }
/** /**
+19
View File
@@ -120,16 +120,35 @@ const syncFacebookBackendActor = fromPromise<
// 受保护 API 401 会由 HTTP 层清掉 token 回到 splash,无需在此处主动校验。 // 受保护 API 401 会由 HTTP 层清掉 token 回到 splash,无需在此处主动校验。
const guestLoginActor = fromPromise<LoginStatus, void>(async () => { const guestLoginActor = fromPromise<LoginStatus, void>(async () => {
console.log("[auth-machine] guestLoginActor ENTRY");
// 1. 先查本地 guestToken —— 已有就直接进 idle(带 pendingRedirect // 1. 先查本地 guestToken —— 已有就直接进 idle(带 pendingRedirect
const hasTokenR = await AuthStorage.getInstance().hasGuestToken(); const hasTokenR = await AuthStorage.getInstance().hasGuestToken();
console.log("[auth-machine] guestLoginActor hasGuestToken", {
success: hasTokenR.success,
hasData: hasTokenR.success ? !!hasTokenR.data : null,
});
if (hasTokenR.success && hasTokenR.data) { if (hasTokenR.success && hasTokenR.data) {
console.log("[auth-machine] guestLoginActor SHORT-CIRCUIT (has local guestToken) → return guest");
return "guest" as LoginStatus; return "guest" as LoginStatus;
} }
// Result.err(_) 时**不**抛 —— 落到 API 路径让真正的错误信号出现 // Result.err(_) 时**不**抛 —— 落到 API 路径让真正的错误信号出现
// 2. 没有(或读不出)才走完整流程:拿 deviceId → 调后端 // 2. 没有(或读不出)才走完整流程:拿 deviceId → 调后端
const deviceId = await deviceIdentifier.getDeviceId(); const deviceId = await deviceIdentifier.getDeviceId();
console.log("[auth-machine] guestLoginActor deviceId", {
length: deviceId.length,
prefix: deviceId.slice(0, 8),
});
console.log("[auth-machine] guestLoginActor calling authRepository.guestLogin");
const result = await authRepository.guestLogin(deviceId); const result = await authRepository.guestLogin(deviceId);
console.log("[auth-machine] guestLoginActor authRepository.guestLogin DONE", {
success: result.success,
hasData: result.success ? !!result.data : null,
errorName: result.success ? null : result.error?.name,
errorMessage: result.success ? null : result.error?.message,
});
if (Result.isErr(result)) throw result.error; if (Result.isErr(result)) throw result.error;
return "guest" as LoginStatus; return "guest" as LoginStatus;
}); });