UNPKG

5.71 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 if fd.match new RegExp "^#{name}.[js|coffee]"
80 matches.push dirname(file) + sep + name
81
82 find: (name) ->
83
84 matches = []
85 try local.recurse underscore(name), local.dir + sep + 'lib', matches
86 try local.recurse underscore(name), local.dir + sep + 'app', matches
87 if matches.length > 1 then throw new Error "ipso: found multiple matches for #{name}, use ipso.modules"
88 return matches[0]
89
90
91 loadModule: deferred (action, name, does) ->
92
93 #
94 # loadModule is async (promise)
95 # -----------------------------
96 #
97 # * enables ipso to involve network/db for does.tag(ged) object injection
98 # * first attempts to load a tagged object from does.tagged
99 # * falls back to local (synchronously loaded) modules
100 #
101
102 does.get query: tag: name, (error, spectated) ->
103
104 #
105 # * does.get() returns error on not found tag or bad args
106 # * for now those errors can be safely ignored
107 # * not found is valid reason to fall through to local injection below
108 # * bad args will not occur becase no pathway exists that leads through
109 # here to a call to does.get with bad args.
110 #
111
112 #
113 # * does.get() returns the entire spectated entity, including expectections,
114 # only resolve with the object itself for injection
115 #
116
117 return action.resolve spectated.object if spectated?
118 # return action.reject error if # TODO: network/db errors later
119
120 if path = (try local.modules[name].require)
121 if path[0] is '.' then path = normalize local.dir + sep + path
122 return action.resolve require path
123
124 return action.resolve require name unless local.upperCase name
125 return action.resolve require path if path = local.find name
126 console.log 'ipso: ' + "warning: missing module #{name}".yellow
127 return action.resolve {
128
129 $ipso:
130 PENDING: true
131 module: name
132
133 $save: (template = 'default') -> save template, name, does
134
135 }
136
137
138 loadModuleSync: (name, does) ->
139
140 try return does.getSync( query: tag: name )
141 if path = (try local.modules[name].require)
142 if path[0] is '.' then path = normalize local.dir + sep + path
143 return require path
144
145 return require name unless local.upperCase name
146 return require path if path = local.find name
147 console.log 'ipso: ' + "warning: missing module #{name}".yellow
148 return {
149
150 $ipso:
151 PENDING: true
152 module: name
153
154 $save: (template = 'default') -> save template, name, does
155
156 }
157
158
159
160 return api =
161
162 loadModules: local.loadModules
163 loadModulesSync: local.loadModulesSync
164
165
166
167