'use strict'; const Either = require('fp-ts/Either'); const _function = require('fp-ts/function'); const ReaderTaskEither = require('fp-ts/ReaderTaskEither'); const Tuple = require('fp-ts/Tuple'); const IO = require('fp-ts/IO'); const TaskEither = require('fp-ts/TaskEither'); const BASE_URL = Symbol("BU"); const U = Symbol("U"); const SIGNAL = Symbol("SG"); const RETRY = Symbol("R"); const REDIRECT = Symbol("RD"); const toRecord = (headers) => { if (Array.isArray(headers)) { return Object.fromEntries(headers); } else if (headers instanceof Headers) { const obj = {}; headers.forEach((v, k) => obj[k] = v); return obj; } else { return headers; } }; const merge = (into, from) => ({ ...toRecord(into), ...toRecord(from) }); const withHeaders = (headers) => ReaderTaskEither.local( Tuple.mapSnd(({ headers: original, ...rest }) => ({ headers: merge(headers, original ?? {}), ...rest })) ); const mkFormData = (form) => Object.entries(form).reduce((m, [k, v]) => { if (typeof v === "string") { m.set(k, v); } else if (v instanceof Blob) { m.set(k, v); } else { m.set(k, v.blob, v.filename); } return m; }, new FormData()); const collectFormable = (form) => { const obj = {}; form.forEach((v, k) => obj[k] = v); return obj; }; const withForm = (form) => ( // TODO Allowing setting the value to `null` to explicitly remove the existing value ReaderTaskEither.local( Tuple.mapSnd( ({ body, ...rest }) => body instanceof FormData ? { body: mkFormData({ ...form, ...collectFormable(body) }), ...rest } : { body: mkFormData(form), ...rest } ) ) ); function withJSONBody(json, replacer, space) { return ReaderTaskEither.local( Tuple.mapSnd((x) => ({ body: JSON.stringify(json, replacer, space), ...x })) ); } function withJSON(json, replacer, space) { return _function.flow( withHeaders({ "Content-Type": "application/json" }), withJSONBody(json, replacer, space) ); } const withBlob = (blob) => ReaderTaskEither.local(Tuple.mapSnd((x) => ({ body: blob, ...x }))); const withReadableStream = (stream) => ReaderTaskEither.local(Tuple.mapSnd((x) => ({ body: stream, duplex: "half", ...x }))); function withSignal(signal, mapError = bail) { return ReaderTaskEither.local( Tuple.mapSnd( (x) => ({ signal, [SIGNAL]: mapError, ...x }) ) ); } function withTimeout(milliseconds, mapError = bail) { return (m) => { let controller; return _function.pipe( ReaderTaskEither.rightIO(() => { controller = new AbortController(); return setTimeout(() => controller.abort(), milliseconds); }), ReaderTaskEither.chain( (id) => _function.pipe( m, withSignal(controller.signal, mapError), ReaderTaskEither.chainFirst(() => ReaderTaskEither.rightIO(() => clearTimeout(id))) ) ) ); }; } const guard = (refinement, otherwise) => ReaderTaskEither.chainEitherKW((a) => refinement(a) ? Either.right(a) : _function.pipe(a, otherwise, Either.left)); const when = (refinement, then) => ReaderTaskEither.chainEitherKW((a) => refinement(a) ? _function.pipe(a, then, Either.left) : Either.right(a)); const fail = (error) => _function.flow(error, ReaderTaskEither.left); const inspect = (inspector) => ReaderTaskEither.chainFirstIOK(_function.flow(inspector, IO.of)); const localE = (f) => (m) => _function.pipe( ReaderTaskEither.ask(), ReaderTaskEither.chain(_function.flow(f, ReaderTaskEither.fromEither)), ReaderTaskEither.chainW( (x) => _function.pipe( m, ReaderTaskEither.local(() => x) ) ) ); const map = (f) => ReaderTaskEither.map(f); const withMethod = (method) => ReaderTaskEither.local(Tuple.mapSnd((x) => ({ method, ...x }))); function asJSON(mapError = bail) { return _function.flow( withHeaders({ Accept: "application/json" }), ReaderTaskEither.chainTaskEitherKW((resp) => TaskEither.tryCatch(() => resp.json(), mapError)) ); } function asBlob(accept, mapError = bail) { return _function.flow( withHeaders({ Accept: accept }), ReaderTaskEither.chainTaskEitherKW((resp) => TaskEither.tryCatch(() => resp.blob(), mapError)) ); } function asArrayBuffer(mapError = bail) { return ReaderTaskEither.chainTaskEitherKW((resp) => TaskEither.tryCatch(() => resp.arrayBuffer(), mapError)); } function asText(mapError = bail) { return _function.flow( withHeaders({ Accept: "text/plain" }), ReaderTaskEither.chainTaskEitherKW((resp) => TaskEither.tryCatch(() => resp.text(), mapError)) ); } function decodeAs(codeC, mapError = bail) { return ReaderTaskEither.chainEitherKW(_function.flow(codeC.decode, Either.mapLeft(mapError))); } function decodeIO(codeC, mapError = bail) { return ReaderTaskEither.chainEitherKW( (x) => _function.pipe( codeC.decode(x), Either.mapLeft((e) => mapError(e, x)) ) ); } function decodeZod(codeC, mapError = bail) { return ReaderTaskEither.chainEitherKW((x) => { const result = codeC.safeParse(x); switch (result.success) { case true: return Either.right(result.data); case false: return Either.left(mapError(result.error, x)); } }); } function ensureStatus(predicate, mapError = bail) { return guard( (resp) => _function.pipe(resp.status, predicate), mapError ); } function withBaseURL(url, mapError = bail) { return ReaderTaskEither.local( Tuple.mapSnd( (x) => ({ [BASE_URL]: [url, mapError], ...x }) ) ); } const withURLSearchParams = (params) => ReaderTaskEither.local( Tuple.mapSnd((x) => { if (!x[U]) x[U] = {}; x[U].params = { ...params, ...x[U].params }; return x; }) ); const withPassword = (password) => ReaderTaskEither.local( Tuple.mapSnd((x) => { if (!x[U]) x[U] = {}; x[U] = { password, ...x[U] }; return x; }) ); const withUsername = (username) => ReaderTaskEither.local( Tuple.mapSnd((x) => { if (!x[U]) x[U] = {}; x[U] = { username, ...x[U] }; return x; }) ); const withPort = (port) => ReaderTaskEither.local( Tuple.mapSnd((x) => { if (!x[U]) x[U] = {}; x[U] = { port, ...x[U] }; return x; }) ); function withRedirection(redirect) { return ReaderTaskEither.local( Tuple.mapSnd((x) => { x.redirect = redirect; return x; }) ); } function retry(strategy) { return ReaderTaskEither.local( Tuple.mapSnd((x) => { if (!x[RETRY]) x[RETRY] = []; x[RETRY].push(strategy); return x; }) ); } function bail(e) { if (e instanceof Error) { throw e; } else { throw new Error(`${e}`); } } function mkRequest(mapError, fetchImpl) { return ([input, init]) => { async function f() { const b = init[BASE_URL], u = init[U], s = init[SIGNAL]; let url; if (b) { try { url = new URL(input, b[0]); } catch (e) { return Either.left(b[1](e)); } } else { try { url = new URL(input); } catch (e) { return Either.left(mapError(e)); } } if (u) { if (u.params) { url.search = new URLSearchParams(u.params).toString(); } if (u.password) { url.password = u.password; } if (u.username) { url.username = u.username; } if (u.port) { url.port = u.port.toString(); } } try { return Either.right(await (fetchImpl ?? fetch)(url.href, init)); } catch (e) { if (s && e instanceof DOMException && e.name === "AbortError") { return Either.left(s(e)); } return Either.left(mapError(e)); } } return async () => { let r = await f(), times = 0; while (r._tag === "Left") { const e = r.left, ds = init[RETRY]?.map((s) => s(e, times, init)).filter( (n) => typeof n === "number" ), delay = ds && ds.length > 0 ? Math.max(...ds) : void 0; if (delay === void 0) break; await new Promise((resolve) => setTimeout(resolve, delay)).then( async () => { r = await f(); times += 1; } ); } delete init[BASE_URL]; delete init[U]; delete init[SIGNAL]; delete init[RETRY]; delete init[REDIRECT]; return r; }; }; } const request = /* @__PURE__ */ mkRequest(bail); const runFetchM = (input, init) => (m) => m([input, init ?? {}]); const runFetchMP = (input, init) => (m) => m([input, init ?? {}])(); const runFetchMPT = (input, init) => async (m) => _function.pipe( await m([input, init ?? {}])(), Either.match(bail, _function.identity) ); const runFetchMPTL = (input, init) => (m) => async () => _function.pipe( await m([input, init ?? {}])(), Either.match(bail, _function.identity) ); const runFetchMFlipped = (m) => (input, init) => m([input, init ?? {}]); const runFetchMFlippedP = (m) => (input, init) => m([input, init ?? {}])(); const runFetchMFlippedPT = (m) => async (input, init) => _function.pipe( await m([input, init ?? {}])(), Either.match(bail, _function.identity) ); const runFetchMFlippedPTL = (m) => (input, init) => async () => _function.pipe( await m([input, init ?? {}])(), Either.match(bail, _function.identity) ); exports.asArrayBuffer = asArrayBuffer; exports.asBlob = asBlob; exports.asJSON = asJSON; exports.asText = asText; exports.bail = bail; exports.collectFormable = collectFormable; exports.decodeAs = decodeAs; exports.decodeIO = decodeIO; exports.decodeZod = decodeZod; exports.ensureStatus = ensureStatus; exports.fail = fail; exports.guard = guard; exports.inspect = inspect; exports.localE = localE; exports.map = map; exports.merge = merge; exports.mkFormData = mkFormData; exports.mkRequest = mkRequest; exports.request = request; exports.retry = retry; exports.runFetchM = runFetchM; exports.runFetchMFlipped = runFetchMFlipped; exports.runFetchMFlippedP = runFetchMFlippedP; exports.runFetchMFlippedPT = runFetchMFlippedPT; exports.runFetchMFlippedPTL = runFetchMFlippedPTL; exports.runFetchMP = runFetchMP; exports.runFetchMPT = runFetchMPT; exports.runFetchMPTL = runFetchMPTL; exports.toRecord = toRecord; exports.when = when; exports.withBaseURL = withBaseURL; exports.withBlob = withBlob; exports.withForm = withForm; exports.withHeaders = withHeaders; exports.withJSON = withJSON; exports.withJSONBody = withJSONBody; exports.withMethod = withMethod; exports.withPassword = withPassword; exports.withPort = withPort; exports.withReadableStream = withReadableStream; exports.withRedirection = withRedirection; exports.withSignal = withSignal; exports.withTimeout = withTimeout; exports.withURLSearchParams = withURLSearchParams; exports.withUsername = withUsername;