// @flow /* eslint-disable flowtype/no-weak-types */ import { type Fetch, type Request, type Response } from '../fetch'; export type JSONValue = any; export type JSONRequest = {| cache?: $PropertyType, credentials?: $PropertyType, data: JSONValue, headers: { 'Content-Type': 'application/json', Accept: 'application/json', [string]: any, }, integrity?: $PropertyType, keepalive?: $PropertyType, method?: $PropertyType, mode?: $PropertyType, redirect?: $PropertyType, referrer?: $PropertyType, referrerPolicy?: $PropertyType, url: $PropertyType, window?: $PropertyType, |}; export type JSONResponse = {| data: JSONValue, headers: $PropertyType, ok: $PropertyType, redirected: $PropertyType, status: $PropertyType, statusText: $PropertyType, trailer: $PropertyType, type: $PropertyType, url: $PropertyType, |}; export function createJSONRequest({ headers, data = null, ...params }: {| ...$Rest, data?: $PropertyType, headers?: { [string]: any, }, |}): JSONRequest { return { data, headers: { Accept: 'application/json', 'Content-Type': 'application/json', ...headers, }, ...params, }; } export function createJSONResponse({ ok = true, headers = {}, redirected = false, status = 200, statusText = 'OK', type = 'basic', data = undefined, trailer = Promise.resolve(), ...params }: $Shape): JSONResponse { return { ok, headers, redirected, status, statusText, type, data, trailer, ...params, }; } /** * JSONCodec middleware */ export function JSONCodec() { return (next: Fetch) => async function fetch(request: JSONRequest): Promise { const { headers, data: requestData, ...requestParams } = request; const response = await next({ headers: { Accept: 'application/json', 'Content-Type': 'application/json', ...headers, }, ...(requestData ? { body: JSON.stringify(requestData) } : {}), ...requestParams, }); const data = await response.json(); return { data, headers: response.headers, ok: response.ok, redirected: response.redirected, status: response.status, statusText: response.statusText, trailer: response.trailer, type: response.type, url: response.url, }; }; }