feat(api): signal loadError when a PL24 catalog fetch fails

A category whose PL24 drill/parts fetch errors (e.g. a broken catalog snapshot
returning HTTP 500) was indistinguishable from a genuinely empty leaf — both
came back with empty parts, so the UI showed a misleading "no parts found".

getCategoryWithParts now: (1) for a pl24 group node (link_wid marks a groups
table) with no children, drills via getChildren — returns the subgroups if PL24
serves them, otherwise flags loadError (these group nodes are never legitimately
empty); (2) sets loadError when the leaf parts fetch throws. loadError is only
true when the lists are actually empty, so genuine empty leaves stay clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-25 04:35:28 +03:00
parent 77947cd162
commit ab5ed62f52

View File

@@ -670,7 +670,29 @@ export class CategoriesService {
// to the parts path rather than returning a misleading empty leaf.
}
// PL24 main/sub-group node (its link_wid marks a groups table) with no
// children yet — drill it. If PL24 serves subgroups, return them as a
// parent. If the drill comes back empty, the catalog snapshot is broken
// server-side: surface that as a load error instead of a misleading
// "no parts" leaf (these group nodes are never legitimately empty).
if (category.source === "pl24" && category.linkWid?.includes("Group") && category.vehicleId) {
const groupChildren = await this.getChildren(categoryId);
const base = {
id: category.id,
name: category.name,
description: category.nameOriginal || null,
parentId: category.parentId || null,
parts: [],
schemaPics: [],
hotspots: [],
};
return groupChildren.length > 0
? { ...base, children: groupChildren }
: { ...base, loadError: true };
}
// Leaf category — get or fetch parts
let loadError = false;
let discoveredChildren: any[] = [];
let dbParts = await this.db.select().from(parts).where(eq(parts.categoryId, categoryId));
@@ -1090,6 +1112,10 @@ export class CategoriesService {
}
}
} catch (err) {
// PL24 fetch failed (e.g. broken catalog snapshot → HTTP 500).
// Signal a load error so the UI can offer a retry instead of
// rendering a misleading empty "no parts" leaf.
loadError = true;
this.logger.error(
`Failed to fetch parts for category ${categoryId}: ${(err as Error).message}`,
);
@@ -1172,6 +1198,9 @@ export class CategoriesService {
parts: dbParts,
schemaPics: mappedPics,
hotspots: mappedHotspots,
// Only meaningful when the lists are empty: true means a source fetch
// failed (retryable), as opposed to a genuinely empty leaf.
loadError: loadError && dbParts.length === 0 && mappedPics.length === 0,
};
}