1 | var getAllRoutes = require('wayfarer/get-all-routes')
|
2 |
|
3 | module.exports.is = function (app) {
|
4 | return Boolean(app &&
|
5 | app.router &&
|
6 | app.router.router &&
|
7 | app.router.router._trie)
|
8 | }
|
9 |
|
10 | module.exports.listRoutes = function (app) {
|
11 | var keys = getAllRoutes(app.router.router)
|
12 | return Object.keys(keys).filter(function (key) {
|
13 | return !/\/:/.test(key) // Server rendering partials is tricky.
|
14 | })
|
15 | }
|
16 |
|
17 | // Do a double render pass - the first time around we wait for promises to be
|
18 | // pushed into `state._experimental_prefetch`. Once all promises resolve, we
|
19 | // take the state, and do a second render pass with the new state.
|
20 | //
|
21 | // In Nanocomponent, people should do a conditional call to render this.
|
22 | //
|
23 | // ## Example
|
24 | //
|
25 | // ```js
|
26 | // class Button extends Nanocomponent {
|
27 | // constructor (name, state, emit) {
|
28 | // super(name)
|
29 | // this.state = state
|
30 | // this.emit = emit
|
31 | // this.local = this.state.components[name] = {
|
32 | // loaded: false // This is set on the global "state" object.
|
33 | // }
|
34 | // }
|
35 | //
|
36 | // render () {
|
37 | // if (!this.local.loaded) {
|
38 | // this.state._experimental_prefetch.push(this.fetch())
|
39 | // }
|
40 | //
|
41 | // html`<button>
|
42 | // ${this.local.loaded ? 'loaded' : 'not loaded'
|
43 | // </button>`
|
44 | // }
|
45 | //
|
46 | // update () {
|
47 | // return true
|
48 | // }
|
49 | //
|
50 | // async fetch () {
|
51 | // this.local.loaded = true // async functions return promises
|
52 | // }
|
53 | // }
|
54 | // ```
|
55 | //
|
56 | // NOTE: state is never passed in it seems. Funky fn signature, this should be
|
57 | // fixed.
|
58 | //
|
59 | // NOTE: Choo currently doesn't use the passed-in state as the base. It probably
|
60 | // should, so we can treat the state as the only stateful bits, and the rest is
|
61 | // just context.
|
62 |
|
63 | module.exports.render = function (app, route, cb) {
|
64 | var state = {}
|
65 | state._experimental_prefetch = []
|
66 |
|
67 | return new Promise(function (resolve, reject) {
|
68 | // First pass to populate prefetch
|
69 | try {
|
70 | app.toString(route, state)
|
71 | } catch (err) {
|
72 | return reject(err)
|
73 | }
|
74 | resolve(state._experimental_prefetch)
|
75 | }).then(function (prefetches) {
|
76 | return Promise.all(prefetches)
|
77 | }).then(render).catch(cb)
|
78 |
|
79 | function render () {
|
80 | var res = { state: state }
|
81 | res.body = app.toString(route, state)
|
82 | delete res.state._experimental_prefetch // State needs to be serializable.
|
83 | if (app.state.title) res.title = app.state.title
|
84 | if (app.state.language) res.language = app.state.language
|
85 | if (app.selector) res.selector = app.selector
|
86 | cb(null, res)
|
87 | }
|
88 | }
|