base-domain
Version:
simple module to help build Domain-Driven Design
297 lines (219 loc) • 6.88 kB
text/coffeescript
require('es6-promise').polyfill()
copy = require('copy-class').copy
{ camelize, requireFile } = require './util'
getProto = Object.getPrototypeOf ? (obj) -> obj.__proto__
###*
Facade class of DDD pattern.
- create instance of factories
- create instance of repositories
Facade
base-domain
###
class Facade
###*
create instance of Facade
createInstance
{Object} [options]
{Facade}
###
: (options= {}) ->
Constructor = @
return new Constructor(options)
###*
constructor
{String} [options]
{String} [options.dirname="."] path where domain definition files are included
###
constructor: (options) ->
= {}
= options.dirname ? '.'
()
# for base-domainify. keep it empty
init: ->
###*
load master tables
loadMasterTables
{Promise}
###
loadMasterTables: (modelNames...) ->
Promise.all ((modelName).load?() for modelName in modelNames)
###*
get a model class
getModel
{String} name
{Class}
###
getModel: (name) ->
return (name)
###*
get a factory class
ISSUE: user will never know load failure
@method getFactory
@param {String} name
{Boolean} [useAnonymousWhenFailed=false]
{Function}
###
getFactory: (name, useAnonymousWhenFailed = off) ->
try
return ("#{name}-factory")
catch e
throw e if not useAnonymousWhenFailed
AnonymousFactory = Facade.BaseFactory.getAnonymousClass(name)
("#{name}-factory", AnonymousFactory, true)
###*
get a repository class
getRepository
{String} name
{Class}
###
getRepository: (name) ->
return ("#{name}-repository")
###*
create a factory instance
createFactory
{String} name
{Boolean} [useAnonymousWhenFailed=false]
{BaseFactory}
###
createFactory: (name, useAnonymousWhenFailed = off) ->
FactoryClass = (name, useAnonymousWhenFailed)
return new FactoryClass()
###*
create a repository instance
createRepository
{String} name
{Object} [options]
{BaseRepository}
###
createRepository: (name, options) ->
("#{name}-repository", options)
###*
read a file and returns class
require
{String} name
{Function}
###
require: (name) ->
return [name] if [name]?
file = "#{@dirname}/#{name}"
klass = requireFile file
name, klass
###*
check existence of the class of the given name
hasClass
{String} name
{Function}
###
hasClass: (name) ->
try
(name)
return true
catch e
return false
###*
add copied class to facade.
the class is acquired by (name)
attaches getFacade() method (for both class and instance)
addClass
{String} name
{Function} klass
{Boolean} skipNameValidation validate class name is compatible with the name to register
{Function}
###
addClass: (name, klass, skipNameValidation = false) ->
if skipNameValidation
camelCasedName = camelize name
else
if klass.getName() isnt name
throw """given class should be named '#{klass.getName()}',
but '#{name}' given."""
camelCasedName = klass.name
ParentClass = getProto(klass::).constructor
if .isBaseClass ParentClass
Class = copy(klass, camelCasedName)
else
CopiedParentClass = ParentClass.getName()
Class = copy(klass, camelCasedName, CopiedParentClass)
facade = @
Class.getFacade = -> facade
Class::getFacade = -> facade
[name] = Class
###*
read a file and returns the instance of the file's class
create
{String} name
{Object} [options]
{BaseFactory}
###
create: (name, options) ->
DomainClass = (name)
return new DomainClass(options)
###*
create instance of DomainError
error
{String} reason reason of the error
{String} [message]
{Error}
###
error: (reason, message) ->
DomainError = .DomainError
return new DomainError(reason, message)
###*
check if given object is instance of DomainError
isDomainError
{Error} e
{Boolean}
###
isDomainError: (e) ->
DomainError = .DomainError
return e instanceof DomainError
###*
insert fixture data
(Node.js only)
insertFixtures
{Object} [options]
{String} [options.dataDir='./data'] directory to have fixture data files
{String} [options.tsvDir='./tsv'] directory to have TSV files
{Array(String)} [options.models=null] model names to insert. default: all models
{Promise(Object)} dataPool inserted data
###
insertFixtures: (options = {}) ->
Fixture = require './fixture'
fixture = new Fixture(@, options)
fixture.insert(options.models).then ->
return fixture.dataPool
###*
check the given class is registered in facade
isBaseClass
{Function} klass
{Boolean}
###
: (klass) ->
(klass is @[klass.name]) or
(klass is ) or
(@[klass.name]?.toString() is klass.toString())
###*
registers the given class as a base class
registerBaseClass
{Function} klass
###
: (klass) -> @[klass.name] = klass
: require './base'
: require './base-model'
: require './entity'
: require './base-list'
: require './base-dict'
: require './base-factory'
: require './list-factory'
: require './dict-factory'
: require './base-repository'
: require './master-repository'
: require './domain-error'
module.exports = Facade