@budibase/server 1.0.123 → 1.0.125

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 (325) hide show
  1. package/builder/assets/index.3d890df7.js +1299 -0
  2. package/builder/assets/index.89795487.css +6 -0
  3. package/builder/assets/{vendor.8e34a169.js → vendor.5240f480.js} +1 -1
  4. package/builder/index.html +3 -3
  5. package/coverage/clover.xml +695 -1678
  6. package/coverage/coverage-final.json +28 -43
  7. package/coverage/lcov-report/api/controllers/analytics.js.html +8 -3
  8. package/coverage/lcov-report/api/controllers/apikeys.js.html +9 -4
  9. package/coverage/lcov-report/api/controllers/auth.js.html +8 -3
  10. package/coverage/lcov-report/api/controllers/automation.js.html +8 -3
  11. package/coverage/lcov-report/api/controllers/backup.js.html +8 -3
  12. package/coverage/lcov-report/api/controllers/cloud.js.html +8 -3
  13. package/coverage/lcov-report/api/controllers/component.js.html +8 -3
  14. package/coverage/lcov-report/api/controllers/datasource.js.html +11 -6
  15. package/coverage/lcov-report/api/controllers/dev.js.html +8 -3
  16. package/coverage/lcov-report/api/controllers/index.html +16 -26
  17. package/coverage/lcov-report/api/controllers/integration.js.html +8 -3
  18. package/coverage/lcov-report/api/controllers/layout.js.html +8 -3
  19. package/coverage/lcov-report/api/controllers/metadata.js.html +8 -3
  20. package/coverage/lcov-report/api/controllers/migrations.js.html +8 -3
  21. package/coverage/lcov-report/api/controllers/permission.js.html +8 -3
  22. package/coverage/lcov-report/api/controllers/query/index.html +16 -26
  23. package/coverage/lcov-report/api/controllers/query/validation.js.html +8 -3
  24. package/coverage/lcov-report/api/controllers/role.js.html +10 -5
  25. package/coverage/lcov-report/api/controllers/routing.js.html +9 -4
  26. package/coverage/lcov-report/api/controllers/row/external.js.html +8 -3
  27. package/coverage/lcov-report/api/controllers/row/index.html +25 -35
  28. package/coverage/lcov-report/api/controllers/row/internal.js.html +32 -24
  29. package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +21 -16
  30. package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +24 -19
  31. package/coverage/lcov-report/api/controllers/row/utils.js.html +33 -19
  32. package/coverage/lcov-report/api/controllers/screen.js.html +9 -4
  33. package/coverage/lcov-report/api/controllers/script.js.html +8 -3
  34. package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +55 -50
  35. package/coverage/lcov-report/api/controllers/table/external.js.html +8 -3
  36. package/coverage/lcov-report/api/controllers/table/index.html +19 -44
  37. package/coverage/lcov-report/api/controllers/table/index.js.html +20 -15
  38. package/coverage/lcov-report/api/controllers/templates.js.html +8 -3
  39. package/coverage/lcov-report/api/controllers/user.js.html +8 -3
  40. package/coverage/lcov-report/api/controllers/view/exporters.js.html +8 -3
  41. package/coverage/lcov-report/api/controllers/view/index.html +8 -3
  42. package/coverage/lcov-report/api/controllers/view/index.js.html +10 -5
  43. package/coverage/lcov-report/api/controllers/view/utils.js.html +8 -3
  44. package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +8 -3
  45. package/coverage/lcov-report/api/controllers/webhook.js.html +10 -5
  46. package/coverage/lcov-report/api/index.html +18 -13
  47. package/coverage/lcov-report/api/index.js.html +28 -8
  48. package/coverage/lcov-report/api/routes/analytics.js.html +8 -3
  49. package/coverage/lcov-report/api/routes/apikeys.js.html +8 -3
  50. package/coverage/lcov-report/api/routes/auth.js.html +8 -3
  51. package/coverage/lcov-report/api/routes/automation.js.html +8 -3
  52. package/coverage/lcov-report/api/routes/backup.js.html +8 -3
  53. package/coverage/lcov-report/api/routes/cloud.js.html +8 -3
  54. package/coverage/lcov-report/api/routes/component.js.html +8 -3
  55. package/coverage/lcov-report/api/routes/datasource.js.html +8 -3
  56. package/coverage/lcov-report/api/routes/deploy.js.html +8 -3
  57. package/coverage/lcov-report/api/routes/dev.js.html +9 -4
  58. package/coverage/lcov-report/api/routes/index.html +13 -68
  59. package/coverage/lcov-report/api/routes/integration.js.html +8 -3
  60. package/coverage/lcov-report/api/routes/layout.js.html +8 -3
  61. package/coverage/lcov-report/api/routes/metadata.js.html +8 -3
  62. package/coverage/lcov-report/api/routes/migrations.js.html +8 -3
  63. package/coverage/lcov-report/api/routes/permission.js.html +8 -3
  64. package/coverage/lcov-report/api/routes/query.js.html +8 -3
  65. package/coverage/lcov-report/api/routes/role.js.html +8 -3
  66. package/coverage/lcov-report/api/routes/routing.js.html +8 -3
  67. package/coverage/lcov-report/api/routes/screen.js.html +8 -3
  68. package/coverage/lcov-report/api/routes/script.js.html +8 -3
  69. package/coverage/lcov-report/api/routes/table.js.html +8 -3
  70. package/coverage/lcov-report/api/routes/templates.js.html +8 -3
  71. package/coverage/lcov-report/api/routes/user.js.html +8 -3
  72. package/coverage/lcov-report/api/routes/utils/index.html +8 -3
  73. package/coverage/lcov-report/api/routes/utils/validators.js.html +8 -3
  74. package/coverage/lcov-report/api/routes/view.js.html +8 -3
  75. package/coverage/lcov-report/api/routes/webhook.js.html +8 -3
  76. package/coverage/lcov-report/automations/actions.js.html +21 -7
  77. package/coverage/lcov-report/automations/automationUtils.js.html +64 -23
  78. package/coverage/lcov-report/automations/bullboard.js.html +8 -3
  79. package/coverage/lcov-report/automations/index.html +27 -37
  80. package/coverage/lcov-report/automations/index.js.html +8 -3
  81. package/coverage/lcov-report/automations/steps/bash.js.html +8 -3
  82. package/coverage/lcov-report/automations/steps/delay.js.html +8 -3
  83. package/coverage/lcov-report/automations/steps/discord.js.html +8 -3
  84. package/coverage/lcov-report/automations/steps/executeQuery.js.html +8 -3
  85. package/coverage/lcov-report/automations/steps/executeScript.js.html +8 -3
  86. package/coverage/lcov-report/automations/steps/filter.js.html +8 -3
  87. package/coverage/lcov-report/automations/steps/index.html +31 -41
  88. package/coverage/lcov-report/automations/steps/integromat.js.html +8 -3
  89. package/coverage/lcov-report/{api/routes/static.js.html → automations/steps/loop.js.html} +70 -80
  90. package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +9 -4
  91. package/coverage/lcov-report/automations/steps/queryRows.js.html +9 -4
  92. package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +8 -3
  93. package/coverage/lcov-report/automations/steps/serverLog.js.html +8 -3
  94. package/coverage/lcov-report/automations/steps/slack.js.html +8 -3
  95. package/coverage/lcov-report/automations/steps/updateRow.js.html +8 -3
  96. package/coverage/lcov-report/automations/steps/utils.js.html +14 -9
  97. package/coverage/lcov-report/automations/steps/zapier.js.html +8 -3
  98. package/coverage/lcov-report/automations/triggerInfo/app.js.html +8 -3
  99. package/coverage/lcov-report/automations/triggerInfo/cron.js.html +8 -3
  100. package/coverage/lcov-report/automations/triggerInfo/index.html +8 -3
  101. package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -3
  102. package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +8 -3
  103. package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +8 -3
  104. package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +8 -3
  105. package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +8 -3
  106. package/coverage/lcov-report/automations/triggers.js.html +16 -11
  107. package/coverage/lcov-report/block-navigation.js +8 -0
  108. package/coverage/lcov-report/constants/index.html +12 -7
  109. package/coverage/lcov-report/constants/index.js.html +55 -32
  110. package/coverage/lcov-report/constants/layouts.js.html +8 -3
  111. package/coverage/lcov-report/constants/screens.js.html +8 -3
  112. package/coverage/lcov-report/db/inMemoryView.js.html +8 -3
  113. package/coverage/lcov-report/db/index.html +8 -3
  114. package/coverage/lcov-report/db/index.js.html +9 -4
  115. package/coverage/lcov-report/db/linkedRows/LinkController.js.html +20 -15
  116. package/coverage/lcov-report/db/linkedRows/index.html +8 -3
  117. package/coverage/lcov-report/db/linkedRows/index.js.html +22 -17
  118. package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +12 -7
  119. package/coverage/lcov-report/db/newid.js.html +11 -6
  120. package/coverage/lcov-report/db/utils.js.html +84 -79
  121. package/coverage/lcov-report/events/AutomationEmitter.js.html +14 -9
  122. package/coverage/lcov-report/events/index.html +8 -3
  123. package/coverage/lcov-report/events/index.js.html +9 -4
  124. package/coverage/lcov-report/events/utils.js.html +18 -13
  125. package/coverage/lcov-report/index.html +125 -120
  126. package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +8 -3
  127. package/coverage/lcov-report/integrations/tests/index.html +8 -3
  128. package/coverage/lcov-report/middleware/appInfo.js.html +8 -3
  129. package/coverage/lcov-report/middleware/builder.js.html +8 -3
  130. package/coverage/lcov-report/middleware/currentapp.js.html +65 -15
  131. package/coverage/lcov-report/middleware/index.html +25 -50
  132. package/coverage/lcov-report/middleware/joi-validator.js.html +9 -4
  133. package/coverage/lcov-report/middleware/publicApi.js.html +8 -3
  134. package/coverage/lcov-report/middleware/resourceId.js.html +8 -3
  135. package/coverage/lcov-report/middleware/selfhost.js.html +9 -4
  136. package/coverage/lcov-report/middleware/utils.js.html +8 -3
  137. package/coverage/lcov-report/sorter.js +26 -0
  138. package/coverage/lcov-report/threads/automation.js.html +581 -90
  139. package/coverage/lcov-report/threads/index.html +30 -40
  140. package/coverage/lcov-report/threads/query.js.html +9 -4
  141. package/coverage/lcov-report/threads/utils.js.html +17 -9
  142. package/coverage/lcov-report/utilities/bcrypt.js.html +8 -3
  143. package/coverage/lcov-report/utilities/budibaseDir.js.html +8 -3
  144. package/coverage/lcov-report/utilities/centralPath.js.html +8 -3
  145. package/coverage/lcov-report/utilities/csvParser.js.html +10 -5
  146. package/coverage/lcov-report/utilities/global.js.html +9 -4
  147. package/coverage/lcov-report/utilities/index.html +8 -3
  148. package/coverage/lcov-report/utilities/index.js.html +11 -6
  149. package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +32 -9
  150. package/coverage/lcov-report/utilities/queue/index.html +12 -7
  151. package/coverage/lcov-report/utilities/routing/index.html +8 -3
  152. package/coverage/lcov-report/utilities/routing/index.js.html +8 -3
  153. package/coverage/lcov-report/utilities/rowProcessor/index.html +8 -3
  154. package/coverage/lcov-report/utilities/rowProcessor/index.js.html +48 -43
  155. package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +18 -13
  156. package/coverage/lcov-report/utilities/scriptRunner.js.html +8 -3
  157. package/coverage/lcov-report/utilities/security.js.html +9 -4
  158. package/coverage/lcov-report/utilities/statusCodes.js.html +8 -3
  159. package/coverage/lcov-report/utilities/usageQuota/index.html +24 -34
  160. package/coverage/lcov-report/utilities/usageQuota/rows.js.html +44 -39
  161. package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +8 -3
  162. package/coverage/lcov-report/utilities/users.js.html +8 -3
  163. package/coverage/lcov-report/utilities/workerRequests.js.html +9 -4
  164. package/coverage/lcov.info +1144 -2875
  165. package/dist/api/controllers/application.js +145 -73
  166. package/dist/api/controllers/deploy/index.js +68 -36
  167. package/dist/api/controllers/public/applications.js +29 -9
  168. package/dist/api/controllers/public/queries.js +27 -7
  169. package/dist/api/controllers/public/rows.js +32 -12
  170. package/dist/api/controllers/public/tables.js +2 -2
  171. package/dist/api/controllers/public/users.js +8 -8
  172. package/dist/api/controllers/public/utils.js +1 -1
  173. package/dist/api/controllers/query/import/index.js +3 -3
  174. package/dist/api/controllers/query/index.js +57 -44
  175. package/dist/api/controllers/row/ExternalRequest.js +27 -27
  176. package/dist/api/controllers/row/index.js +83 -60
  177. package/dist/api/controllers/row/internal.js +2 -1
  178. package/dist/api/controllers/row/utils.js +2 -1
  179. package/dist/api/controllers/static/templates/BudibaseApp.svelte +3 -0
  180. package/dist/api/controllers/table/bulkFormula.js +2 -1
  181. package/dist/api/controllers/table/internal.js +41 -35
  182. package/dist/api/controllers/table/utils.js +271 -229
  183. package/dist/api/index.js +5 -0
  184. package/dist/api/routes/application.js +39 -13
  185. package/dist/api/routes/index.js +61 -56
  186. package/dist/api/routes/public/index.js +6 -9
  187. package/dist/api/routes/public/queries.js +1 -1
  188. package/dist/api/routes/public/rows.js +1 -1
  189. package/dist/api/routes/public/tables.js +3 -3
  190. package/dist/api/routes/public/users.js +1 -1
  191. package/dist/api/routes/row.js +43 -17
  192. package/dist/api/routes/static.js +40 -13
  193. package/dist/api/routes/tests/utilities/TestFunctions.js +75 -33
  194. package/dist/app.js +8 -4
  195. package/dist/automations/actions.js +3 -0
  196. package/dist/automations/automationUtils.js +10 -0
  197. package/dist/automations/steps/createRow.js +12 -12
  198. package/dist/automations/steps/deleteRow.js +13 -16
  199. package/dist/automations/steps/loop.js +51 -0
  200. package/dist/automations/tests/utilities/index.js +13 -11
  201. package/dist/automations/utils.js +187 -133
  202. package/dist/constants/index.js +5 -0
  203. package/dist/definitions/datasource.js +1 -0
  204. package/dist/environment.js +2 -3
  205. package/dist/index.js +4 -0
  206. package/dist/integrations/base/sql.js +2 -2
  207. package/dist/integrations/base/sqlTable.js +2 -2
  208. package/dist/integrations/googlesheets.js +1 -1
  209. package/dist/integrations/index.js +4 -0
  210. package/dist/integrations/microsoftSqlServer.js +8 -8
  211. package/dist/integrations/mysql.js +9 -9
  212. package/dist/integrations/oracle.js +7 -7
  213. package/dist/integrations/postgres.js +7 -7
  214. package/dist/integrations/queries/sql.js +2 -2
  215. package/dist/integrations/redis.js +158 -0
  216. package/dist/integrations/rest.js +1 -1
  217. package/dist/middleware/authorized.js +51 -51
  218. package/dist/middleware/currentapp.js +15 -1
  219. package/dist/migrations/functions/appUrls.js +1 -1
  220. package/dist/migrations/functions/developerQuota.js +49 -0
  221. package/dist/migrations/functions/publishedAppsQuota.js +47 -0
  222. package/dist/migrations/functions/quotas1.js +6 -2
  223. package/dist/migrations/functions/usageQuotas/index.js +0 -4
  224. package/dist/migrations/functions/usageQuotas/syncApps.js +4 -7
  225. package/dist/migrations/functions/usageQuotas/syncDevelopers.js +24 -0
  226. package/dist/migrations/functions/usageQuotas/syncPublishedApps.js +26 -0
  227. package/dist/migrations/functions/usageQuotas/syncRows.js +5 -8
  228. package/dist/migrations/index.js +17 -1
  229. package/dist/package.json +14 -8
  230. package/dist/threads/automation.js +149 -27
  231. package/dist/threads/index.js +36 -10
  232. package/dist/threads/utils.js +1 -0
  233. package/dist/tsconfig.build.tsbuildinfo +1 -0
  234. package/dist/utilities/queue/inMemoryQueue.js +6 -1
  235. package/nodemon.json +1 -1
  236. package/package.json +15 -9
  237. package/scripts/dev/manage.js +2 -0
  238. package/src/api/controllers/{application.js → application.ts} +118 -51
  239. package/src/api/controllers/deploy/{index.js → index.ts} +53 -29
  240. package/src/api/controllers/public/applications.ts +2 -2
  241. package/src/api/controllers/public/queries.ts +1 -1
  242. package/src/api/controllers/public/rows.ts +1 -1
  243. package/src/api/controllers/query/{index.js → index.ts} +51 -48
  244. package/src/api/controllers/row/ExternalRequest.ts +1 -1
  245. package/src/api/controllers/row/{index.js → index.ts} +24 -17
  246. package/src/api/controllers/row/internal.js +2 -1
  247. package/src/api/controllers/row/utils.js +4 -1
  248. package/src/api/controllers/static/templates/BudibaseApp.svelte +3 -0
  249. package/src/api/controllers/table/bulkFormula.js +1 -1
  250. package/src/api/controllers/table/{internal.js → internal.ts} +30 -26
  251. package/src/api/controllers/table/{utils.js → utils.ts} +86 -69
  252. package/src/api/index.js +5 -0
  253. package/src/api/routes/{application.js → application.ts} +8 -14
  254. package/src/api/routes/index.ts +60 -0
  255. package/src/api/routes/public/index.ts +1 -4
  256. package/src/api/routes/{row.js → row.ts} +7 -15
  257. package/src/api/routes/{static.js → static.ts} +11 -11
  258. package/src/api/routes/tests/misc.spec.js +39 -37
  259. package/src/api/routes/tests/utilities/{TestFunctions.js → TestFunctions.ts} +57 -33
  260. package/src/app.ts +1 -2
  261. package/src/automations/actions.js +3 -0
  262. package/src/automations/automationUtils.js +12 -0
  263. package/src/automations/steps/{createRow.js → createRow.ts} +9 -15
  264. package/src/automations/steps/{deleteRow.js → deleteRow.ts} +10 -16
  265. package/src/automations/steps/loop.js +50 -0
  266. package/src/automations/tests/automation.spec.js +0 -1
  267. package/src/automations/tests/{createRow.spec.js → createRow.spec.ts} +4 -15
  268. package/src/automations/tests/{deleteRow.spec.js → deleteRow.spec.ts} +3 -5
  269. package/src/automations/tests/utilities/index.js +12 -10
  270. package/src/automations/{utils.js → utils.ts} +39 -28
  271. package/src/constants/index.js +6 -0
  272. package/src/definitions/common.ts +1 -0
  273. package/src/definitions/datasource.ts +1 -0
  274. package/src/environment.js +2 -3
  275. package/src/index.ts +3 -0
  276. package/src/integrations/index.ts +4 -0
  277. package/src/integrations/redis.ts +152 -0
  278. package/src/integrations/tests/redis.spec.js +60 -0
  279. package/src/middleware/{authorized.js → authorized.ts} +20 -14
  280. package/src/middleware/currentapp.js +16 -1
  281. package/src/middleware/tests/currentapp.spec.js +8 -4
  282. package/src/migrations/functions/developerQuota.ts +15 -0
  283. package/src/migrations/functions/publishedAppsQuota.ts +13 -0
  284. package/src/migrations/functions/tests/quotas1.spec.js +0 -2
  285. package/src/migrations/functions/usageQuotas/index.ts +0 -5
  286. package/src/migrations/functions/usageQuotas/syncApps.ts +3 -6
  287. package/src/migrations/functions/usageQuotas/syncDevelopers.ts +19 -0
  288. package/src/migrations/functions/usageQuotas/syncPublishedApps.ts +21 -0
  289. package/src/migrations/functions/usageQuotas/syncRows.ts +3 -6
  290. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.ts +34 -0
  291. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +40 -0
  292. package/src/migrations/index.ts +13 -1
  293. package/src/threads/automation.js +196 -34
  294. package/src/threads/{index.js → index.ts} +18 -14
  295. package/src/threads/utils.js +1 -0
  296. package/src/utilities/queue/inMemoryQueue.js +7 -1
  297. package/tsconfig.build.json +10 -0
  298. package/tsconfig.json +2 -2
  299. package/builder/assets/index.68a7f4e3.css +0 -6
  300. package/builder/assets/index.8d4a5b33.js +0 -1291
  301. package/coverage/lcov-report/api/controllers/application.js.html +0 -1436
  302. package/coverage/lcov-report/api/controllers/query/index.js.html +0 -713
  303. package/coverage/lcov-report/api/controllers/row/index.js.html +0 -524
  304. package/coverage/lcov-report/api/controllers/table/internal.js.html +0 -620
  305. package/coverage/lcov-report/api/controllers/table/utils.js.html +0 -1331
  306. package/coverage/lcov-report/api/routes/application.js.html +0 -179
  307. package/coverage/lcov-report/api/routes/index.js.html +0 -266
  308. package/coverage/lcov-report/api/routes/row.js.html +0 -908
  309. package/coverage/lcov-report/automations/steps/createRow.js.html +0 -380
  310. package/coverage/lcov-report/automations/steps/deleteRow.js.html +0 -347
  311. package/coverage/lcov-report/automations/utils.js.html +0 -665
  312. package/coverage/lcov-report/middleware/authorized.js.html +0 -458
  313. package/coverage/lcov-report/middleware/usageQuota.js.html +0 -572
  314. package/coverage/lcov-report/threads/index.js.html +0 -296
  315. package/coverage/lcov-report/utilities/usageQuota/index.js.html +0 -359
  316. package/dist/middleware/usageQuota.js +0 -154
  317. package/dist/tsconfig.tsbuildinfo +0 -1
  318. package/dist/utilities/usageQuota/index.js +0 -86
  319. package/src/api/routes/index.js +0 -62
  320. package/src/middleware/tests/usageQuota.spec.js +0 -120
  321. package/src/middleware/usageQuota.js +0 -164
  322. package/src/migrations/functions/usageQuotas/tests/syncApps.spec.js +0 -41
  323. package/src/migrations/functions/usageQuotas/tests/syncRows.spec.js +0 -45
  324. package/src/utilities/tests/usageQuota/usageQuota.spec.js +0 -72
  325. package/src/utilities/usageQuota/index.js +0 -93
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">84.93% </span>
26
+ <span class="strong">60.15% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>62/73</span>
28
+ <span class='fraction'>80/133</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">57.89% </span>
33
+ <span class="strong">36.84% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>11/19</span>
35
+ <span class='fraction'>21/57</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">90.9% </span>
40
+ <span class="strong">83.33% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>10/11</span>
42
+ <span class='fraction'>10/12</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">84.93% </span>
47
+ <span class="strong">59.84% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>62/73</span>
49
+ <span class='fraction'>79/132</span>
50
50
  </div>
