forked from cordjs/core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
AppConfigLoader.coffee
93 lines (78 loc) · 3.07 KB
/
AppConfigLoader.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
define [
'app/application'
'cord!isBrowser'
'cord!utils/Future'
'underscore'
], (application, isBrowser, Future, _) ->
class AppConfigLoader
###
Application configuration loader
Purpose of this class is to load and merge all enabled bundles configurations, including routes and service
definitions for the service container (DI).
This is static class. Loading starts immediately after it's required anywhere. Usage:
```
require ['cord!AppConfigLoader], (AppConfigLoader) ->
AppConfigLoader.ready().done (appConfig) ->
appConfig.routes
appConfig.services
```
###
@_promise: Future.single('AppConfigLoader')
@ready: ->
###
Returns future with merged configuration which is completed asynchronously when all configs are loaded and merged
@return Future(Object)
###
@_promise
@_load: ->
application.unshift('cord/core') # core is always enabled
configs = ("cord!/#{ bundle }/config" for i, bundle of application)
require configs, (args...) ->
routes = {}
services = {}
fallbackRoutes = {}
fallbackApiErrors = {}
processRoutes = (source, destination, bundle) ->
for route, params of source
# expanding widget path to fully-qualified canonical name if short path is given
if params.widget and params.widget.substr(0, 2) is '//'
params.widget = "/#{ bundle }#{ params.widget }"
# eliminating duplicate routes here
# todo: may be it should be reported when there are duplicate routes?
_.extend(destination, source)
for config, i in args
if config.fallbackRoutes?
processRoutes config.fallbackRoutes, fallbackRoutes, application[i]
if config.routes?
processRoutes config.routes, routes, application[i]
if config.services?
# flatten services configuration (excluding server-only or browser-only configuration)
srv = _.clone(config.services)
flatSrv = {}
if srv[':browser']?
_.extend(flatSrv, srv[':browser']) if isBrowser
delete srv[':browser']
if srv[':server']?
_.extend(flatSrv, srv[':server']) if not isBrowser
delete srv[':server']
_.extend(flatSrv, srv)
# normalize services configuration
for name, def of flatSrv
services[name] =
if _.isFunction(def)
deps: []
factory: def
else
deps: def.deps
factory: def.factory
autoStart: def.autoStart
if config.fallbackApiErrors?
for error, fallback of config.fallbackApiErrors
fallbackApiErrors[error] = fallback
AppConfigLoader._promise.resolve
routes: routes
services: services
fallbackRoutes: fallbackRoutes
fallbackApiErrors: fallbackApiErrors
# start loading immediately on class loading
@_load()