api_sketch 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +404 -0
- data/Rakefile +8 -0
- data/api_sketch.gemspec +30 -0
- data/bin/api_sketch +10 -0
- data/lib/api_sketch/config.rb +7 -0
- data/lib/api_sketch/dsl.rb +213 -0
- data/lib/api_sketch/error.rb +2 -0
- data/lib/api_sketch/examples_server.rb +54 -0
- data/lib/api_sketch/generators.rb +87 -0
- data/lib/api_sketch/helpers.rb +21 -0
- data/lib/api_sketch/model.rb +227 -0
- data/lib/api_sketch/renderers.rb +48 -0
- data/lib/api_sketch/runner.rb +92 -0
- data/lib/api_sketch/templates/bootstrap/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/lib/api_sketch/templates/bootstrap/assets/fonts/glyphicons-halflings-regular.svg +229 -0
- data/lib/api_sketch/templates/bootstrap/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/lib/api_sketch/templates/bootstrap/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/lib/api_sketch/templates/bootstrap/assets/images/favicon.ico +0 -0
- data/lib/api_sketch/templates/bootstrap/assets/javascripts/bootstrap.js +2114 -0
- data/lib/api_sketch/templates/bootstrap/assets/javascripts/bootstrap.min.js +6 -0
- data/lib/api_sketch/templates/bootstrap/assets/javascripts/docs.min.js +24 -0
- data/lib/api_sketch/templates/bootstrap/assets/javascripts/ie10-viewport-bug-workaround.js +22 -0
- data/lib/api_sketch/templates/bootstrap/assets/javascripts/jquery-1.11.1.min.js +4 -0
- data/lib/api_sketch/templates/bootstrap/assets/stylesheets/bootstrap-theme.css +442 -0
- data/lib/api_sketch/templates/bootstrap/assets/stylesheets/bootstrap-theme.css.map +1 -0
- data/lib/api_sketch/templates/bootstrap/assets/stylesheets/bootstrap-theme.min.css +5 -0
- data/lib/api_sketch/templates/bootstrap/assets/stylesheets/bootstrap.css +6203 -0
- data/lib/api_sketch/templates/bootstrap/assets/stylesheets/bootstrap.css.map +1 -0
- data/lib/api_sketch/templates/bootstrap/assets/stylesheets/bootstrap.min.css +5 -0
- data/lib/api_sketch/templates/bootstrap/assets/stylesheets/dashboard.css +130 -0
- data/lib/api_sketch/templates/bootstrap/resource.html.erb +215 -0
- data/lib/api_sketch/version.rb +3 -0
- data/lib/api_sketch.rb +19 -0
- data/spec/lib/dsl_spec.rb +474 -0
- data/spec/spec_helper.rb +1 -0
- metadata +187 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6908ab17b9fdfd6d03c2a70024e302fc9e5b7860
|
4
|
+
data.tar.gz: 4444f8b4898282b779172e6111b59bbf80e586e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bf925a6d9b5431b0a5e9d6f63259c42227e366100a9bc51251e874e0d1424feb6caa2801a5a23640aa221cda181931590361e2355b2df5737214d182b51722a9
|
7
|
+
data.tar.gz: 6b8e5af2fd9decc7b1e1b7c75345f06cb185545dcc9075105ee4c223496a937cb297327feb9278b1c497541d8c8d84861ad39577e97052d2cf269a56d24f12b2
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
api_sketch
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1.2
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Alexey Suhoviy
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,404 @@
|
|
1
|
+
# Api Sketch
|
2
|
+
------------
|
3
|
+
|
4
|
+
api_sketch gem provides you with DSL to describe and create API documentation.
|
5
|
+
|
6
|
+
It consists of three main parts:
|
7
|
+
|
8
|
+
1. API definitions DSL
|
9
|
+
2. Documentation generator
|
10
|
+
3. API example responses server
|
11
|
+
|
12
|
+
---
|
13
|
+
|
14
|
+
Installation
|
15
|
+
------------
|
16
|
+
|
17
|
+
Include the gem in your Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem 'api_sketch'
|
21
|
+
```
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
|
25
|
+
$ gem install api_sketch
|
26
|
+
|
27
|
+
Usage
|
28
|
+
-----
|
29
|
+
|
30
|
+
Gem is bundled with the same named executable. It's supported options list is provided below.
|
31
|
+
|
32
|
+
```
|
33
|
+
$ api_sketch -h
|
34
|
+
Usage: /bin/api_sketch (options)
|
35
|
+
-d, --debug Run in verbose mode
|
36
|
+
-i, --input DEFINITIONS Path to the folder with api definitions (required)
|
37
|
+
-o, --output DOCUMENTATION Path to the folder where generated documentation should be saved (Default is 'documentation' folder in current folder)
|
38
|
+
-s, --server Run api examples server
|
39
|
+
-p, --port PORT Api examples server port (Default is 3127)
|
40
|
+
-g, --generate Generate documentation from provided definitions
|
41
|
+
-n, --name PROJECT_NAME Name of the project. (Default is derived from DEFINITIONS folder name)
|
42
|
+
-v, --version Show version number
|
43
|
+
-h, --help Show this help
|
44
|
+
```
|
45
|
+
|
46
|
+
### Documentation generation
|
47
|
+
|
48
|
+
Documentaion generation command example:
|
49
|
+
|
50
|
+
```
|
51
|
+
$ api_sketch -g -i definitions -o documentation
|
52
|
+
```
|
53
|
+
### API example responses server
|
54
|
+
|
55
|
+
Start API example responses server command example:
|
56
|
+
|
57
|
+
```
|
58
|
+
$ api_sketch -s -i definitions
|
59
|
+
[2015-04-12 20:46:19] INFO WEBrick 1.3.1
|
60
|
+
[2015-04-12 20:46:19] INFO ruby 2.1.2 (2014-05-08) [x86_64-darwin13.0]
|
61
|
+
[2015-04-12 20:46:19] INFO WEBrick::HTTPServer#start: pid=5874 port=3127
|
62
|
+
```
|
63
|
+
After this server was started response example may be accessed with this kind url:
|
64
|
+
|
65
|
+
```
|
66
|
+
http://localhost:3127/.json?api_sketch_resource_id=users/update&api_sketch_response_context=Success
|
67
|
+
```
|
68
|
+
|
69
|
+
```json
|
70
|
+
{
|
71
|
+
"user":{
|
72
|
+
"id":345,
|
73
|
+
"email":"user44@email.com",
|
74
|
+
"first_name":"First name 20",
|
75
|
+
"last_name":"Last name 96",
|
76
|
+
"country":{
|
77
|
+
"name":"Ukraine",
|
78
|
+
"id":"UA"
|
79
|
+
},
|
80
|
+
"authentications":[
|
81
|
+
{
|
82
|
+
"uid":"6668-5565-3835-6085-8727",
|
83
|
+
"provider":"facebook"
|
84
|
+
}
|
85
|
+
]
|
86
|
+
}
|
87
|
+
}
|
88
|
+
```
|
89
|
+
|
90
|
+
`api_sketch_resource_id` and `api_sketch_response_context` parameters are used to determine which response should be returned.
|
91
|
+
|
92
|
+
Definitions
|
93
|
+
-----------
|
94
|
+
|
95
|
+
##### Folder
|
96
|
+
|
97
|
+
API definitions files should be placed into directory with structure similar to `definitions` folder in this example. Directory may have only one file or many files and folders with files. Resurce's `namespace` is derived from this hierachical structure.
|
98
|
+
|
99
|
+
```
|
100
|
+
definitions
|
101
|
+
├── places.rb
|
102
|
+
├── users
|
103
|
+
│ └── points.rb
|
104
|
+
└── users.rb
|
105
|
+
```
|
106
|
+
##### DSL
|
107
|
+
|
108
|
+
Definitions DSL is writen in ruby. It consists of special keywords that are used to describe API endpoint resource's request options, url, and list of possible responses.
|
109
|
+
|
110
|
+
Here is dummy example of `resource` definition that includes most part of DSL syntax.
|
111
|
+
|
112
|
+
`action` and `namespace` both form resource ID that should be unique. For this current case resource ID would be `users/update`.
|
113
|
+
|
114
|
+
If `namespace` is omitted than it would be derived from folders structure and file name where this defintion is placed in. So, for example if definition is placed inside `users/points.rb` than it's namespace is `users/points`.
|
115
|
+
|
116
|
+
DSL provides `path`, `http_method`, `headers`, `parameters` keywords for request data definition. Parameters could be placed at `query` and `body` containers. Both of them could have `:array` or `:document` structure.
|
117
|
+
|
118
|
+
Supported attribute types are: `integer`, `string`, `float`, `boolean`, `datetime`, `timestamp`, `document`, `array`
|
119
|
+
|
120
|
+
Each attribute should have name, could have `description`, `example` value, could be `required`.
|
121
|
+
|
122
|
+
`example` keyword accepts callable blocks or just some simple values. Callable blocks may give new value each time `example_value` is requested.
|
123
|
+
|
124
|
+
Array and query attribute types have `content` keyword where their contents are placed in.
|
125
|
+
|
126
|
+
Each `resource` could have many `responses` with different `context`. For example succesful one and few with different errors. Especially for `responses` it is better to provide detailed `example` values as they could be used as responses by examples server.
|
127
|
+
|
128
|
+
Resource `parameters` section's syntax it the same as for `resource` request parameters.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
resource "Update user profile" do # Resource name
|
132
|
+
action "update"
|
133
|
+
namespace "users"
|
134
|
+
description "Authenticated user could update his profile fields and password"
|
135
|
+
path "/api/users/me.json" # Server path where this endpoint would be processed
|
136
|
+
http_method "PUT" # http request method
|
137
|
+
format "json" # response format
|
138
|
+
|
139
|
+
headers do
|
140
|
+
add "Authorization" do
|
141
|
+
value "Token token=:token_value"
|
142
|
+
description ":token_value - is an authorization token value"
|
143
|
+
example { (:A..:z).to_a.shuffle[0,16].join }
|
144
|
+
required true
|
145
|
+
end
|
146
|
+
|
147
|
+
add "X-Test" do
|
148
|
+
value "Test=:perform_test"
|
149
|
+
description ":perform_test - test boolean value"
|
150
|
+
example true
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
parameters do
|
155
|
+
# parametes could be query and body
|
156
|
+
query :document do
|
157
|
+
string "hello_message" do
|
158
|
+
description "some message"
|
159
|
+
end
|
160
|
+
|
161
|
+
integer "repeat_times" do
|
162
|
+
description "times to repeat hello message"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
query :document do
|
167
|
+
integer "page" do
|
168
|
+
description "page number"
|
169
|
+
required false
|
170
|
+
default 1
|
171
|
+
end
|
172
|
+
|
173
|
+
integer "per_page" do
|
174
|
+
description "items per page amount"
|
175
|
+
required false
|
176
|
+
default 25
|
177
|
+
end
|
178
|
+
|
179
|
+
string "name" do
|
180
|
+
description "place name"
|
181
|
+
required true
|
182
|
+
end
|
183
|
+
|
184
|
+
float "range" do
|
185
|
+
description "search range in km"
|
186
|
+
required false
|
187
|
+
example { rand(100) + rand.round(2) }
|
188
|
+
end
|
189
|
+
|
190
|
+
datetime "start_at" do
|
191
|
+
description "start at datetime"
|
192
|
+
required false
|
193
|
+
example { Time.now.to_s }
|
194
|
+
end
|
195
|
+
|
196
|
+
timestamp "seconds" do
|
197
|
+
description "seconds today"
|
198
|
+
example { Time.now.to_i }
|
199
|
+
end
|
200
|
+
|
201
|
+
array "place_ids" do
|
202
|
+
description "user's places ids"
|
203
|
+
required false
|
204
|
+
content do
|
205
|
+
integer do
|
206
|
+
description "hello number"
|
207
|
+
end
|
208
|
+
string do
|
209
|
+
description "more text here"
|
210
|
+
end
|
211
|
+
document do
|
212
|
+
content do
|
213
|
+
boolean "is_it_true" do
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
document do
|
218
|
+
description "some useless data :)"
|
219
|
+
content do
|
220
|
+
string "test" do
|
221
|
+
description "test string"
|
222
|
+
end
|
223
|
+
document "keys" do
|
224
|
+
content do
|
225
|
+
integer "sum" do
|
226
|
+
end
|
227
|
+
string "details text" do
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
body :document do
|
239
|
+
document "user" do
|
240
|
+
description "user's parameters fields"
|
241
|
+
required true
|
242
|
+
content do
|
243
|
+
string "email" do
|
244
|
+
description "user's email value"
|
245
|
+
end
|
246
|
+
string "password" do
|
247
|
+
description "user's profile password"
|
248
|
+
end
|
249
|
+
string "first_name" do
|
250
|
+
description "user's first name"
|
251
|
+
end
|
252
|
+
string "last_name" do
|
253
|
+
description "user's last name"
|
254
|
+
end
|
255
|
+
string "country_locode" do
|
256
|
+
example { ["US", "UA"].sample }
|
257
|
+
description "Country location code"
|
258
|
+
end
|
259
|
+
|
260
|
+
document "stats" do
|
261
|
+
content do
|
262
|
+
timestamp "login_at" do
|
263
|
+
description "last login timestamp"
|
264
|
+
example { Time.now.to_i }
|
265
|
+
end
|
266
|
+
|
267
|
+
integer "login_count" do
|
268
|
+
description "login count"
|
269
|
+
example { rand(10000) }
|
270
|
+
end
|
271
|
+
|
272
|
+
string "rank" do
|
273
|
+
description "users rank"
|
274
|
+
example { ["Junior", "Middle", "Senior"].sample }
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
responses do
|
284
|
+
context "Success" do
|
285
|
+
http_status :ok # 200
|
286
|
+
|
287
|
+
parameters do
|
288
|
+
body :document do
|
289
|
+
document "user" do
|
290
|
+
content do
|
291
|
+
integer "id" do
|
292
|
+
description "User's ID"
|
293
|
+
end
|
294
|
+
string "email" do
|
295
|
+
description "user's email value"
|
296
|
+
example { "user#{rand(100)}@email.com" }
|
297
|
+
end
|
298
|
+
string "first_name" do
|
299
|
+
description "user's first name"
|
300
|
+
example { "First name #{rand(100)}" }
|
301
|
+
end
|
302
|
+
string "last_name" do
|
303
|
+
description "user's last name"
|
304
|
+
example { "Last name #{rand(100)}" }
|
305
|
+
end
|
306
|
+
document "country" do
|
307
|
+
content do
|
308
|
+
string "name" do
|
309
|
+
description "Country name"
|
310
|
+
example { ["USA", "Ukraine", "Poland"].sample }
|
311
|
+
end
|
312
|
+
string "id" do
|
313
|
+
example :location_code
|
314
|
+
description "Country ID (Location code)"
|
315
|
+
example { ["US", "UA", "PL"].sample }
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
array "authentications" do
|
320
|
+
content do
|
321
|
+
document do
|
322
|
+
content do
|
323
|
+
string "uid" do
|
324
|
+
description "user's id at social network"
|
325
|
+
example { 5.times.map { 4.times.map { rand(10).to_s }.join }.join("-") }
|
326
|
+
end
|
327
|
+
string "provider" do
|
328
|
+
example { "facebook" }
|
329
|
+
description "user's social network type"
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
context "Failure" do
|
342
|
+
http_status :bad_request # 400
|
343
|
+
|
344
|
+
parameters do
|
345
|
+
body :document do
|
346
|
+
document "error" do
|
347
|
+
content do
|
348
|
+
string "message" do
|
349
|
+
description "Error description"
|
350
|
+
example { "Epic fail at your parameters" }
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
```
|
360
|
+
|
361
|
+
For more detailed DSL features examples check DSL test files at spec folder.
|
362
|
+
|
363
|
+
TODO
|
364
|
+
----
|
365
|
+
|
366
|
+
- Clean genrated documentation html template css, javascripts. Remove useless classes, html, etc.
|
367
|
+
- Add local javascript search feature at generated html docs
|
368
|
+
- Add API index page similar to [Foursquare API docs](https://developer.foursquare.com/docs/)
|
369
|
+
- Improve documentation, add more examples
|
370
|
+
- Add more documentation templates. For example PDF, curl, some other html styles, etc. It should be configurable as api_sketch command line option. This might be made as some separate extensions gem. There also could be generators for some specific framework api controllers structure scaffold generators.
|
371
|
+
- Put all generated pages data into `{output_folder}/docs` directory. Left `assets` directory outside since it may clash with generated files/folders names.
|
372
|
+
- API examples server also should support endpoint search by request `path` & `http_method` like normal api server does.
|
373
|
+
- Deal with query body at responses (For example redirects may have query body)
|
374
|
+
- Validate HTTP method with path, http method and action unique composition
|
375
|
+
- Add other request/response types like plaintext, xml, etc (should be supprted both at generator and server)
|
376
|
+
- Add realtime viewable page with log for this api examples server application to let client side developers see what data they have sent and how server received it
|
377
|
+
- Add more validations to models.
|
378
|
+
- Add more specs and tests.
|
379
|
+
- Add `shared_block "shared block name"` (definition keyword) search keyword by it's to blocks. Maybe `uses_shared_block "shared block name"`. Maybe shared blocks should be placed into special directory at definitions to be loaded before all examples
|
380
|
+
- Add more complex example values autogeneration for API examples server. Derive values from key names. For example string "email" should have some email value as response example.
|
381
|
+
- Add `api_sketch_response_array_elements_count` for responses server. It should generate responses with provided array elements counts. If array contains different type values than each type of these elements should be placed to response multiple times.
|
382
|
+
- rDoc documentation for code.
|
383
|
+
|
384
|
+
Contributing
|
385
|
+
------------
|
386
|
+
|
387
|
+
1. Fork it ( https://github.com/suhovius/api_sketch/fork )
|
388
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
389
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
390
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
391
|
+
5. Create a new Pull Request
|
392
|
+
|
393
|
+
Inspirations
|
394
|
+
------------
|
395
|
+
- [Calamum](https://github.com/malachheb/calamum)
|
396
|
+
- [Apiary](http://apiary.io/blueprint)
|
397
|
+
- [IO Docs](https://github.com/mashery/iodocs)
|
398
|
+
- [Swagger](https://developers.helloreverb.com/swagger)
|
399
|
+
|
400
|
+
|
401
|
+
License
|
402
|
+
-------
|
403
|
+
|
404
|
+
ApiSketch is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
|
data/Rakefile
ADDED
data/api_sketch.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require File.expand_path('../lib/api_sketch/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "api_sketch"
|
6
|
+
spec.version = ApiSketch::VERSION
|
7
|
+
spec.authors = ["Alexey Suhoviy"]
|
8
|
+
spec.email = ["martinsilenn@gmail.com"]
|
9
|
+
spec.summary = %q{API Prototyping and API Documentation Tool}
|
10
|
+
spec.description = %q{Gem provides DSL for API documentation generation and API request examples server}
|
11
|
+
|
12
|
+
spec.homepage = "https://github.com/suhovius/api_sketch"
|
13
|
+
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.post_install_message = "Thanks for installing!"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency 'mixlib-cli'
|
23
|
+
spec.add_dependency 'mixlib-config'
|
24
|
+
spec.add_dependency 'rack'
|
25
|
+
spec.add_dependency 'rack-contrib'
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
spec.add_development_dependency "rspec"
|
30
|
+
end
|
data/bin/api_sketch
ADDED