51
51
 
52
52
 
@@ -54,8 +54,14 @@
54
54
  <p class="quiet">
55
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
56
  </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input oninput="onInput()" type="search" id="fileSearch">
61
+ </div>
62
+ </template>
57
63
  </div>
58
- <div class='status-line high'></div>
64
+ <div class='status-line medium'></div>
59
65
  <pre><table class="coverage">
60
66
  <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
61
67
  <a name='L2'></a><a href='#L2'>2</a>
@@ -198,20 +204,186 @@
198
204
  <a name='L139'></a><a href='#L139'>139</a>
199
205
  <a name='L140'></a><a href='#L140'>140</a>
200
206
  <a name='L141'></a><a href='#L141'>141</a>
201
- <a name='L142'></a><a href='#L142'>142</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">4x</span>
202
- <span class="cline-any cline-yes">4x</span>
203
- <span class="cline-any cline-yes">4x</span>
204
- <span class="cline-any cline-yes">4x</span>
205
- <span class="cline-any cline-yes">4x</span>
206
- <span class="cline-any cline-yes">4x</span>
207
- <span class="cline-any cline-yes">4x</span>
208
- <span class="cline-any cline-yes">4x</span>
209
- <span class="cline-any cline-yes">4x</span>
210
- <span class="cline-any cline-yes">4x</span>
211
- <span class="cline-any cline-neutral">&nbsp;</span>
212
- <span class="cline-any cline-yes">4x</span>
213
- <span class="cline-any cline-yes">4x</span>
214
- <span class="cline-any cline-yes">4x</span>
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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">3x</span>
370
+ <span class="cline-any cline-yes">3x</span>
371
+ <span class="cline-any cline-yes">3x</span>
372
+ <span class="cline-any cline-yes">3x</span>
373
+ <span class="cline-any cline-yes">3x</span>
374
+ <span class="cline-any cline-yes">3x</span>
375
+ <span class="cline-any cline-yes">3x</span>
376
+ <span class="cline-any cline-yes">3x</span>
377
+ <span class="cline-any cline-yes">3x</span>
378
+ <span class="cline-any cline-yes">3x</span>
379
+ <span class="cline-any cline-yes">3x</span>
380
+ <span class="cline-any cline-yes">3x</span>
381
+ <span class="cline-any cline-yes">3x</span>
382
+ <span class="cline-any cline-neutral">&nbsp;</span>
383
+ <span class="cline-any cline-yes">3x</span>
384
+ <span class="cline-any cline-yes">3x</span>
385
+ <span class="cline-any cline-yes">3x</span>
386
+ <span class="cline-any cline-yes">3x</span>
215
387
  <span class="cline-any cline-neutral">&nbsp;</span>
