base-domain
Version:
simple module to help build Domain-Driven Design
219 lines (136 loc) • 5.14 kB
text/coffeescript
'use strict'
through = require 'through'
fs = require 'fs'
Path = require 'path'
coffee = require 'coffee-script'
require('coffee-script/register')
Path.isAbsolute ?= (str) -> str.charAt(0) is '/'
Facade = require './lib/facade'
MasterDataResource = require './master-data-resource'
class BaseDomainify
constructor: (@moduleName = 'base-domain')->
@initialCodeGenerated = false
###*
get CoffeeScript code of adding addClass methods to all domain files
@method run
@public
@return {String} code CoffeeScript code
###
run: (@file, options = {}) ->
return through() if @initialCodeGenerated
{ dirname, modules } = options
@throwError() if not dirname
modulePaths = {}
for modNamePath in modules?.split(',') ? []
[modName, path] = modNamePath.split(':')
modulePaths[modName] = path
initialCode = @getInitialCode(dirname, modulePaths)
@initialCodeGenerated = true
data = ''
write = (buf) -> data += buf
end = -> @queue val for val in [initialCode, data, null]
return through write, end
relativePath: (path) ->
dir = Path.dirname(@file)
relPath = Path.relative(dir, path)
if relPath.charAt(0) isnt '.'
relPath = './' + relPath
return relPath
absolutePath: (path) ->
return path if Path.isAbsolute path
return process.cwd() + '/' + path
baseName: (path) ->
return Path.basename path
###*
get CoffeeScript code of adding addClass methods to all domain files
@method getInitialCode
@private
@return {String} code CoffeeScript code
###
getInitialCode: (dirname, modulePaths) ->
basename = @baseName dirname
_ = ' ' # spacer for indent
coffeeCode = """
Facade = require '#{@moduleName}'
Facade::init = ->
#{_}return unless @dirname.match '#{basename}'\n
"""
coffeeCode += @getScriptToLoadCoreModule(dirname)
coffeeCode += @getScriptToLoadModule(moduleName, path) for moduleName, path of modulePaths
coffeeCode += "#{_}return\n"
return coffee.compile(coffeeCode, bare: true)
getScriptToLoadCoreModule: (dirname) ->
_ = ' ' # spacer for indent
coffeeCode = ''
if masterJSONPath = @getMasterJSONPath(dirname)
coffeeCode += """
#{_}@master?.loadFromJSON = -> require('#{masterJSONPath}')\n
"""
for filename in @getFiles(dirname)
name = filename.split('.')[0]
path = @relativePath(dirname) + '/' + name
coffeeCode += """
#{_}@addClass '#{name}', require('#{path}')\n
"""
return coffeeCode
getScriptToLoadModule: (moduleName, moduleDirname) ->
basename = @baseName moduleDirname
_ = ' ' # spacer for indent
coffeeCode = """
#{_}if @modules['#{moduleName}'] and @modules['#{moduleName}'].path.match '#{basename}'\n
"""
for filename in @getFiles(moduleDirname)
name = filename.split('.')[0]
path = @relativePath(moduleDirname) + '/' + name
coffeeCode += """
#{_}#{_}@addClass '#{moduleName}/#{name}', require('#{path}')\n
"""
return coffeeCode
###*
@method getCodeOfMasterData
@private
@return {String} path
###
getMasterJSONPath: (dirname) ->
try
facade = Facade.createInstance(dirname: @absolutePath(dirname), master: true)
{ masterJSONPath } = facade.master
return '' if not fs.existsSync(masterJSONPath)
relPath = MasterDataResource.getJSONPath(@relativePath(dirname))
return relPath
catch e
return ''
###*
get domain files to load
@method getFiles
@private
@return {Array} filenames
###
getFiles: (dirname) ->
fileInfoDict = {}
path = @absolutePath(dirname)
for filename in fs.readdirSync(path)
[ name, ext ] = filename.split('.')
continue if ext not in ['js', 'coffee']
klass = require path + '/' + filename
fileInfoDict[name] = filename: filename, klass: klass
files = []
for name, fileInfo of fileInfoDict
{ klass, filename } = fileInfo
continue if filename in files
ParentClass = Object.getPrototypeOf(klass::).constructor
if ParentClass.className and pntFileName = fileInfoDict[ParentClass.getName()]?.filename
files.push pntFileName unless pntFileName in files
files.push filename
return files
###*
throw error
@method throwError
@private
###
throwError: ->
throw new Error """
dirname must be passed.
browserify -t [ base-domain/ify --dirname dirname --modules module1:/path/to/module1,module2:/path/to/module2 ]
"""
module.exports = BaseDomainify