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

barracks

Package Overview
Dependencies
Maintainers
4
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

barracks - npm Package Compare versions

Comparing version 8.2.1 to 8.3.0

122

index.js

@@ -19,4 +19,9 @@ const mutate = require('xtend/mutable')

useHooks(hooks)
const subscriptionWraps = []
const initialStateWraps = []
const reducerWraps = []
const effectWraps = []
use(hooks)
var reducersCalled = false

@@ -36,3 +41,3 @@ var effectsCalled = false

start.start = start
start.use = useHooks
start.use = use
return start

@@ -42,3 +47,3 @@

// obj -> null
function useHooks (hooks) {
function use (hooks) {
assert.equal(typeof hooks, 'object', 'barracks.use: hooks should be an object')

@@ -49,5 +54,9 @@ assert.ok(!hooks.onError || typeof hooks.onError === 'function', 'barracks.use: onError should be undefined or a function')

if (hooks.onStateChange) onStateChangeHooks.push(hooks.onStateChange)
if (hooks.onError) onErrorHooks.push(wrapOnError(hooks.onError))
if (hooks.onAction) onActionHooks.push(hooks.onAction)
if (hooks.onStateChange) onStateChangeHooks.push(hooks.onStateChange)
if (hooks.wrapSubscriptions) subscriptionWraps.push(hooks.wrapSubscriptions)
if (hooks.wrapInitialState) initialStateWraps.push(hooks.wrapInitialState)
if (hooks.wrapReducers) reducerWraps.push(hooks.wrapReducers)
if (hooks.wrapEffects) effectWraps.push(hooks.wrapEffects)
}

@@ -67,22 +76,28 @@

assert.equal(typeof opts, 'object', 'barracks.store.state: opts should be an object')
if (opts.state) {
const initialState = {}
const nsState = {}
models.forEach(function (model) {
const ns = model.namespace
const modelState = model.state || {}
if (ns) {
nsState[ns] = {}
apply(ns, modelState, nsState)
nsState[ns] = xtend(nsState[ns], opts.state[ns])
} else {
apply(model.namespace, modelState, initialState)
}
})
return xtend(_state, xtend(opts.state, nsState))
} else if (opts.freeze === false) {
return xtend(_state)
} else {
return Object.freeze(xtend(_state))
}
const state = opts.state
if (!opts.state && opts.freeze === false) return xtend(_state)
else if (!opts.state) return Object.freeze(xtend(_state))
assert.equal(typeof state, 'object', 'barracks.store.state: state should be an object')
const nsState = {}
models.forEach(function (model) {
const ns = model.namespace
const modelState = model.state || {}
if (ns) {
nsState[ns] = {}
apply(ns, modelState, nsState)
nsState[ns] = xtend(nsState[ns], state[ns])
} else {
mutate(nsState, modelState)
}
})
const tmpState = xtend(_state, xtend(state, nsState))
const wrappedState = wrapHook(tmpState, initialStateWraps)
return (opts.freeze === false)
? wrappedState
: Object.freeze(wrappedState)
}

@@ -100,13 +115,28 @@