216
388
  <span class="cline-any cline-neutral">&nbsp;</span>
217
389
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -220,32 +392,32 @@
220
392
  <span class="cline-any cline-neutral">&nbsp;</span>
221
393
  <span class="cline-any cline-neutral">&nbsp;</span>
222
394
  <span class="cline-any cline-neutral">&nbsp;</span>
223
- <span class="cline-any cline-yes">7x</span>
224
- <span class="cline-any cline-yes">7x</span>
225
- <span class="cline-any cline-yes">7x</span>
226
- <span class="cline-any cline-yes">7x</span>
227
- <span class="cline-any cline-yes">7x</span>
228
- <span class="cline-any cline-yes">7x</span>
395
+ <span class="cline-any cline-yes">6x</span>
396
+ <span class="cline-any cline-yes">6x</span>
397
+ <span class="cline-any cline-yes">6x</span>
398
+ <span class="cline-any cline-yes">6x</span>
399
+ <span class="cline-any cline-yes">6x</span>
400
+ <span class="cline-any cline-yes">6x</span>
229
401
  <span class="cline-any cline-neutral">&nbsp;</span>
230
- <span class="cline-any cline-yes">7x</span>
231
- <span class="cline-any cline-yes">7x</span>
402
+ <span class="cline-any cline-yes">6x</span>
403
+ <span class="cline-any cline-yes">6x</span>
232
404
  <span class="cline-any cline-neutral">&nbsp;</span>
