import {z} from 'zod' export type Sort = {field?: string | undefined, sortOrder?: ('ASC' | 'DESC') | undefined}; export type SearchRequest = {query?: string | undefined, pageSize?: number | undefined, offsetMark?: string | undefined, sorts?: Array | undefined, historical?: boolean | undefined, resultLevel?: string | undefined}; export type CreateApiSearchArgs = {body: SearchRequest}; export type CreateApiSearchOptions = {baseUrl: string, apiKeyScheme?: string | undefined, fetch?: typeof fetch | undefined}; export const searchResult = z.object({title: z.string().optional(), packageId: z.string().optional(), granuleId: z.string().optional(), lastModified: z.string().optional(), governmentAuthor: z.array(z.string()).optional(), dateIssued: z.string().optional(), collectionCode: z.string().optional(), resultLink: z.string().optional(), dateIngested: z.string().optional(), download: z.record(z.string(), z.string()).optional(), relatedLink: z.string().optional()}); export const searchResponse = z.object({results: z.array(searchResult).optional(), offsetMark: z.string().optional(), count: z.number().int().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 }; /** * This service can be used to query the GovInfo search engine and return results that are the equivalent to what is returned by the main user interface. You can use field operators, such as congress, publishdate, branch, and others to construct complex queries that will return only matching documents. For additional information, please see our search service overview. * * POST /search */ export const createApiSearch = async (args: CreateApiSearchArgs, options: CreateApiSearchOptions) => { const {baseUrl, fetch: fetchFn = fetch, apiKeyScheme} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (apiKeyScheme !== undefined) query.set("api_key", apiKeyScheme) const url = `${baseUrl.replace(/\/+$/, '')}/search${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(searchResponse, await res.json()) };