1
1
_ = require ' lodash'
2
- toHTML = require ' vdom-to-html'
3
2
4
3
z = require ' ./z'
5
4
render = require ' ./render'
6
5
StateFactory = require ' ./state_factory'
7
- cookies = require ' ./cookies'
8
6
isSimpleClick = require ' ./is_simple_click'
9
7
ev = require ' ./ev'
10
8
11
- SERVER_TIMEOUT_MS = 250
12
-
13
9
getCurrentPath = (mode ) ->
14
10
hash = window .location .hash .slice (1 )
15
11
pathname = window .location .pathname
@@ -31,16 +27,6 @@ setPath = (path, mode, isReplacement) ->
31
27
32
28
class Server
33
29
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
-
44
30
# coffeelint: disable=missing_fat_arrows
45
31
@ Redirect = ({path}) ->
46
32
@name = ' redirect'
@@ -50,106 +36,42 @@ class Server
50
36
@Redirect .prototype = new Error ()
51
37
# coffeelint: enable=missing_fat_arrows
52
38
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
142
41
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
144
49
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'
149
72
150
- config : ({mode, factory, $$root}) =>
151
73
@mode = mode or @mode
152
- @$root = factory ? () or @$root
74
+ @$root = $root or @$root
153
75
@$ $root = $$root or @$ $root
154
76
155
77
link : (node ) =>
@@ -165,23 +87,6 @@ class Server
165
87
166
88
return node
167
89
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
-
185
90
go : (path ) =>
186
91
unless window ?
187
92
throw new Error ' z.server.go() called server-side'
@@ -200,18 +105,36 @@ class Server
200
105
path : path
201
106
}
202
107
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
+
203
123
if not isRedraw
204
124
@currentPath = path
205
125
setPath path, @mode , hasRouted
206
126
@ emit ' go' , {path}
207
- @ render (props)
127
+ renderOrRedirect (props)
208
128
else
209
129
@isRedrawScheduled = true
210
130
@animationRequestId = window .requestAnimationFrame =>
211
131
@isRedrawScheduled = false
212
- @ render (props)
132
+ renderOrRedirect (props)
213
133
214
134
on : (name , fn ) =>
135
+ unless window ?
136
+ throw new Error ' z.server.on() called server-side'
137
+
215
138
(@events [name] = @events [name] or []).push (fn)
216
139
217
140
emit : (name ) =>
@@ -220,6 +143,9 @@ class Server
220
143
fn .apply null , args
221
144
222
145
off : (name , fn ) =>
146
+ unless window ?
147
+ throw new Error ' z.server.off() called server-side'
148
+
223
149
@events [name] = _ .without (@events [name], fn)
224
150
225
151
server = new Server ()
@@ -229,10 +155,5 @@ module.exports = {
229
155
go : server .go
230
156
link : server .link
231
157
config : server .config
232
- setStatus : server .setStatus
233
- setCookie : server .setCookie
234
- getCookie : server .getCookie
235
- getReq : server .getReq
236
- factoryToMiddleware : server .factoryToMiddleware
237
158
Redirect : server .Redirect
238
159
}
0 commit comments