233
- <span class="cline-any cline-yes">7x</span>
234
- <span class="cline-any cline-yes">7x</span>
405
+ <span class="cline-any cline-yes">6x</span>
406
+ <span class="cline-any cline-yes">6x</span>
235
407
  <span class="cline-any cline-neutral">&nbsp;</span>
236
408
  <span class="cline-any cline-neutral">&nbsp;</span>
237
- <span class="cline-any cline-yes">7x</span>
238
- <span class="cline-any cline-yes">7x</span>
409
+ <span class="cline-any cline-yes">6x</span>
410
+ <span class="cline-any cline-yes">6x</span>
239
411
  <span class="cline-any cline-neutral">&nbsp;</span>
240
- <span class="cline-any cline-yes">7x</span>
241
- <span class="cline-any cline-yes">7x</span>
412
+ <span class="cline-any cline-yes">6x</span>
413
+ <span class="cline-any cline-yes">6x</span>
242
414
  <span class="cline-any cline-neutral">&nbsp;</span>
243
415
  <span class="cline-any cline-neutral">&nbsp;</span>
244
416
  <span class="cline-any cline-neutral">&nbsp;</span>
245
- <span class="cline-any cline-yes">7x</span>
417
+ <span class="cline-any cline-yes">6x</span>
246
418
  <span class="cline-any cline-no">&nbsp;</span>
