import {z} from 'zod' export type GetApiV1SpeciesUsageKeyNameArgs = {usageKey: number}; export type GetApiV1SpeciesUsageKeyNameOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const parsedName = z.object({key: z.number().int().optional(), scientificName: z.string().optional(), type: z.enum(["SCIENTIFIC", "VIRUS", "HYBRID", "INFORMAL", "CULTIVAR", "CANDIDATUS", "OTU", "DOUBTFUL", "PLACEHOLDER", "NO_NAME", "BLACKLISTED"]).optional(), genusOrAbove: z.string().optional(), infraGeneric: z.string().optional(), specificEpithet: z.string().optional(), infraSpecificEpithet: z.string().optional(), cultivarEpithet: z.string().optional(), strain: z.string().optional(), notho: z.enum(["GENERIC", "INFRAGENERIC", "SPECIFIC", "INFRASPECIFIC"]).optional(), authorship: z.string().optional(), year: z.string().optional(), bracketAuthorship: z.string().optional(), bracketYear: z.string().optional(), sensu: z.string().optional(), parsed: z.boolean().optional(), parsedPartially: z.boolean().optional(), nomStatus: z.string().optional(), remarks: z.string().optional(), canonicalName: z.string().optional(), canonicalNameWithMarker: z.string().optional(), canonicalNameComplete: z.string().optional(), rankMarker: z.enum(["DOMAIN", "SUPERKINGDOM", "KINGDOM", "SUBKINGDOM", "INFRAKINGDOM", "SUPERPHYLUM", "PHYLUM", "SUBPHYLUM", "INFRAPHYLUM", "SUPERCLASS", "CLASS", "SUBCLASS", "INFRACLASS", "PARVCLASS", "SUPERLEGION", "LEGION", "SUBLEGION", "INFRALEGION", "SUPERCOHORT", "COHORT", "SUBCOHORT", "INFRACOHORT", "MAGNORDER", "SUPERORDER", "GRANDORDER", "ORDER", "SUBORDER", "INFRAORDER", "PARVORDER", "SUPERFAMILY", "FAMILY", "SUBFAMILY", "INFRAFAMILY", "SUPERTRIBE", "TRIBE", "SUBTRIBE", "INFRATRIBE", "SUPRAGENERIC_NAME", "GENUS", "SUBGENUS", "INFRAGENUS", "SECTION", "SUBSECTION", "SERIES", "SUBSERIES", "INFRAGENERIC_NAME", "SPECIES_AGGREGATE", "SPECIES", "INFRASPECIFIC_NAME", "GREX", "SUBSPECIES", "CULTIVAR_GROUP", "CONVARIETY", "INFRASUBSPECIFIC_NAME", "PROLES", "RACE", "NATIO", "ABERRATION", "MORPH", "VARIETY", "SUBVARIETY", "FORM", "SUBFORM", "PATHOVAR", "BIOVAR", "CHEMOVAR", "MORPHOVAR", "PHAGOVAR", "SEROVAR", "CHEMOFORM", "FORMA_SPECIALIS", "CULTIVAR", "STRAIN", "OTHER", "UNRANKED"]).optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Parsed name usage by id * * GET /v1/species/{usageKey}/name */ export const getApiV1SpeciesUsageKeyName = async (args: GetApiV1SpeciesUsageKeyNameArgs, options?: GetApiV1SpeciesUsageKeyNameOptions) => { const {baseUrl = "https://api.gbif.org", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/v1/species/${encodeURIComponent(String(args.usageKey))}/name${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(parsedName, await res.json()) };