diff --git a/src/utils/govinfo-bulk-listing.ts b/src/utils/govinfo-bulk-listing.ts index e44b0e5..79673b0 100644 --- a/src/utils/govinfo-bulk-listing.ts +++ b/src/utils/govinfo-bulk-listing.ts @@ -53,14 +53,17 @@ export function parseGovInfoBulkListing(xml: string, baseUrl: string): GovInfoBu name, href, url: url.toString(), - kind: classifyListingEntry({ name, href, url: url.toString() }), + kind: classifyListingEntry({ name, href, url: url.toString() }, entry), }); } return dedupeEntries(entries); } -export function classifyListingEntry(entry: Pick): 'directory' | 'file' { +export function classifyListingEntry(entry: Pick, rawEntry?: Record): 'directory' | 'file' { + if (rawEntry?.folder === true || rawEntry?.folder === 'true') { + return 'directory'; + } if (entry.href.endsWith('/') || entry.name.endsWith('/') || new URL(entry.url).pathname.endsWith('/')) { return 'directory'; } @@ -84,6 +87,12 @@ function findEntriesRoot(parsed: unknown): unknown { throw new Error('invalid_listing_payload: listing XML did not parse into an object'); } + // GovInfo XML: ... + const data = parsed.data; + if (isRecord(data) && data.files) { + return data.files; + } + return parsed.directory ?? parsed.listing ?? parsed.files ?? parsed; } @@ -120,6 +129,9 @@ function readStringField(entry: Record, fields: string[]): stri if (typeof value === 'string' && value.trim().length > 0) { return value.trim(); } + if (typeof value === 'number') { + return String(value); + } } return null; }