fix(linking): link subdomains to parent subscription via suffix match #16
@@ -21,6 +21,22 @@ function normalizeDomainLike(value: string) {
|
||||
return value.trim().toLowerCase().replace(/\.$/, "");
|
||||
}
|
||||
|
||||
function findBestSuffixStatusMatch(
|
||||
normalizedDomain: string,
|
||||
candidates: Array<{ normalizedName: string; status: string | null }>,
|
||||
) {
|
||||
let best: { normalizedName: string; status: string | null } | null = null;
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (!normalizedDomain.endsWith(`.${candidate.normalizedName}`)) continue;
|
||||
if (!best || candidate.normalizedName.length > best.normalizedName.length) {
|
||||
best = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return best?.status ?? null;
|
||||
}
|
||||
|
||||
export default async function DashboardPage() {
|
||||
const context = await getServerAgencyContextOrRedirect();
|
||||
const supabase = createSupabaseServerClient() as any;
|
||||
@@ -163,6 +179,24 @@ export default async function DashboardPage() {
|
||||
]),
|
||||
);
|
||||
|
||||
const subscriptionStatusNameCandidatesByInstance = new Map<
|
||||
string,
|
||||
Array<{ normalizedName: string; status: string | null }>
|
||||
>();
|
||||
|
||||
for (const subscription of domainSubscriptions ?? []) {
|
||||
if (!subscription?.plesk_instance_id || !subscription?.name) continue;
|
||||
|
||||
const instanceId = String(subscription.plesk_instance_id);
|
||||
const existing =
|
||||
subscriptionStatusNameCandidatesByInstance.get(instanceId) ?? [];
|
||||
existing.push({
|
||||
normalizedName: normalizeDomainLike(String(subscription.name)),
|
||||
status: subscription?.status ? String(subscription.status) : null,
|
||||
});
|
||||
subscriptionStatusNameCandidatesByInstance.set(instanceId, existing);
|
||||
}
|
||||
|
||||
const autoSyncByInstance = new Map<
|
||||
string,
|
||||
{ status: string; created_at: string; error_message: string | null }
|
||||
@@ -229,10 +263,17 @@ export default async function DashboardPage() {
|
||||
const joinedStatusByName = subscriptionStatusByInstanceAndName.get(
|
||||
`${domain.plesk_instance_id}:${normalizeDomainLike(domain.domain_name)}`,
|
||||
);
|
||||
const joinedStatusBySuffix = findBestSuffixStatusMatch(
|
||||
normalizeDomainLike(domain.domain_name),
|
||||
subscriptionStatusNameCandidatesByInstance.get(
|
||||
domain.plesk_instance_id,
|
||||
) ?? [],
|
||||
);
|
||||
const joinedStatus =
|
||||
joinedStatusByLocalId ??
|
||||
joinedStatusByExternalId ??
|
||||
joinedStatusByName;
|
||||
joinedStatusByName ??
|
||||
joinedStatusBySuffix;
|
||||
|
||||
return {
|
||||
...domain,
|
||||
|
||||
@@ -35,6 +35,21 @@ function normalizeDomainLike(value: string) {
|
||||
return value.trim().toLowerCase().replace(/\.$/, "");
|
||||
}
|
||||
|
||||
function findBestSuffixSubscriptionMatch<
|
||||
T extends { normalizedName: string; id: string; status: string | null },
|
||||
>(normalizedDomain: string, candidates: T[]) {
|
||||
let best: T | undefined;
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (!normalizedDomain.endsWith(`.${candidate.normalizedName}`)) continue;
|
||||
if (!best || candidate.normalizedName.length > best.normalizedName.length) {
|
||||
best = candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
export async function syncPleskInstance(
|
||||
supabase: SupabaseLike,
|
||||
instance: InstanceRow,
|
||||
@@ -220,6 +235,20 @@ export async function syncPleskInstance(
|
||||
.map((row) => [normalizeDomainLike(String(row.name)), row]),
|
||||
);
|
||||
|
||||
const subscriptionNameCandidates: Array<{
|
||||
id: string;
|
||||
pleskSubscriptionId: string;
|
||||
status: string | null;
|
||||
normalizedName: string;
|
||||
}> = subscriptionsIndexed
|
||||
.filter((row) => row.name)
|
||||
.map((row) => ({
|
||||
id: row.id,
|
||||
pleskSubscriptionId: row.pleskSubscriptionId,
|
||||
status: row.status,
|
||||
normalizedName: normalizeDomainLike(String(row.name)),
|
||||
}));
|
||||
|
||||
const domainsForUpsert = domainsRaw
|
||||
.map((item: any) => {
|
||||
const domainId = item?.id ?? item?.guid ?? item?.name;
|
||||
@@ -253,11 +282,18 @@ export async function syncPleskInstance(
|
||||
const localSubscriptionByDomainName = normalizedDomainName
|
||||
? subscriptionByName.get(normalizedDomainName)
|
||||
: undefined;
|
||||
const localSubscriptionBySuffix = normalizedDomainName
|
||||
? findBestSuffixSubscriptionMatch(
|
||||
normalizedDomainName,
|
||||
subscriptionNameCandidates,
|
||||
)
|
||||
: undefined;
|
||||
const localSubscription =
|
||||
localSubscriptionByExternal ??
|
||||
localSubscriptionByLocalId ??
|
||||
localSubscriptionByName ??
|
||||
localSubscriptionByDomainName;
|
||||
localSubscriptionByDomainName ??
|
||||
localSubscriptionBySuffix;
|
||||
|
||||
const externalSubscriptionId = localSubscription
|
||||
? localSubscription.pleskSubscriptionId
|
||||
@@ -469,6 +505,18 @@ export async function backfillDomainSubscriptionLinks(
|
||||
]),
|
||||
);
|
||||
|
||||
const subscriptionNameCandidates: Array<{
|
||||
id: string;
|
||||
status: string;
|
||||
normalizedName: string;
|
||||
}> = (subscriptions ?? [])
|
||||
.filter((subscription: any) => subscription?.name)
|
||||
.map((subscription: any) => ({
|
||||
id: String(subscription.id),
|
||||
status: subscription?.status ? String(subscription.status) : "unknown",
|
||||
normalizedName: normalizeDomainLike(String(subscription.name)),
|
||||
}));
|
||||
|
||||
let linkedCount = 0;
|
||||
const failures: Array<{ domain_id: string; error: string }> = [];
|
||||
|
||||
@@ -479,7 +527,17 @@ export async function backfillDomainSubscriptionLinks(
|
||||
const matchByDomainName = domain?.domain_name
|
||||
? subscriptionByName.get(normalizeDomainLike(String(domain.domain_name)))
|
||||
: undefined;
|
||||
const linkedSubscription = matchByExternal ?? matchByDomainName;
|
||||
const normalizedDomainName = domain?.domain_name
|
||||
? normalizeDomainLike(String(domain.domain_name))
|
||||
: null;
|
||||
const matchBySuffix = normalizedDomainName
|
||||
? findBestSuffixSubscriptionMatch(
|
||||
normalizedDomainName,
|
||||
subscriptionNameCandidates,
|
||||
)
|
||||
: undefined;
|
||||
const linkedSubscription =
|
||||
matchByExternal ?? matchByDomainName ?? matchBySuffix;
|
||||
|
||||
if (!linkedSubscription) continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user