Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fetchmap

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fetchmap - npm Package Compare versions

Comparing version 0.0.15 to 0.0.16

6

dist/index.js

@@ -6,4 +6,4 @@ function createFetchmap(fetch) {

const validationErrorFailure = (validationError, status) => failure({ validationError, status });
const mapFun = async (response, map) => typeof map === 'function'
? map(response)
const mapFun = async (response, map) => 'noBody' in map
? map.noBody(response)
: 'json' in map

@@ -25,3 +25,3 @@ ? map.json(await response.json(), response)

try {
const validated = await mapFun(response, (_b = (_a = map[status]) !== null && _a !== void 0 ? _a : (isOk ? map.ok : map.notOk)) !== null && _b !== void 0 ? _b : success);
const validated = await mapFun(response, (_b = (_a = map[status]) !== null && _a !== void 0 ? _a : (isOk ? map.ok : map.notOk)) !== null && _b !== void 0 ? _b : { noBody: success });
return validated.tag === 'success'

@@ -28,0 +28,0 @@ ? (isOk ? success : serverErrorFailure)(validated.success)

{
"name": "fetchmap",
"version": "0.0.15",
"version": "0.0.16",
"description": "Non-throwing fetch wrapper",

@@ -5,0 +5,0 @@ "sideEffects": false,

@@ -42,8 +42,18 @@ # fetchmap

const success = <T>(value: T) => ({ tag: 'success', success: value } as const)
const fetchmap = createFetchmap(fetch)
const json_success = await fetchmap({ ok: 'json' }, 'https://localhost:5005/json')
const mock_data_validator = (data: unknown) => success(data)
const json_success = await fetchmap(
{ ok: { json: mock_data_validator } },
'https://localhost:5005/json'
)
expect(json_success).toEqual({ tag: 'success', success: { some: 'data' } })
const json_success_only_200 = await fetchmap({ 200: 'json' }, 'https://localhost:5005/json')
const json_success_only_200 = await fetchmap(
{ 200: mock_data_validator },
'https://localhost:5005/json'
)
expect(json_success_only_200).toEqual({ tag: 'success', success: { some: 'data' } })

@@ -50,0 +60,0 @@

@@ -111,123 +111,203 @@ type OkStatus =

}
type SuccessResult<Success> = {
readonly tag: 'success'
readonly success: Success
}
/**
* Creates a `fetchmap` from third-party `fetch` function.
*
* @param fetch A `fetch`-like function. Should take two parameters and return a `Promise<BasicResponse>`.
* `BasicResponse` requires only `status`, `arrayBuffer`, `blob`, `formData`, `json` and `text`
* properties of standard `Response` type to be defined.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
export function createFetchmap<Fetch extends (input: any, init?: any) => Promise<BasicResponse>>(
fetch: Fetch
) {
type Input = Parameters<Fetch>[0]
type Init = Parameters<Fetch>[1]
type FailureResult<Failure> = {
readonly tag: 'failure'
readonly failure: Failure
}
type SuccessResult<Success> = {
readonly tag: 'success'
readonly success: Success
}
type SuccessOf<ResultLike> = ResultLike extends SuccessResult<infer S> ? S : never
type FailureOf<ResultLike> = ResultLike extends FailureResult<infer F> ? F : never
type FailureResult<Failure> = {
readonly tag: 'failure'
readonly failure: Failure
}
type Result<Success = unknown, Failure = unknown> = SuccessResult<Success> | FailureResult<Failure>
type SuccessOf<ResultLike> = ResultLike extends SuccessResult<infer S> ? S : never
type FailureOf<ResultLike> = ResultLike extends FailureResult<infer F> ? F : never
type MapTextResponse<Resp extends BasicResponse> = {
readonly text: (text: string, response: Resp) => Result
}
type Result<Success = unknown, Failure = unknown> =
| SuccessResult<Success>
| FailureResult<Failure>
type MapJsonResponse<Resp extends BasicResponse> = {
readonly json: (json: unknown, response: Resp) => Result
}
type MapResponseBody<Resp extends BasicResponse> =
| { readonly text: (text: string, response: Resp) => Result }
| { readonly json: (json: unknown, response: Resp) => Result }
| { readonly blob: (blob: Blob, response: Resp) => Result }
| { readonly arrayBuffer: (arrayBuffer: ArrayBuffer, response: Resp) => Result }
| { readonly formData: (formData: FormData, response: Resp) => Result }
type MapBlobResponse<Resp extends BasicResponse> = {
readonly blob: (blob: Blob, response: Resp) => Result
}
type MapResponse<Resp extends BasicResponse> =
| MapResponseBody<Resp>
| ((response: Resp) => Result)
type MapArrayBufferResponse<Resp extends BasicResponse> = {
readonly arrayBuffer: (arrayBuffer: ArrayBuffer, response: Resp) => Result
}
type MultiMapResponse<Resp extends BasicResponse> = {
readonly [code: number]: MapResponse<Resp>
readonly ok: MapResponse<Resp>
readonly notOk: MapResponse<Resp>
}
type MapFormDataResponse<Resp extends BasicResponse> = {
readonly formData: (formData: FormData, response: Resp) => Result
}
type MapResultOf<Resp extends BasicResponse, Map extends MapResponse<Resp>> = Map extends (
r: Resp
) => infer T
type MapNoBodyResponse<Resp extends BasicResponse> = { readonly noBody: (response: Resp) => Result }
type MapResponse<Resp extends BasicResponse> =
| MapTextResponse<Resp>
| MapJsonResponse<Resp>
| MapBlobResponse<Resp>
| MapArrayBufferResponse<Resp>
| MapFormDataResponse<Resp>
| MapNoBodyResponse<Resp>
type MultiMapResponse<Resp extends BasicResponse> = {
readonly [code: number]: MapResponse<Resp>
readonly ok: MapResponse<Resp>
readonly notOk: MapResponse<Resp>
}
type MapResultOf<Resp extends BasicResponse, Map extends MapResponse<Resp>> = Map extends {
readonly noBody: (r: Resp) => infer T
}
? T
: Map extends {
readonly text: (b: string, r: Resp) => infer T
}
? ('json' | 'blob' | 'arrayBuffer' | 'formData') & keyof Map extends never
? T
: Map extends { readonly text: (b: string, r: Resp) => infer T }
: never
: Map extends { readonly json: (b: unknown, r: Resp) => infer T }
? ('text' | 'blob' | 'arrayBuffer' | 'formData') & keyof Map extends never
? T
: Map extends { readonly json: (b: unknown, r: Resp) => infer T }
: never
: Map extends { readonly blob: (b: Blob, r: Resp) => infer T }
? ('json' | 'text' | 'arrayBuffer' | 'formData') & keyof Map extends never
? T
: Map extends { readonly blob: (b: Blob, r: Resp) => infer T }
: never
: Map extends { readonly arrayBuffer: (b: ArrayBuffer, r: Resp) => infer T }
? ('json' | 'blob' | 'text' | 'formData') & keyof Map extends never
? T
: Map extends { readonly arrayBuffer: (b: ArrayBuffer, r: Resp) => infer T }
: never
: Map extends { readonly formData: (b: FormData, r: Resp) => infer T }
? ('json' | 'blob' | 'arrayBuffer' | 'text') & keyof Map extends never
? T
: Map extends { readonly formData: (b: FormData, r: Resp) => infer T }
? T
: never
: never
type OkKeys<Resp extends BasicResponse, Map extends MultiMapResponse<Resp>> = (OkStatus | 'ok') &
keyof Map
type OkKeys<Resp extends BasicResponse, Map extends MultiMapResponse<Resp>> = (OkStatus | 'ok') &
keyof Map
type NotOkKeys<
Resp extends BasicResponse,
Map extends MultiMapResponse<Resp>,
Keys = keyof Map
> = Keys extends OkStatus | 'ok' ? never : Keys
type NotOkKeys<
Resp extends BasicResponse,
Map extends MultiMapResponse<Resp>,
Keys = keyof Map
> = Keys extends OkStatus | 'ok' ? never : Keys
type FetchSuccessResult<
Resp extends BasicResponse,
Map extends MultiMapResponse<Resp>,
SuccessKeys extends keyof Map = OkKeys<Resp, Map>
> = SuccessResult<
Map[SuccessKeys] extends MapResponse<Resp>
? SuccessOf<MapResultOf<Resp, Map[SuccessKeys]>>
type FetchFailureResult<
Resp extends BasicResponse,
Map extends MultiMapResponse<Resp>,
FailureKeys extends keyof Map = NotOkKeys<Resp, Map>,
SuccessKeys extends keyof Map = OkKeys<Resp, Map>
> = FailureResult<
| {
readonly status: number
readonly validationError: FailureOf<
| (Map[SuccessKeys] extends MapJsonResponse<Resp>
? ReturnType<Map[SuccessKeys]['json']>
: Map[SuccessKeys] extends MapBlobResponse<Resp>
? ReturnType<Map[SuccessKeys]['blob']>
: Map[SuccessKeys] extends MapTextResponse<Resp>
? ReturnType<Map[SuccessKeys]['text']>
: Map[SuccessKeys] extends MapFormDataResponse<Resp>
? ReturnType<Map[SuccessKeys]['formData']>
: Map[SuccessKeys] extends MapArrayBufferResponse<Resp>
? ReturnType<Map[SuccessKeys]['arrayBuffer']>
: Map[SuccessKeys] extends MapNoBodyResponse<Resp>
? ReturnType<Map[SuccessKeys]['noBody']>
: Map[SuccessKeys] extends MapResponse<Resp>
? MapResultOf<Resp, Map[SuccessKeys]>
: never)
| (Map[FailureKeys] extends MapJsonResponse<Resp>
? ReturnType<Map[FailureKeys]['json']>
: Map[FailureKeys] extends MapBlobResponse<Resp>
? ReturnType<Map[FailureKeys]['blob']>
: Map[FailureKeys] extends MapTextResponse<Resp>
? ReturnType<Map[FailureKeys]['text']>
: Map[FailureKeys] extends MapFormDataResponse<Resp>
? ReturnType<Map[FailureKeys]['formData']>
: Map[FailureKeys] extends MapArrayBufferResponse<Resp>
? ReturnType<Map[FailureKeys]['arrayBuffer']>
: Map[FailureKeys] extends MapNoBodyResponse<Resp>
? ReturnType<Map[FailureKeys]['noBody']>
: Map[FailureKeys] extends MapResponse<Resp>
? MapResultOf<Resp, Map[FailureKeys]>
: never)
>
}
| {
readonly serverError: SuccessOf<
Map[FailureKeys] extends MapJsonResponse<Resp>
? ReturnType<Map[FailureKeys]['json']>
: Map[FailureKeys] extends MapBlobResponse<Resp>
? ReturnType<Map[FailureKeys]['blob']>
: Map[FailureKeys] extends MapTextResponse<Resp>
? ReturnType<Map[FailureKeys]['text']>
: Map[FailureKeys] extends MapFormDataResponse<Resp>
? ReturnType<Map[FailureKeys]['formData']>
: Map[FailureKeys] extends MapArrayBufferResponse<Resp>
? ReturnType<Map[FailureKeys]['arrayBuffer']>
: Map[FailureKeys] extends MapNoBodyResponse<Resp>
? ReturnType<Map[FailureKeys]['noBody']>
: Map[FailureKeys] extends MapResponse<Resp>
? MapResultOf<Resp, Map[FailureKeys]>
: never
>
}
| { readonly clientError: unknown }
| { readonly mapError: unknown }
>
type FetchSuccessResult<
Resp extends BasicResponse,
Map extends MultiMapResponse<Resp>,
SuccessKeys extends keyof Map = OkKeys<Resp, Map>
> = SuccessResult<
SuccessOf<
Map[SuccessKeys] extends MapJsonResponse<Resp>
? ReturnType<Map[SuccessKeys]['json']>
: Map[SuccessKeys] extends MapBlobResponse<Resp>
? ReturnType<Map[SuccessKeys]['blob']>
: Map[SuccessKeys] extends MapTextResponse<Resp>
? ReturnType<Map[SuccessKeys]['text']>
: Map[SuccessKeys] extends MapFormDataResponse<Resp>
? ReturnType<Map[SuccessKeys]['formData']>
: Map[SuccessKeys] extends MapArrayBufferResponse<Resp>
? ReturnType<Map[SuccessKeys]['arrayBuffer']>
: Map[SuccessKeys] extends MapNoBodyResponse<Resp>
? ReturnType<Map[SuccessKeys]['noBody']>
: Map[SuccessKeys] extends MapResponse<Resp>
? MapResultOf<Resp, Map[SuccessKeys]>
: never
>
>
type FetchFailureResult<
Resp extends BasicResponse,
Map extends MultiMapResponse<Resp>,
FailureKeys extends keyof Map = NotOkKeys<Resp, Map>
> = FailureResult<
| ((
Map[keyof Map] extends MapResponse<Resp>
? FailureOf<MapResultOf<Resp, Map[keyof Map]>>
: never
) extends never
? never
: {
readonly status: number
readonly validationError: Map[keyof Map] extends MapResponse<Resp>
? FailureOf<MapResultOf<Resp, Map[keyof Map]>>
: never
})
| {
readonly serverError: Map[FailureKeys] extends MapResponse<Resp>
? SuccessOf<MapResultOf<Resp, Map[FailureKeys]>>
: never
}
| { readonly clientError: unknown }
| { readonly mapError: unknown }
>
type FetchResult<
Resp extends BasicResponse,
PartialMap extends Partial<MultiMapResponse<Resp>>,
Map extends MultiMapResponse<Resp> = {
readonly [Key in keyof PartialMap | 'ok' | 'notOk']: PartialMap[Key] extends MapResponse<Resp>
? PartialMap[Key]
: { readonly noBody: (response: Resp) => SuccessResult<Resp> }
}
> = FetchSuccessResult<Resp, Map> | FetchFailureResult<Resp, Map>
type FetchResult<
Resp extends BasicResponse,
PartialMap extends Partial<MultiMapResponse<Resp>>,
Map extends MultiMapResponse<Resp> = {
readonly [Key in keyof PartialMap | 'ok' | 'notOk']: PartialMap[Key] extends MapResponse<Resp>
? PartialMap[Key]
: (response: Resp) => SuccessResult<Resp>
}
> = FetchSuccessResult<Resp, Map> | FetchFailureResult<Resp, Map>
type PrettyType<V> = Extract<{ [K in keyof V]: V[K] }, unknown>
type PrettyType<V> = Extract<{ [K in keyof V]: V[K] }, unknown>
/**
* Creates a `fetchmap` from third-party `fetch` function.
*
* @param fetch A `fetch`-like function. Should take two parameters and return a `Promise<BasicResponse>`.
* `BasicResponse` requires only `status`, `arrayBuffer`, `blob`, `formData`, `json` and `text`
* properties of standard `Response` type to be defined.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
export function createFetchmap<Fetch extends (input: any, init?: any) => Promise<BasicResponse>>(
fetch: Fetch
) {
type Input = Parameters<Fetch>[0]
type Init = Parameters<Fetch>[1]

@@ -242,4 +322,4 @@ const success = <T>(value: T) => ({ tag: 'success', success: value } as const)

const mapFun = async <Resp extends BasicResponse>(response: Resp, map: MapResponse<Resp>) =>
typeof map === 'function'
? map(response)
'noBody' in map
? map.noBody(response)
: 'json' in map

@@ -286,7 +366,6 @@ ? map.json(await response.json(), response)

*/
function fetchmap<Map extends Partial<MultiMapResponse<Awaited<ReturnType<Fetch>>>>>(
map: Map,
input: Input,
init?: Init
): Promise<PrettyType<FetchResult<Awaited<ReturnType<Fetch>>, Map>>>
function fetchmap<
Response extends Awaited<ReturnType<Fetch>>,
Map extends Partial<MultiMapResponse<Response>>
>(map: Map, input: Input, init?: Init): Promise<PrettyType<FetchResult<Response, Map>>>

@@ -306,3 +385,3 @@ function fetchmap(

response,
map[status] ?? (isOk ? map.ok : map.notOk) ?? success
map[status] ?? (isOk ? map.ok : map.notOk) ?? { noBody: success }
)

@@ -309,0 +388,0 @@

@@ -72,3 +72,3 @@ import { spawn } from 'child_process'

test('ok, ok is function', async () => {
const result = await fetchmap({ ok: (r) => success(r.status) }, url('json'))
const result = await fetchmap({ ok: { noBody: (r) => success(r.status) } }, url('json'))
expect(result).toEqual<typeof result>(success(200))

@@ -117,7 +117,7 @@ })

test('fail, mapError, ok is function', async () => {
const ok = () => {
const noBody = () => {
throw new Error('what?')
}
const result = await fetchmap({ ok }, url('text'))
const result = await fetchmap({ ok: { noBody } }, url('text'))
expect(result).toEqual<typeof result>(failure({ mapError: new Error('what?') }))

@@ -157,3 +157,6 @@ })

test('fail, serverError, notOk is function', async () => {
const result = await fetchmap({ notOk: (r) => success(r.status) }, url('server-error'))
const result = await fetchmap(
{ notOk: { noBody: (r) => success(r.status) } },
url('server-error')
)
expect(result).toEqual<typeof result>(failure({ serverError: 500 }))

@@ -160,0 +163,0 @@ })

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc