npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

reget

v0.10.3

Published

React reactive cache for any async calls, http fetching, or memory store accesses

Downloads

25

Readme

Reget https://img.shields.io/npm/v/reget.svg state npm npm

Deprecated and please migrate to datavan, which provide more features

HTTP API Accessor for React with auto-reactive-cache and middlewares. Restful React reactive cache for any async calls, http fetching, or memory store accesses.

Features

  • auto-reactive-cache

    • API results are cached and auto prune
    • AutoRunner(function) auto watch and re-run when related caches changed
    • reget.get() is synchronized function, which get cache and trigger http fetch as a side effect
  • middlewares

    • koa middleware like
    • can use middlewares to convert data, as ORM or distribute to diff cache keys
    • also work for synchronized access or localStorage or memory

How It works?

reget is simple key-value cache. During data getting, reget will call a list of middlewares if cache is missing or too old. Result from middlewares will put into the cache and notify all listeners.

You can implement koa-like middlewares to asynchronously fetch HTTP RESTful resources, worker communication or synchronously access localStorage.

Welcome to extend or hack Reget or other classes to change behaviours

Table of Contents

Http get, put, post for react component

import {connectReget} from 'reget'

function PureComponent({user}) {
  return user.name
}

export default connectReget(({userId, reget}) => {
  // assume you have setup middleware to fetch HTTP
  const user = reget.get(`user/${userId}`)
  // first get will be undefined
  // after HTTP response and cached, connectReget will be re-run
  // so, second get will get user
  return {user: user}

  // you can return null to stop child component rendering
})(PureComponent)

Setup

import {Reget, RegetProvider, compose} from 'reget'

// create reget cache and assign it with middlewares
const reget = new Reget({
  // create koa-like middlewares
  handler: compose(async ctx => {
    // fetch http based on ctx.url, body and headers
    ctx.body = await window.fetch(ctx.url, {
      body: ctx.input,
      headers: ctx.headers,
    })
  }),
})

// Assign to your React context
<RegetProvider reget={reget}>
  <MyApp />
</RegetProvider>

Comparison

Compare to Flux/Redux

  • Built-in support for async, http, promise call
  • Designed for big state tree. Cached state will be garbage collected
  • No need to define constants (you can define url generate functions)

Compare to Relay/Falcor

  • Can call any http endpoint (Restful or php page or even image)
  • Flexible code your middleware, data conversion and normalization in js side

Server Rendering

reget.serverRender(reget => {
  return ReactDOMServer.renderToString(<RegetProvider reget={reget}><App /></RegetProvider>)
})
.then(outputHtml => {
  console.log(outputHtml)
})

// transfer data to client
const json = JSON.stringify(reget.getCache())
// -------
const isoData = JSON.parse(json)

// client side
const browserReget = new Reget({
  // handler()
})
browserReget.setCache(isoData)
ReactDOM.render(<RegetProvider reget={browserReget}><App /></RegetProvider>, dom)

You can use iso to ship data to browser

Use Reget alone

Reget can be a

import {Reget, compose, mount} from 'reget'

import browserMiddleware from 'reget/lib/middlewares/browser'
import cacheMiddleware from 'reget/lib/middlewares/cache'
import localStorageMiddleware from 'reget/lib/middlewares/localStorage'
import cookieMiddleware from 'reget/lib/middlewares/cookie'
import koaCookieMiddleware from 'reget/lib/middlewares/koaCookie'


const reget = new Reget({
  handler: compose(
    mount('memory', cacheMiddleware()),
    // or
    {mount: 'memory', handler: cacheMiddleware()},

    {
      route: 'abc/:key',
      async get(ctx, next) {
        // ...
      },
      async put(ctx, next) {
        // ...
      },
      async post(ctx, next) {
        // ...
      },
    }
  ),
})

reget.put('memory/foo', 'bar')
reget.get('memory/foo') === 'bar'

API

