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

buhoi-client

v2.1.6

Published

Client side part of buhoi framework.

Downloads

25

Readme

buhoi-client

Client side part of buhoi framework.

Purpose

Provide loading of stateless functional components depending on route, with support of webpack hot module replacement.

Example

// index.js

const buhoi = require('buhoi-client')

buhoi.start({
	createContext: () => require.context('./pages', true, /\.jsx$/),
	acceptHotUpdate: module.hot && module.hot.accept,
	defaultRoute: '/greetings',
})
// pages/greetings/index.jsx

const { combineReducers } = require('redux')
const { actions: { navigateTo } } = require('buhoi-client')

module.exports = Greetings
module.exports.reducer = combineReducers({ someText: someTextReducer })

function Greetings ({ someText, route, dispatch }) {
	return <div>
		<h1 onClick={() => dispatch(navigateTo('/other-page?a=1'))}>Hi!</h1>
		<h1 onClick={() => dispatch(navigateTo({ entity: 'other-page', query: { a: 2 }))}>Hola!</h1>
		<input type="text" onInput={e => dispatch(setSomeText(e.target.value))} value={someText} />
		<p>Change this, save file, and observe following text unchanged: {someText}</p>
	</div>
}

function someTextReducer (state = '', action) {
	switch (action.type) {
		case 'SET_SOME_TEXT': return action.text
		default: return state
	}
}

function setSomeText (text) {
	return { type: 'SET_SOME_TEXT', text }
}
// entities/other-page/index.jsx

module.exports = function ({ route }) {
	return <h1>Param A is {route.query.a}</h1>
}

Concept

  • client application consists of pages
  • each page is a stateless functional component with dedicated reducer (although reducer is optional)
  • application state has two parts: persistent (app) and changing (page and route as page ID)
  • whenever route changes, previous page state is lost, new page loaded and rendered, receiving complete application state (plus dispatch) as props

API Reference

start(options)

Function, starts client application, accepting following options.

createContext

Requied: yes

Function, must return webpack require.context instance. Is used by router to require and render component according to route.

acceptHotUpdate

Required: no

Function, must be falsey, or equal to module.hot.accept, provided by webpack. Simply put module.hot && module.hot.accept here if you want to enable hot reload.

defaultRoute

Requred: yes

String or { entity, action, id, query } object, representing default route.

As example, route-string /books/edit/1?mode=extended corresponds to route-object

{
	entity: 'books',
	action: 'edit',
	id: '1',
	query: { mode: 'extended' }
}

loginRoute

Required: no

String or { entity, action, id, query } object, representing login route. Is used by default route reducer in case if any REST action returns 401 (not authenticated) or 403 (forbidden).

routeReducer

Required: no

Custom route reducer. In most cases you do not need to override default routing behaviour, but, if you need, it can be done by providing route reducer.

appReducer

Required: no

Reducer for persistent part of application state (app). As example, app reducer can handle authentication-related actions, returing { user } state.

middleware

Required: no

Array of middleware functions. As example, you could put here redux-thunk, also you could pass redux-logger middleware in development environment.

containerDomNode

Required: no

DOMNode used for rendering of virtual node, returned by page component. By default, it's element with ID "root".

scope

Object, represents dictionary of scope-related functions.

createDispatch(scope, dispatch)

Function, creates scoped dispatch function. Scoped means that each action dispatched by it will contain scope property.

createReducer(scope, reducer)

Function, creates scoped reducer function. Scoped means that reducer will process actions of given scope, ignoring others.

actions

Object, represents dictionary of actions.

navigateTo(route[, silent])

Function, creates route change action. If silent is true, then URL change will be prevented.

changeQuery(keyValues[, replace])

Functon, creates route query change action. If replace is true, then query will be replaced by keyValues, otherwise it will be extended by keyValues. Note, you can pass { param: undefined } to get rid of param query parameter.

You must provide redux-thunk middleware to use this action.

read(operationName, url[, qs])

Function, creates read action. Whenever it's dispatched:

  • GET request is started using given url and qs (query string object)
  • ${operationName}_STARTED is fired with request property (reference to request promise)
  • once request succeeded, ${operationName}_SUCCEEDED is fired with result property (reference to response body)
  • in case of error, {$operatioName}_FAILED is dispatched with error property (in most cases it will be of type RestRequestError)

You must provide redux-thunk middleware to use this action.

write(operationName, url, body)

Function, creates write action. Whenever it's dispatched:

  • POST request is started using given url and body
  • ${operationName}_STARTED is fired with request property (reference to request promise)
  • once request succeeded, ${operationName}_SUCCEEDED is fired with result property (reference to response body)
  • in case of error, {$operatioName}_FAILED is dispatched with error property (in most cases it will be of type RestRequestError)

You must provide redux-thunk middleware to use this action.

remove(operationName, url)

Function, creates remove action. Whenever it's dispatched:

  • DELETE request is started using given url
  • ${operationName}_STARTED is fired with request property (reference to request promise)
  • once request succeeded, ${operationName}_SUCCEEDED is fired
  • in case of error, {$operatioName}_FAILED is dispatched with error property (in most cases it will be of type RestRequestError)

You must provide redux-thunk middleware to use this action.

RestRequestError

Error, represents REST request error, consisting of statusCode and body properties, corresponding to ones from response.

Motivation

  • bored of complex bootstrap, requiring lots of prior knowledge
  • bored of stateful OOP-based approaches, requiring obscure patching for hot reload or isomorphic rendering
  • bored of components built on top of complex APIs, gathering in complex hierarchies
  • excited about delivering more per unit of time using clear and straightforward tooling
  • want to understand the stack from bottom to top

License

MIT