247
419
  <span class="cline-any cline-neutral">&nbsp;</span>
248
- <span class="cline-any cline-yes">7x</span>
420
+ <span class="cline-any cline-yes">6x</span>
249
421
  <span class="cline-any cline-neutral">&nbsp;</span>
250
422
  <span class="cline-any cline-neutral">&nbsp;</span>
251
423
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -257,45 +429,167 @@
257
429
  <span class="cline-any cline-neutral">&nbsp;</span>
258
430
  <span class="cline-any cline-neutral">&nbsp;</span>
259
431
  <span class="cline-any cline-neutral">&nbsp;</span>
260
- <span class="cline-any cline-yes">7x</span>
432
+ <span class="cline-any cline-yes">6x</span>
261
433
  <span class="cline-any cline-no">&nbsp;</span>
262
434
  <span class="cline-any cline-neutral">&nbsp;</span>
263
- <span class="cline-any cline-yes">7x</span>
264
- <span class="cline-any cline-yes">7x</span>
265
435
  <span class="cline-any cline-yes">6x</span>
436
+ <span class="cline-any cline-yes">6x</span>
437
+ <span class="cline-any cline-yes">6x</span>
438
+ <span class="cline-any cline-neutral">&nbsp;</span>
439
+ <span class="cline-any cline-neutral">&nbsp;</span>
440
+ <span class="cline-any cline-neutral">&nbsp;</span>
441
+ <span class="cline-any cline-yes">11x</span>
442
+ <span class="cline-any cline-neutral">&nbsp;</span>
443
+ <span class="cline-any cline-yes">11x</span>
444
+ <span class="cline-any cline-yes">6x</span>
445
+ <span class="cline-any cline-neutral">&nbsp;</span>
446
+ <span class="cline-any cline-yes">11x</span>
447
+ <span class="cline-any cline-neutral">&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-no">&nbsp;</span>
451
+ <span class="cline-any cline-neutral">&nbsp;</span>
452
+ <span class="cline-any cline-neutral">&nbsp;</span>
453
+ <span class="cline-any cline-neutral">&nbsp;</span>
266
454
  <span class="cline-any cline-neutral">&nbsp;</span>
267
455
  <span class="cline-any cline-neutral">&nbsp;</span>
268
456
  <span class="cline-any cline-neutral">&nbsp;</span>
269
- <span class="cline-any cline-yes">12x</span>
270
457
  <span class="cline-any cline-neutral">&nbsp;</span>
271
- <span class="cline-any cline-yes">12x</span>
272
- <span class="cline-any cline-yes">7x</span>
273
458
  <span class="cline-any cline-neutral">&nbsp;</span>
274
- <span class="cline-any cline-yes">12x</span>
459
+ <span class="cline-any cline-neutral">&nbsp;</span>
460
+ <span class="cline-any cline-no">&nbsp;</span>
461
+ <span class="cline-any cline-neutral">&nbsp;</span>
462
+ <span class="cline-any cline-neutral">&nbsp;</span>
275
463
  <span class="cline-any cline-neutral">&nbsp;</span>
276
464
  <span class="cline-any cline-neutral">&nbsp;</span>
277
465
  <span class="cline-any cline-neutral">&nbsp;</span>
278
- <span class="cline-any cline-yes">7x</span>
279
- <span class="cline-any cline-yes">7x</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">6x</span>
280
469
  <span class="cline-any cline-yes">6x</span>
281
470
  <span class="cline-any cline-yes">6x</span>
282
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">6x</span>
474
+ <span class="cline-any cline-neutral">&nbsp;</span>
475
+ <span class="cline-any cline-yes">6x</span>
476
+ <span class="cline-any cline-yes">6x</span>
477
+ <span class="cline-any cline-yes">5x</span>
478
+ <span class="cline-any cline-neutral">&nbsp;</span>
283
479
  <span class="cline-any cline-yes">5x</span>
284
480
  <span class="cline-any cline-no">&nbsp;</span>
285
481
  <span class="cline-any cline-no">&nbsp;</span>
482
+ <span class="cline-any cline-no">&nbsp;</span>
483
+ <span class="cline-any cline-neutral">&nbsp;</span>
484
+ <span class="cline-any cline-neutral">&nbsp;</span>
485
+ <span class="cline-any cline-yes">5x</span>
486
+ <span class="cline-any cline-no">&nbsp;</span>
286
487
  <span class="cline-any cline-neutral">&nbsp;</span>
287
488
  <span class="cline-any cline-yes">5x</span>
288
489
  <span class="cline-any cline-yes">5x</span>
289
490
  <span class="cline-any cline-yes">5x</span>
491
+ <span class="cline-any cline-yes">5x</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">5x</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-no">&nbsp;</span>
498
+ <span class="cline-any cline-neutral">&nbsp;</span>
499
+ <span class="cline-any cline-neutral">&nbsp;</span>
500
+ <span class="cline-any cline-neutral">&nbsp;</span>
501
+ <span class="cline-any cline-no">&nbsp;</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-no">&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-no">&nbsp;</span>
510
+ <span class="cline-any cline-no">&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-neutral">&nbsp;</span>
515
+ <span class="cline-any cline-neutral">&nbsp;</span>
516
+ <span class="cline-any cline-no">&nbsp;</span>
517
+ <span class="cline-any cline-neutral">&nbsp;</span>
518
+ <span class="cline-any cline-neutral">&nbsp;</span>
519
+ <span class="cline-any cline-neutral">&nbsp;</span>
520
+ <span class="cline-any cline-no">&nbsp;</span>
521
+ <span class="cline-any cline-no">&nbsp;</span>
522
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
528
+ <span class="cline-any cline-no">&nbsp;</span>
529
+ <span class="cline-any cline-no">&nbsp;</span>
530
+ <span class="cline-any cline-neutral">&nbsp;</span>
531
+ <span class="cline-any cline-neutral">&nbsp;</span>
532
+ <span class="cline-any cline-no">&nbsp;</span>
533
+ <span class="cline-any cline-no">&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-neutral">&nbsp;</span>
537
+ <span class="cline-any cline-neutral">&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-no">&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>
290
545
  <span class="cline-any cline-neutral">&nbsp;</span>
291
546
  <span class="cline-any cline-neutral">&nbsp;</span>
292
547
  <span class="cline-any cline-neutral">&nbsp;</span>
293
548
  <span class="cline-any cline-neutral">&nbsp;</span>
