@budibase/server 1.1.32-alpha.6 → 1.1.32

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 (204) hide show
  1. package/builder/assets/index.133db51f.js +978 -0
  2. package/builder/assets/{index.4d57d3d4.css → index.192adf4c.css} +2 -2
  3. package/builder/assets/{vendor.6bcafa60.js → vendor.162098da.js} +1 -1
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +696 -381
  6. package/coverage/coverage-final.json +16 -13
  7. package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
  8. package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
  9. package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
  10. package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
  11. package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
  12. package/coverage/lcov-report/api/controllers/component.js.html +1 -1
  13. package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
  14. package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
  15. package/coverage/lcov-report/api/controllers/index.html +1 -1
  16. package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
  17. package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
  18. package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
  19. package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
  20. package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
  21. package/coverage/lcov-report/api/controllers/query/index.html +1 -1
  22. package/coverage/lcov-report/api/controllers/query/validation.js.html +4 -4
  23. package/coverage/lcov-report/api/controllers/role.js.html +1 -1
  24. package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
  25. package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
  26. package/coverage/lcov-report/api/controllers/row/index.html +18 -18
  27. package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
  28. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +49 -94
  29. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
  30. package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
  31. package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
  32. package/coverage/lcov-report/api/controllers/script.js.html +1 -1
  33. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
  34. package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
  35. package/coverage/lcov-report/api/controllers/table/index.html +1 -1
  36. package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
  37. package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
  38. package/coverage/lcov-report/api/controllers/user.js.html +1 -1
  39. package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
  40. package/coverage/lcov-report/api/controllers/view/index.html +1 -1
  41. package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
  42. package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
  43. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
  44. package/coverage/lcov-report/api/controllers/webhook.js.html +15 -15
  45. package/coverage/lcov-report/api/index.html +1 -1
  46. package/coverage/lcov-report/api/index.js.html +1 -1
  47. package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
  48. package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
  49. package/coverage/lcov-report/api/routes/auth.js.html +1 -1
  50. package/coverage/lcov-report/api/routes/automation.js.html +1 -1
  51. package/coverage/lcov-report/api/routes/backup.js.html +1 -1
  52. package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
  53. package/coverage/lcov-report/api/routes/component.js.html +1 -1
  54. package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
  55. package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
  56. package/coverage/lcov-report/api/routes/dev.js.html +1 -1
  57. package/coverage/lcov-report/api/routes/index.html +1 -1
  58. package/coverage/lcov-report/api/routes/integration.js.html +1 -1
  59. package/coverage/lcov-report/api/routes/layout.js.html +1 -1
  60. package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
  61. package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
  62. package/coverage/lcov-report/api/routes/permission.js.html +1 -1
  63. package/coverage/lcov-report/api/routes/query.js.html +1 -1
  64. package/coverage/lcov-report/api/routes/role.js.html +1 -1
  65. package/coverage/lcov-report/api/routes/routing.js.html +1 -1
  66. package/coverage/lcov-report/api/routes/screen.js.html +1 -1
  67. package/coverage/lcov-report/api/routes/script.js.html +1 -1
  68. package/coverage/lcov-report/api/routes/table.js.html +1 -1
  69. package/coverage/lcov-report/api/routes/templates.js.html +1 -1
  70. package/coverage/lcov-report/api/routes/user.js.html +1 -1
  71. package/coverage/lcov-report/api/routes/utils/index.html +1 -1
  72. package/coverage/lcov-report/api/routes/utils/validators.js.html +2 -2
  73. package/coverage/lcov-report/api/routes/view.js.html +1 -1
  74. package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
  75. package/coverage/lcov-report/automations/actions.js.html +1 -1
  76. package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
  77. package/coverage/lcov-report/automations/bullboard.js.html +17 -17
  78. package/coverage/lcov-report/automations/index.html +1 -1
  79. package/coverage/lcov-report/automations/index.js.html +1 -1
  80. package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
  81. package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
  82. package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
  83. package/coverage/lcov-report/automations/steps/executeQuery.js.html +2 -5
  84. package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
  85. package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
  86. package/coverage/lcov-report/automations/steps/index.html +1 -1
  87. package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
  88. package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
  89. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
  90. package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
  91. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
  92. package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
  93. package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
  94. package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
  95. package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
  96. package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
  97. package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
  98. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
  99. package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
  100. package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
  101. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
  102. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
  103. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
  104. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
  105. package/coverage/lcov-report/automations/triggers.js.html +18 -18
  106. package/coverage/lcov-report/constants/index.html +1 -1
  107. package/coverage/lcov-report/constants/index.js.html +14 -5
  108. package/coverage/lcov-report/constants/layouts.js.html +1 -1
  109. package/coverage/lcov-report/constants/screens.js.html +1 -1
  110. package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
  111. package/coverage/lcov-report/db/index.html +19 -19
  112. package/coverage/lcov-report/db/index.js.html +1 -1
  113. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
  114. package/coverage/lcov-report/db/linkedRows/index.html +1 -1
  115. package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
  116. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
  117. package/coverage/lcov-report/db/newid.js.html +1 -1
  118. package/coverage/lcov-report/db/utils.js.html +13 -61
  119. package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
  120. package/coverage/lcov-report/events/index.html +1 -1
  121. package/coverage/lcov-report/events/index.js.html +1 -1
  122. package/coverage/lcov-report/events/utils.js.html +1 -1
  123. package/coverage/lcov-report/index.html +72 -57
  124. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
  125. package/coverage/lcov-report/integrations/tests/index.html +1 -1
  126. package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
  127. package/coverage/lcov-report/middleware/builder.js.html +1 -1
  128. package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
  129. package/coverage/lcov-report/middleware/index.html +21 -21
  130. package/coverage/lcov-report/middleware/joi-validator.js.html +43 -43
  131. package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
  132. package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
  133. package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
  134. package/coverage/lcov-report/middleware/utils.js.html +1 -1
  135. package/coverage/lcov-report/threads/automation.js.html +1114 -0
  136. package/coverage/lcov-report/threads/index.html +146 -0
  137. package/coverage/lcov-report/threads/query.js.html +916 -0
  138. package/coverage/lcov-report/threads/utils.js.html +319 -0
  139. package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
  140. package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
  141. package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
  142. package/coverage/lcov-report/utilities/global.js.html +14 -68
  143. package/coverage/lcov-report/utilities/index.html +19 -19
  144. package/coverage/lcov-report/utilities/index.js.html +1 -1
  145. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +14 -26
  146. package/coverage/lcov-report/utilities/queue/index.html +17 -17
  147. package/coverage/lcov-report/utilities/routing/index.html +1 -1
  148. package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
  149. package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
  150. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
  151. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
  152. package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
  153. package/coverage/lcov-report/utilities/security.js.html +2 -2
  154. package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
  155. package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
  156. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
  157. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
  158. package/coverage/lcov-report/utilities/users.js.html +1 -1
  159. package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
  160. package/coverage/lcov.info +1214 -695
  161. package/dist/api/controllers/deploy/index.js +0 -1
  162. package/dist/api/controllers/query/index.js +1 -1
  163. package/dist/api/controllers/query/validation.js +3 -3
  164. package/dist/api/controllers/row/internalSearch.js +16 -30
  165. package/dist/api/routes/utils/validators.js +1 -1
  166. package/dist/automations/utils.js +1 -47
  167. package/dist/constants/index.js +4 -1
  168. package/dist/db/utils.js +1 -14
  169. package/dist/integrations/base/sql.js +14 -43
  170. package/dist/package.json +8 -8
  171. package/dist/threads/automation.js +54 -147
  172. package/dist/threads/index.js +20 -27
  173. package/dist/threads/query.js +15 -23
  174. package/dist/threads/utils.js +24 -47
  175. package/dist/tsconfig.build.tsbuildinfo +1 -1
  176. package/dist/utilities/global.js +5 -24
  177. package/dist/utilities/queue/inMemoryQueue.js +0 -5
  178. package/package.json +9 -9
  179. package/src/api/controllers/deploy/index.ts +1 -6
  180. package/src/api/controllers/query/index.ts +1 -1
  181. package/src/api/controllers/query/validation.js +3 -3
  182. package/src/api/controllers/row/internalSearch.js +20 -35
  183. package/src/api/routes/tests/user.spec.js +0 -2
  184. package/src/api/routes/utils/validators.js +1 -1
  185. package/src/automations/steps/executeQuery.js +0 -1
  186. package/src/automations/tests/automation.spec.js +2 -2
  187. package/src/automations/utils.ts +1 -54
  188. package/src/constants/index.js +5 -2
  189. package/src/db/utils.js +0 -16
  190. package/src/definitions/datasource.ts +0 -3
  191. package/src/integrations/base/sql.ts +13 -44
  192. package/src/integrations/tests/sql.spec.js +4 -50
  193. package/src/middleware/tests/currentapp.spec.js +0 -11
  194. package/src/threads/{automation.ts → automation.js} +48 -172
  195. package/src/threads/index.ts +23 -31
  196. package/src/threads/{query.ts → query.js} +12 -32
  197. package/src/threads/{utils.ts → utils.js} +12 -31
  198. package/src/utilities/global.js +3 -21
  199. package/src/utilities/queue/inMemoryQueue.js +0 -4
  200. package/builder/assets/index.fdd9c6c9.js +0 -977
  201. package/dist/definitions/automations.js +0 -8
  202. package/dist/threads/definitions.js +0 -2
  203. package/src/definitions/automations.ts +0 -49
  204. package/src/threads/definitions.ts +0 -18
