Resolve account subscription sync state

This commit is contained in:
2569718930@qq.com
2026-06-14 05:28:48 +08:00
parent 0084235b57
commit e783f35a4f
4 changed files with 60 additions and 1 deletions
@@ -1,6 +1,7 @@
import {
buildAuthMePath,
mergeAccountAuthSnapshot,
shouldResolveAccountUnknownWithFullProfile,
} from "@/lib/auth-snapshot";
import type { AuthSnapshotLike } from "@/lib/auth-snapshot";
@@ -64,4 +65,33 @@ export function runTests() {
inactive.subscription_active === false,
"account snapshot merge must still accept a confirmed inactive subscription response",
);
assert(
shouldResolveAccountUnknownWithFullProfile(
{ authenticated: true, subscription_active: null },
true,
),
"account center must resolve an unknown local-user subscription snapshot with the full auth profile",
);
assert(
!shouldResolveAccountUnknownWithFullProfile(
{ authenticated: true, subscription_active: false },
true,
),
"account center must not re-resolve an explicitly inactive subscription snapshot",
);
assert(
!shouldResolveAccountUnknownWithFullProfile(
{ authenticated: false, subscription_active: null },
true,
),
"account center must not re-resolve an unauthenticated backend snapshot",
);
assert(
!shouldResolveAccountUnknownWithFullProfile(
{ authenticated: true, subscription_active: null },
false,
),
"account center must only resolve unknown subscription snapshots when a local Supabase user exists",
);
}
@@ -259,6 +259,13 @@ export function runTests() {
hookSource.includes("retriedBackendJson"),
"account snapshot loader must retry with a refreshed Supabase token when local user exists but /api/auth/me reports unauthenticated",
);
assert(
hookSource.includes("shouldResolveAccountUnknownWithFullProfile") &&
hookSource.includes("backendJson = await readAuthSnapshot(latestHeaders);") &&
hookSource.indexOf("shouldResolveAccountUnknownWithFullProfile") <
hookSource.indexOf("setBackend((previous) => mergeAccountAuthSnapshot(previous, backendJson))"),
"account snapshot loader must resolve unknown entitlement-scope results through full auth/me before rendering account status",
);
assert(
hookSource.includes("refreshEntitlementAfterPayment") &&
paymentFlowSource.includes("refreshEntitlementAfterPayment") &&
@@ -6,6 +6,7 @@ import type { User } from "@supabase/supabase-js";
import {
buildAuthMePath,
mergeAccountAuthSnapshot,
shouldResolveAccountUnknownWithFullProfile,
} from "@/lib/auth-snapshot";
import { getSupabaseBrowserClient } from "@/lib/supabase/client";
@@ -244,9 +245,19 @@ export function useAccountPayment(params: UseAccountPaymentParams) {
// an unauthenticated backend snapshot as a temporary sync state.
}
}
let resolvedWithFullProfile = false;
if (shouldResolveAccountUnknownWithFullProfile(backendJson, Boolean(localUser))) {
try {
backendJson = await readAuthSnapshot(latestHeaders);
resolvedWithFullProfile = true;
} catch {
// Keep the explicit unknown state only when the full account profile
// cannot be read; the refresh button can retry the same path.
}
}
setBackend((previous) => mergeAccountAuthSnapshot(previous, backendJson));
setUpdatedAt(new Date().toISOString());
if (backendJson.authenticated !== false) {
if (backendJson.authenticated !== false && !resolvedWithFullProfile) {
void readAuthSnapshot(latestHeaders)
.then((fullJson) => {
setBackend((previous) =>
+11
View File
@@ -40,6 +40,17 @@ export function isUnknownSubscriptionSnapshot(
);
}
export function shouldResolveAccountUnknownWithFullProfile(
snapshot: AuthSnapshotLike | null | undefined,
localUserPresent: boolean,
) {
return Boolean(
localUserPresent &&
snapshot?.authenticated !== false &&
isUnknownSubscriptionSnapshot(snapshot),
);
}
export function mergeAccountAuthSnapshot<T extends AuthSnapshotLike>(
previous: T | null | undefined,
next: T,