These are the constructs that Cerebral consists of:
import { Controller, Module, Provider, Compute, CerebralError } from 'cerebral'
The module is how you structure your application.
const app = Module({
state: {},
signals: {},
providers: {},
modules: {},
catch: []
})
// Or callback
const app = Module(({ name, path, controller }) => ({
state: {}
}))
provide
factory:const app = Module({
state: {},
providers: {
http: HttpProvider({})
}
})
catch
an error now is at the module level. Errors propagate up to parent modules if not caught. Meaning there is no signal specific error catching or “global”. “Global” would be your root level module.const app = Module({
state: {},
catch: [[HttpProviderError, sequences.catchHttpError]]
})
The controller takes a module as first argument, and other options as a second argument.
const controller = Controller(rootModule, {
devtools: null
})
The same goes for server side controller.
Providers will now have a stronger concept. The concept is being the API between your application and your tools of choice. It can only be defined in one way, an object with methods. This makes things consistent and also enforces the idea that you think of a provider as a “bridge” between your app and the tools your are using.
const myProvider = Provider({
foo() {}
})
You can point to the existing context using this.context
. It works this way to simplify with just one API surface and we can do prototypal optimizations under the hood.
const api = Provider({
getUser() {
return this.context.http.get('/user')
}
})
All providers defined this way is automatically optimized and wrapped for debugger purposes. If you just want to use a 3rd party tool directly, you can still do that by just attaching it:
Module({
providers: { uuid }
})
This is just a change to be consistent with the other APIs:
const myComputed = Compute(state`foo`, (foo) => ())
To more easily create different error types you can now define your errors by extending the CerebralError:
import { CerebralError } from 'cerebral'
export class AppError extends CerebralError {}
export class ApiError extends CerebralError {}
You can point to the module to make state changes on module executing the signal:
function myAction({ module }) {
module.set('foo', 'bar')
}
You can now use a module
tag to point to the state of the module running the signal:
;[set(module`foo`, 'bar')]
Documentation tags Documentation state
The CerebralTest
API now takes a Module as first argument.
import { CerebralTest } from 'cerebral/test'
import app from './src/app' // A Module
CerebralTest(app)
Since you now use a root Module
, the router will need to be added there.
import { Controller, Module } from 'cerebral'
import router from './router' // Instance of the router module
const rootModule = Module({
modules: {
router
}
})
const controller = Controller(rootModule)
compute
to Compute
new Map(...)
CerebralError
, as you get serialization out of the boxCerebralTest
argument with a Module