@adaptivestone/framework 4.7.0 → 4.8.0

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 (92) hide show
  1. package/CHANGELOG.md +9 -1
  2. package/Cli.js +1 -0
  3. package/commands/SyncIndexes.js +1 -1
  4. package/controllers/Auth.js +3 -5
  5. package/controllers/index.js +0 -2
  6. package/coverage/base.css +224 -0
  7. package/coverage/block-navigation.js +87 -0
  8. package/coverage/clover.xml +3542 -0
  9. package/coverage/coverage-final.json +44 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/framework/config/auth.js.html +100 -0
  12. package/coverage/framework/config/http.js.html +112 -0
  13. package/coverage/framework/config/i18n.js.html +121 -0
  14. package/coverage/framework/config/index.html +236 -0
  15. package/coverage/framework/config/log.js.html +151 -0
  16. package/coverage/framework/config/mail.js.html +172 -0
  17. package/coverage/framework/config/mongo.js.html +94 -0
  18. package/coverage/framework/config/rateLimiter.js.html +133 -0
  19. package/coverage/framework/config/redis.js.html +97 -0
  20. package/coverage/framework/config/validate.js.html +94 -0
  21. package/coverage/framework/controllers/Auth.js.html +715 -0
  22. package/coverage/framework/controllers/Home.js.html +169 -0
  23. package/coverage/framework/controllers/index.html +146 -0
  24. package/coverage/framework/controllers/index.js.html +259 -0
  25. package/coverage/framework/controllers/test/SomeController.js.html +571 -0
  26. package/coverage/framework/controllers/test/index.html +116 -0
  27. package/coverage/framework/helpers/files.js.html +310 -0
  28. package/coverage/framework/helpers/index.html +131 -0
  29. package/coverage/framework/helpers/logger.js.html +142 -0
  30. package/coverage/framework/helpers/redis/clearNamespace.js.html +127 -0
  31. package/coverage/framework/helpers/redis/index.html +116 -0
  32. package/coverage/framework/index.html +116 -0
  33. package/coverage/framework/models/Migration.js.html +130 -0
  34. package/coverage/framework/models/Sequence.js.html +151 -0
  35. package/coverage/framework/models/User.js.html +859 -0
  36. package/coverage/framework/models/index.html +146 -0
  37. package/coverage/framework/modules/AbstractController.js.html +1309 -0
  38. package/coverage/framework/modules/AbstractModel.js.html +268 -0
  39. package/coverage/framework/modules/Base.js.html +244 -0
  40. package/coverage/framework/modules/index.html +146 -0
  41. package/coverage/framework/server.js.html +1186 -0
  42. package/coverage/framework/services/cache/Cache.js.html +445 -0
  43. package/coverage/framework/services/cache/index.html +116 -0
  44. package/coverage/framework/services/documentation/DocumentationGenerator.js.html +592 -0
  45. package/coverage/framework/services/documentation/index.html +116 -0
  46. package/coverage/framework/services/http/HttpServer.js.html +373 -0
  47. package/coverage/framework/services/http/index.html +116 -0
  48. package/coverage/framework/services/http/middleware/AbstractMiddleware.js.html +238 -0
  49. package/coverage/framework/services/http/middleware/Auth.js.html +145 -0
  50. package/coverage/framework/services/http/middleware/GetUserByToken.js.html +223 -0
  51. package/coverage/framework/services/http/middleware/I18n.js.html +442 -0
  52. package/coverage/framework/services/http/middleware/Pagination.js.html +253 -0
  53. package/coverage/framework/services/http/middleware/PrepareAppInfo.js.html +139 -0
  54. package/coverage/framework/services/http/middleware/RateLimiter.js.html +472 -0
  55. package/coverage/framework/services/http/middleware/RequestLogger.js.html +151 -0
  56. package/coverage/framework/services/http/middleware/RequestParser.js.html +199 -0
  57. package/coverage/framework/services/http/middleware/Role.js.html +172 -0
  58. package/coverage/framework/services/http/middleware/index.html +251 -0
  59. package/coverage/framework/services/http/middleware/test/CheckFlag.js.html +139 -0
  60. package/coverage/framework/services/http/middleware/test/index.html +116 -0
  61. package/coverage/framework/services/messaging/email/index.html +116 -0
  62. package/coverage/framework/services/messaging/email/index.js.html +739 -0
  63. package/coverage/framework/services/messaging/index.html +116 -0
  64. package/coverage/framework/services/messaging/index.js.html +100 -0
  65. package/coverage/framework/services/validate/ValidateService.js.html +556 -0
  66. package/coverage/framework/services/validate/drivers/AbstractValidator.js.html +196 -0
  67. package/coverage/framework/services/validate/drivers/CustomValidator.js.html +241 -0
  68. package/coverage/framework/services/validate/drivers/YupValidator.js.html +394 -0
  69. package/coverage/framework/services/validate/drivers/index.html +146 -0
  70. package/coverage/framework/services/validate/index.html +116 -0
  71. package/coverage/index.html +356 -0
  72. package/coverage/prettify.css +1 -0
  73. package/coverage/prettify.js +2 -0
  74. package/coverage/sort-arrow-sprite.png +0 -0
  75. package/coverage/sorter.js +196 -0
  76. package/helpers/files.js +75 -0
  77. package/helpers/logger.js +19 -0
  78. package/models/Migration.test.js +19 -0
  79. package/modules/AbstractController.js +1 -3
  80. package/modules/Base.js +6 -56
  81. package/modules/BaseCli.js +0 -3
  82. package/package.json +2 -2
  83. package/server.d.ts +6 -0
  84. package/server.js +126 -78
  85. package/services/cache/Cache.js +10 -5
  86. package/services/cache/Cache.test.js +81 -0
  87. package/services/http/middleware/Auth.test.js +57 -0
  88. package/services/http/middleware/I18n.test.js +15 -3
  89. package/services/http/middleware/PrepareAppInfo.test.js +1 -1
  90. package/services/http/middleware/Role.test.js +93 -0
  91. package/tests/setup.js +1 -0
  92. package/tests/setupVitest.js +1 -0