reget will create a CallContext instance and pass down to middlewares

CallContext fields, getters and setters

// ctx fields
reget: [Object] // caller reget object. Middleware is valid to call middlewares stack again, (prevent recursive problem on your own).
cache: [Object] // reget's cache. middleware can use this to safely put data into cache

// request related fields
method: 'GET' // default 'GET'
url: '/' // url with query string, default '/'
path: '/' // url without query string, default '/'
ifModifiedSince: null // default null
headers: null // default undefined
input: null // request body or data, default null

// response related fields
status: 404 // http-like response status getter and setter, default 404)
body: null  // http-like response body getter and setter, default null)
get: function() {} // get normalized header
set: function() {} // set header

CacheStore class methods

get(key)  // sync get cache
set(key, value)  // sync set cache, trigger watchers to re-run in next tick.
invalidate(key, allSuffix)  // invalidate cache
watch(key, func)  // register a watcher for change on key
unwatch(key, func)  // unregister a watcher for change on key
hasWatch(key)
getPendingPromise()  // get pending change promise (or null), so you can wait for
prune()  // gc this cache store

Reget class

cache  // this instance's CacheStore
handler()  // assigned handler function for request (GET, PUT, POST), can be created by ```compose``` module
get(pathname, query, option)  // http get (Sync)
put(url, input, option)  // http put (Async/Promise)
post(url, input, option)  // http post (Async/Promise)
reload(url, option)  // http get (Async/Promise)
request(option)  // http request (Async/Promise)
serverRender()
getLoadingPromise(key) // get promise for all loading calls or one cache, null when promise not found
wait()  // wait for all pending requests and events
getCache() // If !key, entire store will be returned
setCache() // If key is object, key&value will be import to this cache store.
invalidate(key, allSuffix)
watch(key, func)
unwatch(key, func)

Middlewares

koa like middlewares system. Please refer to path-to-regexp for path pattern.

import {compose} from 'reget'

const handler = compose(
  {
    route: 'foo/:key',
    async get(ctx, next) {
      // ctx.params = {key: 'hi'}
      await next()
      ctx.body = ctx.body + ' World'
    },
    async put(ctx, next) {
      DB.save(ctx.input)
      ctx.status = 200
    },
  },
  ctx => {
    ctx.body = 'Hello'
  },
)

const ctx = {path: 'foo/hi'}
await handler(ctx)
// ctx.body === 'Hello World'

Middleware API

compose(...middlewares) create a function that accept a context argument and pass down to all middlewares

middlewares can be one of

  • function(ctx, next){}
  • array of function(ctx, next){}
  • object: {route: 'pathPattern', get(){}, put(){}, post(){}, watch(){}, unwatch(){}}
  • object: {mount: 'prefix', handler: anotherMiddleware}
  • mount('prefix', anotherMiddleware)

like koa-route, path pattern use path-to-regexp to build regexp

Middleware Example

browserMiddleware = {
  route: '/:key',
  watch({params: {key}, mountPath, reget}) {
    if (key === 'height' || key === 'width') {
      window.onresize = function() {
        const changes = {
          // mountPath = 'browser' if you use mount('browser', browserMiddleware)
          [`${mountPath}/height`]: window.innerHeight,
          [`${mountPath}/width`]: window.innerWidth,
        }
        reget.setCache(changes)
      }
      window.onresize()
    }
  },
  unwatch(ctx) {
    const {key} = ctx.params
    if (key === 'height' || key === 'width') {
      window.onresize = null
    }
  },
  get(ctx) {
    // just use the cached value
    ctx.status = 304
  },
  put(ctx) {
    // cannot put
    ctx.status = 404
  },
}

SyncPromise

SyncPromise can wrap a value into a Promise like object. Why? because normal Promise .then is not sync

let value = null

Promise.resolve('A')
.then(val => value = val)
// value !== 'A'

// But

SyncPromise.resolve('A')
.then(val => value = val)
// value === 'A'