1 | [![Circle CI](https://circleci.com/gh/CureApp/base-domain.svg?style=svg)](https://circleci.com/gh/CureApp/base-domain)
|
2 |
|
3 | [![Stories in Progress](https://badge.waffle.io/CureApp/base-domain.png?label=In%20Progress&title=In Progress)](https://waffle.io/CureApp/base-domain)
|
4 | # base-domain
|
5 |
|
6 | framework for Domain-Driven Design in JavaScript (or CoffeeScript, recommended.)
|
7 |
|
8 | [latest API documentation Page](http://cureapp.github.io/base-domain/index.html)
|
9 |
|
10 |
|
11 | ## installation
|
12 |
|
13 | ```bash
|
14 | $ npm install -g base-domain
|
15 | ```
|
16 |
|
17 |
|
18 | ## concept
|
19 | base-domain helps easier practice of Domain-Driven Design.
|
20 |
|
21 | 1. list models in the domain of your concern (by your own way)
|
22 | 1. define models with base-domain
|
23 | 1. define their factories with base-domain
|
24 | 1. define their repositories with base-domain
|
25 | 1. define services with base-domain if needed
|
26 |
|
27 | ### essential classes and relations
|
28 | - Base
|
29 | - Facade
|
30 | - BaseModel
|
31 | - BaseFactory
|
32 | - BaseRepository
|
33 | - BaseService
|
34 | - Entity
|
35 | - AggregateRoot
|
36 | - ValueObject
|
37 | - BaseList
|
38 | - BaseDict
|
39 |
|
40 | ![class relations](https://github.com/CureApp/base-domain/blob/master/classes.png "base-domain-classes")
|
41 |
|
42 | #### Base
|
43 | [API Doc](http://cureapp.github.io/base-domain/classes/Base.html)
|
44 | - Base is an origin of all classes
|
45 | - Base has Facade
|
46 | - Base does not have any other properties or methods
|
47 |
|
48 | #### Facade
|
49 | [API Doc](http://cureapp.github.io/base-domain/classes/Facade.html)
|
50 | - Facade is the gate of all classes
|
51 | - Facade knows all classes
|
52 | - Facade is module-exported in base-domain: require('base-domain') returns Facade class
|
53 |
|
54 | #### BaseModel
|
55 | [API Doc](http://cureapp.github.io/base-domain/classes/BaseModel.html)
|
56 | - BaseModel is a base class of model
|
57 | - essential methods for model are defined
|
58 | - BaseModel is a child of Base
|
59 |
|
60 | #### BaseFactory
|
61 | [API Doc](http://cureapp.github.io/base-domain/classes/BaseFactory.html)
|
62 | - BaseFactory is a base class of factory
|
63 | - BaseFactory creates specific BaseModel instance
|
64 | - BaseFactory is a child of Base
|
65 |
|
66 | #### BaseRepository
|
67 | [API Doc](http://cureapp.github.io/base-domain/classes/BaseRepository.html)
|
68 | - BaseRepository is a base class of repository
|
69 | - BaseRepository connects to database, filesystem or other external data resources (settings needed).
|
70 | - BaseRepository saves specific BaseModel to data resources
|
71 | - BaseRepository read BaseModels from data resources
|
72 | - BaseRepository has BaseFactory (to generate BaseModel from data resources)
|
73 |
|
74 |
|
75 | #### ValueObject
|
76 | [API Doc](http://cureapp.github.io/base-domain/classes/ValueObject.html)
|
77 | - ValueObject is child of BaseModel
|
78 | - instance of ValueObject does not have id
|
79 | - ValueObject.isEntity is false
|
80 | - that's all of ValueObject
|
81 |
|
82 | #### Entity
|
83 | [API Doc](http://cureapp.github.io/base-domain/classes/Entity.html)
|
84 | - Entity is child of BaseModel
|
85 | - instance of Entity has id
|
86 | - Entity.isEntity is true
|
87 |
|
88 | #### AggregateRoot
|
89 | [API Doc](http://cureapp.github.io/base-domain/classes/AggregateRoot.html)
|
90 | - AggregateRoot is child of Entity
|
91 | - AggregateRoot implements RootInterface, thus it can create other models, factories and repositories.
|
92 |
|
93 | #### BaseList
|
94 | [API Doc](http://cureapp.github.io/base-domain/classes/BaseList.html)
|
95 | - BaseList is child of ValueObject
|
96 | - BaseList has many BaseModels as items
|
97 | - BaseList#items is array of specific BaseModel
|
98 |
|
99 | #### BaseDict
|
100 | [API Doc](http://cureapp.github.io/base-domain/classes/BaseDict.html)
|
101 | - BaseDict is child of ValueObject
|
102 | - BaseDict has many BaseModels as items
|
103 | - BaseDict#items is dictionary of key => specific BaseModel
|
104 | - BaseDict.key is function to get key from item
|
105 |
|
106 |
|
107 | ## usage
|
108 |
|
109 | ### model definition
|
110 | model is classified into "Entity" and "ValueObject"
|
111 |
|
112 | Entity is model with id, ValueObject is model without id.
|
113 |
|
114 | ```coffee
|
115 | # {domain-dir}/hospital.coffee
|
116 | class Hospital extends require('base-domain').Entity
|
117 |
|
118 | # property types
|
119 | @properties:
|
120 | name : @TYPES.STRING
|
121 | address : @TYPES.STRING
|
122 | beds : @TYPES.NUMBER
|
123 | registeredAt : @TYPES.DATE
|
124 | isValidated : @TYPES.BOOLEAN
|
125 | doctors : @TYPES.MODEL 'doctor-list'
|
126 | flags : @TYPES.MODEL 'flag-dict'
|
127 | state : @TYPES.ENUM ['PREPARED', 'RUNNING', 'CLOSED']
|
128 |
|
129 | module.exports = Hospital
|
130 | ```
|
131 | #### properties definition
|
132 |
|
133 | @TYPES.XXX is an object and also a function.
|
134 |
|
135 | ```coffee
|
136 | @properties:
|
137 | aaa: @TYPES.STRING
|
138 | bbb: @TYPES.NUMBER 3
|
139 | ccc: @TYPES.MODEL 'foo-bar'
|
140 | ```
|
141 |
|
142 | mark | property type | meaning | arg1 | arg2
|
143 | -----|-------------------|------------------------------|-----------------|-----------------------------------
|
144 | x | @TYPES.ANY | prop accepts any type | default value |
|
145 | x | @TYPES.STRING | prop is string | default value |
|
146 | x | @TYPES.NUMBER | prop is number | default value |
|
147 | x | @TYPES.DATE | prop is date | default value |
|
148 | x | @TYPES.BOOLEAN | prop is boolean | default value |
|
149 | x | @TYPES.ARRAY | prop is array | default value |
|
150 | x | @TYPES.OBJECT | prop is object | default value |
|
151 | x | @TYPES.BUFFER | prop is buffer | default value |
|
152 | x | @TYPES.GEOPOINT | prop is geopoint | default value |
|
153 | o | @TYPES.CREATED_AT | date set when first saved | default value |
|
154 | o | @TYPES.UPDATED_AT | date set each time saved | default value |
|
155 | o | @TYPES.MODEL | prop is BaseModel | model name | id prop name (if model is Entity)
|
156 | o | @TYPES.ENUM | prop is index of the alternatives | alternatives | default value
|
157 |
|
158 | Types with marked "x" just provide the name of the type.
|
159 | base-domain **does not validate** the prop's type.
|
160 |
|
161 |
|
162 |
|
163 | ### factory definition
|
164 | ```coffee
|
165 | # {domain-dir}/hospital-factory.coffee
|
166 | class HospitalFactory extends require('base-domain').BaseFactory
|
167 |
|
168 | @modelName: 'hospital'
|
169 |
|
170 | module.exports = HospitalFactory
|
171 | ```
|
172 |
|
173 | ### repository definition
|
174 | ```coffee
|
175 | # {domain-dir}/hospital-repository.coffee
|
176 | class HospitalRepository extends require('base-domain').BaseRepository
|
177 |
|
178 | @modelName: 'hospital'
|
179 |
|
180 | module.exports = HospitalRepository
|
181 | ```
|
182 |
|
183 |
|
184 | ### use them by facade
|
185 |
|
186 | ```coffee
|
187 | domain = require('base-domain').createInstance
|
188 | dirname: '/path/to/domain-dir'
|
189 |
|
190 |
|
191 | Hospital = domain.getModel('hospital')
|
192 | hospitalFactory = domain.createFactory('hospital')
|
193 | hospitalRepository = domain.createRepository('hospital')
|
194 |
|
195 | hosp = hospitalFactory.createFromObject(name: 'Suzuki Clinic')
|
196 |
|
197 |
|
198 | hospitalRepository.query(where: name: 'CureApp Hp.').then (hospitals)->
|
199 | console.log hospitals
|
200 |
|
201 | ```
|
202 |
|
203 | ### list definition
|
204 |
|
205 | ```coffee
|
206 | # {domain-dir}/hospital-list.coffee
|
207 | class HospitalList extends require('base-domain').BaseList
|
208 |
|
209 | @itemModelName: 'hospital'
|
210 |
|
211 | module.exports = HospitalList
|
212 | ```
|
213 |
|
214 | ### dict definition
|
215 |
|
216 | ```coffee
|
217 | # {domain-dir}/hospital-dict.coffee
|
218 | class HospitalDict extends require('base-domain').BaseDict
|
219 |
|
220 | @itemModelName: 'hospital'
|
221 | @key: (item) -> item.id
|
222 |
|
223 | module.exports = HospitalDict
|
224 | ```
|