@@ -398,7 +398,7 @@ app.model({
|
||||
}
|
||||
],
|
||||
effects: {
|
||||
'sse:close': () => stream.close()
|
||||
'sse:close': () => stream.close(),
|
||||
'app:error': (state, event) => console.error(`error: ${event.payload}`),
|
||||
'app:print': (state, event) => console.log(`sse: ${event.payload}`)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
const choo = require('../../')
|
||||
|
||||
const app = choo()
|
||||
app.model(createModel())
|
||||
app.router((route) => [
|
||||
route('/', mainView)
|
||||
])
|
||||
|
||||
const tree = app.start()
|
||||
document.body.appendChild(tree)
|
||||
|
||||
function mainView (params, state, send) {
|
||||
return choo.view`
|
||||
<div>${state.logger.msg}</div>
|
||||
`
|
||||
}
|
||||
|
||||
function createModel () {
|
||||
const stream = new window.EventSource('/sse')
|
||||
return {
|
||||
namespace: 'logger',
|
||||
state: {
|
||||
msg: ''
|
||||
},
|
||||
subscriptions: [
|
||||
function (send) {
|
||||
stream.onerror = (e) => {
|
||||
send('logger:error', { payload: JSON.stringify(e) })
|
||||
}
|
||||
stream.onmessage = (e) => {
|
||||
const msg = JSON.parse(e.data).message
|
||||
send('logger:print', { payload: msg })
|
||||
}
|
||||
}
|
||||
],
|
||||
reducers: {
|
||||
'print': (action, state) => {
|
||||
return ({ msg: state.msg + ' ' + action.payload })
|
||||
}
|
||||
},
|
||||
effects: {
|
||||
close: () => stream.close(),
|
||||
error: (action, state) => console.error(`error: ${action.payload}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "http",
|
||||
"private": true,
|
||||
"main": "client.js",
|
||||
"scripts": {
|
||||
"start": "NODE_ENV=development node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"bankai": "^2.0.2",
|
||||
"browserify": "^13.0.1",
|
||||
"server-router": "^2.1.0",
|
||||
"sse": "0.0.6"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
const serverRouter = require('server-router')
|
||||
const browserify = require('browserify')
|
||||
const bankai = require('bankai')
|
||||
const http = require('http')
|
||||
const SSE = require('sse')
|
||||
|
||||
const clients = []
|
||||
const PORT = 8080
|
||||
|
||||
const server = http.createServer(createRouter())
|
||||
server.listen(PORT, () => {
|
||||
process.stdout.write(`listening on port ${PORT}\n`)
|
||||
var sse = new SSE(server)
|
||||
|
||||
// code adapted from: https://github.com/markbrown4/server-sent-events-demo
|
||||
sse.on('connection', (stream) => {
|
||||
clients.push(stream)
|
||||
console.log('Opened connection 🎉')
|
||||
|
||||
var json = JSON.stringify({ message: 'Gotcha' })
|
||||
stream.send(json)
|
||||
console.log('Sent: ' + json)
|
||||
|
||||
stream.on('close', () => {
|
||||
clients.splice(clients.indexOf(stream), 1)
|
||||
console.log('Closed connection 😱')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// emit data every 1.5 seconds
|
||||
setInterval(() => {
|
||||
var json = JSON.stringify({ message: 'Hello hello!' })
|
||||
clients.forEach((stream) => {
|
||||
stream.send(json)
|
||||
console.log('Sent: ' + json)
|
||||
})
|
||||
}, 1500)
|
||||
|
||||
function createRouter () {
|
||||
const router = serverRouter('/404')
|
||||
|
||||
const html = bankai.html({ css: false })
|
||||
router.on('/', (req, res) => html(req, res).pipe(res))
|
||||
|
||||
const js = bankai.js(browserify, require.resolve('./client.js'))
|
||||
router.on('/bundle.js', (req, res) => js(req, res).pipe(res))
|
||||
|
||||
router.on('/404', (req, res) => {
|
||||
res.statusCode = 404
|
||||
res.end('{ "message": "the server is confused" }')
|
||||
})
|
||||
|
||||
return router
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
const choo = require('../../../')
|
||||
|
||||
module.exports = function (params, state, send) {
|
||||
const error = state.app.error[0]
|
||||
const title = state.api.title
|
||||
return choo.view`
|
||||
<section>
|
||||
<h1>${title}</h1>
|
||||
<h2>Latest error: ${error}</h2>
|
||||
<button onclick=${(e) => send('api:good')}>OK!</button>
|
||||
<button onclick=${(e) => send('api:bad')}>Naughty</button>
|
||||
</section>
|
||||
`
|
||||
}
|
||||
@@ -81,14 +81,17 @@ function choo () {
|
||||
|
||||
// subscriptions are loaded after sendAction() is called
|
||||
// because they both need access to send() and can't
|
||||
// react to actions (read-only)
|
||||
_models.forEach(function (model) {
|
||||
if (model.subscriptions) {
|
||||
assert.ok(Array.isArray(model.subscriptions), 'subs must be an array')
|
||||
model.subscriptions.forEach(function (sub) {
|
||||
sub(send)
|
||||
})
|
||||
}
|
||||
// react to actions (read-only) - also wait on DOM to
|
||||
// be loaded
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
_models.forEach(function (model) {
|
||||
if (model.subscriptions) {
|
||||
assert.ok(Array.isArray(model.subscriptions), 'subs must be an arr')
|
||||
model.subscriptions.forEach(function (sub) {
|
||||
sub(send)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// If an id is provided, the application will rehydrate
|
||||
|
||||
Reference in New Issue
Block a user