if (!stateCalled && model.state && opts.state !== false) {
apply(ns, model.state, _state)
const modelState = model.state || {}
if (ns) {
_state[ns] = _state[ns] || {}
apply(ns, modelState, _state)
} else {
mutate(_state, modelState)
}
}
if (!reducersCalled && model.reducers && opts.reducers !== false) {
apply(ns, model.reducers, reducers)
apply(ns, model.reducers, reducers, function (cb) {
return wrapHook(cb, reducerWraps)
})
}
if (!effectsCalled && model.effects && opts.effects !== false) {
apply(ns, model.effects, effects)
apply(ns, model.effects, effects, function (cb) {
return wrapHook(cb, effectWraps)
})
}
if (!subsCalled && model.subscriptions && opts.subscriptions !== false) {
apply(ns, model.subscriptions, subscriptions, createSend, function (err) {
applyHook(onErrorHooks, err)
apply(ns, model.subscriptions, subscriptions, function (cb, key) {
const send = createSend('subscription: ' + (ns ? ns + ':' + key : key))
cb = wrapHook(cb, subscriptionWraps)
cb(send, function (err) {
applyHook(onErrorHooks, err)
})
return cb
})

@@ -116,6 +146,12 @@ }

if (!opts.noState) stateCalled = true
// the state wrap is special because we want to operate on the full
// state rather than indvidual chunks, so we apply it outside the loop
if (!stateCalled && opts.state !== false) {
_state = wrapHook(_state, initialStateWraps)
}
if (!opts.noSubscriptions) subsCalled = true
if (!opts.noReducers) reducersCalled = true
if (!opts.noEffects) effectsCalled = true
if (!opts.noSubscriptions) subsCalled = true
if (!opts.noState) stateCalled = true

@@ -220,14 +256,8 @@ if (!onErrorHooks.length) onErrorHooks.push(wrapOnError(defaultOnError))

// (str, obj, obj, fn?) -> null
function apply (ns, source, target, createSend, done) {
function apply (ns, source, target, wrap) {
if (ns && !target[ns]) target[ns] = {}
Object.keys(source).forEach(function (key) {
if (ns) {
target[ns][key] = source[key]
} else {
target[key] = source[key]
}
if (createSend && done) {
const send = createSend('subscription: ' + (ns ? ns + ':' + key : key))
source[key](send, done)
}
const cb = wrap ? wrap(source[key], key) : source[key]
if (ns) target[ns][key] = cb
else target[key] = cb
})

@@ -247,1 +277,11 @@ }

}
// take a apply an array of transforms onto a value. The new value
// must be returned synchronously from the transform
// (any, [fn]) -> any
function wrapHook (value, transforms) {
transforms.forEach(function (transform) {
value = transform(value)
})
return value
}
{
"name": "barracks",
"version": "8.2.1",
"version": "8.3.0",
"description": "Action dispatcher for unidirectional data flows",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -8,3 +8,3 @@ # barracks

Action dispatcher for unidirectional data flows. Creates tiny models of data
that can be accessed through actions through a small API.
that can be accessed with actions through a small API.

@@ -53,11 +53,16 @@ ## Usage

Register new hooks on the store. Hooks are little plugins that can extend
behavior or perform actions at specific points in the lifecycle. The following
behavior or perform actions at specific points in the life cycle. The following
hooks are possible:
- __onError(err, state, createSend):__ called when an `effect` or
`subscription` emit an error. If no hook is passed, the default hook will
`throw` on each error.
`subscription` emit an error; if no hook is passed, the default hook will
`throw` on each error
- __onAction(data, state, name, caller, createSend):__ called when an `action`
is fired.
is fired
- __onStateChange(data, state, prev, caller, createSend):__ called after a
reducer changes the `state`.
- __wrapSubscriptions(fn):__ wraps a `subscription` to add custom behavior
- __wrapReducers(fn):__ wraps a `reducer` to add custom behavior
- __wrapEffects(fn):__ wraps an `effect` to add custom behavior
- __wrapInitialState(fn):__ mutate the initial `state` to add custom
behavior - useful to mutate the state before starting up

@@ -67,7 +72,7 @@ `createSend()` is a special function that allows the creation of a new named

second argument is a boolean `callOnError` which can be set to `true` to call
the `onError` hook istead of a provided callback. It then returns a
the `onError` hook instead of a provided callback. It then returns a
`send(actionName, data?)` function.
Hooks should be used with care, as they're the most powerful interface into
the state. For application level code it's generally recommended to delegate to
the state. For application level code, it's generally recommended to delegate to
actions inside models using the `send()` call, and only shape the actions

@@ -78,11 +83,11 @@ inside the hooks.

Register a new model on the store. Models are optionally namespaced objects
with an initial `state`, and handlers for dealing with data:
with an initial `state` and handlers for dealing with data:
- __namespace:__ namespace the model so that it cannot access any properties
and handlers in other models
- __state:__ initial values of `state` inside the model
- __reducers:__ synchronous operations that modify state. Triggered by `actions`
- __effects:__ asynchronous operations that don't modify state directly.
Triggered by `actions`, can call `actions`
- __reducers:__ synchronous operations that modify state; triggered by `actions`
- __effects:__ asynchronous operations that don't modify state directly;
triggered by `actions`, can call `actions`
- __subscriptions:__ asynchronous read-only operations that don't modify state
directly. Can call `actions`
directly; can call `actions`

@@ -93,3 +98,3 @@ `state` within handlers is immutable through `Object.freeze()` and thus cannot

For debugging purposes internal references to values can be inspected through a
For debugging purposes, internal references to values can be inspected through a
series of private accessors:

@@ -103,7 +108,7 @@ - `store._subscriptions`

Get the current state from the store. Opts can take the following values:
- __freeze:__ default: true. Set to false to not freeze state in handlers
using `Object.freeze()`. Useful for optimizing performance in production
builds.
- __freeze:__ default: true; set to false to not freeze state in handlers
using `Object.freeze()`; useful for optimizing performance in production
builds
- __state:__ pass in a state object that will be merged with the state returned
from the store. Useful for rendering in Node.
from the store; useful for rendering in Node

@@ -113,13 +118,13 @@ ### send = createSend(name) = store.start(opts)

`createSend()` to get a `send()` function. Opts can take the following values:
- __subscriptions:__ default: true. Set to false to not register
`subscriptions` when starting the application. Useful to delay `init`
functions until the DOM has loaded.
- __effects:__ default: true. Set to `false` to not register `effects` when
starting the application. Useful when only wanting the initial `state`
- __reducers:__ default: true. Set to false to not register `reducers` when
starting the application. Useful when only wanting the initial `state`
- __subscriptions:__ default: true; set to false to not register
`subscriptions` when starting the application; useful to delay `init`
functions until the DOM has loaded
- __effects:__ default: true; set to `false` to not register `effects` when
starting the application; useful when only wanting the initial `state`
- __reducers:__ default: true; set to false to not register `reducers` when
starting the application; useful when only wanting the initial `state`
If the store has disabled any of the handlers (e.g. `{ reducers: false }`),
calling `store.start()` a second time will register the remaining values. This
is a useful if not everything can be started at the same time (e.g. have
is useful if not everything can be started at the same time (e.g. have
`subscriptions` wait for the `DOMContentLoaded` event).

@@ -165,3 +170,3 @@

### reducers
Reducers are synchronous functions that return a value syncrhonously. No
Reducers are synchronous functions that return a value synchronously. No
eventual values, just values that are relevant for the state. It takes two

@@ -199,5 +204,5 @@ arguments of `data` and `state`. `data` is the data that was emitted, and

`send()`. They never update the state directly, but can instead do thing
asyncrhonously, and then call `send()` again to trigger a `reducer` that can
asynchronously, and then call `send()` again to trigger a `reducer` that can
update the state. `effects` can also trigger other `effects`, making them fully
composable. Generalyy it's recommended to only have `effects` without a
composable. Generally, it's recommended to only have `effects` without a
`namespace` call other `effects`, as to keep namespaced models as isolated as

@@ -208,3 +213,3 @@ possible.

final `done(err)` callback. If the `effect` was called by another `effect` it
will call the callback of the caller. When an error propegates all the way to
will call the callback of the caller. When an error propagates all the way to
the top, the `onError` handler will be called, registered in

@@ -287,7 +292,7 @@ `barracks(handlers)`. If no callback is registered, errors will `throw`.

An action dispatcher gets data from one place to another without tightly
coupling code. The best known use case for this is in the `flux` pattern. Say
coupling code. The best known use case for this is in the `flux` pattern. Say
you want to update a piece of data (for example a user's name), instead of
directly calling the update logic inside the view the action calls a function
directly calling the update logic inside the view, the action calls a function
that updates the user's name for you. Now all the views that need to update a
user's name can call the same action and pass in the relevant data. This
user's name can call the same action and pass in the relevant data. This
pattern tends to make views more robust and easier to maintain.

@@ -298,6 +303,6 @@

casually throw restrictions at users without having a clear architecture. I
don't like that. `barracks` is a package creates a clear flow of data within an
don't like that. `barracks` is a package that creates a clear flow of data within an
application, concerning itself with state, code separation, and data flow. I
believe that having strong opinions and being transparant in them makes for
architectures than sprinkles of opinions left and right, without a cohesive
believe that having strong opinions and being transparent in them makes for
better architectures than sprinkles of opinions left and right, without a cohesive
story as to _why_.

@@ -308,3 +313,3 @@

that. This is a package that only concerns itself with data flow, without being
explicitely tied to the DOM.
explicitly tied to the DOM.

@@ -311,0 +316,0 @@ ### This looks like more than five functions!

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