UNPKG

3.2 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 || conf
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 spread: (obj) -> @value(k, v) for k, v of obj
33
34 get: (name) ->
35 throwNotFound name unless @isRegistered name
36 registeredAt = @_registeredAt(name)
37 if registeredAt == 'local'
38 @_instantiate name unless @_isInstantiated(name)
39 return @_instances[name]
40 else
41 return @_parents[registeredAt].get(name)
42
43 _isInstantiated: (name) -> Object.keys(@_instances).indexOf(name) != -1
44
45 _registeredAt: (name) ->
46 if @_registrations[name]?
47 return 'local'
48 else
49 for p, i in @_parents
50 if p._registeredAt(name)?
51 parentIndex = i
52 return parentIndex
53
54 isRegistered: (name) -> @_registeredAt(name) != undefined
55
56 getRegistrations: ->
57 if @_parents.length == 0
58 return @_registrations
59
60 all = (p.getRegistrations() for p in @_parents)
61 all.push @_registrations
62 all.reduce (acc, item) ->
63 Object.keys(item).forEach (key) -> acc[key] = item[key]
64 return acc
65 , {}
66
67 getArguments: (name) ->
68 if @_modules[name]?
69 @_modules[name]
70 else
71 getArguments @_registrations[name].value
72
73 loadAll: ->
74 p.loadAll() for p in @_parents
75 Object.keys(@_registrations).forEach (name) =>
76 @_instantiate name unless @_isInstantiated(name)
77
78 shutdown: ->
79 Object.keys(@_instances).forEach (key) =>
80 @_instances[key]?.__amendShutdown?()
81 p.shutdown() for p in @_parents
82
83 _register: (type, name, value) -> @_registrations[name] = value: value, type: type
84
85 _instantiate: (name, parent) ->
86 module = @_registrations[name]
87 throwNotFound name, parent unless module?
88 type = module.type
89 value = module.value
90 instance = if type == 'value' then value else @_instantiateWithDependencies name, value, type
91 @_instances[name] = instance
92 return instance
93
94 _instantiateWithDependencies: (name, value, type) ->
95 args = @getArguments name
96
97 dependencies = args.map (depName) =>
98 registeredAt = @_registeredAt(depName)
99 if registeredAt == 'local'
100 if @_isInstantiated(depName) then @_instances[depName] else @_instantiate depName, name
101 else if registeredAt?
102 @_parents[registeredAt].get(depName)
103 else
104 throwNotFound depName, name
105
106 return runFactory value, dependencies if type == 'factory'
107 return construct value, dependencies if type == 'class'