549
+ <span class="cline-any cline-neutral">&nbsp;</span>
550
+ <span class="cline-any cline-no">&nbsp;</span>
551
+ <span class="cline-any cline-neutral">&nbsp;</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-no">&nbsp;</span>
555
+ <span class="cline-any cline-neutral">&nbsp;</span>
556
+ <span class="cline-any cline-neutral">&nbsp;</span>
557
+ <span class="cline-any cline-neutral">&nbsp;</span>
558
+ <span class="cline-any cline-no">&nbsp;</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-neutral">&nbsp;</span>
562
+ <span class="cline-any cline-neutral">&nbsp;</span>
563
+ <span class="cline-any cline-no">&nbsp;</span>
564
+ <span class="cline-any cline-neutral">&nbsp;</span>
565
+ <span class="cline-any cline-neutral">&nbsp;</span>
566
+ <span class="cline-any cline-neutral">&nbsp;</span>
567
+ <span class="cline-any cline-no">&nbsp;</span>
568
+ <span class="cline-any cline-neutral">&nbsp;</span>
569
+ <span class="cline-any cline-neutral">&nbsp;</span>
570
+ <span class="cline-any cline-neutral">&nbsp;</span>
571
+ <span class="cline-any cline-no">&nbsp;</span>
572
+ <span class="cline-any cline-no">&nbsp;</span>
573
+ <span class="cline-any cline-no">&nbsp;</span>
574
+ <span class="cline-any cline-neutral">&nbsp;</span>
575
+ <span class="cline-any cline-neutral">&nbsp;</span>
576
+ <span class="cline-any cline-neutral">&nbsp;</span>
577
+ <span class="cline-any cline-neutral">&nbsp;</span>
578
+ <span class="cline-any cline-yes">5x</span>
579
+ <span class="cline-any cline-no">&nbsp;</span>
580
+ <span class="cline-any cline-no">&nbsp;</span>
581
+ <span class="cline-any cline-neutral">&nbsp;</span>
582
+ <span class="cline-any cline-neutral">&nbsp;</span>
583
+ <span class="cline-any cline-neutral">&nbsp;</span>
294
584
  <span class="cline-any cline-yes">5x</span>
295
585
  <span class="cline-any cline-yes">5x</span>
296
586
  <span class="cline-any cline-yes">5x</span>
297
587
  <span class="cline-any cline-yes">5x</span>
298
588
  <span class="cline-any cline-neutral">&nbsp;</span>
589
+ <span class="cline-any cline-yes">5x</span>
590
+ <span class="cline-any cline-yes">5x</span>
591
+ <span class="cline-any cline-yes">5x</span>
592
+ <span class="cline-any cline-neutral">&nbsp;</span>
299
593
  <span class="cline-any cline-neutral">&nbsp;</span>
300
594
  <span class="cline-any cline-neutral">&nbsp;</span>
301
595
  <span class="cline-any cline-neutral">&nbsp;</span>
@@ -313,23 +607,59 @@
313
607
  <span class="cline-any cline-no">&nbsp;</span>
314
608
  <span class="cline-any cline-neutral">&nbsp;</span>
315
609
  <span class="cline-any cline-yes">5x</span>
610
+ <span class="cline-any cline-no">&nbsp;</span>
611
+ <span class="cline-any cline-neutral">&nbsp;</span>
612
+ <span class="cline-any cline-yes">5x</span>
613
+ <span class="cline-any cline-neutral">&nbsp;</span>
614
+ <span class="cline-any cline-neutral">&nbsp;</span>
615
+ <span class="cline-any cline-neutral">&nbsp;</span>
616
+ <span class="cline-any cline-neutral">&nbsp;</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-neutral">&nbsp;</span>
316
619
  <span class="cline-any cline-neutral">&nbsp;</span>
317
620
  <span class="cline-any cline-no">&nbsp;</span>
318
621
  <span class="cline-any cline-no">&nbsp;</span>
319
622
  <span class="cline-any cline-neutral">&nbsp;</span>
623
+ <span class="cline-any cline-yes">5x</span>
624
+ <span class="cline-any cline-no">&nbsp;</span>
625
+ <span class="cline-any cline-no">&nbsp;</span>
626
+ <span class="cline-any cline-no">&nbsp;</span>
627
+ <span class="cline-any cline-no">&nbsp;</span>
628
+ <span class="cline-any cline-no">&nbsp;</span>
629
+ <span class="cline-any cline-neutral">&nbsp;</span>
630
+ <span class="cline-any cline-neutral">&nbsp;</span>
631
+ <span class="cline-any cline-neutral">&nbsp;</span>
632
+ <span class="cline-any cline-neutral">&nbsp;</span>
633
+ <span class="cline-any cline-yes">5x</span>
634
+ <span class="cline-any cline-no">&nbsp;</span>
635
+ <span class="cline-any cline-neutral">&nbsp;</span>
636
+ <span class="cline-any cline-neutral">&nbsp;</span>
637
+ <span class="cline-any cline-neutral">&nbsp;</span>
638
+ <span class="cline-any cline-neutral">&nbsp;</span>
639
+ <span class="cline-any cline-no">&nbsp;</span>
640
+ <span class="cline-any cline-neutral">&nbsp;</span>
641
+ <span class="cline-any cline-neutral">&nbsp;</span>
642
+ <span class="cline-any cline-neutral">&nbsp;</span>
643
+ <span class="cline-any cline-neutral">&nbsp;</span>
644
+ <span class="cline-any cline-neutral">&nbsp;</span>
645
+ <span class="cline-any cline-neutral">&nbsp;</span>
646
+ <span class="cline-any cline-no">&nbsp;</span>
647
+ <span class="cline-any cline-no">&nbsp;</span>
648
+ <span class="cline-any cline-neutral">&nbsp;</span>
649
+ <span class="cline-any cline-neutral">&nbsp;</span>
320
650
  <span class="cline-any cline-neutral">&nbsp;</span>
321
651
  <span class="cline-any cline-yes">6x</span>
322
652
  <span class="cline-any cline-neutral">&nbsp;</span>
323
653
  <span class="cline-any cline-neutral">&nbsp;</span>
324
654
  <span class="cline-any cline-neutral">&nbsp;</span>
325
- <span class="cline-any cline-yes">4x</span>
326
- <span class="cline-any cline-yes">7x</span>
327
- <span class="cline-any cline-yes">7x</span>
328
- <span class="cline-any cline-yes">7x</span>
655
+ <span class="cline-any cline-yes">3x</span>
656
+ <span class="cline-any cline-yes">6x</span>
657
+ <span class="cline-any cline-yes">6x</span>
658
+ <span class="cline-any cline-yes">6x</span>
329
659
  <span class="cline-any cline-neutral">&nbsp;</span>
330
660
  <span class="cline-any cline-neutral">&nbsp;</span>
331
661
  <span class="cline-any cline-neutral">&nbsp;</span>
332
- <span class="cline-any cline-yes">7x</span>
662
+ <span class="cline-any cline-yes">6x</span>
333
663
  <span class="cline-any cline-neutral">&nbsp;</span>
