Skip to content

Instantly share code, notes, and snippets.

@ishiduca
Created June 29, 2018 10:15
Show Gist options
  • Save ishiduca/bd6ab8c044296c48ecb073cd5f7ba110 to your computer and use it in GitHub Desktop.
Save ishiduca/bd6ab8c044296c48ecb073cd5f7ba110 to your computer and use it in GitHub Desktop.
snoopy-domain
const w = require('global/window')
const d = require('global/document')
const yo = require('yo-yo')
const css = require('sheetify')
const {pipe, through} = require('mississippi')
const {start} = require('@ishiduca/snoopy')
css('./css/bulma.css')
const root = yo`<div></div>`
const commandLine = require('./command-input')
const commandButtons = require('./command-buttons')
const domain = require('./domain')
const {views} = start(
domain([
commandLine,
commandButtons
], {
'/(dashboard)' (params, uri, views) {
return yo`
<div>
<header>
${views.commandButtons}
${views.commandLine}
</header>
</div>
`
}
})
)
pipe(
views(),
through.obj((el, _, done) => {
yo.update(root, yo`<div>${el}</div>`)
done()
}),
onError
)
d.body.appendChild(root)
function onError (err) {
err ? console.error(err)
: console.log('!APP FINISH')
}
const yo = require('yo-yo')
const xtend = require('xtend')
const defined = require('defined')
const {through} = require('mississippi')
const defaults = require('@ishiduca/snoopy/defaults')
const routing = require('@ishiduca/routing')
const routingApp = require('./routing-app')
module.exports = domain
module.exports.domain = domain
function viewNotFound (params, u, view) {
return yo`<div>404 not found "${u}"</div>`
}
function domain (apps, layouts) {
apps = [routingApp].concat(apps)
apps.forEach(app => {
if (!app.name) throw new Error('not found property "name"')
})
const router = routing()
router.define('/404', viewNotFound)
Object.keys(layouts).forEach(route => router.define(route, layouts[route]))
return {
init: combineInit(apps),
update: combineUpdate(apps),
run: combineRun(apps),
view: combineView(apps, router)
}
}
function combineView (apps, router) {
return (model, actionsUp) => {
const uri = model[routingApp.name]
const m = router.match(uri) || router.match('/404')
const layout = m.values[0]
return layout(
m.params,
uri,
apps.reduce((v, app) => {
const view = defined(app.view, defaults.view)
v[app.name] = view(model[app.name], actionsUp)
return v
}, {})
)
}
}
function combineInit (apps) {
return () => (
apps.reduce((state, app) => {
const s = defined(app.init, defaults.init)()
const model = xtend(state.model, {[app.name]: s.model})
const effect = (
s.effect == null ? state.effect : state.effect.concat(s.effect)
)
return {model, effect}
}, {model: {}, effect: []})
)
}
function combineUpdate (apps) {
return (_model, action) => (
apps.reduce((state, app) => {
const s = defined(app.update, defaults.update)(_model[app.name], action)
const model = xtend(state.model, {[app.name]: s.model})
const effect = (
s.effect == null ? state.effect : state.effect.concat(s.effect)
)
return {model, effect}
}, {model: {}, effect: []})
)
}
function combineRun (apps) {
return (effects, sources) => {
const srcs = apps.reduce((apps, app) => {
const run = defined(app.run, defaults.run)
return apps.concat(effects.map(e => run(e, sources)).filter(Boolean))
}, [])
if (srcs.length === 0) return
var c = 0
const effectActionsSource = through.obj()
srcs.forEach(src => {
c += 1
src
.once('error', onEnd)
.once('end', onEnd)
.pipe(effectActionsSource, {end: false})
})
return effectActionsSource
function onEnd (err) {
if (err) effectActionsSource.emit('error', err)
if ((c -= 1) === 0) effectActionsSource.end()
}
}
}
const w = require('global/window')
const href = require('nanohref')
const xtend = require('xtend')
const {through} = require('mississippi')
const {actions, updateHelper, runHelper} = require('./utils')
const routingApp = 'routingApp'
const routingInit = 'routingInit'
const RoutingInit = actions(routingInit)
const changeURI = 'changeURI'
const ChangeURI = actions(changeURI)
const DUMMY = Object.create(null)
module.exports = {
name: routingApp,
init () {
return {
model: w.location.pathname,
effect: RoutingInit()
}
},
update: updateHelper({
[changeURI] (model, action) {
return {model: xtend(model, action)}
}
}),
run: runHelper({
[routingInit] (effect) {
const s = through.obj()
href(loc => {
w.history.pushState(DUMMY, '', loc.pathname)
s.write(ChangeURI(loc.pathname))
})
w.onpopstate = e => s.write(ChangeURI(w.location.pathname))
return s
}
})
}
const {through} = require('mississippi')
module.exports.actions = (type) => (payload) => ({type, payload})
module.exports.updateHelper = (map) => (model, action) => (
map[action.type] != null
? map[action.type](model, action.payload)
: {model}
)
module.exports.runHelper = (map) => (effect, sources) => (
_help(map, effect, sources)
)
function _help (map, effect, sources) {
return (
map[effect.type] != null && map[effect.type](effect.payload, sources)
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment