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

adnf

Package Overview
Dependencies
Maintainers
0
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

adnf

**A Dog Named Fetch** - A strict, tiny typescript fetch wrapper.


Version published
Weekly downloads
5
decreased by-16.67%
Maintainers
0
Weekly downloads
 
Created
Source

🐕 ADNF

A Dog Named Fetch - A strict, tiny typescript fetch wrapper.

Overview

import { fetch } from 'adnf'

const result = await fetch<User>('/me') // Result<User, unknown>

result.user // undefined | User

if (result.success) {
  result.user satisfies User
}

The FetchResult

The fetch function has 3 result types. The FetchResult<V, E> type describes all three result types:

  • Success<V>: Fetch was successful
  • ErrResponse<E>: Fetch returned response but with error status code
  • Err: No response. Strict error thrown, network error, fetch aborted

Additionally FetchResult extends a rust inspired Result wrapper proving a useful API.

const result = await fetch<Flower | null, 'NoFlower'>('/flower') // FetchResult<Flower[], "NoFlower">

// Unwrap your value
result.unwrap() // (throws Error) | Flower | null
result.notNullable() // (throws Error) | Flower

// Response data
result.data // Flower | null | 'NoFlower'

// Success data
if (result.success) {
  result // Success<Flower[]>
  result.value // Flower[]
}

// Error cases
if (result.failed) {
  if (result.response) return result // ErrResponse

  // Error response
  result.type // alias for errorType
  result.errorType // "NoFlower" | null | undefined

  result.error // the thrown Error object
  result.message // string
}

result.aborted // fetch was aborted
result.timeout // fetch was aborted due to a timeout
result.resolved // fetch was able to resolve to a request

Extend fetchers

You can use the maker functions withOptions, withResource, withBase and withFetch to sequentially extend a fetch.

import { fetch, withBase } from 'adnf'

// base fetch config
const baseFetch = withOptions(fetch, { cache: 'no-cache' })
const apiFetch = withBase(baseFetch, '/api')
const authFetch = withOptions(apiFetch, options => ({
  headers: { Authorization: localStorage.get('token') },
}))

// Use `withMethods` to extend your fetch with http methods
const auth = withMethods(authFetch)

await auth.get('/me')

Reference

Fetchers

fetch

The ResultFetch returning a FetchResult

import { fetch } from "adnf"

// ResultFetch
const result = fetch(
  resource: string,
  options: RequestInit & {
    fetch // fetch implementation, default: window.fetch
    strict: boolean // default: true
    timeout: number // timeout in ms. returns "Err" with timeout set to true
    group: AbortControllerGroup
    abortPrevious: boolean // aborts all previous fetches in provided AbortControllerGroup
    data: object // json body data
    params: Record<string, any> // search params
    form: FormData | FormDataRecord
    files: FormDataRecord
  }
)


result satisfies FetchResult
debugFetch

A fetch function that logs fetches. Does not perform the fetch.

import { debugFetch } from 'adnf'

debugFetch('/user') // logs fetch to console

Makers

withMethods

Extends your fetch with http methods. Note that this does not return a fetch signature but an object of fetches, meaning it can not be passed to other makers. Do this last.

import { fetch, withMethods } from 'adnf'

const methods = withMethods(fetch)

methods.get('/') // fetch("/", { method: "get" })
methods.post('/') // fetch("/", { method: "post" })
withResource & withBase

Rewrite your fetch resource

withResource(fetch, '/workspace')
// same as: withResource(fetch, (resource) => resource + "/workspace")

withBase(fetch, '/api')
// same as: withResource(fetch, (resource) => "/api" + resource)
withOptions

Extend your fetch options

const noCacheFetch = withOptions(fetch, { cache: 'no-cache' })
const cacheFetch = withOptions(noCacheFetch, { cache: 'default' }) // overwrites cache

