@kalisio/kdk 2.6.3 → 2.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/core/api/hooks/hooks.model.js +1 -1
  2. package/extras/tours/pane.top.js +9 -0
  3. package/map/client/i18n/map_en.json +2 -1
  4. package/map/client/i18n/map_fr.json +2 -1
  5. package/package.json +1 -1
  6. package/test/api/core/test-log-2026-03-26.log +0 -0
  7. package/client/css/core.variables.scss +0 -72
  8. package/client/i18n/core_en.json +0 -744
  9. package/client/i18n/core_fr.json +0 -744
  10. package/client/i18n/map_en.json +0 -800
  11. package/client/i18n/map_fr.json +0 -800
  12. package/client/kdk.client.css +0 -47
  13. package/client/kdk.client.js +0 -41097
  14. package/client/kdk.client.map.css +0 -47
  15. package/client/kdk.client.map.js +0 -38182
  16. package/client/kdk.client.map.min.css +0 -1
  17. package/client/kdk.client.map.min.js +0 -27032
  18. package/client/kdk.client.min.css +0 -1
  19. package/client/kdk.client.min.js +0 -29074
  20. package/client/schemas/capture.create.json +0 -132
  21. package/client/schemas/catalog.update.json +0 -44
  22. package/client/schemas/messages.update.json +0 -16
  23. package/client/schemas/projects.create.json +0 -52
  24. package/client/schemas/projects.update.json +0 -52
  25. package/client/schemas/settings.update.json +0 -286
  26. package/client/schemas/tags.update.json +0 -35
  27. package/client/schemas/users.update-profile.json +0 -34
  28. package/coverage/base.css +0 -224
  29. package/coverage/block-navigation.js +0 -87
  30. package/coverage/core/api/application.js.html +0 -1864
  31. package/coverage/core/api/authentication.js.html +0 -907
  32. package/coverage/core/api/db.js.html +0 -817
  33. package/coverage/core/api/hooks/hooks.authentication.js.html +0 -139
  34. package/coverage/core/api/hooks/hooks.authorisations.js.html +0 -964
  35. package/coverage/core/api/hooks/hooks.logger.js.html +0 -163
  36. package/coverage/core/api/hooks/hooks.model.js.html +0 -967
  37. package/coverage/core/api/hooks/hooks.push.js.html +0 -268
  38. package/coverage/core/api/hooks/hooks.query.js.html +0 -910
  39. package/coverage/core/api/hooks/hooks.schemas.js.html +0 -298
  40. package/coverage/core/api/hooks/hooks.service.js.html +0 -319
  41. package/coverage/core/api/hooks/hooks.storage.js.html +0 -193
  42. package/coverage/core/api/hooks/hooks.tags.js.html +0 -253
  43. package/coverage/core/api/hooks/hooks.users.js.html +0 -676
  44. package/coverage/core/api/hooks/index.html +0 -281
  45. package/coverage/core/api/hooks/index.js.html +0 -115
  46. package/coverage/core/api/index.html +0 -176
  47. package/coverage/core/api/index.js.html +0 -148
  48. package/coverage/core/api/marshall.js.html +0 -448
  49. package/coverage/core/api/models/configurations.model.mongodb.js.html +0 -97
  50. package/coverage/core/api/models/index.html +0 -161
  51. package/coverage/core/api/models/messages.model.mongodb.js.html +0 -121
  52. package/coverage/core/api/models/tags.model.mongodb.js.html +0 -109
  53. package/coverage/core/api/models/users.model.mongodb.js.html +0 -115
  54. package/coverage/core/api/services/account/account.hooks.js.html +0 -208
  55. package/coverage/core/api/services/account/account.service.js.html +0 -436
  56. package/coverage/core/api/services/account/index.html +0 -131
  57. package/coverage/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  58. package/coverage/core/api/services/authorisations/authorisations.service.js.html +0 -520
  59. package/coverage/core/api/services/authorisations/index.html +0 -131
  60. package/coverage/core/api/services/configurations/configurations.hooks.js.html +0 -184
  61. package/coverage/core/api/services/configurations/index.html +0 -116
  62. package/coverage/core/api/services/databases/databases.hooks.js.html +0 -193
  63. package/coverage/core/api/services/databases/databases.service.js.html +0 -100
  64. package/coverage/core/api/services/databases/index.html +0 -131
  65. package/coverage/core/api/services/import-export/import-export.hooks.js.html +0 -184
  66. package/coverage/core/api/services/import-export/import-export.service.js.html +0 -118
  67. package/coverage/core/api/services/import-export/index.html +0 -131
  68. package/coverage/core/api/services/index.html +0 -116
  69. package/coverage/core/api/services/index.js.html +0 -727
  70. package/coverage/core/api/services/mailer/index.html +0 -131
  71. package/coverage/core/api/services/mailer/mailer.hooks.js.html +0 -190
  72. package/coverage/core/api/services/mailer/mailer.service.js.html +0 -118
  73. package/coverage/core/api/services/messages/index.html +0 -116
  74. package/coverage/core/api/services/messages/messages.hooks.js.html +0 -220
  75. package/coverage/core/api/services/push/index.html +0 -131
  76. package/coverage/core/api/services/push/push.hooks.js.html +0 -190
  77. package/coverage/core/api/services/push/push.service.js.html +0 -121
  78. package/coverage/core/api/services/storage/index.html +0 -131
  79. package/coverage/core/api/services/storage/storage.hooks.js.html +0 -190
  80. package/coverage/core/api/services/storage/storage.service.js.html +0 -172
  81. package/coverage/core/api/services/tags/index.html +0 -116
  82. package/coverage/core/api/services/tags/tags.hooks.js.html +0 -226
  83. package/coverage/core/api/services/users/index.html +0 -131
  84. package/coverage/core/api/services/users/users.hooks.js.html +0 -310
  85. package/coverage/core/api/services/users/users.service.js.html +0 -100
  86. package/coverage/core/common/errors.js.html +0 -88
  87. package/coverage/core/common/index.html +0 -191
  88. package/coverage/core/common/index.js.html +0 -115
  89. package/coverage/core/common/permissions.js.html +0 -742
  90. package/coverage/core/common/schema.js.html +0 -190
  91. package/coverage/core/common/utils.js.html +0 -226
  92. package/coverage/core/common/utils.offline.js.html +0 -199
  93. package/coverage/favicon.png +0 -0
  94. package/coverage/index.html +0 -506
  95. package/coverage/lcov-report/base.css +0 -224
  96. package/coverage/lcov-report/block-navigation.js +0 -87
  97. package/coverage/lcov-report/core/api/application.js.html +0 -1864
  98. package/coverage/lcov-report/core/api/authentication.js.html +0 -907
  99. package/coverage/lcov-report/core/api/db.js.html +0 -817
  100. package/coverage/lcov-report/core/api/hooks/hooks.authentication.js.html +0 -139
  101. package/coverage/lcov-report/core/api/hooks/hooks.authorisations.js.html +0 -964
  102. package/coverage/lcov-report/core/api/hooks/hooks.logger.js.html +0 -163
  103. package/coverage/lcov-report/core/api/hooks/hooks.model.js.html +0 -967
  104. package/coverage/lcov-report/core/api/hooks/hooks.push.js.html +0 -268
  105. package/coverage/lcov-report/core/api/hooks/hooks.query.js.html +0 -910
  106. package/coverage/lcov-report/core/api/hooks/hooks.schemas.js.html +0 -298
  107. package/coverage/lcov-report/core/api/hooks/hooks.service.js.html +0 -319
  108. package/coverage/lcov-report/core/api/hooks/hooks.storage.js.html +0 -193
  109. package/coverage/lcov-report/core/api/hooks/hooks.tags.js.html +0 -253
  110. package/coverage/lcov-report/core/api/hooks/hooks.users.js.html +0 -676
  111. package/coverage/lcov-report/core/api/hooks/index.html +0 -281
  112. package/coverage/lcov-report/core/api/hooks/index.js.html +0 -115
  113. package/coverage/lcov-report/core/api/index.html +0 -176
  114. package/coverage/lcov-report/core/api/index.js.html +0 -148
  115. package/coverage/lcov-report/core/api/marshall.js.html +0 -448
  116. package/coverage/lcov-report/core/api/models/configurations.model.mongodb.js.html +0 -97
  117. package/coverage/lcov-report/core/api/models/index.html +0 -161
  118. package/coverage/lcov-report/core/api/models/messages.model.mongodb.js.html +0 -121
  119. package/coverage/lcov-report/core/api/models/tags.model.mongodb.js.html +0 -109
  120. package/coverage/lcov-report/core/api/models/users.model.mongodb.js.html +0 -115
  121. package/coverage/lcov-report/core/api/services/account/account.hooks.js.html +0 -208
  122. package/coverage/lcov-report/core/api/services/account/account.service.js.html +0 -436
  123. package/coverage/lcov-report/core/api/services/account/index.html +0 -131
  124. package/coverage/lcov-report/core/api/services/authorisations/authorisations.hooks.js.html +0 -184
  125. package/coverage/lcov-report/core/api/services/authorisations/authorisations.service.js.html +0 -520
  126. package/coverage/lcov-report/core/api/services/authorisations/index.html +0 -131
  127. package/coverage/lcov-report/core/api/services/configurations/configurations.hooks.js.html +0 -184
  128. package/coverage/lcov-report/core/api/services/configurations/index.html +0 -116
  129. package/coverage/lcov-report/core/api/services/databases/databases.hooks.js.html +0 -193
  130. package/coverage/lcov-report/core/api/services/databases/databases.service.js.html +0 -100
  131. package/coverage/lcov-report/core/api/services/databases/index.html +0 -131
  132. package/coverage/lcov-report/core/api/services/import-export/import-export.hooks.js.html +0 -184
  133. package/coverage/lcov-report/core/api/services/import-export/import-export.service.js.html +0 -118
  134. package/coverage/lcov-report/core/api/services/import-export/index.html +0 -131
  135. package/coverage/lcov-report/core/api/services/index.html +0 -116
  136. package/coverage/lcov-report/core/api/services/index.js.html +0 -727
  137. package/coverage/lcov-report/core/api/services/mailer/index.html +0 -131
  138. package/coverage/lcov-report/core/api/services/mailer/mailer.hooks.js.html +0 -190
  139. package/coverage/lcov-report/core/api/services/mailer/mailer.service.js.html +0 -118
  140. package/coverage/lcov-report/core/api/services/messages/index.html +0 -116
  141. package/coverage/lcov-report/core/api/services/messages/messages.hooks.js.html +0 -220
  142. package/coverage/lcov-report/core/api/services/push/index.html +0 -131
  143. package/coverage/lcov-report/core/api/services/push/push.hooks.js.html +0 -190
  144. package/coverage/lcov-report/core/api/services/push/push.service.js.html +0 -121
  145. package/coverage/lcov-report/core/api/services/storage/index.html +0 -131
  146. package/coverage/lcov-report/core/api/services/storage/storage.hooks.js.html +0 -190
  147. package/coverage/lcov-report/core/api/services/storage/storage.service.js.html +0 -172
  148. package/coverage/lcov-report/core/api/services/tags/index.html +0 -116
  149. package/coverage/lcov-report/core/api/services/tags/tags.hooks.js.html +0 -226
  150. package/coverage/lcov-report/core/api/services/users/index.html +0 -131
  151. package/coverage/lcov-report/core/api/services/users/users.hooks.js.html +0 -310
  152. package/coverage/lcov-report/core/api/services/users/users.service.js.html +0 -100
  153. package/coverage/lcov-report/core/common/errors.js.html +0 -88
  154. package/coverage/lcov-report/core/common/index.html +0 -191
  155. package/coverage/lcov-report/core/common/index.js.html +0 -115
  156. package/coverage/lcov-report/core/common/permissions.js.html +0 -742
  157. package/coverage/lcov-report/core/common/schema.js.html +0 -190
  158. package/coverage/lcov-report/core/common/utils.js.html +0 -226
  159. package/coverage/lcov-report/core/common/utils.offline.js.html +0 -199
  160. package/coverage/lcov-report/favicon.png +0 -0
  161. package/coverage/lcov-report/index.html +0 -506
  162. package/coverage/lcov-report/map/api/hooks/hooks.catalog.js.html +0 -595
  163. package/coverage/lcov-report/map/api/hooks/hooks.features.js.html +0 -397
  164. package/coverage/lcov-report/map/api/hooks/hooks.query.js.html +0 -1309
  165. package/coverage/lcov-report/map/api/hooks/index.html +0 -161
  166. package/coverage/lcov-report/map/api/hooks/index.js.html +0 -94
  167. package/coverage/lcov-report/map/api/index.html +0 -131
  168. package/coverage/lcov-report/map/api/index.js.html +0 -139
  169. package/coverage/lcov-report/map/api/marshall.js.html +0 -178
  170. package/coverage/lcov-report/map/api/models/alerts.model.mongodb.js.html +0 -106
  171. package/coverage/lcov-report/map/api/models/catalog.model.mongodb.js.html +0 -202
  172. package/coverage/lcov-report/map/api/models/features.model.mongodb.js.html +0 -196
  173. package/coverage/lcov-report/map/api/models/index.html +0 -176
  174. package/coverage/lcov-report/map/api/models/projects.model.mongodb.js.html +0 -109
  175. package/coverage/lcov-report/map/api/models/styles.model.mongodb.js.html +0 -112
  176. package/coverage/lcov-report/map/api/services/alerts/alerts.hooks.js.html +0 -274
  177. package/coverage/lcov-report/map/api/services/alerts/alerts.service.js.html +0 -610
  178. package/coverage/lcov-report/map/api/services/alerts/index.html +0 -131
  179. package/coverage/lcov-report/map/api/services/catalog/catalog.hooks.js.html +0 -337
  180. package/coverage/lcov-report/map/api/services/catalog/index.html +0 -116
  181. package/coverage/lcov-report/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  182. package/coverage/lcov-report/map/api/services/daptiles/index.html +0 -116
  183. package/coverage/lcov-report/map/api/services/features/features.hooks.js.html +0 -316
  184. package/coverage/lcov-report/map/api/services/features/features.service.js.html +0 -544
  185. package/coverage/lcov-report/map/api/services/features/index.html +0 -131
  186. package/coverage/lcov-report/map/api/services/index.html +0 -116
  187. package/coverage/lcov-report/map/api/services/index.js.html +0 -1093
  188. package/coverage/lcov-report/map/api/services/projects/index.html +0 -116
  189. package/coverage/lcov-report/map/api/services/projects/projects.hooks.js.html +0 -439
  190. package/coverage/lcov-report/map/api/services/styles/index.html +0 -116
  191. package/coverage/lcov-report/map/api/services/styles/styles.hooks.js.html +0 -211
  192. package/coverage/lcov-report/map/common/dynamic-grid-source.js.html +0 -466
  193. package/coverage/lcov-report/map/common/errors.js.html +0 -94
  194. package/coverage/lcov-report/map/common/geotiff-grid-source.js.html +0 -538
  195. package/coverage/lcov-report/map/common/grid.js.html +0 -1612
  196. package/coverage/lcov-report/map/common/index.html +0 -371
  197. package/coverage/lcov-report/map/common/index.js.html +0 -172
  198. package/coverage/lcov-report/map/common/meteo-model-grid-source.js.html +0 -556
  199. package/coverage/lcov-report/map/common/moment-utils.js.html +0 -157
  200. package/coverage/lcov-report/map/common/opendap-grid-source.js.html +0 -868
  201. package/coverage/lcov-report/map/common/opendap-utils.js.html +0 -823
  202. package/coverage/lcov-report/map/common/permissions.js.html +0 -130
  203. package/coverage/lcov-report/map/common/time-based-grid-source.js.html +0 -418
  204. package/coverage/lcov-report/map/common/tms-utils.js.html +0 -271
  205. package/coverage/lcov-report/map/common/wcs-grid-source.js.html +0 -364
  206. package/coverage/lcov-report/map/common/wcs-utils.js.html +0 -583
  207. package/coverage/lcov-report/map/common/weacast-grid-source.js.html +0 -1033
  208. package/coverage/lcov-report/map/common/wfs-utils.js.html +0 -571
  209. package/coverage/lcov-report/map/common/wms-utils.js.html +0 -469
  210. package/coverage/lcov-report/map/common/wmts-utils.js.html +0 -544
  211. package/coverage/lcov-report/prettify.css +0 -1
  212. package/coverage/lcov-report/prettify.js +0 -2
  213. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  214. package/coverage/lcov-report/sorter.js +0 -196
  215. package/coverage/lcov.info +0 -11012
  216. package/coverage/map/api/hooks/hooks.catalog.js.html +0 -595
  217. package/coverage/map/api/hooks/hooks.features.js.html +0 -397
  218. package/coverage/map/api/hooks/hooks.query.js.html +0 -1309
  219. package/coverage/map/api/hooks/index.html +0 -161
  220. package/coverage/map/api/hooks/index.js.html +0 -94
  221. package/coverage/map/api/index.html +0 -131
  222. package/coverage/map/api/index.js.html +0 -139
  223. package/coverage/map/api/marshall.js.html +0 -178
  224. package/coverage/map/api/models/alerts.model.mongodb.js.html +0 -106
  225. package/coverage/map/api/models/catalog.model.mongodb.js.html +0 -202
  226. package/coverage/map/api/models/features.model.mongodb.js.html +0 -196
  227. package/coverage/map/api/models/index.html +0 -176
  228. package/coverage/map/api/models/projects.model.mongodb.js.html +0 -109
  229. package/coverage/map/api/models/styles.model.mongodb.js.html +0 -112
  230. package/coverage/map/api/services/alerts/alerts.hooks.js.html +0 -274
  231. package/coverage/map/api/services/alerts/alerts.service.js.html +0 -610
  232. package/coverage/map/api/services/alerts/index.html +0 -131
  233. package/coverage/map/api/services/catalog/catalog.hooks.js.html +0 -337
  234. package/coverage/map/api/services/catalog/index.html +0 -116
  235. package/coverage/map/api/services/daptiles/daptiles.service.js.html +0 -1510
  236. package/coverage/map/api/services/daptiles/index.html +0 -116
  237. package/coverage/map/api/services/features/features.hooks.js.html +0 -316
  238. package/coverage/map/api/services/features/features.service.js.html +0 -544
  239. package/coverage/map/api/services/features/index.html +0 -131
  240. package/coverage/map/api/services/index.html +0 -116
  241. package/coverage/map/api/services/index.js.html +0 -1093
  242. package/coverage/map/api/services/projects/index.html +0 -116
  243. package/coverage/map/api/services/projects/projects.hooks.js.html +0 -439
  244. package/coverage/map/api/services/styles/index.html +0 -116
  245. package/coverage/map/api/services/styles/styles.hooks.js.html +0 -211
  246. package/coverage/map/common/dynamic-grid-source.js.html +0 -466
  247. package/coverage/map/common/errors.js.html +0 -94
  248. package/coverage/map/common/geotiff-grid-source.js.html +0 -538
  249. package/coverage/map/common/grid.js.html +0 -1612
  250. package/coverage/map/common/index.html +0 -371
  251. package/coverage/map/common/index.js.html +0 -172
  252. package/coverage/map/common/meteo-model-grid-source.js.html +0 -556
  253. package/coverage/map/common/moment-utils.js.html +0 -157
  254. package/coverage/map/common/opendap-grid-source.js.html +0 -868
  255. package/coverage/map/common/opendap-utils.js.html +0 -823
  256. package/coverage/map/common/permissions.js.html +0 -130
  257. package/coverage/map/common/time-based-grid-source.js.html +0 -418
  258. package/coverage/map/common/tms-utils.js.html +0 -271
  259. package/coverage/map/common/wcs-grid-source.js.html +0 -364
  260. package/coverage/map/common/wcs-utils.js.html +0 -583
  261. package/coverage/map/common/weacast-grid-source.js.html +0 -1033
  262. package/coverage/map/common/wfs-utils.js.html +0 -571
  263. package/coverage/map/common/wms-utils.js.html +0 -469
  264. package/coverage/map/common/wmts-utils.js.html +0 -544
  265. package/coverage/prettify.css +0 -1
  266. package/coverage/prettify.js +0 -2
  267. package/coverage/sort-arrow-sprite.png +0 -0
  268. package/coverage/sorter.js +0 -196
  269. package/coverage/tmp/coverage-222524-1765963609350-0.json +0 -1
  270. package/coverage/tmp/coverage-222536-1765963609335-0.json +0 -1
  271. package/coverage/tmp/coverage-222547-1765963609324-0.json +0 -1
  272. package/coverage/tmp/coverage-222559-1765963609309-0.json +0 -1
  273. package/coverage/tmp/coverage-222566-1765963609278-0.json +0 -1
