UNPKG

3.15 kBtext/coffeescriptView Raw
1ModuleNotFound = require './ModuleNotFound'
2getArguments = require './get-arguments'
3
4construct = (c, args) ->
5 class F
6 constructor: -> c.apply @, args
7 F.prototype = c.prototype
8 return new F()
9
10runFactory = (factory, args) ->
11 factory.apply null, args
12
13throwNotFound = (name, parent) ->
14 throw new ModuleNotFound name, parent
15
16module.exports = class Container
17 constructor: (conf = {}, @_parents = []) ->
18 @_modules = conf.modules || {}
19 @_registrations = {}
20 @_instances = {}
21
22 factory: (name, func) ->
23 throw new Error 'A factory must be a function' unless func instanceof Function
24 @_register 'factory', name, func
25
26 value: (name, value) -> @_register 'value', name, value
27
28 class: (name, constructor) ->
29 throw new TypeError 'A constructor must be a function' unless constructor instanceof Function
30 @_register 'class', name, constructor
31
32 get: (name) ->
33 throwNotFound name unless @isRegistered name
34 registeredAt = @_registeredAt(name)
35 if registeredAt == 'local'
36 @_instantiate name unless @_isInstantiated(name)
37 return @_instances[name]
38 else
39 return @_parents[registeredAt].get(name)
40
41 _isInstantiated: (name) -> Object.keys(@_instances).indexOf(name) != -1
42
43 _registeredAt: (name) ->
44 if @_registrations[name]?
45 return 'local'
46 else
47 for p, i in @_parents
48 if p._registeredAt(name)?
49 parentIndex = i
50 return parentIndex
51
52 isRegistered: (name) -> @_registeredAt(name) != undefined
53
54 getRegistrations: ->
55 if @_parents.length == 0
56 return @_registrations
57
58 all = (p.getRegistrations() for p in @_parents)
59 all.push @_registrations
60 all.reduce (acc, item) ->
61 Object.keys(item).forEach (key) -> acc[key] = item[key]
62 return acc
63 , {}
64
65 getArguments: (name) ->
66 if @_modules[name]?
67 @_modules[name]
68 else
69 getArguments @_registrations[name].value
70
71 loadAll: ->
72 p.loadAll() for p in @_parents
73 Object.keys(@_registrations).forEach (name) =>
74 @_instantiate name unless @_isInstantiated(name)
75
76 shutdown: ->
77 Object.keys(@_instances).forEach (key) =>
78 @_instances[key]?.__amendShutdown?()
79 p.shutdown() for p in @_parents
80
81 _register: (type, name, value) -> @_registrations[name] = value: value, type: type
82
83 _instantiate: (name, parent) ->
84 module = @_registrations[name]
85 throwNotFound name, parent unless module?
86 type = module.type
87 value = module.value
88 instance = if type == 'value' then value else @_instantiateWithDependencies name, value, type
89 @_instances[name] = instance
90 return instance
91
92 _instantiateWithDependencies: (name, value, type) ->
93 args = @getArguments name
94
95 dependencies = args.map (depName) =>
96 registeredAt = @_registeredAt(depName)
97 if registeredAt == 'local'
98 if @_isInstantiated(depName) then @_instances[depName] else @_instantiate depName, name
99 else if registeredAt?
100 @_parents[registeredAt].get(depName)
101 else
102 throwNotFound depName, name
103
104 return runFactory value, dependencies if type == 'factory'
105 return construct value, dependencies if type == 'class'