// pass a callback for fresh on-fetch options
const auth = withOptions(noCacheFetch, options => ({
  headers: { Authorization: localStorage.get('token') },
}))
withDeclarations

Declares fetches instead of running them immediately. Helps with prepared fetches, creating services and generating an cache identifier key.

import { fetch, withDeclarations, params } from 'adnf'

const declare = withDeclarations(fetch)

// Declare GET fetch

const getUser = (id: string) => declare<{}, 'Unauthorized'>('/user', { params: { id } })

const declaration = getUser('a')

declaration.key // /user?id=a
declaration.fetch() // run fetch as usual

declare('/user', { params: { id } }).key // /user?id=a
declare('/user', () => ({ params: { id } })).key // /user
declare(params('/user', { id })).key // /user?id=a
declare(`/user/${id}`).key // /user/a
declare(['/user', id]).key // /user/a

// Declare mutative fetch

import { params } from 'adnf'

const editFlower = (id: string) =>
  declare<{}, 'Unauthorized', Partial<Flower>>(params('/flower', { id }), flower => ({
    method: 'put',
    data: flower,
  }))

const declaration = editFlower('tulip')

declaration.key // /flower?id=tulip

For mutations where some arguments should not be part of the cache key, declare can be provided a function that will build options after the key was generated. Note that this will force your fetch to be a mutate method i.e. post, put, delete or patch.

const fetchUser = declare<User, void, { id: string }>('/user', args => ({
  params: { id: args.id },
}))

declaration.key // "@"/user",#params,,"

const declaration = fetchUser.fetch({ id: 'a' }) // fetch('/user', { method: "post", params: { id: 'a' }, ... })
withFetch

Create fetch creators that run sequentially when initiating a fetch. Used to create a fetch that is dependent on the next fetch. Used internally to implement other makers. Read more about fetch dependency below.

const newFetch = withFetch(fetch, fetch => (resource, options) => fetch(resource, { ...options }))

Helpers

createAbortGroup

Creates a grouped abort controller.

import { createAbortGroup } from 'adnf'

const group = createAbortGroup()

// use abortPrevious for grouped fetched before fetch
fetch.post('/upload', { abortPrevious: true, group }) // Err
fetch.post('/upload', { abortPrevious: true, group }) // Err
fetch.post('/upload', { abortPrevious: true, group }) // Success

// or manually
group.cancel()
params

Merge/replace search params to resource or complete URL. Will respect provided format.

params(path: string, params, replace: boolean)

params('/user', { id: 'a' })
// /user?id=a
params('https://github.com/user?id=a&for=b', { id: 'b' })
// https://github.com/user?id=b&for=b
params('https://github.com/user?id=a&for=b', { id: 'b' }, true)
// https://github.com/user?id=b

Recipes

Fetch logger
import { fetch, useFetch } from 'adnf'

const loggedFetch = useFetch(fetch, fetch => (resource, options) => {
  console.log(options.method ?? 'get', resource, options)
  return fetch(resource, options)
})

Resources

Fetch dependency

Dependent fetches follow other fetches. Maker functions return a special fetch that maintains a specific order. When using withFetch the fetch provided in the creator is the next fetch. Your fetch creators are made "dependent" and run in sequence once you have initiated a fetch.

const a = withFetch(fetch, fetch => {
  console.log('init: a')
  return (resource, options) => {
    console.log('fetch: a')
    return fetch(resource, options)
  }
})

const b = withFetch(a, fetch => {
  console.log('init: b')
  return (resource, options) => {
    console.log('fetch: b')
    return fetch(resource, options)
  }
})

const c = withFetch(c, fetch => {
  console.log('init: c')
  return (resource, options) => {
    console.log('fetch: c')
    return fetch(resource, options)
  }
})

c()
// init: c
// init: b
// init: a
// fetch: a
// fetch: b
// fetch: c
ADNF + SWR

See repo resources

FAQs

Package last updated on 12 Jul 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

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