@@ -0,0 +1,1186 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for framework/server.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">framework</a> server.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">86.64% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>318/367</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">78.72% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>37/47</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">90.9% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>20/22</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">86.64% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>318/367</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 high'></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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">15x</span>
434
+ <span class="cline-any cline-yes">15x</span>
435
+ <span class="cline-any cline-yes">15x</span>
436
+ <span class="cline-any cline-yes">15x</span>
437
+ <span class="cline-any cline-yes">15x</span>
438
+ <span class="cline-any cline-yes">15x</span>
439
+ <span class="cline-any cline-yes">15x</span>
440
+ <span class="cline-any cline-yes">15x</span>
441
+ <span class="cline-any cline-yes">15x</span>
442
+ <span class="cline-any cline-yes">15x</span>
443
+ <span class="cline-any cline-yes">15x</span>
444
+ <span class="cline-any cline-yes">15x</span>
445
+ <span class="cline-any cline-yes">15x</span>
446
+ <span class="cline-any cline-yes">15x</span>
447
+ <span class="cline-any cline-yes">15x</span>
448
+ <span class="cline-any cline-yes">15x</span>
449
+ <span class="cline-any cline-yes">15x</span>
450
+ <span class="cline-any cline-yes">15x</span>
451
+ <span class="cline-any cline-yes">15x</span>
452
+ <span class="cline-any cline-yes">15x</span>
453
+ <span class="cline-any cline-yes">15x</span>
454
+ <span class="cline-any cline-yes">15x</span>
455
+ <span class="cline-any cline-yes">15x</span>
456
+ <span class="cline-any cline-yes">15x</span>
457
+ <span class="cline-any cline-yes">15x</span>
458
+ <span class="cline-any cline-yes">15x</span>
459
+ <span class="cline-any cline-yes">15x</span>
460
+ <span class="cline-any cline-yes">15x</span>
461
+ <span class="cline-any cline-yes">15x</span>
462
+ <span class="cline-any cline-yes">15x</span>
463
+ <span class="cline-any cline-yes">15x</span>
464
+ <span class="cline-any cline-yes">15x</span>
465
+ <span class="cline-any cline-yes">15x</span>
466
+ <span class="cline-any cline-yes">15x</span>
467
+ <span class="cline-any cline-yes">15x</span>
468
+ <span class="cline-any cline-yes">15x</span>
469
+ <span class="cline-any cline-yes">15x</span>
470
+ <span class="cline-any cline-yes">15x</span>
471
+ <span class="cline-any cline-yes">15x</span>
472
+ <span class="cline-any cline-yes">15x</span>
473
+ <span class="cline-any cline-yes">15x</span>
474
+ <span class="cline-any cline-yes">15x</span>
475
+ <span class="cline-any cline-yes">15x</span>
476
+ <span class="cline-any cline-yes">5x</span>
477
+ <span class="cline-any cline-yes">15x</span>
478
+ <span class="cline-any cline-yes">15x</span>
479
+ <span class="cline-any cline-yes">142x</span>
480
+ <span class="cline-any cline-yes">15x</span>
481
+ <span class="cline-any cline-yes">15x</span>
482
+ <span class="cline-any cline-yes">15x</span>
483
+ <span class="cline-any cline-yes">15x</span>
484
+ <span class="cline-any cline-yes">15x</span>
485
+ <span class="cline-any cline-yes">15x</span>
486
+ <span class="cline-any cline-yes">15x</span>
487
+ <span class="cline-any cline-yes">15x</span>
488
+ <span class="cline-any cline-yes">15x</span>
489
+ <span class="cline-any cline-yes">15x</span>
490
+ <span class="cline-any cline-yes">15x</span>
491
+ <span class="cline-any cline-yes">15x</span>
492
+ <span class="cline-any cline-yes">15x</span>
493
+ <span class="cline-any cline-yes">15x</span>
494
+ <span class="cline-any cline-yes">15x</span>
495
+ <span class="cline-any cline-yes">15x</span>
496
+ <span class="cline-any cline-yes">15x</span>
497
+ <span class="cline-any cline-yes">15x</span>
498
+ <span class="cline-any cline-yes">15x</span>
499
+ <span class="cline-any cline-yes">15x</span>
500
+ <span class="cline-any cline-yes">15x</span>
501
+ <span class="cline-any cline-yes">15x</span>
502
+ <span class="cline-any cline-yes">15x</span>
503
+ <span class="cline-any cline-yes">15x</span>
504
+ <span class="cline-any cline-yes">15x</span>
505
+ <span class="cline-any cline-yes">15x</span>
506
+ <span class="cline-any cline-yes">15x</span>
507
+ <span class="cline-any cline-yes">15x</span>
508
+ <span class="cline-any cline-yes">15x</span>
509
+ <span class="cline-any cline-yes">15x</span>
510
+ <span class="cline-any cline-yes">15x</span>
511
+ <span class="cline-any cline-yes">15x</span>
512
+ <span class="cline-any cline-yes">15x</span>
513
+ <span class="cline-any cline-yes">15x</span>
514
+ <span class="cline-any cline-yes">15x</span>
515
+ <span class="cline-any cline-yes">15x</span>
516
+ <span class="cline-any cline-yes">15x</span>
517
+ <span class="cline-any cline-yes">15x</span>
518
+ <span class="cline-any cline-yes">15x</span>
519
+ <span class="cline-any cline-yes">15x</span>
520
+ <span class="cline-any cline-yes">15x</span>
521
+ <span class="cline-any cline-yes">15x</span>
522
+ <span class="cline-any cline-yes">15x</span>
523
+ <span class="cline-any cline-yes">15x</span>
524
+ <span class="cline-any cline-yes">30x</span>
525
+ <span class="cline-any cline-yes">15x</span>
526
+ <span class="cline-any cline-yes">15x</span>
527
+ <span class="cline-any cline-yes">15x</span>
528
+ <span class="cline-any cline-yes">15x</span>
529
+ <span class="cline-any cline-yes">15x</span>
530
+ <span class="cline-any cline-yes">15x</span>
531
+ <span class="cline-any cline-yes">15x</span>
532
+ <span class="cline-any cline-yes">15x</span>
533
+ <span class="cline-any cline-yes">15x</span>
534
+ <span class="cline-any cline-yes">15x</span>
535
+ <span class="cline-any cline-yes">15x</span>
536
+ <span class="cline-any cline-yes">30x</span>
537
+ <span class="cline-any cline-yes">15x</span>
538
+ <span class="cline-any cline-yes">15x</span>
539
+ <span class="cline-any cline-yes">15x</span>
540
+ <span class="cline-any cline-yes">15x</span>
541
+ <span class="cline-any cline-yes">15x</span>
542
+ <span class="cline-any cline-yes">15x</span>
543
+ <span class="cline-any cline-yes">15x</span>
544
+ <span class="cline-any cline-yes">15x</span>
545
+ <span class="cline-any cline-yes">15x</span>
546
+ <span class="cline-any cline-yes">15x</span>
547
+ <span class="cline-any cline-yes">15x</span>
548
+ <span class="cline-any cline-yes">15x</span>
549
+ <span class="cline-any cline-yes">15x</span>
550
+ <span class="cline-any cline-yes">15x</span>
551
+ <span class="cline-any cline-yes">15x</span>
552
+ <span class="cline-any cline-yes">135x</span>
553
+ <span class="cline-any cline-yes">135x</span>
554
+ <span class="cline-any cline-yes">135x</span>
555
+ <span class="cline-any cline-yes">135x</span>
556
+ <span class="cline-any cline-yes">135x</span>
557
+ <span class="cline-any cline-yes">135x</span>
558
+ <span class="cline-any cline-yes">135x</span>
559
+ <span class="cline-any cline-no">&nbsp;</span>
560
+ <span class="cline-any cline-no">&nbsp;</span>
561
+ <span class="cline-any cline-yes">135x</span>
562
+ <span class="cline-any cline-yes">15x</span>
563
+ <span class="cline-any cline-yes">15x</span>
564
+ <span class="cline-any cline-yes">135x</span>
565
+ <span class="cline-any cline-yes">135x</span>
566
+ <span class="cline-any cline-no">&nbsp;</span>
567
+ <span class="cline-any cline-no">&nbsp;</span>
568
+ <span class="cline-any cline-yes">135x</span>
569
+ <span class="cline-any cline-yes">135x</span>
570
+ <span class="cline-any cline-yes">135x</span>
571
+ <span class="cline-any cline-yes">135x</span>
572
+ <span class="cline-any cline-yes">135x</span>
573
+ <span class="cline-any cline-yes">135x</span>
574
+ <span class="cline-any cline-yes">135x</span>
575
+ <span class="cline-any cline-yes">15x</span>
576
+ <span class="cline-any cline-yes">15x</span>
577
+ <span class="cline-any cline-yes">15x</span>
578
+ <span class="cline-any cline-yes">15x</span>
579
+ <span class="cline-any cline-yes">15x</span>
580
+ <span class="cline-any cline-yes">135x</span>
581
+ <span class="cline-any cline-yes">135x</span>
582
+ <span class="cline-any cline-yes">15x</span>
583
+ <span class="cline-any cline-yes">15x</span>
584
+ <span class="cline-any cline-yes">15x</span>
585
+ <span class="cline-any cline-yes">15x</span>
586
+ <span class="cline-any cline-yes">135x</span>
587
+ <span class="cline-any cline-yes">135x</span>
588
+ <span class="cline-any cline-yes">15x</span>
589
+ <span class="cline-any cline-yes">15x</span>
590
+ <span class="cline-any cline-yes">15x</span>
591
+ <span class="cline-any cline-yes">15x</span>
592
+ <span class="cline-any cline-yes">15x</span>
593
+ <span class="cline-any cline-yes">15x</span>
594
+ <span class="cline-any cline-yes">15x</span>
595
+ <span class="cline-any cline-yes">15x</span>
596
+ <span class="cline-any cline-yes">15x</span>
597
+ <span class="cline-any cline-yes">15x</span>
598
+ <span class="cline-any cline-yes">15x</span>
599
+ <span class="cline-any cline-yes">15x</span>
600
+ <span class="cline-any cline-yes">15x</span>
601
+ <span class="cline-any cline-yes">45x</span>
602
+ <span class="cline-any cline-yes">45x</span>
603
+ <span class="cline-any cline-yes">45x</span>
604
+ <span class="cline-any cline-yes">45x</span>
605
+ <span class="cline-any cline-yes">45x</span>
606
+ <span class="cline-any cline-yes">45x</span>
607
+ <span class="cline-any cline-yes">45x</span>
608
+ <span class="cline-any cline-yes">45x</span>
609
+ <span class="cline-any cline-yes">45x</span>
610
+ <span class="cline-any cline-yes">15x</span>
611
+ <span class="cline-any cline-yes">15x</span>
612
+ <span class="cline-any cline-yes">15x</span>
613
+ <span class="cline-any cline-yes">15x</span>
614
+ <span class="cline-any cline-yes">45x</span>
615
+ <span class="cline-any cline-yes">45x</span>
616
+ <span class="cline-any cline-yes">15x</span>
617
+ <span class="cline-any cline-yes">15x</span>
618
+ <span class="cline-any cline-yes">15x</span>
619
+ <span class="cline-any cline-yes">15x</span>
620
+ <span class="cline-any cline-yes">15x</span>
621
+ <span class="cline-any cline-yes">15x</span>
622
+ <span class="cline-any cline-yes">15x</span>
623
+ <span class="cline-any cline-yes">15x</span>
624
+ <span class="cline-any cline-yes">15x</span>
625
+ <span class="cline-any cline-yes">15x</span>
626
+ <span class="cline-any cline-yes">15x</span>
627
+ <span class="cline-any cline-yes">1x</span>
628
+ <span class="cline-any cline-yes">15x</span>
629
+ <span class="cline-any cline-yes">15x</span>
630
+ <span class="cline-any cline-yes">15x</span>
631
+ <span class="cline-any cline-yes">15x</span>
632
+ <span class="cline-any cline-yes">15x</span>
633
+ <span class="cline-any cline-yes">15x</span>
634
+ <span class="cline-any cline-yes">15x</span>
635
+ <span class="cline-any cline-yes">15x</span>
636
+ <span class="cline-any cline-yes">15x</span>
637
+ <span class="cline-any cline-yes">15x</span>
638
+ <span class="cline-any cline-yes">15x</span>
639
+ <span class="cline-any cline-yes">15x</span>
640
+ <span class="cline-any cline-yes">15x</span>
641
+ <span class="cline-any cline-yes">15x</span>
642
+ <span class="cline-any cline-yes">771x</span>
643
+ <span class="cline-any cline-no">&nbsp;</span>
644
+ <span class="cline-any cline-no">&nbsp;</span>
645
+ <span class="cline-any cline-yes">771x</span>
646
+ <span class="cline-any cline-yes">771x</span>
647
+ <span class="cline-any cline-no">&nbsp;</span>
648
+ <span class="cline-any cline-no">&nbsp;</span>
649
+ <span class="cline-any cline-no">&nbsp;</span>
650
+ <span class="cline-any cline-no">&nbsp;</span>
651
+ <span class="cline-any cline-no">&nbsp;</span>
652
+ <span class="cline-any cline-yes">771x</span>
653
+ <span class="cline-any cline-yes">771x</span>
654
+ <span class="cline-any cline-yes">15x</span>
655
+ <span class="cline-any cline-yes">15x</span>
656
+ <span class="cline-any cline-yes">15x</span>
657
+ <span class="cline-any cline-yes">15x</span>
658
+ <span class="cline-any cline-yes">15x</span>
659
+ <span class="cline-any cline-yes">142x</span>
660
+ <span class="cline-any cline-yes">15x</span>
661
+ <span class="cline-any cline-yes">15x</span>
662
+ <span class="cline-any cline-yes">142x</span>
663
+ <span class="cline-any cline-yes">142x</span>
664
+ <span class="cline-any cline-yes">15x</span>
665
+ <span class="cline-any cline-yes">15x</span>
666
+ <span class="cline-any cline-yes">15x</span>
667
+ <span class="cline-any cline-yes">15x</span>
668
+ <span class="cline-any cline-yes">15x</span>
669
+ <span class="cline-any cline-yes">15x</span>
670
+ <span class="cline-any cline-yes">15x</span>
671
+ <span class="cline-any cline-yes">15x</span>
672
+ <span class="cline-any cline-yes">15x</span>
673
+ <span class="cline-any cline-yes">8x</span>
674
+ <span class="cline-any cline-yes">8x</span>
675
+ <span class="cline-any cline-yes">8x</span>
676
+ <span class="cline-any cline-yes">8x</span>
677
+ <span class="cline-any cline-yes">15x</span>
678
+ <span class="cline-any cline-yes">15x</span>
679
+ <span class="cline-any cline-yes">15x</span>
680
+ <span class="cline-any cline-yes">15x</span>
681
+ <span class="cline-any cline-yes">15x</span>
682
+ <span class="cline-any cline-no">&nbsp;</span>
683
+ <span class="cline-any cline-no">&nbsp;</span>
684
+ <span class="cline-any cline-no">&nbsp;</span>
685
+ <span class="cline-any cline-no">&nbsp;</span>
686
+ <span class="cline-any cline-no">&nbsp;</span>
687
+ <span class="cline-any cline-no">&nbsp;</span>
688
+ <span class="cline-any cline-no">&nbsp;</span>
689
+ <span class="cline-any cline-yes">15x</span>
690
+ <span class="cline-any cline-yes">15x</span>
691
+ <span class="cline-any cline-yes">15x</span>
692
+ <span class="cline-any cline-yes">15x</span>
693
+ <span class="cline-any cline-yes">15x</span>
694
+ <span class="cline-any cline-yes">15x</span>
695
+ <span class="cline-any cline-yes">15x</span>
696
+ <span class="cline-any cline-yes">30x</span>
697
+ <span class="cline-any cline-yes">15x</span>
698
+ <span class="cline-any cline-yes">15x</span>
699
+ <span class="cline-any cline-yes">15x</span>
700
+ <span class="cline-any cline-yes">15x</span>
701
+ <span class="cline-any cline-yes">15x</span>
702
+ <span class="cline-any cline-yes">15x</span>
703
+ <span class="cline-any cline-yes">15x</span>
704
+ <span class="cline-any cline-yes">15x</span>
705
+ <span class="cline-any cline-yes">15x</span>
706
+ <span class="cline-any cline-yes">15x</span>
707
+ <span class="cline-any cline-yes">15x</span>
708
+ <span class="cline-any cline-no">&nbsp;</span>
709
+ <span class="cline-any cline-no">&nbsp;</span>
710
+ <span class="cline-any cline-no">&nbsp;</span>
711
+ <span class="cline-any cline-no">&nbsp;</span>
712
+ <span class="cline-any cline-no">&nbsp;</span>
713
+ <span class="cline-any cline-no">&nbsp;</span>
714
+ <span class="cline-any cline-no">&nbsp;</span>
715
+ <span class="cline-any cline-no">&nbsp;</span>
716
+ <span class="cline-any cline-no">&nbsp;</span>
717
+ <span class="cline-any cline-no">&nbsp;</span>
718
+ <span class="cline-any cline-no">&nbsp;</span>
719
+ <span class="cline-any cline-no">&nbsp;</span>
720
+ <span class="cline-any cline-no">&nbsp;</span>
721
+ <span class="cline-any cline-no">&nbsp;</span>
722
+ <span class="cline-any cline-no">&nbsp;</span>
723
+ <span class="cline-any cline-yes">15x</span>
724
+ <span class="cline-any cline-yes">30x</span>
725
+ <span class="cline-any cline-yes">15x</span>
726
+ <span class="cline-any cline-yes">15x</span>
727
+ <span class="cline-any cline-yes">15x</span>
728
+ <span class="cline-any cline-yes">15x</span>
729
+ <span class="cline-any cline-yes">15x</span>
730
+ <span class="cline-any cline-yes">15x</span>
731
+ <span class="cline-any cline-yes">15x</span>
732
+ <span class="cline-any cline-yes">15x</span>
733
+ <span class="cline-any cline-yes">15x</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">15x</span>
737
+ <span class="cline-any cline-yes">152x</span>
738
+ <span class="cline-any cline-yes">152x</span>
739
+ <span class="cline-any cline-yes">152x</span>
740
+ <span class="cline-any cline-yes">152x</span>
741
+ <span class="cline-any cline-yes">152x</span>
742
+ <span class="cline-any cline-yes">152x</span>
743
+ <span class="cline-any cline-yes">15x</span>
744
+ <span class="cline-any cline-yes">15x</span>
745
+ <span class="cline-any cline-yes">15x</span>
746
+ <span class="cline-any cline-yes">15x</span>
747
+ <span class="cline-any cline-yes">15x</span>
748
+ <span class="cline-any cline-yes">15x</span>
749
+ <span class="cline-any cline-yes">15x</span>
750
+ <span class="cline-any cline-yes">15x</span>
751
+ <span class="cline-any cline-yes">66x</span>
752
+ <span class="cline-any cline-no">&nbsp;</span>
753
+ <span class="cline-any cline-no">&nbsp;</span>
754
+ <span class="cline-any cline-no">&nbsp;</span>
755
+ <span class="cline-any cline-no">&nbsp;</span>
756
+ <span class="cline-any cline-yes">66x</span>
757
+ <span class="cline-any cline-yes">17x</span>
758
+ <span class="cline-any cline-yes">17x</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-yes">17x</span>
763
+ <span class="cline-any cline-yes">17x</span>
764
+ <span class="cline-any cline-yes">17x</span>
765
+ <span class="cline-any cline-yes">17x</span>
766
+ <span class="cline-any cline-yes">17x</span>
767
+ <span class="cline-any cline-no">&nbsp;</span>
768
+ <span class="cline-any cline-no">&nbsp;</span>
769
+ <span class="cline-any cline-no">&nbsp;</span>
770
+ <span class="cline-any cline-yes">17x</span>
771
+ <span class="cline-any cline-yes">66x</span>
772
+ <span class="cline-any cline-yes">66x</span>
773
+ <span class="cline-any cline-yes">15x</span>
774
+ <span class="cline-any cline-yes">15x</span>
775
+ <span class="cline-any cline-yes">15x</span>
776
+ <span class="cline-any cline-yes">15x</span>
777
+ <span class="cline-any cline-yes">15x</span>
778
+ <span class="cline-any cline-yes">15x</span>
779
+ <span class="cline-any cline-yes">15x</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-no">&nbsp;</span>
785
+ <span class="cline-any cline-no">&nbsp;</span>
786
+ <span class="cline-any cline-yes">15x</span>
787
+ <span class="cline-any cline-yes">15x</span>
788
+ <span class="cline-any cline-yes">15x</span>
789
+ <span class="cline-any cline-yes">15x</span>
790
+ <span class="cline-any cline-yes">15x</span>
791
+ <span class="cline-any cline-yes">15x</span>
792
+ <span class="cline-any cline-yes">5x</span>
793
+ <span class="cline-any cline-yes">1x</span>
794
+ <span class="cline-any cline-yes">1x</span>
795
+ <span class="cline-any cline-yes">5x</span>
796
+ <span class="cline-any cline-yes">5x</span>
797
+ <span class="cline-any cline-yes">15x</span>
798
+ <span class="cline-any cline-yes">15x</span>
799
+ <span class="cline-any cline-yes">15x</span>
800
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/* eslint-disable no-console */
801
+ const EventEmitter = require('node:events');
802
+ const { hrtime } = require('node:process');
803
+ &nbsp;
804
+ require('dotenv').config();
805
+ const merge = require('deepmerge');
806
+ const winston = require('winston');
807
+ const { getFilesPathWithInheritance } = require('./helpers/files');
808
+ const { consoleLogger } = require('./helpers/logger');
809
+ &nbsp;
810
+ const Cache = require('./services/cache/Cache');
811
+ &nbsp;
812
+ /**
813
+ * Main framework class.
814
+ */
815
+ class Server {
816
+ #realLogger = null;
817
+ &nbsp;
818
+ #isInited = false;
819
+ &nbsp;
820
+ /**
821
+ * Construct new server
822
+ * @param {Object} config main config object
823
+ * @param {Object} config.folders folders config
824
+ * @param {String} config.folders.config path to folder with config files
825
+ * @param {String} config.folders.models path to folder with moidels files
826
+ * @param {String} config.folders.controllers path to folder with controllers files
827
+ * @param {String} config.folders.views path to folder with view files
828
+ * @param {String} config.folders.public path to folder with public files
829
+ * @param {String} config.folders.locales path to folder with locales files
830
+ * @param {String} config.folders.emails path to folder with emails files
831
+ */
832
+ constructor(config) {
833
+ this.config = config;
834
+ const that = this;
835
+ this.app = {
836
+ getConfig: this.getConfig.bind(this),
837
+ getModel: this.getModel.bind(this),
838
+ runCliCommand: this.runCliCommand.bind(this),
839
+ updateConfig: this.updateConfig.bind(this),
840
+ foldersConfig: this.config.folders,
841
+ events: new EventEmitter(),
842
+ get cache() {
843
+ return that.getCache();
844
+ },
845
+ get logger() {
846
+ return that.getLogger();
847
+ },
848
+ httpServer: null,
849
+ controllerManager: null,
850
+ };
851
+ &nbsp;
852
+ this.cache = {
853
+ configs: new Map(),
854
+ models: new Map(),
855
+ modelConstructors: new Map(),
856
+ };
857
+ &nbsp;
858
+ this.cli = false;
859
+ }
860
+ &nbsp;
861
+ /**
862
+ * Start server (http + init all http ralated functions)
863
+ * @param &lt;Promise&gt;callbackBefore404 code that should be executed before adding page 404
864
+ * @returns {Promise}
865
+ */
866
+ async startServer(callbackBefore404 = async () =&gt; Promise.resolve()) {
867
+ const [{ default: HttpServer }, { default: ControllerManager }] =
868
+ await Promise.all([
869
+ import('./services/http/HttpServer.js'), // Speed optimisation
870
+ import('./controllers/index.js'), // Speed optimisation
871
+ this.init(),
872
+ ]);
873
+ &nbsp;
874
+ this.addErrorHandling();
875
+ &nbsp;
876
+ // TODO config
877
+ this.app.httpServer = new HttpServer(this.app);
878
+ &nbsp;
879
+ this.app.controllerManager = new ControllerManager(this.app);
880
+ &nbsp;
881
+ await this.app.controllerManager.initControllers();
882
+ await callbackBefore404();
883
+ this.app.httpServer.add404Page();
884
+ }
885
+ &nbsp;
886
+ /**
887
+ * Do an initialization (config reading, etc)
888
+ * @returns {Promise}
889
+ */
890
+ async init() {
891
+ if (this.#isInited) {
892
+ return true;
893
+ }
894
+ &nbsp;
895
+ console.time('Server init. Done');
896
+ await Promise.all([this.#initConfigFiles(), this.#loadModelFiles()]);
897
+ &nbsp;
898
+ this.#isInited = true;
899
+ &nbsp;
900
+ console.timeEnd('Server init. Done');
901
+ &nbsp;
902
+ return true;
903
+ }
904
+ &nbsp;
905
+ async #initConfigFiles() {
906
+ const files = await getFilesPathWithInheritance({
907
+ internalFolder: `${__dirname}/config`,
908
+ externalFolder: this.app.foldersConfig.config,
909
+ loggerFileType: 'CONFIG',
910
+ logger: (m) =&gt; consoleLogger('info', m),
911
+ filter: {
912
+ startWithCapital: false,
913
+ },
914
+ });
915
+ &nbsp;
916
+ const configFiles = {};
917
+ &nbsp;
918
+ for (const file of files) {
919
+ const config = file.file.split('.');
920
+ if (!configFiles[config[0]]) {
921
+ configFiles[config[0]] = {};
922
+ }
923
+ if (config.length === 2) {
924
+ configFiles[config[0]].default = file.path;
925
+ }<span class="branch-0 cbranch-no" title="branch not covered" > else {</span>
926
+ <span class="cstat-no" title="statement not covered" > configFiles[config[0]][config[1]] = file.path;</span>
927
+ <span class="cstat-no" title="statement not covered" > }</span>
928
+ }
929
+ &nbsp;
930
+ const loadConfig = async (configName, values) =&gt; {
931
+ const promises = [import(values.default)];
932
+ if (process.env.NODE_ENV &amp;&amp; values[process.env.NODE_ENV]) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
933
+ <span class="cstat-no" title="statement not covered" > promises.push(import(values[process.env.NODE_ENV]));</span>
934
+ <span class="cstat-no" title="statement not covered" > }</span>
935
+ const result = await Promise.all(promises);
936
+ return {
937
+ name: configName,
938
+ finalValue: merge(result[0].default, result[1]<span class="branch-0 cbranch-no" title="branch not covered" >?.default </span>|| {}, {
939
+ arrayMerge: (destinationArray, sourceArray) =&gt; sourceArray,
940
+ }),
941
+ };
942
+ };
943
+ &nbsp;
944
+ const loadingPromises = [];
945
+ &nbsp;
946
+ for (const [configFile, value] of Object.entries(configFiles)) {
947
+ loadingPromises.push(loadConfig(configFile, value));
948
+ }
949
+ &nbsp;
950
+ const configs = await Promise.all(loadingPromises);
951
+ &nbsp;
952
+ for (const config of configs) {
953
+ this.cache.configs.set(config.name, config.finalValue);
954
+ }
955
+ return true;
956
+ }
957
+ &nbsp;
958
+ async #loadModelFiles() {
959
+ const files = await getFilesPathWithInheritance({
960
+ internalFolder: `${__dirname}/models`,
961
+ externalFolder: this.app.foldersConfig.models,
962
+ loggerFileType: 'MODEL',
963
+ logger: (m) =&gt; consoleLogger('info', m),
964
+ });
965
+ &nbsp;
966
+ const promises = [];
967
+ for (const file of files) {
968
+ const t = hrtime.bigint();
969
+ promises.push(
970
+ import(file.path).then((f) =&gt; ({
971
+ name: file.file.split('.')[0],
972
+ file: f,
973
+ took: hrtime.bigint() - t,
974
+ })),
975
+ );
976
+ }
977
+ &nbsp;
978
+ const loadedModels = await Promise.all(promises);
979
+ &nbsp;
980
+ for (const model of loadedModels) {
981
+ this.cache.modelConstructors.set(model.name, model.file.default);
982
+ }
983
+ return true;
984
+ }
985
+ &nbsp;
986
+ /**
987
+ * Add error logging on promise reject
988
+ */
989
+ addErrorHandling() {
990
+ process.on('uncaughtException', (e) =&gt;
991
+ this.app.logger.error('uncaughtException', e),
992
+ );
993
+ process.on('unhandledRejection', (e) =&gt; {
994
+ this.app.logger.error('unhandledRejection', e);
995
+ });
996
+ }
997
+ &nbsp;
998
+ /**
999
+ * Return config from {configName} (file name) on config folder.
1000
+ * Support cache and updating confing into cache
1001
+ * Also will update config based on NODE_ENV. If config.js and config.production.js
1002
+ * and NODE_ENV is production then we will load base config (config.js) and the load
1003
+ * environment config (config.production.js) and overwrite base config options
1004
+ * @see updateConfig
1005
+ * @param {String} configName name on config file to load
1006
+ * @returns {Object} config object. Structure depends of config file
1007
+ */
1008
+ getConfig(configName) {
1009
+ if (!this.#isInited) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1010
+ <span class="cstat-no" title="statement not covered" > throw new Error('You should call Server.init() before using it');</span>
1011
+ <span class="cstat-no" title="statement not covered" > }</span>
1012
+ &nbsp;
1013
+ if (!this.cache.configs.has(configName)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1014
+ <span class="cstat-no" title="statement not covered" > this.logger.warn(</span>
1015
+ <span class="cstat-no" title="statement not covered" > `You asked for config ${configName} that not exists. Please check you codebase `,</span>
1016
+ <span class="cstat-no" title="statement not covered" > );</span>
1017
+ <span class="cstat-no" title="statement not covered" > return {};</span>
1018
+ <span class="cstat-no" title="statement not covered" > }</span>
1019
+ return this.cache.configs.get(configName);
1020
+ }
1021
+ &nbsp;
1022
+ /**
1023
+ * Return or create new logger instance. This is a main logger instance
1024
+ */
1025
+ getLogger() {
1026
+ if (!this.#realLogger) {
1027
+ this.#realLogger = this.#createLogger();
1028
+ }
1029
+ return this.#realLogger;
1030
+ }
1031
+ &nbsp;
1032
+ #createLogger() {
1033
+ const alignColorsAndTime = winston.format.combine(
1034
+ winston.format.colorize({
1035
+ all: true,
1036
+ }),
1037
+ winston.format.timestamp(),
1038
+ winston.format.printf(
1039
+ (info) =&gt;
1040
+ `(${process.pid}) \x1B[32m[${info.label ?? 'SERVER'}]\x1B[39m ${
1041
+ info.timestamp
1042
+ } ${info.level} : ${info.message} ${info?.stack ?? ''} ${
1043
+ info.durationMs <span class="branch-0 cbranch-no" title="branch not covered" >? `Duration: ${info.durationMs}ms` </span>: ''
1044
+ }`,
1045
+ ),
1046
+ );
1047
+ const logConfig = this.app.getConfig('log').transports;
1048
+ <span class="fstat-no" title="function not covered" > function IsConstructor(f) {</span>
1049
+ <span class="cstat-no" title="statement not covered" > try {</span>
1050
+ <span class="cstat-no" title="statement not covered" > Reflect.construct(String, [], f);</span>
1051
+ <span class="cstat-no" title="statement not covered" > } catch (e) {</span>
1052
+ <span class="cstat-no" title="statement not covered" > return false;</span>
1053
+ <span class="cstat-no" title="statement not covered" > }</span>
1054
+ <span class="cstat-no" title="statement not covered" > return true;</span>
1055
+ <span class="cstat-no" title="statement not covered" > }</span>
1056
+ &nbsp;
1057
+ const logger = winston.createLogger({
1058
+ format: winston.format.errors({ stack: true }),
1059
+ level: 'silly',
1060
+ });
1061
+ &nbsp;
1062
+ for (const log of logConfig) {
1063
+ if (log.enable) {
1064
+ if (log.transport === 'console') {
1065
+ logger.add(
1066
+ new winston.transports.Console({
1067
+ level: log.transportOptions.level,
1068
+ format: winston.format.combine(
1069
+ winston.format.colorize(),
1070
+ alignColorsAndTime,
1071
+ ),
1072
+ }),
1073
+ );
1074
+ }<span class="branch-0 cbranch-no" title="branch not covered" > else {</span>
1075
+ <span class="cstat-no" title="statement not covered" > import(log.transport).then((Tr) =&gt; {</span>
1076
+ <span class="cstat-no" title="statement not covered" > let Transport = Tr.default;</span>
1077
+ <span class="cstat-no" title="statement not covered" > if (!IsConstructor(Transport) &amp;&amp; Transport.default) {</span>
1078
+ <span class="cstat-no" title="statement not covered" > Transport = Transport.default;</span>
1079
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1080
+ <span class="cstat-no" title="statement not covered" > console.error(</span>
1081
+ <span class="cstat-no" title="statement not covered" > `${log.transport} not a constructor. Please check it`,</span>
1082
+ <span class="cstat-no" title="statement not covered" > );</span>
1083
+ <span class="cstat-no" title="statement not covered" > return;</span>
1084
+ <span class="cstat-no" title="statement not covered" > }</span>
1085
+ <span class="cstat-no" title="statement not covered" > logger.profile(`Adding new logger ${log.transport}`);</span>
1086
+ <span class="cstat-no" title="statement not covered" > logger.add(new Transport(log.transportOptions));</span>
1087
+ <span class="cstat-no" title="statement not covered" > logger.profile(`Adding new logger ${log.transport}`);</span>
1088
+ <span class="cstat-no" title="statement not covered" > });</span>
1089
+ <span class="cstat-no" title="statement not covered" > }</span>
1090
+ }
1091
+ }
1092
+ &nbsp;
1093
+ return logger;
1094
+ }
1095
+ &nbsp;
1096
+ /**
1097
+ * Primary designed for tests when we need to update some configs before start testing
1098
+ * Should be called before any initialization was done
1099
+ * @TODO send event to all inited components to update config
1100
+ * @param {String} configName
1101
+ * @param {Object} config
1102
+ */
1103
+ updateConfig(configName, config) {
1104
+ // const confName = configName.charAt(0).toUpperCase() + configName.slice(1);
1105
+ const conf = this.getConfig(configName);
1106
+ const newConf = Object.assign(conf, config); // TODO deep clone
1107
+ this.cache.configs.set(configName, newConf);
1108
+ return newConf;
1109
+ }
1110
+ &nbsp;
1111
+ /**
1112
+ * Return model from {modelName} (file name) on model folder.
1113
+ * Support cache
1114
+ * @param {String} modelName name on config file to load
1115
+ * @returns {import('mongoose').Model}
1116
+ */
1117
+ getModel(modelName) {
1118
+ if (modelName.endsWith('s')) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1119
+ <span class="cstat-no" title="statement not covered" > this.app.logger.warn(</span>
1120
+ <span class="cstat-no" title="statement not covered" > `Probably your model name '${modelName}' in plural from. Try to avoid plural form`,</span>
1121
+ <span class="cstat-no" title="statement not covered" > );</span>
1122
+ <span class="cstat-no" title="statement not covered" > }</span>
1123
+ if (!this.cache.models.has(modelName)) {
1124
+ const Model = this.cache.modelConstructors.get(modelName);
1125
+ if (!Model) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1126
+ <span class="cstat-no" title="statement not covered" > this.app.logger.error(`Model not found: ${modelName}`);</span>
1127
+ <span class="cstat-no" title="statement not covered" > return false;</span>
1128
+ <span class="cstat-no" title="statement not covered" > }</span>
1129
+ try {
1130
+ const model = new Model(this.app);
1131
+ &nbsp;
1132
+ this.cache.models.set(modelName, model.mongooseModel);
1133
+ } <span class="branch-0 cbranch-no" title="branch not covered" >catch (e) {</span>
1134
+ <span class="cstat-no" title="statement not covered" > this.app.logger.error(`Problem with model ${modelName}, ${e.message}`);</span>
1135
+ <span class="cstat-no" title="statement not covered" > this.app.logger.error(e);</span>
1136
+ <span class="cstat-no" title="statement not covered" > }</span>
1137
+ }
1138
+ return this.cache.models.get(modelName);
1139
+ }
1140
+ &nbsp;
1141
+ /**
1142
+ * Run cli command into framework (http, ws, etc)
1143
+ * @param {String} commandName name of command to load
1144
+ * @param {Object} args list of arguments to pass into command
1145
+ */
1146
+ <span class="fstat-no" title="function not covered" > async runCliCommand(commandName, args) {</span>
1147
+ <span class="cstat-no" title="statement not covered" > if (!this.cli) {</span>
1148
+ <span class="cstat-no" title="statement not covered" > const { default: BaseCli } = await import('./modules/BaseCli.js'); // Speed optimisation</span>
1149
+ <span class="cstat-no" title="statement not covered" > this.cli = new BaseCli(this);</span>
1150
+ <span class="cstat-no" title="statement not covered" > }</span>
1151
+ <span class="cstat-no" title="statement not covered" > return this.cli.run(commandName, args);</span>
1152
+ <span class="cstat-no" title="statement not covered" > }</span>
1153
+ &nbsp;
1154
+ /**
1155
+ * Get internal cache service
1156
+ * @returns
1157
+ */
1158
+ getCache() {
1159
+ if (!this.cacheService) {
1160
+ this.cacheService = new Cache(this.app);
1161
+ }
1162
+ return this.cacheService;
1163
+ }
1164
+ }
1165
+ &nbsp;
1166
+ module.exports = Server;
1167
+ &nbsp;</pre></td></tr></table></pre>
1168
+
1169
+ <div class='push'></div><!-- for sticky footer -->
1170
+ </div><!-- /wrapper -->
1171
+ <div class='footer quiet pad2 space-top1 center small'>
1172
+ Code coverage generated by
1173
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1174
+ at 2023-09-21T04:47:08.309Z
1175
+ </div>
1176
+ <script src="../prettify.js"></script>
1177
+ <script>
1178
+ window.onload = function () {
1179
+ prettyPrint();
1180
+ };
1181
+ </script>
1182
+ <script src="../sorter.js"></script>
1183
+ <script src="../block-navigation.js"></script>
1184
+ </body>
1185
+ </html>
1186
+