@@ -1,1864 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for core/api/application.js</title>
7
- <meta charset="utf-8" />
8
- <link rel="stylesheet" href="../../prettify.css" />
9
- <link rel="stylesheet" href="../../base.css" />
10
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
- <meta name="viewport" content="width=device-width, initial-scale=1" />
12
- <style type='text/css'>
13
- .coverage-summary .sorter {
14
- background-image: url(../../sort-arrow-sprite.png);
15
- }
16
- </style>
17
- </head>
18
-
19
- <body>
20
- <div class='wrapper'>
21
- <div class='pad1'>
22
- <h1><a href="../../index.html">All files</a> / <a href="index.html">core/api</a> application.js</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">60.7% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>360/593</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">56% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>42/75</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">60.86% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>14/23</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">60.7% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>360/593</span>
50
- </div>
51
-
52
-
53
- </div>
54
- <p class="quiet">
55
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
- </p>
57
- <template id="filterTemplate">
58
- <div class="quiet">
59
- Filter:
60
- <input oninput="onInput()" type="search" id="fileSearch">
61
- </div>
62
- </template>
63
- </div>
64
- <div class='status-line medium'></div>
65
- <pre><table class="coverage">
66
- <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
- <a name='L2'></a><a href='#L2'>2</a>
68
- <a name='L3'></a><a href='#L3'>3</a>
69
- <a name='L4'></a><a href='#L4'>4</a>
70
- <a name='L5'></a><a href='#L5'>5</a>
71
- <a name='L6'></a><a href='#L6'>6</a>
72
- <a name='L7'></a><a href='#L7'>7</a>
73
- <a name='L8'></a><a href='#L8'>8</a>
74
- <a name='L9'></a><a href='#L9'>9</a>
75
- <a name='L10'></a><a href='#L10'>10</a>
76
- <a name='L11'></a><a href='#L11'>11</a>
77
- <a name='L12'></a><a href='#L12'>12</a>
78
- <a name='L13'></a><a href='#L13'>13</a>
79
- <a name='L14'></a><a href='#L14'>14</a>
80
- <a name='L15'></a><a href='#L15'>15</a>
81
- <a name='L16'></a><a href='#L16'>16</a>
82
- <a name='L17'></a><a href='#L17'>17</a>
83
- <a name='L18'></a><a href='#L18'>18</a>
84
- <a name='L19'></a><a href='#L19'>19</a>
85
- <a name='L20'></a><a href='#L20'>20</a>
86
- <a name='L21'></a><a href='#L21'>21</a>
87
- <a name='L22'></a><a href='#L22'>22</a>
88
- <a name='L23'></a><a href='#L23'>23</a>
89
- <a name='L24'></a><a href='#L24'>24</a>
90
- <a name='L25'></a><a href='#L25'>25</a>
91
- <a name='L26'></a><a href='#L26'>26</a>
92
- <a name='L27'></a><a href='#L27'>27</a>
93
- <a name='L28'></a><a href='#L28'>28</a>
94
- <a name='L29'></a><a href='#L29'>29</a>
95
- <a name='L30'></a><a href='#L30'>30</a>
96
- <a name='L31'></a><a href='#L31'>31</a>
97
- <a name='L32'></a><a href='#L32'>32</a>
98
- <a name='L33'></a><a href='#L33'>33</a>
99
- <a name='L34'></a><a href='#L34'>34</a>
100
- <a name='L35'></a><a href='#L35'>35</a>
101
- <a name='L36'></a><a href='#L36'>36</a>
102
- <a name='L37'></a><a href='#L37'>37</a>
103
- <a name='L38'></a><a href='#L38'>38</a>
104
- <a name='L39'></a><a href='#L39'>39</a>
105
- <a name='L40'></a><a href='#L40'>40</a>
106
- <a name='L41'></a><a href='#L41'>41</a>
107
- <a name='L42'></a><a href='#L42'>42</a>
108
- <a name='L43'></a><a href='#L43'>43</a>
109
- <a name='L44'></a><a href='#L44'>44</a>
110
- <a name='L45'></a><a href='#L45'>45</a>
111
- <a name='L46'></a><a href='#L46'>46</a>
112
- <a name='L47'></a><a href='#L47'>47</a>
113
- <a name='L48'></a><a href='#L48'>48</a>
114
- <a name='L49'></a><a href='#L49'>49</a>
115
- <a name='L50'></a><a href='#L50'>50</a>
116
- <a name='L51'></a><a href='#L51'>51</a>
117
- <a name='L52'></a><a href='#L52'>52</a>
118
- <a name='L53'></a><a href='#L53'>53</a>
119
- <a name='L54'></a><a href='#L54'>54</a>
120
- <a name='L55'></a><a href='#L55'>55</a>
121
- <a name='L56'></a><a href='#L56'>56</a>
122
- <a name='L57'></a><a href='#L57'>57</a>
123
- <a name='L58'></a><a href='#L58'>58</a>
124
- <a name='L59'></a><a href='#L59'>59</a>
125
- <a name='L60'></a><a href='#L60'>60</a>
126
- <a name='L61'></a><a href='#L61'>61</a>
127
- <a name='L62'></a><a href='#L62'>62</a>
128
- <a name='L63'></a><a href='#L63'>63</a>
129
- <a name='L64'></a><a href='#L64'>64</a>
130
- <a name='L65'></a><a href='#L65'>65</a>
131
- <a name='L66'></a><a href='#L66'>66</a>
132
- <a name='L67'></a><a href='#L67'>67</a>
133
- <a name='L68'></a><a href='#L68'>68</a>
134
- <a name='L69'></a><a href='#L69'>69</a>
135
- <a name='L70'></a><a href='#L70'>70</a>
136
- <a name='L71'></a><a href='#L71'>71</a>
137
- <a name='L72'></a><a href='#L72'>72</a>
138
- <a name='L73'></a><a href='#L73'>73</a>
139
- <a name='L74'></a><a href='#L74'>74</a>
140
- <a name='L75'></a><a href='#L75'>75</a>
141
- <a name='L76'></a><a href='#L76'>76</a>
142
- <a name='L77'></a><a href='#L77'>77</a>
143
- <a name='L78'></a><a href='#L78'>78</a>
144
- <a name='L79'></a><a href='#L79'>79</a>
145
- <a name='L80'></a><a href='#L80'>80</a>
146
- <a name='L81'></a><a href='#L81'>81</a>
147
- <a name='L82'></a><a href='#L82'>82</a>
148
- <a name='L83'></a><a href='#L83'>83</a>
149
- <a name='L84'></a><a href='#L84'>84</a>
150
- <a name='L85'></a><a href='#L85'>85</a>
151
- <a name='L86'></a><a href='#L86'>86</a>
152
- <a name='L87'></a><a href='#L87'>87</a>
153
- <a name='L88'></a><a href='#L88'>88</a>
154
- <a name='L89'></a><a href='#L89'>89</a>
155
- <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a>
157
- <a name='L92'></a><a href='#L92'>92</a>
158
- <a name='L93'></a><a href='#L93'>93</a>
159
- <a name='L94'></a><a href='#L94'>94</a>
160
- <a name='L95'></a><a href='#L95'>95</a>
161
- <a name='L96'></a><a href='#L96'>96</a>
162
- <a name='L97'></a><a href='#L97'>97</a>
163
- <a name='L98'></a><a href='#L98'>98</a>
164
- <a name='L99'></a><a href='#L99'>99</a>
165
- <a name='L100'></a><a href='#L100'>100</a>
166
- <a name='L101'></a><a href='#L101'>101</a>
167
- <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a>
169
- <a name='L104'></a><a href='#L104'>104</a>
170
- <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a>
172
- <a name='L107'></a><a href='#L107'>107</a>
173
- <a name='L108'></a><a href='#L108'>108</a>
174
- <a name='L109'></a><a href='#L109'>109</a>
175
- <a name='L110'></a><a href='#L110'>110</a>
176
- <a name='L111'></a><a href='#L111'>111</a>
177
- <a name='L112'></a><a href='#L112'>112</a>
178
- <a name='L113'></a><a href='#L113'>113</a>
179
- <a name='L114'></a><a href='#L114'>114</a>
180
- <a name='L115'></a><a href='#L115'>115</a>
181
- <a name='L116'></a><a href='#L116'>116</a>
182
- <a name='L117'></a><a href='#L117'>117</a>
183
- <a name='L118'></a><a href='#L118'>118</a>
184
- <a name='L119'></a><a href='#L119'>119</a>
185
- <a name='L120'></a><a href='#L120'>120</a>
186
- <a name='L121'></a><a href='#L121'>121</a>
187
- <a name='L122'></a><a href='#L122'>122</a>
188
- <a name='L123'></a><a href='#L123'>123</a>
189
- <a name='L124'></a><a href='#L124'>124</a>
190
- <a name='L125'></a><a href='#L125'>125</a>
191
- <a name='L126'></a><a href='#L126'>126</a>
192
- <a name='L127'></a><a href='#L127'>127</a>
193
- <a name='L128'></a><a href='#L128'>128</a>
194
- <a name='L129'></a><a href='#L129'>129</a>
195
- <a name='L130'></a><a href='#L130'>130</a>
196
- <a name='L131'></a><a href='#L131'>131</a>
197
- <a name='L132'></a><a href='#L132'>132</a>
198
- <a name='L133'></a><a href='#L133'>133</a>
199
- <a name='L134'></a><a href='#L134'>134</a>
200
- <a name='L135'></a><a href='#L135'>135</a>
201
- <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a>
216
- <a name='L151'></a><a href='#L151'>151</a>
217
- <a name='L152'></a><a href='#L152'>152</a>
218
- <a name='L153'></a><a href='#L153'>153</a>
219
- <a name='L154'></a><a href='#L154'>154</a>
220
- <a name='L155'></a><a href='#L155'>155</a>
221
- <a name='L156'></a><a href='#L156'>156</a>
222
- <a name='L157'></a><a href='#L157'>157</a>
223
- <a name='L158'></a><a href='#L158'>158</a>
224
- <a name='L159'></a><a href='#L159'>159</a>
225
- <a name='L160'></a><a href='#L160'>160</a>
226
- <a name='L161'></a><a href='#L161'>161</a>
227
- <a name='L162'></a><a href='#L162'>162</a>
228
- <a name='L163'></a><a href='#L163'>163</a>
229
- <a name='L164'></a><a href='#L164'>164</a>
230
- <a name='L165'></a><a href='#L165'>165</a>
231
- <a name='L166'></a><a href='#L166'>166</a>
232
- <a name='L167'></a><a href='#L167'>167</a>
233
- <a name='L168'></a><a href='#L168'>168</a>
234
- <a name='L169'></a><a href='#L169'>169</a>
235
- <a name='L170'></a><a href='#L170'>170</a>
236
- <a name='L171'></a><a href='#L171'>171</a>
237
- <a name='L172'></a><a href='#L172'>172</a>
238
- <a name='L173'></a><a href='#L173'>173</a>
239
- <a name='L174'></a><a href='#L174'>174</a>
240
- <a name='L175'></a><a href='#L175'>175</a>
241
- <a name='L176'></a><a href='#L176'>176</a>
242
- <a name='L177'></a><a href='#L177'>177</a>
243
- <a name='L178'></a><a href='#L178'>178</a>
244
- <a name='L179'></a><a href='#L179'>179</a>
245
- <a name='L180'></a><a href='#L180'>180</a>
246
- <a name='L181'></a><a href='#L181'>181</a>
247
- <a name='L182'></a><a href='#L182'>182</a>
248
- <a name='L183'></a><a href='#L183'>183</a>
249
- <a name='L184'></a><a href='#L184'>184</a>
250
- <a name='L185'></a><a href='#L185'>185</a>
251
- <a name='L186'></a><a href='#L186'>186</a>
252
- <a name='L187'></a><a href='#L187'>187</a>
253
- <a name='L188'></a><a href='#L188'>188</a>
254
- <a name='L189'></a><a href='#L189'>189</a>
255
- <a name='L190'></a><a href='#L190'>190</a>
256
- <a name='L191'></a><a href='#L191'>191</a>
257
- <a name='L192'></a><a href='#L192'>192</a>
258
- <a name='L193'></a><a href='#L193'>193</a>
259
- <a name='L194'></a><a href='#L194'>194</a>
260
- <a name='L195'></a><a href='#L195'>195</a>
261
- <a name='L196'></a><a href='#L196'>196</a>
262
- <a name='L197'></a><a href='#L197'>197</a>
263
- <a name='L198'></a><a href='#L198'>198</a>
264
- <a name='L199'></a><a href='#L199'>199</a>
265
- <a name='L200'></a><a href='#L200'>200</a>
266
- <a name='L201'></a><a href='#L201'>201</a>
267
- <a name='L202'></a><a href='#L202'>202</a>
268
- <a name='L203'></a><a href='#L203'>203</a>
269
- <a name='L204'></a><a href='#L204'>204</a>
270
- <a name='L205'></a><a href='#L205'>205</a>
271
- <a name='L206'></a><a href='#L206'>206</a>
272
- <a name='L207'></a><a href='#L207'>207</a>
273
- <a name='L208'></a><a href='#L208'>208</a>
274
- <a name='L209'></a><a href='#L209'>209</a>
275
- <a name='L210'></a><a href='#L210'>210</a>
276
- <a name='L211'></a><a href='#L211'>211</a>
277
- <a name='L212'></a><a href='#L212'>212</a>
278
- <a name='L213'></a><a href='#L213'>213</a>
279
- <a name='L214'></a><a href='#L214'>214</a>
280
- <a name='L215'></a><a href='#L215'>215</a>
281
- <a name='L216'></a><a href='#L216'>216</a>
282
- <a name='L217'></a><a href='#L217'>217</a>
283
- <a name='L218'></a><a href='#L218'>218</a>
284
- <a name='L219'></a><a href='#L219'>219</a>
285
- <a name='L220'></a><a href='#L220'>220</a>
286
- <a name='L221'></a><a href='#L221'>221</a>
287
- <a name='L222'></a><a href='#L222'>222</a>
288
- <a name='L223'></a><a href='#L223'>223</a>
289
- <a name='L224'></a><a href='#L224'>224</a>
290
- <a name='L225'></a><a href='#L225'>225</a>
291
- <a name='L226'></a><a href='#L226'>226</a>
292
- <a name='L227'></a><a href='#L227'>227</a>
293
- <a name='L228'></a><a href='#L228'>228</a>
294
- <a name='L229'></a><a href='#L229'>229</a>
295
- <a name='L230'></a><a href='#L230'>230</a>
296
- <a name='L231'></a><a href='#L231'>231</a>
297
- <a name='L232'></a><a href='#L232'>232</a>
298
- <a name='L233'></a><a href='#L233'>233</a>
299
- <a name='L234'></a><a href='#L234'>234</a>
300
- <a name='L235'></a><a href='#L235'>235</a>
301
- <a name='L236'></a><a href='#L236'>236</a>
302
- <a name='L237'></a><a href='#L237'>237</a>
303
- <a name='L238'></a><a href='#L238'>238</a>
304
- <a name='L239'></a><a href='#L239'>239</a>
305
- <a name='L240'></a><a href='#L240'>240</a>
306
- <a name='L241'></a><a href='#L241'>241</a>
307
- <a name='L242'></a><a href='#L242'>242</a>
308
- <a name='L243'></a><a href='#L243'>243</a>
309
- <a name='L244'></a><a href='#L244'>244</a>
310
- <a name='L245'></a><a href='#L245'>245</a>
311
- <a name='L246'></a><a href='#L246'>246</a>
312
- <a name='L247'></a><a href='#L247'>247</a>
313
- <a name='L248'></a><a href='#L248'>248</a>
314
- <a name='L249'></a><a href='#L249'>249</a>
315
- <a name='L250'></a><a href='#L250'>250</a>
316
- <a name='L251'></a><a href='#L251'>251</a>
317
- <a name='L252'></a><a href='#L252'>252</a>
318
- <a name='L253'></a><a href='#L253'>253</a>
319
- <a name='L254'></a><a href='#L254'>254</a>
320
- <a name='L255'></a><a href='#L255'>255</a>
321
- <a name='L256'></a><a href='#L256'>256</a>
322
- <a name='L257'></a><a href='#L257'>257</a>
323
- <a name='L258'></a><a href='#L258'>258</a>
324
- <a name='L259'></a><a href='#L259'>259</a>
325
- <a name='L260'></a><a href='#L260'>260</a>
326
- <a name='L261'></a><a href='#L261'>261</a>
327
- <a name='L262'></a><a href='#L262'>262</a>
328
- <a name='L263'></a><a href='#L263'>263</a>
329
- <a name='L264'></a><a href='#L264'>264</a>
330
- <a name='L265'></a><a href='#L265'>265</a>
331
- <a name='L266'></a><a href='#L266'>266</a>
332
- <a name='L267'></a><a href='#L267'>267</a>
333
- <a name='L268'></a><a href='#L268'>268</a>
334
- <a name='L269'></a><a href='#L269'>269</a>
335
- <a name='L270'></a><a href='#L270'>270</a>
336
- <a name='L271'></a><a href='#L271'>271</a>
337
- <a name='L272'></a><a href='#L272'>272</a>
338
- <a name='L273'></a><a href='#L273'>273</a>
339
- <a name='L274'></a><a href='#L274'>274</a>
340
- <a name='L275'></a><a href='#L275'>275</a>
341
- <a name='L276'></a><a href='#L276'>276</a>
342
- <a name='L277'></a><a href='#L277'>277</a>
343
- <a name='L278'></a><a href='#L278'>278</a>
344
- <a name='L279'></a><a href='#L279'>279</a>
345
- <a name='L280'></a><a href='#L280'>280</a>
346
- <a name='L281'></a><a href='#L281'>281</a>
347
- <a name='L282'></a><a href='#L282'>282</a>
348
- <a name='L283'></a><a href='#L283'>283</a>
349
- <a name='L284'></a><a href='#L284'>284</a>
350
- <a name='L285'></a><a href='#L285'>285</a>
351
- <a name='L286'></a><a href='#L286'>286</a>
352
- <a name='L287'></a><a href='#L287'>287</a>
353
- <a name='L288'></a><a href='#L288'>288</a>
354
- <a name='L289'></a><a href='#L289'>289</a>
355
- <a name='L290'></a><a href='#L290'>290</a>
356
- <a name='L291'></a><a href='#L291'>291</a>
357
- <a name='L292'></a><a href='#L292'>292</a>
358
- <a name='L293'></a><a href='#L293'>293</a>
359
- <a name='L294'></a><a href='#L294'>294</a>
360
- <a name='L295'></a><a href='#L295'>295</a>
361
- <a name='L296'></a><a href='#L296'>296</a>
362
- <a name='L297'></a><a href='#L297'>297</a>
363
- <a name='L298'></a><a href='#L298'>298</a>
364
- <a name='L299'></a><a href='#L299'>299</a>
365
- <a name='L300'></a><a href='#L300'>300</a>
366
- <a name='L301'></a><a href='#L301'>301</a>
367
- <a name='L302'></a><a href='#L302'>302</a>
368
- <a name='L303'></a><a href='#L303'>303</a>
369
- <a name='L304'></a><a href='#L304'>304</a>
370
- <a name='L305'></a><a href='#L305'>305</a>
371
- <a name='L306'></a><a href='#L306'>306</a>
372
- <a name='L307'></a><a href='#L307'>307</a>
373
- <a name='L308'></a><a href='#L308'>308</a>
374
- <a name='L309'></a><a href='#L309'>309</a>
375
- <a name='L310'></a><a href='#L310'>310</a>
376
- <a name='L311'></a><a href='#L311'>311</a>
377
- <a name='L312'></a><a href='#L312'>312</a>
378
- <a name='L313'></a><a href='#L313'>313</a>
379
- <a name='L314'></a><a href='#L314'>314</a>
380
- <a name='L315'></a><a href='#L315'>315</a>
381
- <a name='L316'></a><a href='#L316'>316</a>
382
- <a name='L317'></a><a href='#L317'>317</a>
383
- <a name='L318'></a><a href='#L318'>318</a>
384
- <a name='L319'></a><a href='#L319'>319</a>
385
- <a name='L320'></a><a href='#L320'>320</a>
386
- <a name='L321'></a><a href='#L321'>321</a>
387
- <a name='L322'></a><a href='#L322'>322</a>
388
- <a name='L323'></a><a href='#L323'>323</a>
389
- <a name='L324'></a><a href='#L324'>324</a>
390
- <a name='L325'></a><a href='#L325'>325</a>
391
- <a name='L326'></a><a href='#L326'>326</a>
392
- <a name='L327'></a><a href='#L327'>327</a>
393
- <a name='L328'></a><a href='#L328'>328</a>
394
- <a name='L329'></a><a href='#L329'>329</a>
395
- <a name='L330'></a><a href='#L330'>330</a>
396
- <a name='L331'></a><a href='#L331'>331</a>
397
- <a name='L332'></a><a href='#L332'>332</a>
398
- <a name='L333'></a><a href='#L333'>333</a>
399
- <a name='L334'></a><a href='#L334'>334</a>
400
- <a name='L335'></a><a href='#L335'>335</a>
401
- <a name='L336'></a><a href='#L336'>336</a>
402
- <a name='L337'></a><a href='#L337'>337</a>
403
- <a name='L338'></a><a href='#L338'>338</a>
404
- <a name='L339'></a><a href='#L339'>339</a>
405
- <a name='L340'></a><a href='#L340'>340</a>
406
- <a name='L341'></a><a href='#L341'>341</a>
407
- <a name='L342'></a><a href='#L342'>342</a>
408
- <a name='L343'></a><a href='#L343'>343</a>
409
- <a name='L344'></a><a href='#L344'>344</a>
410
- <a name='L345'></a><a href='#L345'>345</a>
411
- <a name='L346'></a><a href='#L346'>346</a>
412
- <a name='L347'></a><a href='#L347'>347</a>
413
- <a name='L348'></a><a href='#L348'>348</a>
414
- <a name='L349'></a><a href='#L349'>349</a>
415
- <a name='L350'></a><a href='#L350'>350</a>
416
- <a name='L351'></a><a href='#L351'>351</a>
417
- <a name='L352'></a><a href='#L352'>352</a>
418
- <a name='L353'></a><a href='#L353'>353</a>
419
- <a name='L354'></a><a href='#L354'>354</a>
420
- <a name='L355'></a><a href='#L355'>355</a>
421
- <a name='L356'></a><a href='#L356'>356</a>
422
- <a name='L357'></a><a href='#L357'>357</a>
423
- <a name='L358'></a><a href='#L358'>358</a>
424
- <a name='L359'></a><a href='#L359'>359</a>
425
- <a name='L360'></a><a href='#L360'>360</a>
426
- <a name='L361'></a><a href='#L361'>361</a>
427
- <a name='L362'></a><a href='#L362'>362</a>
428
- <a name='L363'></a><a href='#L363'>363</a>
429
- <a name='L364'></a><a href='#L364'>364</a>
430
- <a name='L365'></a><a href='#L365'>365</a>
431
- <a name='L366'></a><a href='#L366'>366</a>
432
- <a name='L367'></a><a href='#L367'>367</a>
433
- <a name='L368'></a><a href='#L368'>368</a>
434
- <a name='L369'></a><a href='#L369'>369</a>
435
- <a name='L370'></a><a href='#L370'>370</a>
436
- <a name='L371'></a><a href='#L371'>371</a>
437
- <a name='L372'></a><a href='#L372'>372</a>
438
- <a name='L373'></a><a href='#L373'>373</a>
439
- <a name='L374'></a><a href='#L374'>374</a>
440
- <a name='L375'></a><a href='#L375'>375</a>
441
- <a name='L376'></a><a href='#L376'>376</a>
442
- <a name='L377'></a><a href='#L377'>377</a>
443
- <a name='L378'></a><a href='#L378'>378</a>
444
- <a name='L379'></a><a href='#L379'>379</a>
445
- <a name='L380'></a><a href='#L380'>380</a>
446
- <a name='L381'></a><a href='#L381'>381</a>
447
- <a name='L382'></a><a href='#L382'>382</a>
448
- <a name='L383'></a><a href='#L383'>383</a>
449
- <a name='L384'></a><a href='#L384'>384</a>
450
- <a name='L385'></a><a href='#L385'>385</a>
451
- <a name='L386'></a><a href='#L386'>386</a>
452
- <a name='L387'></a><a href='#L387'>387</a>
453
- <a name='L388'></a><a href='#L388'>388</a>
454
- <a name='L389'></a><a href='#L389'>389</a>
455
- <a name='L390'></a><a href='#L390'>390</a>
456
- <a name='L391'></a><a href='#L391'>391</a>
457
- <a name='L392'></a><a href='#L392'>392</a>
458
- <a name='L393'></a><a href='#L393'>393</a>
459
- <a name='L394'></a><a href='#L394'>394</a>
460
- <a name='L395'></a><a href='#L395'>395</a>
461
- <a name='L396'></a><a href='#L396'>396</a>
462
- <a name='L397'></a><a href='#L397'>397</a>
463
- <a name='L398'></a><a href='#L398'>398</a>
464
- <a name='L399'></a><a href='#L399'>399</a>
465
- <a name='L400'></a><a href='#L400'>400</a>
466
- <a name='L401'></a><a href='#L401'>401</a>
467
- <a name='L402'></a><a href='#L402'>402</a>
468
- <a name='L403'></a><a href='#L403'>403</a>
469
- <a name='L404'></a><a href='#L404'>404</a>
470
- <a name='L405'></a><a href='#L405'>405</a>
471
- <a name='L406'></a><a href='#L406'>406</a>
472
- <a name='L407'></a><a href='#L407'>407</a>
473
- <a name='L408'></a><a href='#L408'>408</a>
474
- <a name='L409'></a><a href='#L409'>409</a>
475
- <a name='L410'></a><a href='#L410'>410</a>
476
- <a name='L411'></a><a href='#L411'>411</a>
477
- <a name='L412'></a><a href='#L412'>412</a>
478
- <a name='L413'></a><a href='#L413'>413</a>
479
- <a name='L414'></a><a href='#L414'>414</a>
480
- <a name='L415'></a><a href='#L415'>415</a>
481
- <a name='L416'></a><a href='#L416'>416</a>
482
- <a name='L417'></a><a href='#L417'>417</a>
483
- <a name='L418'></a><a href='#L418'>418</a>
484
- <a name='L419'></a><a href='#L419'>419</a>
485
- <a name='L420'></a><a href='#L420'>420</a>
486
- <a name='L421'></a><a href='#L421'>421</a>
487
- <a name='L422'></a><a href='#L422'>422</a>
488
- <a name='L423'></a><a href='#L423'>423</a>
489
- <a name='L424'></a><a href='#L424'>424</a>
490
- <a name='L425'></a><a href='#L425'>425</a>
491
- <a name='L426'></a><a href='#L426'>426</a>
492
- <a name='L427'></a><a href='#L427'>427</a>
493
- <a name='L428'></a><a href='#L428'>428</a>
494
- <a name='L429'></a><a href='#L429'>429</a>
495
- <a name='L430'></a><a href='#L430'>430</a>
496
- <a name='L431'></a><a href='#L431'>431</a>
497
- <a name='L432'></a><a href='#L432'>432</a>
498
- <a name='L433'></a><a href='#L433'>433</a>
499
- <a name='L434'></a><a href='#L434'>434</a>
500
- <a name='L435'></a><a href='#L435'>435</a>
501
- <a name='L436'></a><a href='#L436'>436</a>
502
- <a name='L437'></a><a href='#L437'>437</a>
503
- <a name='L438'></a><a href='#L438'>438</a>
504
- <a name='L439'></a><a href='#L439'>439</a>
505
- <a name='L440'></a><a href='#L440'>440</a>
506
- <a name='L441'></a><a href='#L441'>441</a>
507
- <a name='L442'></a><a href='#L442'>442</a>
508
- <a name='L443'></a><a href='#L443'>443</a>
509
- <a name='L444'></a><a href='#L444'>444</a>
510
- <a name='L445'></a><a href='#L445'>445</a>
511
- <a name='L446'></a><a href='#L446'>446</a>
512
- <a name='L447'></a><a href='#L447'>447</a>
513
- <a name='L448'></a><a href='#L448'>448</a>
514
- <a name='L449'></a><a href='#L449'>449</a>
515
- <a name='L450'></a><a href='#L450'>450</a>
516
- <a name='L451'></a><a href='#L451'>451</a>
517
- <a name='L452'></a><a href='#L452'>452</a>
518
- <a name='L453'></a><a href='#L453'>453</a>
519
- <a name='L454'></a><a href='#L454'>454</a>
520
- <a name='L455'></a><a href='#L455'>455</a>
521
- <a name='L456'></a><a href='#L456'>456</a>
522
- <a name='L457'></a><a href='#L457'>457</a>
523
- <a name='L458'></a><a href='#L458'>458</a>
524
- <a name='L459'></a><a href='#L459'>459</a>
525
- <a name='L460'></a><a href='#L460'>460</a>
526
- <a name='L461'></a><a href='#L461'>461</a>
527
- <a name='L462'></a><a href='#L462'>462</a>
528
- <a name='L463'></a><a href='#L463'>463</a>
529
- <a name='L464'></a><a href='#L464'>464</a>
530
- <a name='L465'></a><a href='#L465'>465</a>
531
- <a name='L466'></a><a href='#L466'>466</a>
532
- <a name='L467'></a><a href='#L467'>467</a>
533
- <a name='L468'></a><a href='#L468'>468</a>
534
- <a name='L469'></a><a href='#L469'>469</a>
535
- <a name='L470'></a><a href='#L470'>470</a>
536
- <a name='L471'></a><a href='#L471'>471</a>
537
- <a name='L472'></a><a href='#L472'>472</a>
538
- <a name='L473'></a><a href='#L473'>473</a>
539
- <a name='L474'></a><a href='#L474'>474</a>
540
- <a name='L475'></a><a href='#L475'>475</a>
541
- <a name='L476'></a><a href='#L476'>476</a>
542
- <a name='L477'></a><a href='#L477'>477</a>
543
- <a name='L478'></a><a href='#L478'>478</a>
544
- <a name='L479'></a><a href='#L479'>479</a>
545
- <a name='L480'></a><a href='#L480'>480</a>
546
- <a name='L481'></a><a href='#L481'>481</a>
547
- <a name='L482'></a><a href='#L482'>482</a>
548
- <a name='L483'></a><a href='#L483'>483</a>
549
- <a name='L484'></a><a href='#L484'>484</a>
550
- <a name='L485'></a><a href='#L485'>485</a>
551
- <a name='L486'></a><a href='#L486'>486</a>
552
- <a name='L487'></a><a href='#L487'>487</a>
553
- <a name='L488'></a><a href='#L488'>488</a>
554
- <a name='L489'></a><a href='#L489'>489</a>
555
- <a name='L490'></a><a href='#L490'>490</a>
556
- <a name='L491'></a><a href='#L491'>491</a>
557
- <a name='L492'></a><a href='#L492'>492</a>
558
- <a name='L493'></a><a href='#L493'>493</a>
559
- <a name='L494'></a><a href='#L494'>494</a>
560
- <a name='L495'></a><a href='#L495'>495</a>
561
- <a name='L496'></a><a href='#L496'>496</a>
562
- <a name='L497'></a><a href='#L497'>497</a>
563
- <a name='L498'></a><a href='#L498'>498</a>
564
- <a name='L499'></a><a href='#L499'>499</a>
565
- <a name='L500'></a><a href='#L500'>500</a>
566
- <a name='L501'></a><a href='#L501'>501</a>
567
- <a name='L502'></a><a href='#L502'>502</a>
568
- <a name='L503'></a><a href='#L503'>503</a>
569
- <a name='L504'></a><a href='#L504'>504</a>
570
- <a name='L505'></a><a href='#L505'>505</a>
571
- <a name='L506'></a><a href='#L506'>506</a>
572
- <a name='L507'></a><a href='#L507'>507</a>
573
- <a name='L508'></a><a href='#L508'>508</a>
574
- <a name='L509'></a><a href='#L509'>509</a>
575
- <a name='L510'></a><a href='#L510'>510</a>
576
- <a name='L511'></a><a href='#L511'>511</a>
577
- <a name='L512'></a><a href='#L512'>512</a>
578
- <a name='L513'></a><a href='#L513'>513</a>
579
- <a name='L514'></a><a href='#L514'>514</a>
580
- <a name='L515'></a><a href='#L515'>515</a>
581
- <a name='L516'></a><a href='#L516'>516</a>
582
- <a name='L517'></a><a href='#L517'>517</a>
583
- <a name='L518'></a><a href='#L518'>518</a>
584
- <a name='L519'></a><a href='#L519'>519</a>
585
- <a name='L520'></a><a href='#L520'>520</a>
586
- <a name='L521'></a><a href='#L521'>521</a>
587
- <a name='L522'></a><a href='#L522'>522</a>
588
- <a name='L523'></a><a href='#L523'>523</a>
589
- <a name='L524'></a><a href='#L524'>524</a>
590
- <a name='L525'></a><a href='#L525'>525</a>
591
- <a name='L526'></a><a href='#L526'>526</a>
592
- <a name='L527'></a><a href='#L527'>527</a>
593
- <a name='L528'></a><a href='#L528'>528</a>
594
- <a name='L529'></a><a href='#L529'>529</a>
595
- <a name='L530'></a><a href='#L530'>530</a>
596
- <a name='L531'></a><a href='#L531'>531</a>
597
- <a name='L532'></a><a href='#L532'>532</a>
598
- <a name='L533'></a><a href='#L533'>533</a>
599
- <a name='L534'></a><a href='#L534'>534</a>
600
- <a name='L535'></a><a href='#L535'>535</a>
601
- <a name='L536'></a><a href='#L536'>536</a>
602
- <a name='L537'></a><a href='#L537'>537</a>
603
- <a name='L538'></a><a href='#L538'>538</a>
604
- <a name='L539'></a><a href='#L539'>539</a>
605
- <a name='L540'></a><a href='#L540'>540</a>
606
- <a name='L541'></a><a href='#L541'>541</a>
607
- <a name='L542'></a><a href='#L542'>542</a>
608
- <a name='L543'></a><a href='#L543'>543</a>
609
- <a name='L544'></a><a href='#L544'>544</a>
610
- <a name='L545'></a><a href='#L545'>545</a>
611
- <a name='L546'></a><a href='#L546'>546</a>
612
- <a name='L547'></a><a href='#L547'>547</a>
613
- <a name='L548'></a><a href='#L548'>548</a>
614
- <a name='L549'></a><a href='#L549'>549</a>
615
- <a name='L550'></a><a href='#L550'>550</a>
616
- <a name='L551'></a><a href='#L551'>551</a>
617
- <a name='L552'></a><a href='#L552'>552</a>
618
- <a name='L553'></a><a href='#L553'>553</a>
619
- <a name='L554'></a><a href='#L554'>554</a>
620
- <a name='L555'></a><a href='#L555'>555</a>
621
- <a name='L556'></a><a href='#L556'>556</a>
622
- <a name='L557'></a><a href='#L557'>557</a>
623
- <a name='L558'></a><a href='#L558'>558</a>
624
- <a name='L559'></a><a href='#L559'>559</a>
625
- <a name='L560'></a><a href='#L560'>560</a>
626
- <a name='L561'></a><a href='#L561'>561</a>
627
- <a name='L562'></a><a href='#L562'>562</a>
628
- <a name='L563'></a><a href='#L563'>563</a>
629
- <a name='L564'></a><a href='#L564'>564</a>
630
- <a name='L565'></a><a href='#L565'>565</a>
631
- <a name='L566'></a><a href='#L566'>566</a>
632
- <a name='L567'></a><a href='#L567'>567</a>
633
- <a name='L568'></a><a href='#L568'>568</a>
634
- <a name='L569'></a><a href='#L569'>569</a>
635
- <a name='L570'></a><a href='#L570'>570</a>
636
- <a name='L571'></a><a href='#L571'>571</a>
637
- <a name='L572'></a><a href='#L572'>572</a>
638
- <a name='L573'></a><a href='#L573'>573</a>
639
- <a name='L574'></a><a href='#L574'>574</a>
640
- <a name='L575'></a><a href='#L575'>575</a>
641
- <a name='L576'></a><a href='#L576'>576</a>
642
- <a name='L577'></a><a href='#L577'>577</a>
643
- <a name='L578'></a><a href='#L578'>578</a>
644
- <a name='L579'></a><a href='#L579'>579</a>
645
- <a name='L580'></a><a href='#L580'>580</a>
646
- <a name='L581'></a><a href='#L581'>581</a>
647
- <a name='L582'></a><a href='#L582'>582</a>
648
- <a name='L583'></a><a href='#L583'>583</a>
649
- <a name='L584'></a><a href='#L584'>584</a>
650
- <a name='L585'></a><a href='#L585'>585</a>
651
- <a name='L586'></a><a href='#L586'>586</a>
652
- <a name='L587'></a><a href='#L587'>587</a>
653
- <a name='L588'></a><a href='#L588'>588</a>
654
- <a name='L589'></a><a href='#L589'>589</a>
655
- <a name='L590'></a><a href='#L590'>590</a>
656
- <a name='L591'></a><a href='#L591'>591</a>
657
- <a name='L592'></a><a href='#L592'>592</a>
658
- <a name='L593'></a><a href='#L593'>593</a>
659
- <a name='L594'></a><a href='#L594'>594</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
660
- <span class="cline-any cline-yes">1x</span>
661
- <span class="cline-any cline-yes">1x</span>
662
- <span class="cline-any cline-yes">1x</span>
663
- <span class="cline-any cline-yes">1x</span>
664
- <span class="cline-any cline-yes">1x</span>
665
- <span class="cline-any cline-yes">1x</span>
666
- <span class="cline-any cline-yes">1x</span>
667
- <span class="cline-any cline-yes">1x</span>
668
- <span class="cline-any cline-yes">1x</span>
669
- <span class="cline-any cline-yes">1x</span>
670
- <span class="cline-any cline-yes">1x</span>
671
- <span class="cline-any cline-yes">1x</span>
672
- <span class="cline-any cline-yes">1x</span>
673
- <span class="cline-any cline-yes">1x</span>
674
- <span class="cline-any cline-yes">1x</span>
675
- <span class="cline-any cline-yes">1x</span>
676
- <span class="cline-any cline-yes">1x</span>
677
- <span class="cline-any cline-yes">1x</span>
678
- <span class="cline-any cline-yes">1x</span>
679
- <span class="cline-any cline-yes">1x</span>
680
- <span class="cline-any cline-yes">1x</span>
681
- <span class="cline-any cline-yes">1x</span>
682
- <span class="cline-any cline-yes">1x</span>
683
- <span class="cline-any cline-yes">1x</span>
684
- <span class="cline-any cline-yes">1x</span>
685
- <span class="cline-any cline-yes">1x</span>
686
- <span class="cline-any cline-yes">1x</span>
687
- <span class="cline-any cline-yes">1x</span>
688
- <span class="cline-any cline-yes">1x</span>
689
- <span class="cline-any cline-no">&nbsp;</span>
690
- <span class="cline-any cline-no">&nbsp;</span>
691
- <span class="cline-any cline-no">&nbsp;</span>
692
- <span class="cline-any cline-no">&nbsp;</span>
693
- <span class="cline-any cline-no">&nbsp;</span>
694
- <span class="cline-any cline-no">&nbsp;</span>
695
- <span class="cline-any cline-no">&nbsp;</span>
696
- <span class="cline-any cline-yes">1x</span>
697
- <span class="cline-any cline-yes">1x</span>
698
- <span class="cline-any cline-yes">74x</span>
699
- <span class="cline-any cline-yes">74x</span>
700
- <span class="cline-any cline-yes">74x</span>
701
- <span class="cline-any cline-no">&nbsp;</span>
702
- <span class="cline-any cline-no">&nbsp;</span>
703
- <span class="cline-any cline-no">&nbsp;</span>
704
- <span class="cline-any cline-yes">74x</span>
705
- <span class="cline-any cline-yes">74x</span>
706
- <span class="cline-any cline-yes">74x</span>
707
- <span class="cline-any cline-yes">74x</span>
708
- <span class="cline-any cline-yes">74x</span>
709
- <span class="cline-any cline-yes">74x</span>
710
- <span class="cline-any cline-yes">74x</span>
711
- <span class="cline-any cline-yes">74x</span>
712
- <span class="cline-any cline-yes">74x</span>
713
- <span class="cline-any cline-yes">74x</span>
714
- <span class="cline-any cline-yes">74x</span>
715
- <span class="cline-any cline-yes">74x</span>
716
- <span class="cline-any cline-yes">74x</span>
717
- <span class="cline-any cline-yes">74x</span>
718
- <span class="cline-any cline-yes">74x</span>
719
- <span class="cline-any cline-yes">74x</span>
720
- <span class="cline-any cline-yes">74x</span>
721
- <span class="cline-any cline-yes">74x</span>
722
- <span class="cline-any cline-yes">74x</span>
723
- <span class="cline-any cline-yes">74x</span>
724
- <span class="cline-any cline-yes">74x</span>
725
- <span class="cline-any cline-yes">74x</span>
726
- <span class="cline-any cline-yes">74x</span>
727
- <span class="cline-any cline-yes">74x</span>
728
- <span class="cline-any cline-yes">29x</span>
729
- <span class="cline-any cline-yes">74x</span>
730
- <span class="cline-any cline-yes">74x</span>
731
- <span class="cline-any cline-yes">74x</span>
732
- <span class="cline-any cline-yes">74x</span>
733
- <span class="cline-any cline-yes">74x</span>
734
- <span class="cline-any cline-yes">15x</span>
735
- <span class="cline-any cline-yes">15x</span>
736
- <span class="cline-any cline-yes">10x</span>
737
- <span class="cline-any cline-yes">10x</span>
738
- <span class="cline-any cline-yes">15x</span>
739
- <span class="cline-any cline-yes">15x</span>
740
- <span class="cline-any cline-yes">74x</span>
741
- <span class="cline-any cline-no">&nbsp;</span>
742
- <span class="cline-any cline-no">&nbsp;</span>
743
- <span class="cline-any cline-yes">74x</span>
744
- <span class="cline-any cline-yes">74x</span>
745
- <span class="cline-any cline-yes">74x</span>
746
- <span class="cline-any cline-yes">1x</span>
747
- <span class="cline-any cline-yes">1x</span>
748
- <span class="cline-any cline-yes">73x</span>
749
- <span class="cline-any cline-yes">73x</span>
750
- <span class="cline-any cline-yes">73x</span>
751
- <span class="cline-any cline-yes">73x</span>
752
- <span class="cline-any cline-yes">73x</span>
753
- <span class="cline-any cline-yes">73x</span>
754
- <span class="cline-any cline-yes">73x</span>
755
- <span class="cline-any cline-yes">73x</span>
756
- <span class="cline-any cline-yes">73x</span>
757
- <span class="cline-any cline-no">&nbsp;</span>
758
- <span class="cline-any cline-no">&nbsp;</span>
759
- <span class="cline-any cline-no">&nbsp;</span>
760
- <span class="cline-any cline-no">&nbsp;</span>
761
- <span class="cline-any cline-no">&nbsp;</span>
762
- <span class="cline-any cline-no">&nbsp;</span>
763
- <span class="cline-any cline-no">&nbsp;</span>
764
- <span class="cline-any cline-yes">73x</span>
765
- <span class="cline-any cline-yes">73x</span>
766
- <span class="cline-any cline-yes">73x</span>
767
- <span class="cline-any cline-yes">73x</span>
768
- <span class="cline-any cline-yes">73x</span>
769
- <span class="cline-any cline-no">&nbsp;</span>
770
- <span class="cline-any cline-no">&nbsp;</span>
771
- <span class="cline-any cline-no">&nbsp;</span>
772
- <span class="cline-any cline-no">&nbsp;</span>
773
- <span class="cline-any cline-no">&nbsp;</span>
774
- <span class="cline-any cline-no">&nbsp;</span>
775
- <span class="cline-any cline-no">&nbsp;</span>
776
- <span class="cline-any cline-yes">73x</span>
777
- <span class="cline-any cline-no">&nbsp;</span>
778
- <span class="cline-any cline-no">&nbsp;</span>
779
- <span class="cline-any cline-no">&nbsp;</span>
780
- <span class="cline-any cline-no">&nbsp;</span>
781
- <span class="cline-any cline-no">&nbsp;</span>
782
- <span class="cline-any cline-no">&nbsp;</span>
783
- <span class="cline-any cline-no">&nbsp;</span>
784
- <span class="cline-any cline-yes">73x</span>
785
- <span class="cline-any cline-yes">73x</span>
786
- <span class="cline-any cline-yes">73x</span>
787
- <span class="cline-any cline-yes">1x</span>
788
- <span class="cline-any cline-yes">1x</span>
789
- <span class="cline-any cline-no">&nbsp;</span>
790
- <span class="cline-any cline-no">&nbsp;</span>
791
- <span class="cline-any cline-no">&nbsp;</span>
792
- <span class="cline-any cline-no">&nbsp;</span>
793
- <span class="cline-any cline-no">&nbsp;</span>
794
- <span class="cline-any cline-no">&nbsp;</span>
795
- <span class="cline-any cline-no">&nbsp;</span>
796
- <span class="cline-any cline-no">&nbsp;</span>
797
- <span class="cline-any cline-no">&nbsp;</span>
798
- <span class="cline-any cline-no">&nbsp;</span>
799
- <span class="cline-any cline-no">&nbsp;</span>
800
- <span class="cline-any cline-no">&nbsp;</span>
801
- <span class="cline-any cline-no">&nbsp;</span>
802
- <span class="cline-any cline-no">&nbsp;</span>
803
- <span class="cline-any cline-no">&nbsp;</span>
804
- <span class="cline-any cline-no">&nbsp;</span>
805
- <span class="cline-any cline-no">&nbsp;</span>
806
- <span class="cline-any cline-no">&nbsp;</span>
807
- <span class="cline-any cline-no">&nbsp;</span>
808
- <span class="cline-any cline-no">&nbsp;</span>
809
- <span class="cline-any cline-no">&nbsp;</span>
810
- <span class="cline-any cline-no">&nbsp;</span>
811
- <span class="cline-any cline-no">&nbsp;</span>
812
- <span class="cline-any cline-no">&nbsp;</span>
813
- <span class="cline-any cline-no">&nbsp;</span>
814
- <span class="cline-any cline-no">&nbsp;</span>
815
- <span class="cline-any cline-no">&nbsp;</span>
816
- <span class="cline-any cline-no">&nbsp;</span>
817
- <span class="cline-any cline-no">&nbsp;</span>
818
- <span class="cline-any cline-no">&nbsp;</span>
819
- <span class="cline-any cline-no">&nbsp;</span>
820
- <span class="cline-any cline-no">&nbsp;</span>
821
- <span class="cline-any cline-no">&nbsp;</span>
822
- <span class="cline-any cline-yes">1x</span>
823
- <span class="cline-any cline-yes">73x</span>
824
- <span class="cline-any cline-yes">73x</span>
825
- <span class="cline-any cline-yes">73x</span>
826
- <span class="cline-any cline-yes">73x</span>
827
- <span class="cline-any cline-yes">73x</span>
828
- <span class="cline-any cline-yes">73x</span>
829
- <span class="cline-any cline-yes">73x</span>
830
- <span class="cline-any cline-yes">73x</span>
831
- <span class="cline-any cline-yes">73x</span>
832
- <span class="cline-any cline-yes">73x</span>
833
- <span class="cline-any cline-yes">73x</span>
834
- <span class="cline-any cline-yes">73x</span>
835
- <span class="cline-any cline-yes">73x</span>
836
- <span class="cline-any cline-yes">73x</span>
837
- <span class="cline-any cline-yes">73x</span>
838
- <span class="cline-any cline-yes">73x</span>
839
- <span class="cline-any cline-yes">73x</span>
840
- <span class="cline-any cline-yes">73x</span>
841
- <span class="cline-any cline-yes">73x</span>
842
- <span class="cline-any cline-yes">73x</span>
843
- <span class="cline-any cline-yes">73x</span>
844
- <span class="cline-any cline-yes">73x</span>
845
- <span class="cline-any cline-yes">73x</span>
846
- <span class="cline-any cline-yes">28x</span>
847
- <span class="cline-any cline-yes">28x</span>
848
- <span class="cline-any cline-yes">28x</span>
849
- <span class="cline-any cline-yes">19x</span>
850
- <span class="cline-any cline-yes">19x</span>
851
- <span class="cline-any cline-yes">19x</span>
852
- <span class="cline-any cline-yes">19x</span>
853
- <span class="cline-any cline-yes">19x</span>
854
- <span class="cline-any cline-yes">28x</span>
855
- <span class="cline-any cline-yes">73x</span>
856
- <span class="cline-any cline-no">&nbsp;</span>
857
- <span class="cline-any cline-no">&nbsp;</span>
858
- <span class="cline-any cline-no">&nbsp;</span>
859
- <span class="cline-any cline-no">&nbsp;</span>
860
- <span class="cline-any cline-no">&nbsp;</span>
861
- <span class="cline-any cline-no">&nbsp;</span>
862
- <span class="cline-any cline-no">&nbsp;</span>
863
- <span class="cline-any cline-yes">73x</span>
864
- <span class="cline-any cline-yes">73x</span>
865
- <span class="cline-any cline-yes">73x</span>
866
- <span class="cline-any cline-yes">73x</span>
867
- <span class="cline-any cline-yes">19x</span>
868
- <span class="cline-any cline-yes">19x</span>
869
- <span class="cline-any cline-yes">73x</span>
870
- <span class="cline-any cline-no">&nbsp;</span>
871
- <span class="cline-any cline-yes">54x</span>
872
- <span class="cline-any cline-yes">54x</span>
873
- <span class="cline-any cline-yes">54x</span>
874
- <span class="cline-any cline-yes">54x</span>
875
- <span class="cline-any cline-yes">54x</span>
876
- <span class="cline-any cline-yes">54x</span>
877
- <span class="cline-any cline-yes">45x</span>
878
- <span class="cline-any cline-yes">45x</span>
879
- <span class="cline-any cline-yes">54x</span>
880
- <span class="cline-any cline-yes">54x</span>
881
- <span class="cline-any cline-yes">54x</span>
882
- <span class="cline-any cline-yes">73x</span>
883
- <span class="cline-any cline-yes">73x</span>
884
- <span class="cline-any cline-yes">19x</span>
885
- <span class="cline-any cline-yes">19x</span>
886
- <span class="cline-any cline-yes">19x</span>
887
- <span class="cline-any cline-yes">19x</span>
888
- <span class="cline-any cline-yes">9x</span>
889
- <span class="cline-any cline-yes">9x</span>
890
- <span class="cline-any cline-yes">9x</span>
891
- <span class="cline-any cline-no">&nbsp;</span>
892
- <span class="cline-any cline-no">&nbsp;</span>
893
- <span class="cline-any cline-yes">9x</span>
894
- <span class="cline-any cline-yes">9x</span>
895
- <span class="cline-any cline-yes">9x</span>
896
- <span class="cline-any cline-yes">19x</span>
897
- <span class="cline-any cline-no">&nbsp;</span>
898
- <span class="cline-any cline-no">&nbsp;</span>
899
- <span class="cline-any cline-no">&nbsp;</span>
900
- <span class="cline-any cline-no">&nbsp;</span>
901
- <span class="cline-any cline-no">&nbsp;</span>
902
- <span class="cline-any cline-no">&nbsp;</span>
903
- <span class="cline-any cline-no">&nbsp;</span>
904
- <span class="cline-any cline-yes">19x</span>
905
- <span class="cline-any cline-yes">73x</span>
906
- <span class="cline-any cline-yes">73x</span>
907
- <span class="cline-any cline-yes">73x</span>
908
- <span class="cline-any cline-yes">73x</span>
909
- <span class="cline-any cline-yes">73x</span>
910
- <span class="cline-any cline-yes">73x</span>
911
- <span class="cline-any cline-yes">73x</span>
912
- <span class="cline-any cline-yes">73x</span>
913
- <span class="cline-any cline-yes">73x</span>
914
- <span class="cline-any cline-yes">73x</span>
915
- <span class="cline-any cline-yes">1x</span>
916
- <span class="cline-any cline-no">&nbsp;</span>
917
- <span class="cline-any cline-no">&nbsp;</span>
918
- <span class="cline-any cline-no">&nbsp;</span>
919
- <span class="cline-any cline-no">&nbsp;</span>
920
- <span class="cline-any cline-no">&nbsp;</span>
921
- <span class="cline-any cline-no">&nbsp;</span>
922
- <span class="cline-any cline-no">&nbsp;</span>
923
- <span class="cline-any cline-no">&nbsp;</span>
924
- <span class="cline-any cline-no">&nbsp;</span>
925
- <span class="cline-any cline-no">&nbsp;</span>
926
- <span class="cline-any cline-no">&nbsp;</span>
927
- <span class="cline-any cline-no">&nbsp;</span>
928
- <span class="cline-any cline-no">&nbsp;</span>
929
- <span class="cline-any cline-yes">1x</span>
930
- <span class="cline-any cline-yes">1x</span>
931
- <span class="cline-any cline-yes">1x</span>
932
- <span class="cline-any cline-yes">1x</span>
933
- <span class="cline-any cline-no">&nbsp;</span>
934
- <span class="cline-any cline-no">&nbsp;</span>
935
- <span class="cline-any cline-yes">1x</span>
936
- <span class="cline-any cline-yes">3x</span>
937
- <span class="cline-any cline-yes">3x</span>
938
- <span class="cline-any cline-yes">3x</span>
939
- <span class="cline-any cline-yes">3x</span>
940
- <span class="cline-any cline-yes">3x</span>
941
- <span class="cline-any cline-yes">1x</span>
942
- <span class="cline-any cline-yes">1x</span>
943
- <span class="cline-any cline-yes">3x</span>
944
- <span class="cline-any cline-yes">3x</span>
945
- <span class="cline-any cline-yes">3x</span>
946
- <span class="cline-any cline-yes">3x</span>
947
- <span class="cline-any cline-yes">3x</span>
948
- <span class="cline-any cline-yes">3x</span>
949
- <span class="cline-any cline-no">&nbsp;</span>
950
- <span class="cline-any cline-no">&nbsp;</span>
951
- <span class="cline-any cline-yes">3x</span>
952
- <span class="cline-any cline-yes">3x</span>
953
- <span class="cline-any cline-yes">3x</span>
954
- <span class="cline-any cline-yes">3x</span>
955
- <span class="cline-any cline-yes">3x</span>
956
- <span class="cline-any cline-no">&nbsp;</span>
957
- <span class="cline-any cline-no">&nbsp;</span>
958
- <span class="cline-any cline-yes">3x</span>
959
- <span class="cline-any cline-yes">3x</span>
960
- <span class="cline-any cline-yes">3x</span>
961
- <span class="cline-any cline-yes">3x</span>
962
- <span class="cline-any cline-yes">1x</span>
963
- <span class="cline-any cline-yes">1x</span>
964
- <span class="cline-any cline-yes">1x</span>
965
- <span class="cline-any cline-yes">1x</span>
966
- <span class="cline-any cline-yes">1x</span>
967
- <span class="cline-any cline-yes">1x</span>
968
- <span class="cline-any cline-yes">1x</span>
969
- <span class="cline-any cline-yes">1x</span>
970
- <span class="cline-any cline-yes">1x</span>
971
- <span class="cline-any cline-yes">3x</span>
972
- <span class="cline-any cline-no">&nbsp;</span>
973
- <span class="cline-any cline-no">&nbsp;</span>
974
- <span class="cline-any cline-no">&nbsp;</span>
975
- <span class="cline-any cline-yes">1x</span>
976
- <span class="cline-any cline-yes">1x</span>
977
- <span class="cline-any cline-yes">3x</span>
978
- <span class="cline-any cline-no">&nbsp;</span>
979
- <span class="cline-any cline-no">&nbsp;</span>
980
- <span class="cline-any cline-yes">1x</span>
981
- <span class="cline-any cline-yes">1x</span>
982
- <span class="cline-any cline-yes">1x</span>
983
- <span class="cline-any cline-yes">1x</span>
984
- <span class="cline-any cline-yes">1x</span>
985
- <span class="cline-any cline-yes">3x</span>
986
- <span class="cline-any cline-no">&nbsp;</span>
987
- <span class="cline-any cline-no">&nbsp;</span>
988
- <span class="cline-any cline-yes">3x</span>
989
- <span class="cline-any cline-yes">2x</span>
990
- <span class="cline-any cline-yes">2x</span>
991
- <span class="cline-any cline-yes">2x</span>
992
- <span class="cline-any cline-yes">2x</span>
993
- <span class="cline-any cline-yes">1x</span>
994
- <span class="cline-any cline-yes">1x</span>
995
- <span class="cline-any cline-yes">1x</span>
996
- <span class="cline-any cline-yes">1x</span>
997
- <span class="cline-any cline-yes">1x</span>
998
- <span class="cline-any cline-yes">11x</span>
999
- <span class="cline-any cline-yes">11x</span>
1000
- <span class="cline-any cline-yes">11x</span>
1001
- <span class="cline-any cline-yes">11x</span>
1002
- <span class="cline-any cline-yes">11x</span>
1003
- <span class="cline-any cline-yes">11x</span>
1004
- <span class="cline-any cline-yes">11x</span>
1005
- <span class="cline-any cline-yes">11x</span>
1006
- <span class="cline-any cline-yes">11x</span>
1007
- <span class="cline-any cline-yes">11x</span>
1008
- <span class="cline-any cline-yes">11x</span>
1009
- <span class="cline-any cline-no">&nbsp;</span>
1010
- <span class="cline-any cline-no">&nbsp;</span>
1011
- <span class="cline-any cline-no">&nbsp;</span>
1012
- <span class="cline-any cline-yes">11x</span>
1013
- <span class="cline-any cline-yes">11x</span>
1014
- <span class="cline-any cline-yes">11x</span>
1015
- <span class="cline-any cline-yes">11x</span>
1016
- <span class="cline-any cline-yes">11x</span>
1017
- <span class="cline-any cline-yes">22x</span>
1018
- <span class="cline-any cline-yes">22x</span>
1019
- <span class="cline-any cline-yes">22x</span>
1020
- <span class="cline-any cline-yes">22x</span>
1021
- <span class="cline-any cline-yes">22x</span>
1022
- <span class="cline-any cline-no">&nbsp;</span>
1023
- <span class="cline-any cline-no">&nbsp;</span>
1024
- <span class="cline-any cline-no">&nbsp;</span>
1025
- <span class="cline-any cline-yes">11x</span>
1026
- <span class="cline-any cline-yes">11x</span>
1027
- <span class="cline-any cline-yes">11x</span>
1028
- <span class="cline-any cline-yes">11x</span>
1029
- <span class="cline-any cline-yes">11x</span>
1030
- <span class="cline-any cline-yes">1x</span>
1031
- <span class="cline-any cline-yes">11x</span>
1032
- <span class="cline-any cline-yes">11x</span>
1033
- <span class="cline-any cline-yes">11x</span>
1034
- <span class="cline-any cline-yes">11x</span>
1035
- <span class="cline-any cline-yes">11x</span>
1036
- <span class="cline-any cline-yes">11x</span>
1037
- <span class="cline-any cline-yes">8x</span>
1038
- <span class="cline-any cline-yes">8x</span>
1039
- <span class="cline-any cline-yes">8x</span>
1040
- <span class="cline-any cline-yes">8x</span>
1041
- <span class="cline-any cline-yes">8x</span>
1042
- <span class="cline-any cline-yes">8x</span>
1043
- <span class="cline-any cline-yes">8x</span>
1044
- <span class="cline-any cline-no">&nbsp;</span>
1045
- <span class="cline-any cline-no">&nbsp;</span>
1046
- <span class="cline-any cline-no">&nbsp;</span>
1047
- <span class="cline-any cline-no">&nbsp;</span>
1048
- <span class="cline-any cline-no">&nbsp;</span>
1049
- <span class="cline-any cline-no">&nbsp;</span>
1050
- <span class="cline-any cline-no">&nbsp;</span>
1051
- <span class="cline-any cline-no">&nbsp;</span>
1052
- <span class="cline-any cline-no">&nbsp;</span>
1053
- <span class="cline-any cline-no">&nbsp;</span>
1054
- <span class="cline-any cline-no">&nbsp;</span>
1055
- <span class="cline-any cline-no">&nbsp;</span>
1056
- <span class="cline-any cline-no">&nbsp;</span>
1057
- <span class="cline-any cline-no">&nbsp;</span>
1058
- <span class="cline-any cline-no">&nbsp;</span>
1059
- <span class="cline-any cline-no">&nbsp;</span>
1060
- <span class="cline-any cline-no">&nbsp;</span>
1061
- <span class="cline-any cline-no">&nbsp;</span>
1062
- <span class="cline-any cline-no">&nbsp;</span>
1063
- <span class="cline-any cline-no">&nbsp;</span>
1064
- <span class="cline-any cline-no">&nbsp;</span>
1065
- <span class="cline-any cline-no">&nbsp;</span>
1066
- <span class="cline-any cline-no">&nbsp;</span>
1067
- <span class="cline-any cline-no">&nbsp;</span>
1068
- <span class="cline-any cline-no">&nbsp;</span>
1069
- <span class="cline-any cline-no">&nbsp;</span>
1070
- <span class="cline-any cline-no">&nbsp;</span>
1071
- <span class="cline-any cline-no">&nbsp;</span>
1072
- <span class="cline-any cline-no">&nbsp;</span>
1073
- <span class="cline-any cline-no">&nbsp;</span>
1074
- <span class="cline-any cline-no">&nbsp;</span>
1075
- <span class="cline-any cline-no">&nbsp;</span>
1076
- <span class="cline-any cline-no">&nbsp;</span>
1077
- <span class="cline-any cline-no">&nbsp;</span>
1078
- <span class="cline-any cline-no">&nbsp;</span>
1079
- <span class="cline-any cline-no">&nbsp;</span>
1080
- <span class="cline-any cline-no">&nbsp;</span>
1081
- <span class="cline-any cline-no">&nbsp;</span>
1082
- <span class="cline-any cline-no">&nbsp;</span>
1083
- <span class="cline-any cline-no">&nbsp;</span>
1084
- <span class="cline-any cline-no">&nbsp;</span>
1085
- <span class="cline-any cline-no">&nbsp;</span>
1086
- <span class="cline-any cline-no">&nbsp;</span>
1087
- <span class="cline-any cline-no">&nbsp;</span>
1088
- <span class="cline-any cline-no">&nbsp;</span>
1089
- <span class="cline-any cline-no">&nbsp;</span>
1090
- <span class="cline-any cline-no">&nbsp;</span>
1091
- <span class="cline-any cline-no">&nbsp;</span>
1092
- <span class="cline-any cline-no">&nbsp;</span>
1093
- <span class="cline-any cline-no">&nbsp;</span>
1094
- <span class="cline-any cline-no">&nbsp;</span>
1095
- <span class="cline-any cline-no">&nbsp;</span>
1096
- <span class="cline-any cline-no">&nbsp;</span>
1097
- <span class="cline-any cline-no">&nbsp;</span>
1098
- <span class="cline-any cline-no">&nbsp;</span>
1099
- <span class="cline-any cline-no">&nbsp;</span>
1100
- <span class="cline-any cline-no">&nbsp;</span>
1101
- <span class="cline-any cline-no">&nbsp;</span>
1102
- <span class="cline-any cline-no">&nbsp;</span>
1103
- <span class="cline-any cline-no">&nbsp;</span>
1104
- <span class="cline-any cline-no">&nbsp;</span>
1105
- <span class="cline-any cline-no">&nbsp;</span>
1106
- <span class="cline-any cline-no">&nbsp;</span>
1107
- <span class="cline-any cline-no">&nbsp;</span>
1108
- <span class="cline-any cline-no">&nbsp;</span>
1109
- <span class="cline-any cline-no">&nbsp;</span>
1110
- <span class="cline-any cline-no">&nbsp;</span>
1111
- <span class="cline-any cline-no">&nbsp;</span>
1112
- <span class="cline-any cline-no">&nbsp;</span>
1113
- <span class="cline-any cline-no">&nbsp;</span>
1114
- <span class="cline-any cline-no">&nbsp;</span>
1115
- <span class="cline-any cline-no">&nbsp;</span>
1116
- <span class="cline-any cline-no">&nbsp;</span>
1117
- <span class="cline-any cline-no">&nbsp;</span>
1118
- <span class="cline-any cline-no">&nbsp;</span>
1119
- <span class="cline-any cline-no">&nbsp;</span>
1120
- <span class="cline-any cline-no">&nbsp;</span>
1121
- <span class="cline-any cline-yes">8x</span>
1122
- <span class="cline-any cline-yes">8x</span>
1123
- <span class="cline-any cline-yes">11x</span>
1124
- <span class="cline-any cline-yes">1x</span>
1125
- <span class="cline-any cline-yes">11x</span>
1126
- <span class="cline-any cline-yes">11x</span>
1127
- <span class="cline-any cline-yes">1x</span>
1128
- <span class="cline-any cline-yes">1x</span>
1129
- <span class="cline-any cline-yes">1x</span>
1130
- <span class="cline-any cline-yes">1x</span>
1131
- <span class="cline-any cline-yes">11x</span>
1132
- <span class="cline-any cline-yes">11x</span>
1133
- <span class="cline-any cline-yes">1x</span>
1134
- <span class="cline-any cline-yes">1x</span>
1135
- <span class="cline-any cline-yes">11x</span>
1136
- <span class="cline-any cline-yes">11x</span>
1137
- <span class="cline-any cline-yes">11x</span>
1138
- <span class="cline-any cline-yes">11x</span>
1139
- <span class="cline-any cline-yes">11x</span>
1140
- <span class="cline-any cline-yes">11x</span>
1141
- <span class="cline-any cline-yes">11x</span>
1142
- <span class="cline-any cline-yes">11x</span>
1143
- <span class="cline-any cline-yes">11x</span>
1144
- <span class="cline-any cline-yes">11x</span>
1145
- <span class="cline-any cline-yes">11x</span>
1146
- <span class="cline-any cline-yes">11x</span>
1147
- <span class="cline-any cline-yes">2x</span>
1148
- <span class="cline-any cline-yes">2x</span>
1149
- <span class="cline-any cline-yes">2x</span>
1150
- <span class="cline-any cline-yes">11x</span>
1151
- <span class="cline-any cline-yes">11x</span>
1152
- <span class="cline-any cline-yes">11x</span>
1153
- <span class="cline-any cline-yes">11x</span>
1154
- <span class="cline-any cline-no">&nbsp;</span>
1155
- <span class="cline-any cline-no">&nbsp;</span>
1156
- <span class="cline-any cline-no">&nbsp;</span>
1157
- <span class="cline-any cline-no">&nbsp;</span>
1158
- <span class="cline-any cline-yes">11x</span>
1159
- <span class="cline-any cline-yes">11x</span>
1160
- <span class="cline-any cline-yes">119x</span>
1161
- <span class="cline-any cline-yes">119x</span>
1162
- <span class="cline-any cline-yes">119x</span>
1163
- <span class="cline-any cline-no">&nbsp;</span>
1164
- <span class="cline-any cline-yes">119x</span>
1165
- <span class="cline-any cline-no">&nbsp;</span>
1166
- <span class="cline-any cline-no">&nbsp;</span>
1167
- <span class="cline-any cline-no">&nbsp;</span>
1168
- <span class="cline-any cline-yes">119x</span>
1169
- <span class="cline-any cline-yes">119x</span>
1170
- <span class="cline-any cline-yes">119x</span>
1171
- <span class="cline-any cline-yes">119x</span>
1172
- <span class="cline-any cline-yes">2x</span>
1173
- <span class="cline-any cline-yes">2x</span>
1174
- <span class="cline-any cline-yes">2x</span>
1175
- <span class="cline-any cline-yes">119x</span>
1176
- <span class="cline-any cline-yes">11x</span>
1177
- <span class="cline-any cline-yes">11x</span>
1178
- <span class="cline-any cline-no">&nbsp;</span>
1179
- <span class="cline-any cline-no">&nbsp;</span>
1180
- <span class="cline-any cline-no">&nbsp;</span>
1181
- <span class="cline-any cline-yes">11x</span>
1182
- <span class="cline-any cline-yes">11x</span>
1183
- <span class="cline-any cline-no">&nbsp;</span>
1184
- <span class="cline-any cline-no">&nbsp;</span>
1185
- <span class="cline-any cline-no">&nbsp;</span>
1186
- <span class="cline-any cline-yes">11x</span>
1187
- <span class="cline-any cline-yes">11x</span>
1188
- <span class="cline-any cline-yes">73x</span>
1189
- <span class="cline-any cline-yes">73x</span>
1190
- <span class="cline-any cline-yes">73x</span>
1191
- <span class="cline-any cline-yes">11x</span>
1192
- <span class="cline-any cline-yes">11x</span>
1193
- <span class="cline-any cline-no">&nbsp;</span>
1194
- <span class="cline-any cline-no">&nbsp;</span>
1195
- <span class="cline-any cline-no">&nbsp;</span>
1196
- <span class="cline-any cline-yes">11x</span>
1197
- <span class="cline-any cline-yes">11x</span>
1198
- <span class="cline-any cline-yes">1x</span>
1199
- <span class="cline-any cline-yes">1x</span>
1200
- <span class="cline-any cline-yes">11x</span>
1201
- <span class="cline-any cline-yes">11x</span>
1202
- <span class="cline-any cline-yes">11x</span>
1203
- <span class="cline-any cline-yes">95x</span>
1204
- <span class="cline-any cline-yes">95x</span>
1205
- <span class="cline-any cline-yes">95x</span>
1206
- <span class="cline-any cline-yes">11x</span>
1207
- <span class="cline-any cline-yes">11x</span>
1208
- <span class="cline-any cline-no">&nbsp;</span>
1209
- <span class="cline-any cline-no">&nbsp;</span>
1210
- <span class="cline-any cline-no">&nbsp;</span>
1211
- <span class="cline-any cline-no">&nbsp;</span>
1212
- <span class="cline-any cline-no">&nbsp;</span>
1213
- <span class="cline-any cline-no">&nbsp;</span>
1214
- <span class="cline-any cline-no">&nbsp;</span>
1215
- <span class="cline-any cline-no">&nbsp;</span>
1216
- <span class="cline-any cline-no">&nbsp;</span>
1217
- <span class="cline-any cline-no">&nbsp;</span>
1218
- <span class="cline-any cline-no">&nbsp;</span>
1219
- <span class="cline-any cline-no">&nbsp;</span>
1220
- <span class="cline-any cline-no">&nbsp;</span>
1221
- <span class="cline-any cline-no">&nbsp;</span>
1222
- <span class="cline-any cline-no">&nbsp;</span>
1223
- <span class="cline-any cline-no">&nbsp;</span>
1224
- <span class="cline-any cline-no">&nbsp;</span>
1225
- <span class="cline-any cline-no">&nbsp;</span>
1226
- <span class="cline-any cline-no">&nbsp;</span>
1227
- <span class="cline-any cline-no">&nbsp;</span>
1228
- <span class="cline-any cline-no">&nbsp;</span>
1229
- <span class="cline-any cline-no">&nbsp;</span>
1230
- <span class="cline-any cline-no">&nbsp;</span>
1231
- <span class="cline-any cline-no">&nbsp;</span>
1232
- <span class="cline-any cline-yes">11x</span>
1233
- <span class="cline-any cline-yes">11x</span>
1234
- <span class="cline-any cline-yes">11x</span>
1235
- <span class="cline-any cline-yes">11x</span>
1236
- <span class="cline-any cline-yes">11x</span>
1237
- <span class="cline-any cline-yes">11x</span>
1238
- <span class="cline-any cline-yes">11x</span>
1239
- <span class="cline-any cline-yes">11x</span>
1240
- <span class="cline-any cline-yes">11x</span>
1241
- <span class="cline-any cline-yes">11x</span>
1242
- <span class="cline-any cline-yes">11x</span>
1243
- <span class="cline-any cline-yes">11x</span>
1244
- <span class="cline-any cline-yes">11x</span>
1245
- <span class="cline-any cline-yes">11x</span>
1246
- <span class="cline-any cline-yes">11x</span>
1247
- <span class="cline-any cline-yes">11x</span>
1248
- <span class="cline-any cline-yes">11x</span>
1249
- <span class="cline-any cline-yes">11x</span>
1250
- <span class="cline-any cline-yes">11x</span>
1251
- <span class="cline-any cline-yes">11x</span>
1252
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import path from 'path'
1253
- import url from 'url'
1254
- import fs from 'fs-extra'
1255
- import makeDebug from 'debug'
1256
- import winston from 'winston'
1257
- import _ from 'lodash'
1258
- import siftModule from 'sift'
1259
- import 'winston-daily-rotate-file'
1260
- import compress from 'compression'
1261
- import cors from 'cors'
1262
- import helmet from 'helmet'
1263
- import { RateLimiter as SocketLimiter } from 'limiter'
1264
- import HttpLimiter from 'express-rate-limit'
1265
- import feathers from '@feathersjs/feathers'
1266
- import configuration from '@feathersjs/configuration'
1267
- import errors from '@feathersjs/errors'
1268
- import express, { authenticate } from '@feathersjs/express'
1269
- import socketio from '@feathersjs/socketio'
1270
- import { Database, isObjectID, idToString } from './db.js'
1271
- import auth from './authentication.js'
1272
- &nbsp;
1273
- const debug = makeDebug('kdk:core:application')
1274
- const debugLimiter = makeDebug('kdk:core:application:limiter')
1275
- const { TooManyRequests, Forbidden, BadRequest } = errors
1276
- const { rest } = express
1277
- const sift = siftModule.default
1278
- &nbsp;
1279
- // Initialize debugger to be used in feathers
1280
- feathers.setDebug(makeDebug)
1281
- &nbsp;
1282
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function tooManyRequests (socket, message, key) {</span></span>
1283
- <span class="cstat-no" title="statement not covered" > debug(message)</span>
1284
- <span class="cstat-no" title="statement not covered" > const error = new TooManyRequests(message, { translation: { key } })</span>
1285
- <span class="cstat-no" title="statement not covered" > socket.emit('rate-limit', error)</span>
1286
- <span class="cstat-no" title="statement not covered" > // Add a timeout so that error message is correctly handled</span>
1287
- <span class="cstat-no" title="statement not covered" > setTimeout(() =&gt; socket.disconnect(true), 3000)</span>
1288
- <span class="cstat-no" title="statement not covered" >}</span>
1289
- &nbsp;
1290
- export function declareService (name, app, service, serviceOptions = {}) {
1291
- let servicePath = serviceOptions.path || name
1292
- let contextId
1293
- if (serviceOptions.context) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1294
- <span class="cstat-no" title="statement not covered" > contextId = idToString(serviceOptions.context)</span>
1295
- <span class="cstat-no" title="statement not covered" > servicePath = contextId + '/' + servicePath</span>
1296
- <span class="cstat-no" title="statement not covered" > }</span>
1297
- &nbsp;
1298
- let feathersPath = app.get('apiPath') + '/' + servicePath
1299
- if (feathersPath.startsWith('/')) feathersPath = feathersPath.substr(1)
1300
- &nbsp;
1301
- try {
1302
- const feathersService = app.service(feathersPath)
1303
- // Some internal Feathers service might internally declare the service
1304
- return feathersService
1305
- } catch (error) {
1306
- // Initialize our service by providing any middleware as well
1307
- let args = [feathersPath]
1308
- if (_.has(serviceOptions, 'middlewares.before')) <span class="branch-0 cbranch-no" title="branch not covered" >args = args.concat(_.get(serviceOptions, 'middlewares.before'))</span>
1309
- args.push(service)
1310
- const options = _.pick(serviceOptions, ['methods', 'events'])
1311
- if (!_.isEmpty(options)) args = args.concat(options)
1312
- if (_.has(serviceOptions, 'middlewares.after')) <span class="branch-0 cbranch-no" title="branch not covered" >args = args.concat(_.get(serviceOptions, 'middlewares.after'))</span>
1313
- app.use.apply(app, args)
1314
- // Get the Feathers service, ie base service + Feathers' internals
1315
- service = app.service(feathersPath)
1316
- debug('Service declared on path ' + feathersPath)
1317
- // Then configuration
1318
- service.name = name
1319
- service.app = app
1320
- if (!service.options) service.options = serviceOptions
1321
- else Object.assign(service.options, serviceOptions)
1322
- service.path = servicePath
1323
- service.context = serviceOptions.context
1324
- &nbsp;
1325
- // Add some utility functions
1326
- service.getPath = function (withApiPrefix) {
1327
- let path = service.path
1328
- if (withApiPrefix &amp;&amp; !path.startsWith(app.get('apiPath'))) {
1329
- path = app.get('apiPath') + '/' + path
1330
- }
1331
- return path
1332
- }
1333
- service.getContextId = <span class="fstat-no" title="function not covered" >function () {</span>
1334
- <span class="cstat-no" title="statement not covered" > return contextId // As string</span>
1335
- <span class="cstat-no" title="statement not covered" > }</span>
1336
- return service
1337
- }
1338
- }
1339
- &nbsp;
1340
- export async function configureService (name, service, servicesPath) {
1341
- let filepath = path.join(servicesPath, name, `${name}.hooks.js`)
1342
- try {
1343
- const fileExists = await fs.pathExists(filepath)
1344
- if (fileExists) {
1345
- const hooks = (await import(url.pathToFileURL(filepath))).default
1346
- service.hooks(hooks)
1347
- debug(name + ' service hooks configured on path ' + servicesPath)
1348
- }
1349
- } <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
1350
- <span class="cstat-no" title="statement not covered" > debug('No ' + name + ' service hooks configured on path ' + servicesPath)</span>
1351
- <span class="cstat-no" title="statement not covered" > // if (error.code !== 'ERR_MODULE_NOT_FOUND') {</span>
1352
- <span class="cstat-no" title="statement not covered" > // Log error in this case as this might be linked to a syntax error in required file</span>
1353
- <span class="cstat-no" title="statement not covered" > debug(filepath, error)</span>
1354
- <span class="cstat-no" title="statement not covered" > // }</span>
1355
- <span class="cstat-no" title="statement not covered" > // As this is optionnal this require has to fail silently</span>
1356
- <span class="cstat-no" title="statement not covered" > }</span>
1357
- &nbsp;
1358
- filepath = path.join(servicesPath, name, `${name}.channels.js`)
1359
- try {
1360
- const fileExists = await fs.pathExists(filepath)
1361
- if (fileExists) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1362
- <span class="cstat-no" title="statement not covered" > const channels = (await import(url.pathToFileURL(filepath))).default</span>
1363
- <span class="cstat-no" title="statement not covered" > _.forOwn(channels, (publisher, event) =&gt; {</span>
1364
- <span class="cstat-no" title="statement not covered" > if (event === 'all') service.publish(publisher)</span>
1365
- <span class="cstat-no" title="statement not covered" > else service.publish(event, publisher)</span>
1366
- <span class="cstat-no" title="statement not covered" > })</span>
1367
- <span class="cstat-no" title="statement not covered" > debug(name + ' service channels configured on path ' + servicesPath)</span>
1368
- <span class="cstat-no" title="statement not covered" > }</span>
1369
- } <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
1370
- <span class="cstat-no" title="statement not covered" > debug('No ' + name + ' service channels configured on path ' + servicesPath)</span>
1371
- <span class="cstat-no" title="statement not covered" > // if (error.code !== 'ERR_MODULE_NOT_FOUND') {</span>
1372
- <span class="cstat-no" title="statement not covered" > // Log error in this case as this might be linked to a syntax error in required file</span>
1373
- <span class="cstat-no" title="statement not covered" > debug(filepath, error)</span>
1374
- <span class="cstat-no" title="statement not covered" > // }</span>
1375
- <span class="cstat-no" title="statement not covered" > // As this is optionnal this require has to fail silently</span>
1376
- <span class="cstat-no" title="statement not covered" > }</span>
1377
- &nbsp;
1378
- return service
1379
- }
1380
- &nbsp;
1381
- export <span class="fstat-no" title="function not covered" >function createProxyService (options) {</span>
1382
- <span class="cstat-no" title="statement not covered" > const targetService = options.service</span>
1383
- <span class="cstat-no" title="statement not covered" > function proxyParams (params) {</span>
1384
- <span class="cstat-no" title="statement not covered" > if (options.params) {</span>
1385
- <span class="cstat-no" title="statement not covered" > let proxiedParams</span>
1386
- <span class="cstat-no" title="statement not covered" > if (typeof options.params === 'function') {</span>
1387
- <span class="cstat-no" title="statement not covered" > proxiedParams = options.params(params)</span>
1388
- <span class="cstat-no" title="statement not covered" > } else {</span>
1389
- <span class="cstat-no" title="statement not covered" > proxiedParams = _.merge(params, options.params)</span>
1390
- <span class="cstat-no" title="statement not covered" > }</span>
1391
- <span class="cstat-no" title="statement not covered" > return proxiedParams</span>
1392
- <span class="cstat-no" title="statement not covered" > } else return params</span>
1393
- <span class="cstat-no" title="statement not covered" > }</span>
1394
- <span class="cstat-no" title="statement not covered" > function proxyId (id) {</span>
1395
- <span class="cstat-no" title="statement not covered" > if (options.id) return options.id(id)</span>
1396
- <span class="cstat-no" title="statement not covered" > else return id</span>
1397
- <span class="cstat-no" title="statement not covered" > }</span>
1398
- <span class="cstat-no" title="statement not covered" > function proxyData (data) {</span>
1399
- <span class="cstat-no" title="statement not covered" > if (options.data) return options.data(data)</span>
1400
- <span class="cstat-no" title="statement not covered" > else return data</span>
1401
- <span class="cstat-no" title="statement not covered" > }</span>
1402
- <span class="cstat-no" title="statement not covered" > function proxyResult (data) {</span>
1403
- <span class="cstat-no" title="statement not covered" > if (options.result) return options.result(data)</span>
1404
- <span class="cstat-no" title="statement not covered" > else return data</span>
1405
- <span class="cstat-no" title="statement not covered" > }</span>
1406
- <span class="cstat-no" title="statement not covered" > return {</span>
1407
- <span class="cstat-no" title="statement not covered" > async find (params) { return proxyResult(await targetService.find(proxyParams(params))) },</span>
1408
- <span class="cstat-no" title="statement not covered" > async get (id, params) { return proxyResult(await targetService.get(proxyId(id), proxyParams(params))) },</span>
1409
- <span class="cstat-no" title="statement not covered" > async create (data, params) { return proxyResult(await targetService.create(proxyData(data), proxyParams(params))) },</span>
1410
- <span class="cstat-no" title="statement not covered" > async update (id, data, params) { return proxyResult(await targetService.update(proxyId(id), proxyData(data), proxyParams(params))) },</span>
1411
- <span class="cstat-no" title="statement not covered" > async patch (id, data, params) { return proxyResult(await targetService.patch(proxyId(id), proxyData(data), proxyParams(params))) },</span>
1412
- <span class="cstat-no" title="statement not covered" > async remove (id, params) { return proxyResult(await targetService.remove(proxyId(id), proxyParams(params))) }</span>
1413
- <span class="cstat-no" title="statement not covered" > }</span>
1414
- <span class="cstat-no" title="statement not covered" >}</span>
1415
- &nbsp;
1416
- async function createService (name, app, options = {}) {
1417
- debug(`Creating service ${name}`)
1418
- const createFeathersService = (await import('feathers-' + app.db.adapter)).default
1419
- &nbsp;
1420
- const paginate = app.get('paginate')
1421
- const serviceOptions = Object.assign({
1422
- name,
1423
- paginate,
1424
- multi: true,
1425
- whitelist: [
1426
- '$exists', '$and', '$or', '$not', '$eq', '$elemMatch', '$distinct', '$groupBy', '$group', '$regex',
1427
- '$text', '$search', '$caseSensitive', '$language', '$diacriticSensitive',
1428
- '$aggregate', '$near', '$nearSphere', '$geoIntersects', '$geoWithin',
1429
- '$maxDistance', '$minDistance', '$geometry', '$box', '$polygon', '$center', '$centerSphere'
1430
- ]
1431
- }, options)
1432
- if (serviceOptions.disabled) <span class="branch-0 cbranch-no" title="branch not covered" >return undefined</span>
1433
- // For DB services a model has to be provided
1434
- const fileName = serviceOptions.modelName || name
1435
- &nbsp;
1436
- let dbService = false
1437
- try {
1438
- if (serviceOptions.modelsPath) {
1439
- const filepath = path.join(serviceOptions.modelsPath, `${fileName}.model.${app.db.adapter}.js`)
1440
- const fileExists = await fs.pathExists(filepath)
1441
- if (fileExists) {
1442
- const configureModel = (await import(url.pathToFileURL(filepath))).default
1443
- configureModel(app, serviceOptions)
1444
- debug(name + ' service model configured on path ' + serviceOptions.modelsPath)
1445
- dbService = true
1446
- }
1447
- }
1448
- } <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
1449
- <span class="cstat-no" title="statement not covered" > debug('No ' + fileName + ' service model configured on path ' + serviceOptions.modelsPath)</span>
1450
- <span class="cstat-no" title="statement not covered" > // if (error.code !== 'ERR_MODULE_NOT_FOUND') {</span>
1451
- <span class="cstat-no" title="statement not covered" > // Log error in this case as this might be linked to a syntax error in required file</span>
1452
- <span class="cstat-no" title="statement not covered" > debug(fileName, error)</span>
1453
- <span class="cstat-no" title="statement not covered" > // }</span>
1454
- <span class="cstat-no" title="statement not covered" > // As this is optionnal this require has to fail silently</span>
1455
- <span class="cstat-no" title="statement not covered" > }</span>
1456
- &nbsp;
1457
- // Initialize our service with any options it requires
1458
- let service
1459
- if (dbService) {
1460
- service = createFeathersService(serviceOptions)
1461
- dbService = service
1462
- } else if (serviceOptions.proxy) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1463
- <span class="cstat-no" title="statement not covered" > service = createProxyService(serviceOptions.proxy)</span>
1464
- } else {
1465
- const filepath = path.join(serviceOptions.servicesPath, fileName, `${fileName}.service.js`)
1466
- // Otherwise we expect the service to be provided as a Feathers service interface
1467
- service = (await import(url.pathToFileURL(filepath))).default
1468
- // If we get a function try to call it assuming it will return the service object
1469
- if (typeof service === 'function') {
1470
- service = service(name, app, serviceOptions)
1471
- }
1472
- // Need to set this manually for services not using class inheritance or default adapters
1473
- if (serviceOptions.events) service.events = serviceOptions.events
1474
- }
1475
- // Optionnally a specific service mixin can be provided, apply it
1476
- if (dbService &amp;&amp; serviceOptions.servicesPath) {
1477
- const filepath = path.join(serviceOptions.servicesPath, fileName, `${fileName}.service.js`)
1478
- try {
1479
- const fileExists = await fs.pathExists(filepath)
1480
- if (fileExists) {
1481
- let serviceMixin = (await import(url.pathToFileURL(filepath))).default
1482
- // If we get a function try to call it assuming it will return the mixin object
1483
- if (typeof serviceMixin === 'function') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1484
- <span class="cstat-no" title="statement not covered" > serviceMixin = await serviceMixin.bind(dbService)(fileName, app, serviceOptions)</span>
1485
- <span class="cstat-no" title="statement not covered" > }</span>
1486
- Object.assign(service, serviceMixin)
1487
- debug(name + ' service mixin configured on path ' + serviceOptions.servicesPath)
1488
- }
1489
- } <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
1490
- <span class="cstat-no" title="statement not covered" > debug('No ' + fileName + ' service mixin configured on path ' + serviceOptions.servicesPath)</span>
1491
- <span class="cstat-no" title="statement not covered" > // if (error.code !== 'ERR_MODULE_NOT_FOUND') {</span>
1492
- <span class="cstat-no" title="statement not covered" > // Log error in this case as this might be linked to a syntax error in required file</span>
1493
- <span class="cstat-no" title="statement not covered" > debug(filepath, error)</span>
1494
- <span class="cstat-no" title="statement not covered" > // }</span>
1495
- <span class="cstat-no" title="statement not covered" > // As this is optionnal this require has to fail silently</span>
1496
- <span class="cstat-no" title="statement not covered" > }</span>
1497
- }
1498
- &nbsp;
1499
- service = declareService(name, app, service, serviceOptions)
1500
- // Register hooks and event filters
1501
- service = await configureService(fileName, service, serviceOptions.servicesPath)
1502
- &nbsp;
1503
- debug(service.name + ' service registration completed')
1504
- app.emit('service', service)
1505
- &nbsp;
1506
- return service
1507
- }
1508
- &nbsp;
1509
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >async function removeService (service, app) {</span></span>
1510
- <span class="cstat-no" title="statement not covered" > // Often called like removeService(getService('xxx'))</span>
1511
- <span class="cstat-no" title="statement not covered" > // so that we don't want to crash if the service does not exist or has already been unregistered</span>
1512
- <span class="cstat-no" title="statement not covered" > if (!service) return</span>
1513
- <span class="cstat-no" title="statement not covered" > let feathersPath = app.get('apiPath') + '/' + service.path</span>
1514
- <span class="cstat-no" title="statement not covered" > if (feathersPath.startsWith('/')) feathersPath = feathersPath.substr(1)</span>
1515
- <span class="cstat-no" title="statement not covered" ></span>
1516
- <span class="cstat-no" title="statement not covered" > app.unuse(feathersPath)</span>
1517
- <span class="cstat-no" title="statement not covered" > debug(service.name + ' service unregistration completed')</span>
1518
- <span class="cstat-no" title="statement not covered" > app.emit('service-removed', service)</span>
1519
- <span class="cstat-no" title="statement not covered" ></span>
1520
- <span class="cstat-no" title="statement not covered" > return service</span>
1521
- <span class="cstat-no" title="statement not covered" >}</span>
1522
- &nbsp;
1523
- export function createWebhook (path, app, options = {}) {
1524
- let webhookPath = path
1525
- if (options.context) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1526
- <span class="cstat-no" title="statement not covered" > webhookPath = idToString(options.context) + '/' + webhookPath</span>
1527
- <span class="cstat-no" title="statement not covered" > }</span>
1528
- const isAllowed = (payload) =&gt; {
1529
- // Default is to expose all services/operations
1530
- if (!options.filter) <span class="branch-0 cbranch-no" title="branch not covered" >return true</span>
1531
- const result = [payload].filter(sift(options.filter))
1532
- return result.length &gt; 0
1533
- }
1534
- &nbsp;
1535
- app.post(app.get('apiPath') + '/webhooks/' + webhookPath, authenticate('jwt'), async (req, res, next) =&gt; {
1536
- const payload = req.body
1537
- const config = app.get('authentication')
1538
- res.set('content-type', 'application/json')
1539
- const params = _.get(req, 'feathers', {})
1540
- try {
1541
- if (options.preprocessor) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1542
- <span class="cstat-no" title="statement not covered" > await options.preprocessor(req, res, payload)</span>
1543
- <span class="cstat-no" title="statement not covered" > }</span>
1544
- // Authenticate when required
1545
- if (config) {
1546
- params.checkAuthorisation = true
1547
- }
1548
- if (req.headers['content-type'] !== 'application/json') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1549
- <span class="cstat-no" title="statement not covered" > throw new BadRequest('Webhooks expect application/json content type')</span>
1550
- <span class="cstat-no" title="statement not covered" > }</span>
1551
- if (!isAllowed(payload)) throw new Forbidden('Service or operation not allowed for webhook')
1552
- const service = app.getService(payload.service, options.context || payload.context)
1553
- if (!service) <span class="branch-0 cbranch-no" title="branch not covered" >throw new BadRequest('Service could not be found')</span>
1554
- if (typeof service[payload.operation] !== 'function') <span class="branch-0 cbranch-no" title="branch not covered" >throw new BadRequest('Service operation could not be found')</span>
1555
- const args = []
1556
- // Get/Update/Patch/Remove
1557
- const operationsWithId = ['get', 'update', 'patch', 'remove']
1558
- if (operationsWithId.includes(payload.operation)) {
1559
- if (!_.has(payload, 'id')) <span class="branch-0 cbranch-no" title="branch not covered" >throw new BadRequest('Missing id for operation')</span>
1560
- args.push(_.get(payload, 'id'))
1561
- }
1562
- // Create/Update/Patch
1563
- const operationsWithData = ['create', 'update', 'patch']
1564
- if (operationsWithData.includes(payload.operation)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1565
- <span class="cstat-no" title="statement not covered" > if (!_.has(payload, 'data')) throw new BadRequest('Missing data for operation')</span>
1566
- <span class="cstat-no" title="statement not covered" > args.push(_.get(payload, 'data'))</span>
1567
- <span class="cstat-no" title="statement not covered" > }</span>
1568
- // Params
1569
- args.push(params)
1570
- if (options.postprocessor) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1571
- <span class="cstat-no" title="statement not covered" > await options.postprocessor(service, args, payload)</span>
1572
- <span class="cstat-no" title="statement not covered" > }</span>
1573
- try {
1574
- debug(`Performing ${payload.service} service ${payload.operation} operation through webhook ${webhookPath} with args:`, args)
1575
- const result = await service[payload.operation].apply(service, args)
1576
- // Send back result
1577
- res.json(result)
1578
- } <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
1579
- <span class="cstat-no" title="statement not covered" > throw new BadRequest('Service operation could not be performed')</span>
1580
- <span class="cstat-no" title="statement not covered" > }</span>
1581
- } catch (error) {
1582
- debug(`Webhook ${webhookPath} error:`, error)
1583
- // Send back error
1584
- res.status(error.code <span class="branch-0 cbranch-no" title="branch not covered" >|| 500)</span>.json(error.toJSON())
1585
- }
1586
- })
1587
- &nbsp;
1588
- debug(`Webhook ${webhookPath} registration completed`)
1589
- }
1590
- &nbsp;
1591
- function setupLogger (app) {
1592
- debug('Setup application loggers')
1593
- const logsConfig = Object.assign({ // Default logger erased by provided one if any
1594
- Console: {
1595
- format: winston.format.combine(winston.format.colorize(), winston.format.simple())
1596
- }
1597
- }, _.omit(app.get('logs'), ['level', 'format']))
1598
- // Remove winston defaults
1599
- try {
1600
- winston.clear()
1601
- } <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
1602
- <span class="cstat-no" title="statement not covered" > // Logger might be down, use console</span>
1603
- <span class="cstat-no" title="statement not covered" > console.error('Could not remove default logger transport(s)', error)</span>
1604
- <span class="cstat-no" title="statement not covered" > }</span>
1605
- // We have one entry per log type
1606
- const logsTypes = Object.getOwnPropertyNames(logsConfig)
1607
- // Create corresponding winston transports with options
1608
- const transports = []
1609
- logsTypes.forEach(logType =&gt; {
1610
- const logOptions = logsConfig[logType]
1611
- debug(`Setup ${logType} transport with options`, logOptions)
1612
- try {
1613
- transports.push(new winston.transports[logType](logOptions))
1614
- } <span class="branch-0 cbranch-no" title="branch not covered" >catch (error) {</span>
1615
- <span class="cstat-no" title="statement not covered" > // Logger might be down, use console</span>
1616
- <span class="cstat-no" title="statement not covered" > console.error(`Could not setup logger ${logType}`, error)</span>
1617
- <span class="cstat-no" title="statement not covered" > }</span>
1618
- })
1619
- app.logger = winston.createLogger(Object.assign({
1620
- level: (process.env.NODE_ENV === 'development' <span class="branch-0 cbranch-no" title="branch not covered" >? 'debug' </span>: 'info'), transports
1621
- }, _.pick(logsConfig, ['level', 'format'])))
1622
- }
1623
- &nbsp;
1624
- function setupSockets (app) {
1625
- const apiLimiter = app.get('apiLimiter')
1626
- const connections = {}
1627
- let nbConnections = 0
1628
- &nbsp;
1629
- return io =&gt; {
1630
- // By default EventEmitters will print a warning if more than 10 listeners are added for a particular event.
1631
- // The value can be set to Infinity (or 0) to indicate an unlimited number of listeners.
1632
- io.sockets.setMaxListeners(0)
1633
- const maxConnections = _.get(apiLimiter, 'websocket.maxConcurrency', 0)
1634
- const maxIpConnections = _.get(apiLimiter, 'websocket.concurrency', 0)
1635
- &nbsp;
1636
- io.on('connection', socket =&gt; {
1637
- <span class="cstat-no" title="statement not covered" > nbConnections++</span>
1638
- <span class="cstat-no" title="statement not covered" > debug(`New socket connection on server with pid ${process.pid}`, socket.id, socket.conn.remoteAddress, nbConnections)</span>
1639
- <span class="cstat-no" title="statement not covered" > // Setup disconnect handler first</span>
1640
- <span class="cstat-no" title="statement not covered" > socket.on('disconnect', (reason) =&gt; {</span>
1641
- <span class="cstat-no" title="statement not covered" > nbConnections--</span>
1642
- <span class="cstat-no" title="statement not covered" > debug(reason)</span>
1643
- <span class="cstat-no" title="statement not covered" > debug(`Socket disconnection on server with pid ${process.pid}`, socket.id, socket.conn.remoteAddress, nbConnections)</span>
1644
- <span class="cstat-no" title="statement not covered" > if (maxIpConnections &gt; 0) {</span>
1645
- <span class="cstat-no" title="statement not covered" > const nbIpConnections = _.get(connections, socket.conn.remoteAddress) - 1</span>
1646
- <span class="cstat-no" title="statement not covered" > debug('Total number of connections for', socket.id, socket.conn.remoteAddress, nbIpConnections)</span>
1647
- <span class="cstat-no" title="statement not covered" > _.set(connections, socket.conn.remoteAddress, nbIpConnections)</span>
1648
- <span class="cstat-no" title="statement not covered" > }</span>
1649
- <span class="cstat-no" title="statement not covered" > })</span>
1650
- <span class="cstat-no" title="statement not covered" > if (maxConnections &gt; 0) {</span>
1651
- <span class="cstat-no" title="statement not covered" > if (nbConnections &gt; maxConnections) {</span>
1652
- <span class="cstat-no" title="statement not covered" > tooManyRequests(socket, 'Too many concurrent connections (rate limiting)', 'RATE_LIMITING_CONCURRENCY')</span>
1653
- <span class="cstat-no" title="statement not covered" > return</span>
1654
- <span class="cstat-no" title="statement not covered" > }</span>
1655
- <span class="cstat-no" title="statement not covered" > }</span>
1656
- <span class="cstat-no" title="statement not covered" > if (maxIpConnections &gt; 0) {</span>
1657
- <span class="cstat-no" title="statement not covered" > if (_.has(connections, socket.conn.remoteAddress)) {</span>
1658
- <span class="cstat-no" title="statement not covered" > const nbIpConnections = _.get(connections, socket.conn.remoteAddress) + 1</span>
1659
- <span class="cstat-no" title="statement not covered" > debug('Total number of connections for', socket.id, socket.conn.remoteAddress, nbConnections)</span>
1660
- <span class="cstat-no" title="statement not covered" > _.set(connections, socket.conn.remoteAddress, nbIpConnections)</span>
1661
- <span class="cstat-no" title="statement not covered" > if (nbIpConnections &gt; maxIpConnections) {</span>
1662
- <span class="cstat-no" title="statement not covered" > tooManyRequests(socket, 'Too many concurrent connections (rate limiting)', 'RATE_LIMITING_CONCURRENCY')</span>
1663
- <span class="cstat-no" title="statement not covered" > return</span>
1664
- <span class="cstat-no" title="statement not covered" > }</span>
1665
- <span class="cstat-no" title="statement not covered" > } else {</span>
1666
- <span class="cstat-no" title="statement not covered" > _.set(connections, socket.conn.remoteAddress, 1)</span>
1667
- <span class="cstat-no" title="statement not covered" > }</span>
1668
- <span class="cstat-no" title="statement not covered" > }</span>
1669
- <span class="cstat-no" title="statement not covered" > /* For debug purpose: trace all data received</span>
1670
- <span class="cstat-no" title="statement not covered" > socket.use((packet, next) =&gt; {</span>
1671
- <span class="cstat-no" title="statement not covered" > console.log(packet)</span>
1672
- <span class="cstat-no" title="statement not covered" > next()</span>
1673
- <span class="cstat-no" title="statement not covered" > })</span>
1674
- <span class="cstat-no" title="statement not covered" > */</span>
1675
- <span class="cstat-no" title="statement not covered" > if (apiLimiter &amp;&amp; apiLimiter.websocket) {</span>
1676
- <span class="cstat-no" title="statement not covered" > const { tokensPerInterval, interval } = apiLimiter.websocket</span>
1677
- <span class="cstat-no" title="statement not covered" > // Function used to filter whitelisted services, defaults to none</span>
1678
- <span class="cstat-no" title="statement not covered" > const services = _.get(apiLimiter.websocket, 'services', (service) =&gt; false)</span>
1679
- <span class="cstat-no" title="statement not covered" > socket.socketLimiter = new SocketLimiter(tokensPerInterval, interval)</span>
1680
- <span class="cstat-no" title="statement not covered" > socket.use((packet, next) =&gt; {</span>
1681
- <span class="cstat-no" title="statement not covered" > if (packet.length &gt; 0) {</span>
1682
- <span class="cstat-no" title="statement not covered" > // Packets are formatted according to service interface,</span>
1683
- <span class="cstat-no" title="statement not covered" > // e.g. like [service_method, service_path, id or data, params]</span>
1684
- <span class="cstat-no" title="statement not covered" > // Bypass rate limiting on whitelist</span>
1685
- <span class="cstat-no" title="statement not covered" > if ((packet.length &gt; 1) &amp;&amp; (typeof packet[1] === 'string')) {</span>
1686
- <span class="cstat-no" title="statement not covered" > // Service path includes API prefix (but without trailing /)</span>
1687
- <span class="cstat-no" title="statement not covered" > // Get name from service path without api prefix</span>
1688
- <span class="cstat-no" title="statement not covered" > const serviceName = packet[1].replace(app.get('apiPath').substring(1) + '/', '')</span>
1689
- <span class="cstat-no" title="statement not covered" > const service = app.getService(serviceName)</span>
1690
- <span class="cstat-no" title="statement not covered" > if (service &amp;&amp; services(service)) {</span>
1691
- <span class="cstat-no" title="statement not covered" > debugLimiter('By-pass rate limiting on whitelisted service operation', socket.id, socket.conn.remoteAddress, packet[0], packet[1])</span>
1692
- <span class="cstat-no" title="statement not covered" > next()</span>
1693
- <span class="cstat-no" title="statement not covered" > return</span>
1694
- <span class="cstat-no" title="statement not covered" > }</span>
1695
- <span class="cstat-no" title="statement not covered" > }</span>
1696
- <span class="cstat-no" title="statement not covered" > debugLimiter(socket.socketLimiter.getTokensRemaining() + ' remaining API token for socket', socket.id, socket.conn.remoteAddress)</span>
1697
- <span class="cstat-no" title="statement not covered" > if (!socket.socketLimiter.tryRemoveTokens(1)) { // if exceeded</span>
1698
- <span class="cstat-no" title="statement not covered" > tooManyRequests(socket, 'Too many requests in a given amount of time (rate limiting)', 'RATE_LIMITING')</span>
1699
- <span class="cstat-no" title="statement not covered" > // FIXME: calling this causes a client timeout</span>
1700
- <span class="cstat-no" title="statement not covered" > // next(error)</span>
1701
- <span class="cstat-no" title="statement not covered" > // Need to normalize the error object as JSON</span>
1702
- <span class="cstat-no" title="statement not covered" > // let result = {}</span>
1703
- <span class="cstat-no" title="statement not covered" > // Object.getOwnPropertyNames(error).forEach(key =&gt; (result[key] = error[key]))</span>
1704
- <span class="cstat-no" title="statement not covered" > // Trying to send error like in https://github.com/feathersjs/transport-commons/blob/auk/src/events.js#L103</span>
1705
- <span class="cstat-no" title="statement not covered" > // does not work either (also generates a client timeout)</span>
1706
- <span class="cstat-no" title="statement not covered" > // socket.emit(`${servicePath} error`, result)</span>
1707
- <span class="cstat-no" title="statement not covered" > // socket.emit(result)</span>
1708
- <span class="cstat-no" title="statement not covered" > return</span>
1709
- <span class="cstat-no" title="statement not covered" > }</span>
1710
- <span class="cstat-no" title="statement not covered" > }</span>
1711
- <span class="cstat-no" title="statement not covered" > next()</span>
1712
- <span class="cstat-no" title="statement not covered" > })</span>
1713
- <span class="cstat-no" title="statement not covered" > }</span>
1714
- })
1715
- }
1716
- }
1717
- &nbsp;
1718
- function setupHealthcheck (app) {
1719
- app.get('/healthcheck', async (req, res) =&gt; {
1720
- res.set('Content-Type', 'application/json')
1721
- const result = await app.db.healthcheck()
1722
- const status = (result ? 200 <span class="branch-0 cbranch-no" title="branch not covered" >: 500)</span>
1723
- return res.status(status).json({ isRunning: true, isDatabaseRunning: result })
1724
- })
1725
- }
1726
- &nbsp;
1727
- export function kdk (config = {}) {
1728
- const app = express(feathers())
1729
- // By default EventEmitters will print a warning if more than 10 listeners are added for a particular event.
1730
- // The value can be set to Infinity (or 0) to indicate an unlimited number of listeners.
1731
- app.setMaxListeners(0)
1732
- // Load app configuration first
1733
- app.configure(configuration())
1734
- // Then setup logger, healthcheck, etc.
1735
- setupLogger(app)
1736
- setupHealthcheck(app)
1737
- &nbsp;
1738
- // Override config
1739
- Object.keys(config).forEach((name) =&gt; {
1740
- const value = config[name]
1741
- debug(`Setting ${name} configuration value to`, value)
1742
- app.set(name, value)
1743
- })
1744
- &nbsp;
1745
- // This retrieve corresponding service options from app config if any
1746
- app.getServiceOptions = <span class="fstat-no" title="function not covered" >function (name) {</span>
1747
- <span class="cstat-no" title="statement not covered" > const services = app.get('services')</span>
1748
- <span class="cstat-no" title="statement not covered" > if (!services) return {}</span>
1749
- <span class="cstat-no" title="statement not covered" > return _.get(services, name, {})</span>
1750
- <span class="cstat-no" title="statement not covered" > }</span>
1751
- // This avoid managing the API path before each service name
1752
- app.getService = function (path, context) {
1753
- try {
1754
- // Context is given as string ID
1755
- if (context <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; typeof context === 'string')</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1756
- <span class="cstat-no" title="statement not covered" > return app.service(app.get('apiPath') + '/' + context + '/' + path)</span>
1757
- } else if (context <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; typeof context === 'object')</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1758
- <span class="cstat-no" title="statement not covered" > // Could be Object ID or raw object</span>
1759
- <span class="cstat-no" title="statement not covered" > if (isObjectID(context)) return app.service(app.get('apiPath') + '/' + context.toString() + '/' + path)</span>
1760
- <span class="cstat-no" title="statement not covered" > else return app.service(app.get('apiPath') + '/' + context._id.toString() + '/' + path)</span>
1761
- } else {
1762
- return app.service(app.get('apiPath') + '/' + path)
1763
- }
1764
- } catch {
1765
- // We return a false-y value in case the service wasn't found
1766
- return null
1767
- }
1768
- }
1769
- // This is used to add hooks/filters to services
1770
- app.configureService = <span class="fstat-no" title="function not covered" >async function (name, service, servicesPath) {</span>
1771
- <span class="cstat-no" title="statement not covered" > service = await configureService(name, service, servicesPath)</span>
1772
- <span class="cstat-no" title="statement not covered" > return service</span>
1773
- <span class="cstat-no" title="statement not covered" > }</span>
1774
- // This is used to declare existing service
1775
- app.declareService = <span class="fstat-no" title="function not covered" >function (name, service, serviceOptions) {</span>
1776
- <span class="cstat-no" title="statement not covered" > service = declareService(name, app, service, serviceOptions)</span>
1777
- <span class="cstat-no" title="statement not covered" > return service</span>
1778
- <span class="cstat-no" title="statement not covered" > }</span>
1779
- // This is used to create standard services
1780
- app.createService = async function (name, options) {
1781
- const service = await createService(name, app, options)
1782
- return service
1783
- }
1784
- // This is used to remove standard services
1785
- app.removeService = <span class="fstat-no" title="function not covered" >async function (service) {</span>
1786
- <span class="cstat-no" title="statement not covered" > service = await removeService(service, app)</span>
1787
- <span class="cstat-no" title="statement not covered" > return service</span>
1788
- <span class="cstat-no" title="statement not covered" > }</span>
1789
- // This is used to create webhooks
1790
- app.createWebhook = function (path, options) {
1791
- return createWebhook(path, app, options)
1792
- }
1793
- // Override Feathers configure that do not manage async operations,
1794
- // here we also simply call the function given as parameter but await for it
1795
- app.configure = async function (fn) {
1796
- await fn.call(this, this)
1797
- return this
1798
- }
1799
- const apiLimiter = app.get('apiLimiter')
1800
- if (apiLimiter <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; apiLimiter.http)</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1801
- <span class="cstat-no" title="statement not covered" > // Function used to filter whitelisted services, defaults to none</span>
1802
- <span class="cstat-no" title="statement not covered" > const services = _.get(apiLimiter.http, 'services', (service) =&gt; false)</span>
1803
- <span class="cstat-no" title="statement not covered" > const handler = <span class="fstat-no" title="function not covered" >(req, res, next) =&gt; {</span></span>
1804
- <span class="cstat-no" title="statement not covered" > // Bypass rate limiting on whitelist</span>
1805
- <span class="cstat-no" title="statement not covered" > let service</span>
1806
- <span class="cstat-no" title="statement not covered" > try {</span>
1807
- <span class="cstat-no" title="statement not covered" > const serviceUrl = new url.URL(req.originalUrl)</span>
1808
- <span class="cstat-no" title="statement not covered" > service = app.service(serviceUrl.pathname)</span>
1809
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1810
- <span class="cstat-no" title="statement not covered" > debugLimiter(error)</span>
1811
- <span class="cstat-no" title="statement not covered" > }</span>
1812
- <span class="cstat-no" title="statement not covered" > if (service &amp;&amp; services(service)) {</span>
1813
- <span class="cstat-no" title="statement not covered" > debugLimiter('By-pass rate limiting on whitelisted service operation', req.method, path)</span>
1814
- <span class="cstat-no" title="statement not covered" > next()</span>
1815
- <span class="cstat-no" title="statement not covered" > } else {</span>
1816
- <span class="cstat-no" title="statement not covered" > const error = new TooManyRequests('Too many requests in a given amount of time (rate limiting)',</span>
1817
- <span class="cstat-no" title="statement not covered" > { translation: { key: 'RATE_LIMITING' } })</span>
1818
- <span class="cstat-no" title="statement not covered" > res.status(error.code)</span>
1819
- <span class="cstat-no" title="statement not covered" > res.set('Content-Type', 'application/json')</span>
1820
- <span class="cstat-no" title="statement not covered" > res.json(Object.assign({}, error.toJSON()))</span>
1821
- <span class="cstat-no" title="statement not covered" > }</span>
1822
- <span class="cstat-no" title="statement not covered" > }</span>
1823
- <span class="cstat-no" title="statement not covered" > app.use(app.get('apiPath') || '/', new HttpLimiter(Object.assign({ handler }, apiLimiter.http)))</span>
1824
- <span class="cstat-no" title="statement not covered" > }</span>
1825
- &nbsp;
1826
- // Enable CORS, security, compression, and body parsing
1827
- app.use(cors(app.get('cors')))
1828
- app.use(helmet(app.get('helmet')))
1829
- app.use(compress(app.get('compression')))
1830
- const bodyParserConfig = app.get('bodyParser')
1831
- app.use(express.json(_.get(bodyParserConfig, 'json')))
1832
- app.use(express.urlencoded(Object.assign({ extended: true }, _.get(bodyParserConfig, 'urlencoded'))))
1833
- &nbsp;
1834
- // Set up plugins and providers
1835
- app.configure(rest())
1836
- const socketioConfig = app.get('socketio') || {}
1837
- app.configure(socketio(Object.assign({ path: (app.get('apiPath') <span class="branch-0 cbranch-no" title="branch not covered" >|| '/')</span> + 'ws' }, socketioConfig), setupSockets(app)))
1838
- app.configure(auth)
1839
- &nbsp;
1840
- // Initialize DB
1841
- app.db = Database.create(app)
1842
- &nbsp;
1843
- return app
1844
- }
1845
- &nbsp;</pre></td></tr></table></pre>
1846
-
1847
- <div class='push'></div><!-- for sticky footer -->
1848
- </div><!-- /wrapper -->
1849
- <div class='footer quiet pad2 space-top1 center small'>
1850
- Code coverage generated by
1851
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1852
- at 2025-12-17T09:26:49.744Z
1853
- </div>
1854
- <script src="../../prettify.js"></script>
1855
- <script>
1856
- window.onload = function () {
1857
- prettyPrint();
1858
- };
1859
- </script>
1860
- <script src="../../sorter.js"></script>
1861
- <script src="../../block-navigation.js"></script>
1862
- </body>
1863
- </html>
1864
-