( contract: C, input: ApiClientRequest<C> )
| 162 | } |
| 163 | |
| 164 | export async function requestJson<C extends AnyApiRouteContract>( |
| 165 | contract: C, |
| 166 | input: ApiClientRequest<C> |
| 167 | ): Promise<ContractJsonResponse<C>> { |
| 168 | if (contract.response.mode !== 'json') { |
| 169 | throw new Error(`Contract ${contract.method} ${contract.path} does not declare a JSON response`) |
| 170 | } |
| 171 | |
| 172 | const parsedParams = parseOptionalSchema(contract.params, input.params) |
| 173 | const parsedQuery = parseOptionalSchema(contract.query, input.query) |
| 174 | const parsedBody = parseOptionalSchema(contract.body, input.body) |
| 175 | const parsedHeaders = parseOptionalSchema(contract.headers, input.headers) |
| 176 | |
| 177 | const url = appendQuery(replacePathParams(contract.path, parsedParams), parsedQuery) |
| 178 | const hasBody = parsedBody !== undefined && contract.method !== 'GET' |
| 179 | |
| 180 | const response = await fetch(url, { |
| 181 | method: contract.method, |
| 182 | headers: buildHeaders(parsedHeaders, hasBody), |
| 183 | body: hasBody ? JSON.stringify(parsedBody) : undefined, |
| 184 | signal: input.signal, |
| 185 | }) |
| 186 | |
| 187 | const { parsed, raw } = await readResponseBody(response) |
| 188 | if (!response.ok) { |
| 189 | throw new ApiClientError({ |
| 190 | status: response.status, |
| 191 | message: messageFromErrorBody(parsed, `Request failed with ${response.status}`), |
| 192 | body: parsed, |
| 193 | rawBody: raw, |
| 194 | code: codeFromErrorBody(parsed), |
| 195 | }) |
| 196 | } |
| 197 | |
| 198 | try { |
| 199 | return contract.response.schema.parse(parsed) as ContractJsonResponse<C> |
| 200 | } catch (error) { |
| 201 | if (isSchemaValidationError(error)) { |
| 202 | throw new ApiClientError({ |
| 203 | status: response.status, |
| 204 | message: 'Response failed contract validation', |
| 205 | body: parsed, |
| 206 | rawBody: raw, |
| 207 | }) |
| 208 | } |
| 209 | throw error |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | export async function requestRaw<C extends AnyApiRouteContract>( |
| 214 | contract: C, |
no test coverage detected