File size: 3,140 Bytes
6111b2b | 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 | /**
* Pure parser for the Trae SOLO /authorize callback query string. Extracted
* from route.ts so it can be unit-tested without touching the DB layer.
*
* Returns the credential bundle that the route hands to createProviderConnection,
* or a structured error if the payload is missing/malformed.
*/
export type ParsedTraeCallback = {
ok: true;
record: {
provider: "trae";
authType: "oauth";
accessToken: string;
refreshToken: string | null;
expiresAt: string | null;
email: string | null;
providerSpecificData: {
userId: string;
tenantId: string;
bizUserId: string;
userUniqueId: string;
webId: string;
scope: "marscode-us";
tenant: "marscode";
region: string;
aiRegion: string;
host: string;
screenName: string | null;
clientId: string;
refreshExpireAt: number | null;
authMethod: "oauth_callback";
};
testStatus: "active";
};
};
export type ParseError = { ok: false; error: string };
export function parseTraeCallbackQuery(q: URLSearchParams): ParsedTraeCallback | ParseError {
const userJwtRaw = q.get("userJwt");
if (!userJwtRaw) return { ok: false, error: "Missing userJwt in callback" };
let userJwt: Record<string, unknown>;
try {
userJwt = JSON.parse(userJwtRaw);
} catch {
return { ok: false, error: "Malformed userJwt payload" };
}
const token = userJwt.Token as string | undefined;
if (!token) return { ok: false, error: "userJwt.Token missing" };
const refresh = (userJwt.RefreshToken as string) || q.get("refreshToken") || null;
const tokenExpiresAtMs = Number(userJwt.TokenExpireAt) || 0;
const refreshExpiresAtMs = Number(userJwt.RefreshExpireAt || q.get("refreshExpireAt")) || 0;
let info: Record<string, unknown> = {};
const userInfoRaw = q.get("userInfo");
if (userInfoRaw) {
try {
info = JSON.parse(userInfoRaw);
} catch {
// userInfo is best-effort metadata — fall back to defaults silently.
}
}
const userId = (info.UserID as string) || "";
const region = (info.Region as string) || "US-East";
return {
ok: true,
record: {
provider: "trae",
authType: "oauth",
accessToken: token,
refreshToken: refresh,
expiresAt: tokenExpiresAtMs ? new Date(tokenExpiresAtMs).toISOString() : null,
email: (info.NonPlainTextEmail as string) || null,
providerSpecificData: {
userId,
tenantId: (info.TenantID as string) || "",
bizUserId: userId,
userUniqueId: userId,
webId: userId,
scope: "marscode-us",
tenant: "marscode",
region,
aiRegion: (info.AIRegion as string) || region,
host: q.get("host") || "https://api-us-east.trae.ai",
screenName: (info.ScreenName as string) || null,
clientId: (userJwt.ClientID as string) || "en1oxy7wnw8j9n",
refreshExpireAt: refreshExpiresAtMs || null,
authMethod: "oauth_callback",
},
testStatus: "active",
},
};
}
|