UNPKG

5.79 kBtext/coffeescriptView Raw
1{deferred, parallel, pipeline} = require 'also'
2{normalize, sep, dirname} = require 'path'
3{underscore} = require 'inflection'
4{readdirSync,lstatSync} = require 'fs'
5{save} = require './saver'
6require 'colors'
7
8lastInstance = undefined
9module.exports._test = -> lastInstance
10module.exports.create = (config) ->
11
12 lastInstance = local =
13
14 #
15 # `loadModules( arrayOfNames, doesInstance )`
16 # -----------------------------------------
17 #
18 # * Asynchronously load the list of modules.
19 # * Used by `it()`'s and `before()`'s and `after()`'s in mocha (they're async)
20 # * Can load special case ipso.tag(ged) objects
21 # * Objects are assigned spectateability. ( `objct.does(...` )
22 #
23
24 loadModules: (arrayOfNames, doesInstance) ->
25
26 return promise = parallel( for moduleName in arrayOfNames
27
28 #
29 # https://github.com/nomilous/knowledge/blob/master/spec/promise/loops.coffee#L81
30 #
31
32 do (moduleName) -> -> return nestedPromise = pipeline [
33
34 ( ) -> local.loadModule moduleName, doesInstance
35 (module) -> doesInstance.spectate name: moduleName, tagged: false, module
36
37 ]
38 )
39
40
41 #
42 # `loadModulesSync( arrayOfNames, doesInstance )`
43 # ----------------------------------------------
44 #
45 # * Synchronously load the list of modules.
46 # * Used by `describe()`'s and `context()`'s in mocha (they're sync)
47 # * VERY IMPORTANT
48 # * does not load tagged objects
49 #
50
51 loadModulesSync: (arrayOfNames, doesInstance) ->
52
53 return arrayOfModules = for moduleName in arrayOfNames
54
55 Module = local.loadModuleSync moduleName, doesInstance
56 doesInstance.spectateSync name: moduleName, tagged: false, Module
57
58
59
60 dir: config.dir
61 modules: config.modules
62
63 upperCase: (string) ->
64
65 try char = string[0].charCodeAt 0
66 catch error
67 return false
68 return true if char > 64 and char < 91
69 return false
70
71 recurse: (name, path, matches) ->
72
73 for fd in readdirSync path
74 file = path + sep + fd
75 stat = lstatSync file
76 if stat.isDirectory()
77 local.recurse name, file, matches
78 continue
79
80 if match = fd.match new RegExp "^(#{name})\.(js|coffee)$"
81 matches.push dirname(file) + sep + name
82
83 find: (name) ->
84
85 matches = []
86 try local.recurse underscore(name), local.dir + sep + 'lib', matches
87 try local.recurse underscore(name), local.dir + sep + 'app', matches
88
89 if matches.length > 1 then throw new Error "ipso: found multiple matches for #{name}, use ipso.modules"
90 return matches[0]
91
92
93 loadModule: deferred (action, name, does) ->
94
95 #
96 # loadModule is async (promise)
97 # -----------------------------
98 #
99 # * enables ipso to involve network/db for does.tag(ged) object injection
100 # * first attempts to load a tagged object from does.tagged
101 # * falls back to local (synchronously loaded) modules
102 #
103
104 does.get query: tag: name, (error, spectated) ->
105
106 #
107 # * does.get() returns error on not found tag or bad args
108 # * for now those errors can be safely ignored
109 # * not found is valid reason to fall through to local injection below
110 # * bad args will not occur becase no pathway exists that leads through
111 # here to a call to does.get with bad args.
112 #
113
114 #
115 # * does.get() returns the entire spectated entity, including expectections,
116 # only resolve with the object itself for injection
117 #
118
119 return action.resolve spectated.object if spectated?
120 # return action.reject error if # TODO: network/db errors later
121
122 if path = (try local.modules[name].require)
123 if path[0] is '.' then path = normalize local.dir + sep + path
124 return action.resolve require path
125
126 return action.resolve require name unless local.upperCase name
127 return action.resolve require path if path = local.find name
128 console.log 'ipso: ' + "warning: missing module #{name}".yellow
129 return action.resolve {
130
131 $ipso:
132 PENDING: true
133 module: name
134
135 $save: (template = 'default') -> save template, name, does
136
137 }
138
139
140 loadModuleSync: (name, does) ->
141
142 if Module = (try does.getSync( query: tag: name ))
143 return Module
144
145 if path = (try local.modules[name].require)
146 console.log path: path
147 if path[0] is '.' then path = normalize local.dir + sep + path
148 return require path
149
150 return require name unless local.upperCase name
151 return require path if path = local.find name
152 console.log 'ipso: ' + "warning: missing module #{name}".yellow
153 return {
154
155 $ipso:
156 PENDING: true
157 module: name
158
159 $save: (template = 'default') -> save template, name, does
160
161 }
162
163
164
165 return api =
166
167 loadModules: local.loadModules
168 loadModulesSync: local.loadModulesSync
169
170
171
172