@@ -0,0 +1,916 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for threads/query.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">threads</a> query.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">81.34% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>109/134</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">64.4% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>38/59</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">76.92% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>10/13</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">81.53% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>106/130</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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
344
+ <span class="cline-any cline-yes">2x</span>
345
+ <span class="cline-any cline-yes">2x</span>
346
+ <span class="cline-any cline-yes">2x</span>
347
+ <span class="cline-any cline-yes">2x</span>
348
+ <span class="cline-any cline-yes">2x</span>
349
+ <span class="cline-any cline-neutral">&nbsp;</span>
350
+ <span class="cline-any cline-neutral">&nbsp;</span>
351
+ <span class="cline-any cline-neutral">&nbsp;</span>
352
+ <span class="cline-any cline-yes">2x</span>
353
+ <span class="cline-any cline-yes">2x</span>
354
+ <span class="cline-any cline-yes">2x</span>
355
+ <span class="cline-any cline-yes">2x</span>
356
+ <span class="cline-any cline-neutral">&nbsp;</span>
357
+ <span class="cline-any cline-yes">2x</span>
358
+ <span class="cline-any cline-neutral">&nbsp;</span>
359
+ <span class="cline-any cline-neutral">&nbsp;</span>
360
+ <span class="cline-any cline-neutral">&nbsp;</span>
361
+ <span class="cline-any cline-yes">2x</span>
362
+ <span class="cline-any cline-neutral">&nbsp;</span>
363
+ <span class="cline-any cline-neutral">&nbsp;</span>
364
+ <span class="cline-any cline-neutral">&nbsp;</span>
365
+ <span class="cline-any cline-yes">22x</span>
366
+ <span class="cline-any cline-yes">22x</span>
367
+ <span class="cline-any cline-yes">22x</span>
368
+ <span class="cline-any cline-yes">22x</span>
369
+ <span class="cline-any cline-yes">22x</span>
370
+ <span class="cline-any cline-yes">22x</span>
371
+ <span class="cline-any cline-yes">22x</span>
372
+ <span class="cline-any cline-yes">22x</span>
373
+ <span class="cline-any cline-yes">22x</span>
374
+ <span class="cline-any cline-neutral">&nbsp;</span>
375
+ <span class="cline-any cline-yes">22x</span>
376
+ <span class="cline-any cline-neutral">&nbsp;</span>
377
+ <span class="cline-any cline-neutral">&nbsp;</span>
378
+ <span class="cline-any cline-neutral">&nbsp;</span>
379
+ <span class="cline-any cline-yes">22x</span>
380
+ <span class="cline-any cline-yes">22x</span>
381
+ <span class="cline-any cline-yes">22x</span>
382
+ <span class="cline-any cline-neutral">&nbsp;</span>
383
+ <span class="cline-any cline-neutral">&nbsp;</span>
384
+ <span class="cline-any cline-neutral">&nbsp;</span>
385
+ <span class="cline-any cline-yes">23x</span>
386
+ <span class="cline-any cline-neutral">&nbsp;</span>
387
+ <span class="cline-any cline-yes">23x</span>
388
+ <span class="cline-any cline-yes">23x</span>
389
+ <span class="cline-any cline-neutral">&nbsp;</span>
390
+ <span class="cline-any cline-yes">23x</span>
391
+ <span class="cline-any cline-yes">23x</span>
392
+ <span class="cline-any cline-yes">2x</span>
393
+ <span class="cline-any cline-neutral">&nbsp;</span>
394
+ <span class="cline-any cline-neutral">&nbsp;</span>
395
+ <span class="cline-any cline-yes">21x</span>
396
+ <span class="cline-any cline-no">&nbsp;</span>
397
+ <span class="cline-any cline-neutral">&nbsp;</span>
398
+ <span class="cline-any cline-no">&nbsp;</span>
399
+ <span class="cline-any cline-neutral">&nbsp;</span>
400
+ <span class="cline-any cline-neutral">&nbsp;</span>
401
+ <span class="cline-any cline-neutral">&nbsp;</span>
402
+ <span class="cline-any cline-yes">21x</span>
403
+ <span class="cline-any cline-neutral">&nbsp;</span>
404
+ <span class="cline-any cline-neutral">&nbsp;</span>
405
+ <span class="cline-any cline-yes">21x</span>
406
+ <span class="cline-any cline-neutral">&nbsp;</span>
407
+ <span class="cline-any cline-neutral">&nbsp;</span>
408
+ <span class="cline-any cline-neutral">&nbsp;</span>
409
+ <span class="cline-any cline-yes">21x</span>
410
+ <span class="cline-any cline-yes">21x</span>
411
+ <span class="cline-any cline-neutral">&nbsp;</span>
412
+ <span class="cline-any cline-neutral">&nbsp;</span>
413
+ <span class="cline-any cline-yes">21x</span>
414
+ <span class="cline-any cline-yes">1x</span>
415
+ <span class="cline-any cline-neutral">&nbsp;</span>
416
+ <span class="cline-any cline-neutral">&nbsp;</span>
417
+ <span class="cline-any cline-neutral">&nbsp;</span>
418
+ <span class="cline-any cline-neutral">&nbsp;</span>
419
+ <span class="cline-any cline-neutral">&nbsp;</span>
420
+ <span class="cline-any cline-neutral">&nbsp;</span>
421
+ <span class="cline-any cline-neutral">&nbsp;</span>
422
+ <span class="cline-any cline-yes">21x</span>
423
+ <span class="cline-any cline-yes">2x</span>
424
+ <span class="cline-any cline-neutral">&nbsp;</span>
425
+ <span class="cline-any cline-yes">19x</span>
426
+ <span class="cline-any cline-neutral">&nbsp;</span>
427
+ <span class="cline-any cline-neutral">&nbsp;</span>
428
+ <span class="cline-any cline-neutral">&nbsp;</span>
429
+ <span class="cline-any cline-yes">21x</span>
430
+ <span class="cline-any cline-no">&nbsp;</span>
431
+ <span class="cline-any cline-neutral">&nbsp;</span>
432
+ <span class="cline-any cline-neutral">&nbsp;</span>
433
+ <span class="cline-any cline-yes">21x</span>
434
+ <span class="cline-any cline-yes">21x</span>
435
+ <span class="cline-any cline-yes">21x</span>
436
+ <span class="cline-any cline-yes">21x</span>
437
+ <span class="cline-any cline-yes">21x</span>
438
+ <span class="cline-any cline-yes">21x</span>
439
+ <span class="cline-any cline-yes">19x</span>
440
+ <span class="cline-any cline-yes">19x</span>
441
+ <span class="cline-any cline-yes">19x</span>
442
+ <span class="cline-any cline-yes">19x</span>
443
+ <span class="cline-any cline-neutral">&nbsp;</span>
444
+ <span class="cline-any cline-neutral">&nbsp;</span>
445
+ <span class="cline-any cline-neutral">&nbsp;</span>
446
+ <span class="cline-any cline-yes">21x</span>
447
+ <span class="cline-any cline-no">&nbsp;</span>
448
+ <span class="cline-any cline-neutral">&nbsp;</span>
449
+ <span class="cline-any cline-neutral">&nbsp;</span>
450
+ <span class="cline-any cline-neutral">&nbsp;</span>
451
+ <span class="cline-any cline-no">&nbsp;</span>
452
+ <span class="cline-any cline-neutral">&nbsp;</span>
453
+ <span class="cline-any cline-neutral">&nbsp;</span>
454
+ <span class="cline-any cline-neutral">&nbsp;</span>
455
+ <span class="cline-any cline-yes">21x</span>
456
+ <span class="cline-any cline-yes">1x</span>
457
+ <span class="cline-any cline-neutral">&nbsp;</span>
458
+ <span class="cline-any cline-neutral">&nbsp;</span>
459
+ <span class="cline-any cline-neutral">&nbsp;</span>
460
+ <span class="cline-any cline-neutral">&nbsp;</span>
461
+ <span class="cline-any cline-no">&nbsp;</span>
462
+ <span class="cline-any cline-neutral">&nbsp;</span>
463
+ <span class="cline-any cline-no">&nbsp;</span>
464
+ <span class="cline-any cline-neutral">&nbsp;</span>
465
+ <span class="cline-any cline-yes">1x</span>
466
+ <span class="cline-any cline-neutral">&nbsp;</span>
467
+ <span class="cline-any cline-neutral">&nbsp;</span>
468
+ <span class="cline-any cline-yes">1x</span>
469
+ <span class="cline-any cline-yes">1x</span>
470
+ <span class="cline-any cline-neutral">&nbsp;</span>
471
+ <span class="cline-any cline-neutral">&nbsp;</span>
472
+ <span class="cline-any cline-neutral">&nbsp;</span>
473
+ <span class="cline-any cline-yes">20x</span>
474
+ <span class="cline-any cline-no">&nbsp;</span>
475
+ <span class="cline-any cline-neutral">&nbsp;</span>
476
+ <span class="cline-any cline-neutral">&nbsp;</span>
477
+ <span class="cline-any cline-neutral">&nbsp;</span>
478
+ <span class="cline-any cline-yes">20x</span>
479
+ <span class="cline-any cline-yes">18x</span>
480
+ <span class="cline-any cline-neutral">&nbsp;</span>
481
+ <span class="cline-any cline-neutral">&nbsp;</span>
482
+ <span class="cline-any cline-neutral">&nbsp;</span>
483
+ <span class="cline-any cline-yes">20x</span>
484
+ <span class="cline-any cline-no">&nbsp;</span>
485
+ <span class="cline-any cline-neutral">&nbsp;</span>
486
+ <span class="cline-any cline-neutral">&nbsp;</span>
487
+ <span class="cline-any cline-neutral">&nbsp;</span>
488
+ <span class="cline-any cline-yes">20x</span>
489
+ <span class="cline-any cline-neutral">&nbsp;</span>
490
+ <span class="cline-any cline-yes">20x</span>
491
+ <span class="cline-any cline-no">&nbsp;</span>
492
+ <span class="cline-any cline-neutral">&nbsp;</span>
493
+ <span class="cline-any cline-neutral">&nbsp;</span>
494
+ <span class="cline-any cline-yes">20x</span>
495
+ <span class="cline-any cline-neutral">&nbsp;</span>
496
+ <span class="cline-any cline-neutral">&nbsp;</span>
497
+ <span class="cline-any cline-neutral">&nbsp;</span>
498
+ <span class="cline-any cline-yes">5x</span>
499
+ <span class="cline-any cline-yes">5x</span>
500
+ <span class="cline-any cline-yes">5x</span>
501
+ <span class="cline-any cline-yes">5x</span>
502
+ <span class="cline-any cline-neutral">&nbsp;</span>
503
+ <span class="cline-any cline-neutral">&nbsp;</span>
504
+ <span class="cline-any cline-neutral">&nbsp;</span>
505
+ <span class="cline-any cline-neutral">&nbsp;</span>
506
+ <span class="cline-any cline-neutral">&nbsp;</span>
507
+ <span class="cline-any cline-neutral">&nbsp;</span>
508
+ <span class="cline-any cline-neutral">&nbsp;</span>
509
+ <span class="cline-any cline-neutral">&nbsp;</span>
510
+ <span class="cline-any cline-neutral">&nbsp;</span>
511
+ <span class="cline-any cline-neutral">&nbsp;</span>
512
+ <span class="cline-any cline-neutral">&nbsp;</span>
513
+ <span class="cline-any cline-neutral">&nbsp;</span>
514
+ <span class="cline-any cline-no">&nbsp;</span>
515
+ <span class="cline-any cline-no">&nbsp;</span>
516
+ <span class="cline-any cline-neutral">&nbsp;</span>
517
+ <span class="cline-any cline-no">&nbsp;</span>
518
+ <span class="cline-any cline-no">&nbsp;</span>
519
+ <span class="cline-any cline-neutral">&nbsp;</span>
520
+ <span class="cline-any cline-neutral">&nbsp;</span>
521
+ <span class="cline-any cline-no">&nbsp;</span>
522
+ <span class="cline-any cline-neutral">&nbsp;</span>
523
+ <span class="cline-any cline-neutral">&nbsp;</span>
524
+ <span class="cline-any cline-neutral">&nbsp;</span>
525
+ <span class="cline-any cline-neutral">&nbsp;</span>
526
+ <span class="cline-any cline-neutral">&nbsp;</span>
527
+ <span class="cline-any cline-neutral">&nbsp;</span>
528
+ <span class="cline-any cline-neutral">&nbsp;</span>
529
+ <span class="cline-any cline-no">&nbsp;</span>
530
+ <span class="cline-any cline-no">&nbsp;</span>
531
+ <span class="cline-any cline-no">&nbsp;</span>
532
+ <span class="cline-any cline-no">&nbsp;</span>
533
+ <span class="cline-any cline-neutral">&nbsp;</span>
534
+ <span class="cline-any cline-neutral">&nbsp;</span>
535
+ <span class="cline-any cline-neutral">&nbsp;</span>
536
+ <span class="cline-any cline-no">&nbsp;</span>
537
+ <span class="cline-any cline-no">&nbsp;</span>
538
+ <span class="cline-any cline-neutral">&nbsp;</span>
539
+ <span class="cline-any cline-neutral">&nbsp;</span>
540
+ <span class="cline-any cline-neutral">&nbsp;</span>
541
+ <span class="cline-any cline-neutral">&nbsp;</span>
542
+ <span class="cline-any cline-no">&nbsp;</span>
543
+ <span class="cline-any cline-neutral">&nbsp;</span>
544
+ <span class="cline-any cline-neutral">&nbsp;</span>
545
+ <span class="cline-any cline-neutral">&nbsp;</span>
546
+ <span class="cline-any cline-yes">6x</span>
547
+ <span class="cline-any cline-yes">6x</span>
548
+ <span class="cline-any cline-yes">6x</span>
549
+ <span class="cline-any cline-yes">6x</span>
550
+ <span class="cline-any cline-yes">6x</span>
551
+ <span class="cline-any cline-yes">5x</span>
552
+ <span class="cline-any cline-neutral">&nbsp;</span>
553
+ <span class="cline-any cline-neutral">&nbsp;</span>
554
+ <span class="cline-any cline-neutral">&nbsp;</span>
555
+ <span class="cline-any cline-yes">5x</span>
556
+ <span class="cline-any cline-yes">5x</span>
557
+ <span class="cline-any cline-neutral">&nbsp;</span>
558
+ <span class="cline-any cline-yes">1x</span>
559
+ <span class="cline-any cline-neutral">&nbsp;</span>
560
+ <span class="cline-any cline-yes">6x</span>
561
+ <span class="cline-any cline-neutral">&nbsp;</span>
562
+ <span class="cline-any cline-neutral">&nbsp;</span>
563
+ <span class="cline-any cline-neutral">&nbsp;</span>
564
+ <span class="cline-any cline-yes">21x</span>
565
+ <span class="cline-any cline-yes">21x</span>
566
+ <span class="cline-any cline-no">&nbsp;</span>
567
+ <span class="cline-any cline-neutral">&nbsp;</span>
568
+ <span class="cline-any cline-yes">21x</span>
569
+ <span class="cline-any cline-yes">21x</span>
570
+ <span class="cline-any cline-yes">21x</span>
571
+ <span class="cline-any cline-yes">2x</span>
572
+ <span class="cline-any cline-yes">2x</span>
573
+ <span class="cline-any cline-neutral">&nbsp;</span>
574
+ <span class="cline-any cline-neutral">&nbsp;</span>
575
+ <span class="cline-any cline-yes">21x</span>
576
+ <span class="cline-any cline-neutral">&nbsp;</span>
577
+ <span class="cline-any cline-yes">16x</span>
578
+ <span class="cline-any cline-yes">16x</span>
579
+ <span class="cline-any cline-neutral">&nbsp;</span>
580
+ <span class="cline-any cline-yes">6x</span>
581
+ <span class="cline-any cline-no">&nbsp;</span>
582
+ <span class="cline-any cline-neutral">&nbsp;</span>
583
+ <span class="cline-any cline-neutral">&nbsp;</span>
584
+ <span class="cline-any cline-yes">6x</span>
585
+ <span class="cline-any cline-yes">6x</span>
586
+ <span class="cline-any cline-neutral">&nbsp;</span>
587
+ <span class="cline-any cline-yes">16x</span>
588
+ <span class="cline-any cline-yes">16x</span>
589
+ <span class="cline-any cline-yes">16x</span>
590
+ <span class="cline-any cline-yes">6x</span>
591
+ <span class="cline-any cline-yes">6x</span>
592
+ <span class="cline-any cline-neutral">&nbsp;</span>
593
+ <span class="cline-any cline-neutral">&nbsp;</span>
594
+ <span class="cline-any cline-neutral">&nbsp;</span>
595
+ <span class="cline-any cline-neutral">&nbsp;</span>
596
+ <span class="cline-any cline-neutral">&nbsp;</span>
597
+ <span class="cline-any cline-neutral">&nbsp;</span>
598
+ <span class="cline-any cline-neutral">&nbsp;</span>
599
+ <span class="cline-any cline-neutral">&nbsp;</span>
600
+ <span class="cline-any cline-neutral">&nbsp;</span>
601
+ <span class="cline-any cline-neutral">&nbsp;</span>
602
+ <span class="cline-any cline-yes">6x</span>
603
+ <span class="cline-any cline-neutral">&nbsp;</span>
604
+ <span class="cline-any cline-neutral">&nbsp;</span>
605
+ <span class="cline-any cline-yes">21x</span>
606
+ <span class="cline-any cline-neutral">&nbsp;</span>
607
+ <span class="cline-any cline-neutral">&nbsp;</span>
608
+ <span class="cline-any cline-neutral">&nbsp;</span>
609
+ <span class="cline-any cline-yes">2x</span>
610
+ <span class="cline-any cline-yes">17x</span>
611
+ <span class="cline-any cline-yes">17x</span>
612
+ <span class="cline-any cline-yes">17x</span>
613
+ <span class="cline-any cline-yes">17x</span>
614
+ <span class="cline-any cline-yes">15x</span>
615
+ <span class="cline-any cline-neutral">&nbsp;</span>
616
+ <span class="cline-any cline-yes">2x</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-neutral">&nbsp;</span>
619
+ <span class="cline-any cline-neutral">&nbsp;</span>
620
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">const threadUtils = require("./utils")
621
+ threadUtils.threadSetup()
622
+ const ScriptRunner = require("../utilities/scriptRunner")
623
+ const { integrations } = require("../integrations")
624
+ const { processStringSync } = require("@budibase/string-templates")
625
+ const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
626
+ const {
627
+ refreshOAuthToken,
628
+ updateUserOAuth,
629
+ } = require("@budibase/backend-core/auth")
630
+ const { user: userCache } = require("@budibase/backend-core/cache")
631
+ const { getGlobalIDFromUserMetadataID } = require("../db/utils")
632
+ const { cloneDeep } = require("lodash/fp")
633
+ &nbsp;
634
+ const { isSQL } = require("../integrations/utils")
635
+ const {
636
+ enrichQueryFields,
637
+ interpolateSQL,
638
+ } = require("../integrations/queries/sql")
639
+ &nbsp;
640
+ class QueryRunner {
641
+ constructor(input, flags = { noRecursiveQuery: false }) {
642
+ this.datasource = input.datasource
643
+ this.queryVerb = input.queryVerb
644
+ this.fields = input.fields
645
+ this.parameters = input.parameters
646
+ this.pagination = input.pagination
647
+ this.transformer = input.transformer
648
+ this.queryId = input.queryId
649
+ this.noRecursiveQuery = flags.noRecursiveQuery
650
+ this.cachedVariables = []
651
+ // Additional context items for enrichment
652
+ this.ctx = input.ctx
653
+ // allows the response from a query to be stored throughout this
654
+ // execution so that if it needs to be re-used for another variable
655
+ // it can be
656
+ this.queryResponse = {}
657
+ this.hasRerun = false
658
+ this.hasRefreshedOAuth = false
659
+ }
660
+ &nbsp;
661
+ async execute() {
662
+ let { datasource, fields, queryVerb, transformer } = this
663
+ &nbsp;
664
+ let datasourceClone = cloneDeep(datasource)
665
+ let fieldsClone = cloneDeep(fields)
666
+ &nbsp;
667
+ const Integration = integrations[datasourceClone.source]
668
+ if (!Integration) {
669
+ throw "Integration type does not exist."
670
+ }
671
+ &nbsp;
672
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (datasourceClone.config.authConfigs) {
673
+ <span class="cstat-no" title="statement not covered" > datasourceClone.config.authConfigs =</span>
674
+ datasourceClone.config.authConfigs.map(<span class="fstat-no" title="function not covered" >co</span>nfig =&gt; {
675
+ <span class="cstat-no" title="statement not covered" > return enrichQueryFields(config, this.ctx)</span>
676
+ })
677
+ }
678
+ &nbsp;
679
+ const integration = new Integration(datasourceClone.config)
680
+ &nbsp;
681
+ // pre-query, make sure datasource variables are added to parameters
682
+ const parameters = await this.addDatasourceVariables()
683
+ &nbsp;
684
+ // Enrich the parameters with the addition context items.
685
+ // 'user' is now a reserved variable key in mapping parameters
686
+ const enrichedParameters = enrichQueryFields(parameters, this.ctx)
687
+ const enrichedContext = { ...enrichedParameters, ...this.ctx }
688
+ &nbsp;
689
+ // Parse global headers
690
+ if (datasourceClone.config.defaultHeaders) {
691
+ datasourceClone.config.defaultHeaders = enrichQueryFields(
692
+ datasourceClone.config.defaultHeaders,
693
+ enrichedContext
694
+ )
695
+ }
696
+ &nbsp;
697
+ let query
698
+ // handle SQL injections by interpolating the variables
699
+ if (isSQL(datasourceClone)) {
700
+ query = interpolateSQL(fieldsClone, enrichedParameters, integration)
701
+ } else {
702
+ query = enrichQueryFields(fieldsClone, enrichedContext)
703
+ }
704
+ &nbsp;
705
+ // Add pagination values for REST queries
706
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (this.pagination) {
707
+ <span class="cstat-no" title="statement not covered" > query.paginationValues = this.pagination</span>
708
+ }
709
+ &nbsp;
710
+ let output = threadUtils.formatResponse(await integration[queryVerb](query))
711
+ let rows = output,
712
+ info = undefined,
713
+ extra = undefined,
714
+ pagination = undefined
715
+ if (threadUtils.hasExtraData(output)) {
716
+ rows = output.data
717
+ info = output.info
718
+ extra = output.extra
719
+ pagination = output.pagination
720
+ }
721
+ &nbsp;
722
+ // transform as required
723
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (transformer) {
724
+ const runner = <span class="cstat-no" title="statement not covered" >new ScriptRunner(transformer, {</span>
725
+ data: rows,
726
+ params: enrichedParameters,
727
+ })
728
+ <span class="cstat-no" title="statement not covered" > rows = runner.execute()</span>
729
+ }
730
+ &nbsp;
731
+ // if the request fails we retry once, invalidating the cached value
732
+ if (info &amp;&amp; info.code &gt;= 400 &amp;&amp; !this.hasRerun) {
733
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (
734
+ this.ctx.user?.provider &amp;&amp;
735
+ <span class="branch-1 cbranch-no" title="branch not covered" > info.code === 401 </span>&amp;&amp;
736
+ <span class="branch-2 cbranch-no" title="branch not covered" > !this.hasRefreshedOAuth</span>
737
+ ) {
738
+ <span class="cstat-no" title="statement not covered" > await this.refreshOAuth2(this.ctx)</span>
739
+ // Attempt to refresh the access token from the provider
740
+ <span class="cstat-no" title="statement not covered" > this.hasRefreshedOAuth = true</span>
741
+ } else {
742
+ this.hasRerun = true
743
+ }
744
+ &nbsp;
745
+ await threadUtils.invalidateDynamicVariables(this.cachedVariables)
746
+ return this.execute()
747
+ }
748
+ &nbsp;
749
+ // check for undefined response
750
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!rows) {
751
+ <span class="cstat-no" title="statement not covered" > rows = []</span>
752
+ }
753
+ &nbsp;
754
+ // needs to an array for next step
755
+ if (!Array.isArray(rows)) {
756
+ rows = [rows]
757
+ }
758
+ &nbsp;
759
+ // map into JSON if just raw primitive here
760
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (rows.find(row =&gt; typeof row !== "object")) {
761
+ <span class="cstat-no" title="statement not covered" > rows = rows.map(<span class="fstat-no" title="function not covered" >va</span>lue =&gt; (<span class="cstat-no" title="statement not covered" >{ value })</span>)</span>
762
+ }
763
+ &nbsp;
764
+ // get all the potential fields in the schema
765
+ let keys = rows.flatMap(Object.keys)
766
+ &nbsp;
767
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (integration.end) {
768
+ <span class="cstat-no" title="statement not covered" > integration.end()</span>
769
+ }
770
+ &nbsp;
771
+ return { rows, keys, info, extra, pagination }
772
+ }
773
+ &nbsp;
774
+ async runAnotherQuery(queryId, parameters) {
775
+ const db = getAppDB()
776
+ const query = await db.get(queryId)
777
+ const datasource = await db.get(query.datasourceId)
778
+ return new QueryRunner(
779
+ {
780
+ datasource,
781
+ queryVerb: query.queryVerb,
782
+ fields: query.fields,
783
+ parameters,
784
+ transformer: query.transformer,
785
+ },
786
+ { noRecursiveQuery: true }
787
+ ).execute()
788
+ }
789
+ &nbsp;
790
+ <span class="fstat-no" title="function not covered" > as</span>ync refreshOAuth2(ctx) {
791
+ const { oauth2, providerType, _id } = <span class="cstat-no" title="statement not covered" >ctx.user</span>
792
+ const { configId } = <span class="cstat-no" title="statement not covered" >ctx.auth</span>
793
+ &nbsp;
794
+ <span class="cstat-no" title="statement not covered" > if (!providerType || !oauth2?.refreshToken) {</span>
795
+ <span class="cstat-no" title="statement not covered" > throw new Error("No refresh token found for authenticated user")</span>
796
+ }
797
+ &nbsp;
798
+ const resp = <span class="cstat-no" title="statement not covered" >await refreshOAuthToken(</span>
799
+ oauth2.refreshToken,
800
+ providerType,
801
+ configId
802
+ )
803
+ &nbsp;
804
+ // Refresh session flow. Should be in same location as refreshOAuthToken
805
+ // There are several other properties available in 'resp'
806
+ <span class="cstat-no" title="statement not covered" > if (!resp.err) {</span>
807
+ const globalUserId = <span class="cstat-no" title="statement not covered" >getGlobalIDFromUserMetadataID(_id)</span>
808
+ <span class="cstat-no" title="statement not covered" > await updateUserOAuth(globalUserId, resp)</span>
809
+ <span class="cstat-no" title="statement not covered" > this.ctx.user = await userCache.getUser(globalUserId)</span>
810
+ } else {
811
+ // In this event the user may have oAuth issues that
812
+ // could require re-authenticating with their provider.
813
+ let errorMessage = <span class="cstat-no" title="statement not covered" >resp.err.data ? resp.err.data : resp.err.toString()</span>
814
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
815
+ "OAuth2 access token could not be refreshed: " + errorMessage
816
+ )
817
+ }
818
+ &nbsp;
819
+ <span class="cstat-no" title="statement not covered" > return resp</span>
820
+ }
821
+ &nbsp;
822
+ async getDynamicVariable(variable) {
823
+ let { parameters } = this
824
+ const queryId = variable.queryId,
825
+ name = variable.name
826
+ let value = await threadUtils.checkCacheForDynamicVariable(queryId, name)
827
+ if (!value) {
828
+ value = this.queryResponse[queryId]
829
+ ? <span class="branch-0 cbranch-no" title="branch not covered" >this.queryResponse[queryId]</span>
830
+ : await this.runAnotherQuery(queryId, parameters)
831
+ // store incase this query is to be called again
832
+ this.queryResponse[queryId] = value
833
+ await threadUtils.storeDynamicVariable(queryId, name, value)
834
+ } else {
835
+ this.cachedVariables.push({ queryId, name })
836
+ }
837
+ return value
838
+ }
839
+ &nbsp;
840
+ async addDatasourceVariables() {
841
+ let { datasource, parameters, fields } = this
842
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!datasource || !datasource.config) {
843
+ <span class="cstat-no" title="statement not covered" > return parameters</span>
844
+ }
845
+ const staticVars = datasource.config.staticVariables || {}
846
+ const dynamicVars = datasource.config.dynamicVariables || []
847
+ for (let [key, value] of Object.entries(staticVars)) {
848
+ <span class="missing-if-branch" title="else path not taken" >E</span>if (!parameters[key]) {
849
+ parameters[key] = value
850
+ }
851
+ }
852
+ if (!this.noRecursiveQuery) {
853
+ // need to see if this uses any variables
854
+ const stringFields = JSON.stringify(fields)
855
+ const foundVars = dynamicVars.filter(variable =&gt; {
856
+ // don't allow a query to use its own dynamic variable (loop)
857
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (variable.queryId === this.queryId) {
858
+ <span class="cstat-no" title="statement not covered" > return false</span>
859
+ }
860
+ // look for {{ variable }} but allow spaces between handlebars
861
+ const regex = new RegExp(`{{[ ]*${variable.name}[ ]*}}`)
862
+ return regex.test(stringFields)
863
+ })
864
+ const dynamics = foundVars.map(dynVar =&gt; this.getDynamicVariable(dynVar))
865
+ const responses = await Promise.all(dynamics)
866
+ for (let i = 0; i &lt; foundVars.length; i++) {
867
+ const variable = foundVars[i]
868
+ parameters[variable.name] = processStringSync(
869
+ variable.value,
870
+ {
871
+ data: responses[i].rows,
872
+ info: responses[i].extra,
873
+ },
874
+ {
875
+ escapeNewlines: true,
876
+ }
877
+ )
878
+ // make sure its known that this uses dynamic variables in case it fails
879
+ this.hasDynamicVariables = true
880
+ }
881
+ }
882
+ return parameters
883
+ }
884
+ }
885
+ &nbsp;
886
+ module.exports = (input, callback) =&gt; {
887
+ doInAppContext(input.appId, async () =&gt; {
888
+ const Runner = new QueryRunner(input)
889
+ try {
890
+ const response = await Runner.execute()
891
+ callback(null, response)
892
+ } catch (err) {
893
+ callback(err)
894
+ }
895
+ })
896
+ }
897
+ &nbsp;</pre></td></tr></table></pre>
898
+
899
+ <div class='push'></div><!-- for sticky footer -->
900
+ </div><!-- /wrapper -->
901
+ <div class='footer quiet pad2 space-top1 center small'>
902
+ Code coverage generated by
903
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
904
+ at Mon Aug 01 2022 15:42:56 GMT+0000 (Coordinated Universal Time)
905
+ </div>
906
+ <script src="../prettify.js"></script>
907
+ <script>
908
+ window.onload = function () {
909
+ prettyPrint();
910
+ };
911
+ </script>
912
+ <script src="../sorter.js"></script>
913
+ <script src="../block-navigation.js"></script>
914
+ </body>
915
+ </html>
916
+