11_ = require ' lodash'
2- toHTML = require ' vdom-to-html'
32
43z = require ' ./z'
54render = require ' ./render'
65StateFactory = require ' ./state_factory'
7- cookies = require ' ./cookies'
86isSimpleClick = require ' ./is_simple_click'
97ev = require ' ./ev'
108
11- SERVER_TIMEOUT_MS = 250
12-
139getCurrentPath = (mode ) ->
1410 hash = window .location .hash .slice (1 )
1511 pathname = window .location .pathname
@@ -31,16 +27,6 @@ setPath = (path, mode, isReplacement) ->
3127
3228class Server
3329 constructor : ->
34- @events = {}
35- @$ $root = null
36- @mode = if window ? .history ? .pushState then ' pathname' else ' hash'
37- @currentPath = null
38- @isRedrawScheduled = false
39- @animationRequestId = null
40- @$root = null
41- @status = null # server only
42- @req = null # server only
43-
4430 # coffeelint: disable=missing_fat_arrows
4531 @ Redirect = ({path}) ->
4632 @name = ' redirect'
@@ -50,106 +36,42 @@ class Server
5036 @Redirect .prototype = new Error ()
5137 # coffeelint: enable=missing_fat_arrows
5238
53- if window ?
54- StateFactory .onAnyUpdate =>
55- if @$root
56- @ go @currentPath
57-
58- # used for full-page rendering
59- @globalRoot = document .getElementById ' zorium-root'
60-
61- unless @globalRoot
62- @globalRoot = document .createElement ' div'
63- @globalRoot .id = ' zorium-root'
64- document .body .appendChild @globalRoot
65-
66- # some browsers erroneously call popstate on intial page load (iOS Safari)
67- # We need to ignore that first event.
68- # https://code.google.com/p/chromium/issues/detail?id=63040
69- window .addEventListener ' popstate' , (e ) =>
70- if @currentPath
71- setTimeout @go
72-
73- setStatus : (@status ) =>
74- if window ?
75- throw new Error ' z.server.setStatus() called client-side'
76- null
77-
78- setCookie : cookies .set
79- getCookie : cookies .get
80-
81- getReq : =>
82- if window ?
83- throw new Error ' z.server.getReq() called client-side'
84- @req
85-
86- factoryToMiddleware : (factory ) =>
87- handleRenderError = (err , req , res , next ) =>
88- if err instanceof @Redirect
89- return res .redirect err .path
90- else
91- return next err
92-
93- setResCookies = (res , cookies ) ->
94- _ .map cookies .getConstructors (), (config , key ) ->
95- res .cookie key, config .value , config .opts
96-
97- (req , res , next ) =>
98- # Reset state between requests
99- @ setStatus 200
100- @req = req
101- cookies .reset ()
102- StateFactory .reset ()
103- hasResolved = false
104-
105- StateFactory .onError (err) ->
106- if _ .isPlainObject err
107- err = new Error JSON .stringify err
108- next err
109-
110- cookies .populate req .headers ? .cookie
111-
112- $root = factory ()
113-
114- # FIXME
115- # timeout = setTimeout =>
116- # @emit 'timeout', {req}
117- # resolve()
118- # , SERVER_TIMEOUT_MSgd
119-
120- resolve = =>
121- if hasResolved
122- return
123- hasResolved = true
124- # FIXME
125- # clearTimeout timeout
126- try
127- tree = z $root, {
128- path : req .url
129- }
130-
131- setResCookies (res, cookies)
132- res .status (@status ).send ' <!DOCTYPE html>' + toHTML tree
133- catch err
134- setResCookies (res, cookies)
135- handleRenderError (err, req, res, next)
136-
137- # Initialize tree, kicking off async fetches
138- try
139- z $root, {
140- path : req .url
141- }
39+ unless window ?
40+ return
14241
143- StateFactory .onNextAllSettlemenmt resolve
42+ @events = {}
43+ @$ $root = null
44+ @mode = if window ? .history ? .pushState then ' pathname' else ' hash'
45+ @currentPath = null
46+ @isRedrawScheduled = false
47+ @animationRequestId = null
48+ @$root = null
14449
145- catch err
146- hasResolved = true
147- setResCookies (res, cookies)
148- handleRenderError (err, req, res, next)
50+ StateFactory .onAnyUpdate =>
51+ if @$root
52+ @ go @currentPath
53+
54+ # used for full-page rendering
55+ @globalRoot = document .getElementById ' zorium-root'
56+
57+ unless @globalRoot
58+ @globalRoot = document .createElement ' div'
59+ @globalRoot .id = ' zorium-root'
60+ document .body .appendChild @globalRoot
61+
62+ # some browsers erroneously call popstate on intial page load (iOS Safari)
63+ # We need to ignore that first event.
64+ # https://code.google.com/p/chromium/issues/detail?id=63040
65+ window .addEventListener ' popstate' , (e ) =>
66+ if @currentPath
67+ setTimeout @go
68+
69+ config : ({mode, $root, $$root}) =>
70+ unless window ?
71+ throw new Error ' config called server-side'
14972
150- config : ({mode, factory, $$root}) =>
15173 @mode = mode or @mode
152- @$root = factory ? () or @$root
74+ @$root = $root or @$root
15375 @$ $root = $$root or @$ $root
15476
15577 link : (node ) =>
@@ -165,23 +87,6 @@ class Server
16587
16688 return node
16789
168- render : (props ) =>
169- try
170- tree = z @$root , props
171- catch err
172- if err instanceof @Redirect
173- return @ go err .path
174- else throw err
175-
176- # Because the DOM doesn't let us directly manipulate top-level elements
177- # We have to standardize a hack around it
178-
179- $root = if @$ $root is document \
180- then @globalRoot \
181- else @$ $root
182-
183- render $root, tree
184-
18590 go : (path ) =>
18691 unless window ?
18792 throw new Error ' z.server.go() called server-side'
@@ -200,18 +105,36 @@ class Server
200105 path : path
201106 }
202107
108+ renderOrRedirect = (props ) =>
109+ try
110+ tree = z @$root , props
111+ catch err
112+ if err instanceof @Redirect
113+ return @ go err .path
114+ else throw err
115+
116+ # Because the DOM doesn't let us directly manipulate top-level elements
117+ # We have to standardize a hack around it
118+ $root = if @$ $root is document \
119+ then @globalRoot \
120+ else @$ $root
121+ render $root, tree
122+
203123 if not isRedraw
204124 @currentPath = path
205125 setPath path, @mode , hasRouted
206126 @ emit ' go' , {path}
207- @ render (props)
127+ renderOrRedirect (props)
208128 else
209129 @isRedrawScheduled = true
210130 @animationRequestId = window .requestAnimationFrame =>
211131 @isRedrawScheduled = false
212- @ render (props)
132+ renderOrRedirect (props)
213133
214134 on : (name , fn ) =>
135+ unless window ?
136+ throw new Error ' z.server.on() called server-side'
137+
215138 (@events [name] = @events [name] or []).push (fn)
216139
217140 emit : (name ) =>
@@ -220,6 +143,9 @@ class Server
220143 fn .apply null , args
221144
222145 off : (name , fn ) =>
146+ unless window ?
147+ throw new Error ' z.server.off() called server-side'
148+
223149 @events [name] = _ .without (@events [name], fn)
224150
225151server = new Server ()
@@ -229,10 +155,5 @@ module.exports = {
229155 go : server .go
230156 link : server .link
231157 config : server .config
232- setStatus : server .setStatus
233- setCookie : server .setCookie
234- getCookie : server .getCookie
235- getReq : server .getReq
236- factoryToMiddleware : server .factoryToMiddleware
237158 Redirect : server .Redirect
238159}
0 commit comments