334
664
  <span class="cline-any cline-neutral">&nbsp;</span>
335
665
  <span class="cline-any cline-yes">6x</span>
@@ -349,10 +679,14 @@ const { DocumentTypes } = require("../db/utils")
349
679
  const { doInTenant } = require("@budibase/backend-core/tenancy")
350
680
  const { definitions: triggerDefs } = require("../automations/triggerInfo")
351
681
  const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
352
- &nbsp;
682
+ const { AutomationErrors } = require("../constants")
353
683
  const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
684
+ const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
685
+ &nbsp;
354
686
  const CRON_STEP_ID = triggerDefs.CRON.stepId
355
687
  const STOPPED_STATUS = { success: false, status: "STOPPED" }
688
+ const { cloneDeep } = require("lodash/fp")
689
+ const env = require("../environment")
356
690
  &nbsp;
357
691
  /**
358
692
  * The automation orchestrator is a class responsible for executing automations.
@@ -414,51 +748,209 @@ class Orchestrator {
414
748
  }
415
749
  this.executionOutput.steps.push(stepObj)
416
750
  }
751
+ &nbsp;
752
+ <span class="fstat-no" title="function not covered" > up</span>dateContextAndOutput(loopStepNumber, step, output, result) {
753
+ <span class="cstat-no" title="statement not covered" > this.executionOutput.steps.splice(loopStepNumber, 0, {</span>
754
+ id: step.id,
755
+ stepId: step.stepId,
756
+ outputs: {
757
+ ...output,
758
+ success: result.success,
759
+ status: result.status,
760
+ },
761
+ inputs: step.inputs,
762
+ })
763
+ <span class="cstat-no" title="statement not covered" > this._context.steps.splice(loopStepNumber, 0, {</span>
764
+ ...output,
765
+ success: result.success,
766
+ status: result.status,
767
+ })
768
+ }
417
769
  &nbsp;
418
770
  async execute() {
419
771
  let automation = this._automation
420
772
  const app = await this.getApp()
421
773
  let stopped = false
774
+ let loopStep
775
+ &nbsp;
776
+ let stepCount = 0
777
+ let loopStepNumber
778
+ let loopSteps = []
422
779
  for (let step of automation.definition.steps) {
423
- // execution stopped, record state for that
424
- <span class="missing-if-branch" title="if path not taken" >I</span>if (stopped) {
425
- <span class="cstat-no" title="statement not covered" > this.updateExecutionOutput(step.id, step.stepId, {}, STOPPED_STATUS)</span>
780
+ stepCount++
781
+ let input
782
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (step.stepId === LOOP_STEP_ID) {
783
+ <span class="cstat-no" title="statement not covered" > loopStep = step</span>
784
+ <span class="cstat-no" title="statement not covered" > loopStepNumber = stepCount</span>
426
785
  <span class="cstat-no" title="statement not covered" > continue</span>
427
786
  }
428
- let stepFn = await this.getStepFunctionality(step.stepId)
429
- step.inputs = await processObject(step.inputs, this._context)
430
- step.inputs = automationUtils.cleanInputValues(
431
- step.inputs,
432
- step.schema.inputs
433
- )
434
- // appId is always passed
435
- try {
436
- let tenantId = app.tenantId || <span class="branch-1 cbranch-no" title="branch not covered" >DEFAULT_TENANT_ID</span>
437
- const outputs = await doInTenant(tenantId, () =&gt; {
438
- return stepFn({
439
- inputs: step.inputs,
440
- appId: this._appId,
441
- emitter: this._emitter,
442
- context: this._context,
443
- })
444
- })
445
- this._context.steps.push(outputs)
446
- // if filter causes us to stop execution don't break the loop, set a var
447
- // so that we can finish iterating through the steps and record that it stopped
448
- <span class="missing-if-branch" title="if path not taken" >I</span>if (step.stepId === FILTER_STEP_ID &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >!outputs.success)</span> {
449
- <span class="cstat-no" title="statement not covered" > stopped = true</span>
450
- <span class="cstat-no" title="statement not covered" > this.updateExecutionOutput(step.id, step.stepId, step.inputs, {</span>
451
- ...outputs,
452
- ...STOPPED_STATUS,
453
- })
787
+ &nbsp;
788
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (loopStep) {
789
+ <span class="cstat-no" title="statement not covered" > input = await processObject(loopStep.inputs, this._context)</span>
790
+ }
791
+ let iterations = loopStep ? <span class="branch-0 cbranch-no" title="branch not covered" >input.binding.length </span>: 1
792
+ let iterationCount = 0
793
+ for (let index = 0; index &lt; iterations; index++) {
794
+ let originalStepInput = cloneDeep(step.inputs)
795
+ &nbsp;
796
+ // Handle if the user has set a max iteration count or if it reaches the max limit set by us
797
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (loopStep) {
798
+ // lets first of all handle the input
799
+ // if the input is array then use it, if it is a string then split it on every new line
800
+ let newInput = <span class="cstat-no" title="statement not covered" >await processObject(</span>
801
+ loopStep.inputs,
802
+ cloneDeep(this._context)
803
+ )
804
+ <span class="cstat-no" title="statement not covered" > newInput = automationUtils.cleanInputValues(</span>
805
+ newInput,
806
+ loopStep.schema.inputs
807
+ )
808
+ <span class="cstat-no" title="statement not covered" > this._context.steps[loopStepNumber] = {</span>
809
+ currentItem: newInput.binding[index],
810
+ }
811
+ &nbsp;
812
+ let tempOutput = <span class="cstat-no" title="statement not covered" >{ items: loopSteps, iterations: iterationCount }</span>
813
+ <span class="cstat-no" title="statement not covered" > if (</span>
814
+ (loopStep.inputs.option === "Array" &amp;&amp;
815
+ !Array.isArray(newInput.binding)) ||
816
+ (loopStep.inputs.option === "String" &amp;&amp;
817
+ typeof newInput.binding !== "string")
818
+ ) {
819
+ <span class="cstat-no" title="statement not covered" > this.updateContextAndOutput(loopStepNumber, step, tempOutput, {</span>
820
+ status: AutomationErrors.INCORRECT_TYPE,
821
+ success: false,
822
+ })
823
+ <span class="cstat-no" title="statement not covered" > loopSteps = null</span>
824
+ <span class="cstat-no" title="statement not covered" > loopStep = null</span>
825
+ <span class="cstat-no" title="statement not covered" > break</span>
826
+ }
827
+ &nbsp;
828
+ // The "Loop" binding in the front end is "fake", so replace it here so the context can understand it
829
+ // Pretty hacky because we need to account for the row object
830
+ <span class="cstat-no" title="statement not covered" > for (let [key, value] of Object.entries(originalStepInput)) {</span>
831
+ <span class="cstat-no" title="statement not covered" > if (typeof value === "object") {</span>
832
+ <span class="cstat-no" title="statement not covered" > for (let [innerKey, innerValue] of Object.entries(</span>
833
+ originalStepInput[key]
834
+ )) {
835
+ <span class="cstat-no" title="statement not covered" > if (typeof innerValue === "string") {</span>
836
+ <span class="cstat-no" title="statement not covered" > originalStepInput[key][innerKey] =</span>
837
+ automationUtils.substituteLoopStep(
838
+ innerValue,
839
+ `steps.${loopStepNumber}`
840
+ )
841
+ }
842
+ }
843
+ } else {
844
+ <span class="cstat-no" title="statement not covered" > if (typeof value === "string") {</span>
845
+ <span class="cstat-no" title="statement not covered" > originalStepInput[key] = automationUtils.substituteLoopStep(</span>
846
+ value,
847
+ `steps.${loopStepNumber}`
848
+ )
849
+ }
850
+ }
851
+ }
852
+ &nbsp;
853
+ <span class="cstat-no" title="statement not covered" > if (</span>
854
+ index === parseInt(env.AUTOMATION_MAX_ITERATIONS) ||
855
+ index === loopStep.inputs.iterations
856
+ ) {
857
+ <span class="cstat-no" title="statement not covered" > this.updateContextAndOutput(loopStepNumber, step, tempOutput, {</span>
858
+ status: AutomationErrors.MAX_ITERATIONS,
859
+ success: true,
860
+ })
861
+ <span class="cstat-no" title="statement not covered" > loopSteps = null</span>
862
+ <span class="cstat-no" title="statement not covered" > loopStep = null</span>
863
+ <span class="cstat-no" title="statement not covered" > break</span>
864
+ }
865
+ &nbsp;
866
+ <span class="cstat-no" title="statement not covered" > if (</span>
867
+ this._context.steps[loopStepNumber]?.currentItem ===
868
+ loopStep.inputs.failure
869
+ ) {
870
+ <span class="cstat-no" title="statement not covered" > this.updateContextAndOutput(loopStepNumber, step, tempOutput, {</span>
871
+ status: AutomationErrors.FAILURE_CONDITION,
872
+ success: false,
873
+ })
874
+ <span class="cstat-no" title="statement not covered" > loopSteps = null</span>
875
+ <span class="cstat-no" title="statement not covered" > loopStep = null</span>
876
+ <span class="cstat-no" title="statement not covered" > break</span>
877
+ }
878
+ }
879
+ &nbsp;
880
+ // execution stopped, record state for that
881
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (stopped) {
882
+ <span class="cstat-no" title="statement not covered" > this.updateExecutionOutput(step.id, step.stepId, {}, STOPPED_STATUS)</span>
454
883
  <span class="cstat-no" title="statement not covered" > continue</span>
455
884
  }
456
- this.updateExecutionOutput(step.id, step.stepId, step.inputs, outputs)
457
- } catch (err) {
458
- <span class="cstat-no" title="statement not covered" > console.error(`Automation error - ${step.stepId} - ${err}`)</span>
459
- <span class="cstat-no" title="statement not covered" > return err</span>
885
+ &nbsp;
886
+ // If it's a loop step, we need to manually add the bindings to the context
887
+ let stepFn = await this.getStepFunctionality(step.stepId)
888
+ let inputs = await processObject(originalStepInput, this._context)
889
+ inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs)
890
+ try {
891
+ // appId is always passed
892
+ let tenantId = app.tenantId || <span class="branch-1 cbranch-no" title="branch not covered" >DEFAULT_TENANT_ID</span>
893
+ const outputs = await doInTenant(tenantId, () =&gt; {
894
+ return stepFn({
895
+ inputs: inputs,
896
+ appId: this._appId,
897
+ emitter: this._emitter,
898
+ context: this._context,
899
+ })
900
+ })
901
+ this._context.steps[stepCount] = outputs
902
+ // if filter causes us to stop execution don't break the loop, set a var
903
+ // so that we can finish iterating through the steps and record that it stopped
904
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (step.stepId === FILTER_STEP_ID &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >!outputs.success)</span> {
905
+ <span class="cstat-no" title="statement not covered" > stopped = true</span>
906
+ <span class="cstat-no" title="statement not covered" > this.updateExecutionOutput(step.id, step.stepId, step.inputs, {</span>
907
+ ...outputs,
908
+ ...STOPPED_STATUS,
909
+ })
910
+ <span class="cstat-no" title="statement not covered" > continue</span>
911
+ }
912
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (loopStep &amp;&amp; <span class="branch-1 cbranch-no" title="branch not covered" >loopSteps)</span> {
913
+ <span class="cstat-no" title="statement not covered" > loopSteps.push(outputs)</span>
914
+ } else {
915
+ this.updateExecutionOutput(
916
+ step.id,
917
+ step.stepId,
918
+ step.inputs,
919
+ outputs
920
+ )
921
+ }
922
+ } catch (err) {
923
+ <span class="cstat-no" title="statement not covered" > console.error(`Automation error - ${step.stepId} - ${err}`)</span>
924
+ <span class="cstat-no" title="statement not covered" > return err</span>
925
+ }
926
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (loopStep) {
927
+ <span class="cstat-no" title="statement not covered" > iterationCount++</span>
928
+ <span class="cstat-no" title="statement not covered" > if (index === iterations - 1) {</span>
929
+ <span class="cstat-no" title="statement not covered" > loopStep = null</span>
930
+ <span class="cstat-no" title="statement not covered" > this._context.steps.splice(loopStepNumber, 1)</span>
931
+ <span class="cstat-no" title="statement not covered" > break</span>
932
+ }
933
+ }
934
+ }
935
+ &nbsp;
936
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (loopSteps &amp;&amp; loopSteps.length) {
937
+ let tempOutput = <span class="cstat-no" title="statement not covered" >{</span>
938
+ success: true,
939
+ items: loopSteps,
940
+ iterations: iterationCount,
941
+ }
942
+ <span class="cstat-no" title="statement not covered" > this.executionOutput.steps.splice(loopStepNumber + 1, 0, {</span>
943
+ id: step.id,
944
+ stepId: step.stepId,
945
+ outputs: tempOutput,
946
+ inputs: step.inputs,
947
+ })
948
+ &nbsp;
949
+ <span class="cstat-no" title="statement not covered" > this._context.steps.splice(loopStepNumber, 0, tempOutput)</span>
950
+ <span class="cstat-no" title="statement not covered" > loopSteps = null</span>
460
951
  }
461
952
  }
953
+ &nbsp;
462
954
  return this.executionOutput
463
955
  }
464
956
  }
@@ -486,10 +978,9 @@ module.exports = (input, callback) =&gt; {
486
978
  </div><!-- /wrapper -->
487
979
  <div class='footer quiet pad2 space-top1 center small'>
488
980
  Code coverage generated by
489
- <a href="https://istanbul.js.org/" target="_blank">istanbul</a>
490
- at Tue Apr 26 2022 17:11:02 GMT+0000 (Coordinated Universal Time)
981
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
982
+ at Wed Apr 27 2022 09:28:42 GMT+0000 (Coordinated Universal Time)
491
983
  </div>
492
- </div>
493
984
  <script src="../prettify.js"></script>
494
985
  <script>
495
986
  window.onload = function () {