velocious 1.0.429 → 1.0.431

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 (812) hide show
  1. package/bin/velocious.js +48 -0
  2. package/build/bin/velocious.js +39 -34
  3. package/build/index.js +1 -2
  4. package/build/src/application.js +214 -187
  5. package/build/src/authorization/ability.d.ts +24 -23
  6. package/build/src/authorization/ability.d.ts.map +1 -1
  7. package/build/src/authorization/ability.js +300 -252
  8. package/build/src/authorization/base-resource.d.ts +20 -26
  9. package/build/src/authorization/base-resource.d.ts.map +1 -1
  10. package/build/src/authorization/base-resource.js +136 -118
  11. package/build/src/background-jobs/client.js +47 -43
  12. package/build/src/background-jobs/cron-expression.js +166 -127
  13. package/build/src/background-jobs/forked-runner-child.js +47 -37
  14. package/build/src/background-jobs/job-record.js +10 -8
  15. package/build/src/background-jobs/job-registry.js +84 -72
  16. package/build/src/background-jobs/job-runner.js +81 -74
  17. package/build/src/background-jobs/job.js +72 -62
  18. package/build/src/background-jobs/json-socket.js +70 -65
  19. package/build/src/background-jobs/main.js +900 -841
  20. package/build/src/background-jobs/normalize-error.js +11 -12
  21. package/build/src/background-jobs/scheduler.js +247 -205
  22. package/build/src/background-jobs/socket-request.js +65 -60
  23. package/build/src/background-jobs/status-reporter.js +96 -86
  24. package/build/src/background-jobs/store.js +980 -862
  25. package/build/src/background-jobs/types.js +3 -2
  26. package/build/src/background-jobs/web/authorization.js +50 -38
  27. package/build/src/background-jobs/web/controller.js +268 -232
  28. package/build/src/background-jobs/web/index.js +40 -36
  29. package/build/src/background-jobs/web/path-matcher.js +48 -45
  30. package/build/src/background-jobs/web/registry.js +14 -9
  31. package/build/src/background-jobs/worker.js +639 -585
  32. package/build/src/beacon/client.js +293 -264
  33. package/build/src/beacon/in-process-broker.js +25 -20
  34. package/build/src/beacon/in-process-client.js +116 -104
  35. package/build/src/beacon/server.js +126 -110
  36. package/build/src/beacon/types.js +8 -2
  37. package/build/src/cli/base-command.js +57 -49
  38. package/build/src/cli/browser-cli.js +42 -37
  39. package/build/src/cli/commands/background-jobs-main.js +5 -5
  40. package/build/src/cli/commands/background-jobs-runner.js +5 -5
  41. package/build/src/cli/commands/background-jobs-worker.js +5 -5
  42. package/build/src/cli/commands/beacon.js +5 -5
  43. package/build/src/cli/commands/console.js +10 -10
  44. package/build/src/cli/commands/db/base-command.js +76 -71
  45. package/build/src/cli/commands/db/create.js +61 -53
  46. package/build/src/cli/commands/db/drop.js +71 -62
  47. package/build/src/cli/commands/db/migrate.js +15 -13
  48. package/build/src/cli/commands/db/reset.js +19 -16
  49. package/build/src/cli/commands/db/rollback.js +13 -12
  50. package/build/src/cli/commands/db/schema/dump.js +9 -9
  51. package/build/src/cli/commands/db/schema/load.js +9 -9
  52. package/build/src/cli/commands/db/seed.js +9 -9
  53. package/build/src/cli/commands/db/tenants/check.js +35 -32
  54. package/build/src/cli/commands/db/tenants/create.js +29 -26
  55. package/build/src/cli/commands/db/tenants/migrate.js +44 -40
  56. package/build/src/cli/commands/destroy/migration.js +5 -5
  57. package/build/src/cli/commands/generate/base-models.js +5 -5
  58. package/build/src/cli/commands/generate/frontend-models.js +9 -9
  59. package/build/src/cli/commands/generate/migration.js +5 -5
  60. package/build/src/cli/commands/generate/model.js +5 -5
  61. package/build/src/cli/commands/init.js +9 -7
  62. package/build/src/cli/commands/routes.js +6 -6
  63. package/build/src/cli/commands/run-script.js +9 -9
  64. package/build/src/cli/commands/runner.js +9 -9
  65. package/build/src/cli/commands/server.js +6 -6
  66. package/build/src/cli/commands/test.js +7 -6
  67. package/build/src/cli/index.js +141 -127
  68. package/build/src/cli/tenant-database-command-helper.js +185 -154
  69. package/build/src/cli/use-browser-cli.js +20 -15
  70. package/build/src/configuration-resolver.js +54 -47
  71. package/build/src/configuration-types.d.ts +21 -2
  72. package/build/src/configuration-types.d.ts.map +1 -1
  73. package/build/src/configuration-types.js +60 -3
  74. package/build/src/configuration.js +2547 -2240
  75. package/build/src/controller.js +407 -363
  76. package/build/src/current-configuration.js +12 -9
  77. package/build/src/current.js +75 -70
  78. package/build/src/database/annotations-async-hooks.js +22 -16
  79. package/build/src/database/annotations.js +18 -12
  80. package/build/src/database/drivers/base-column.js +179 -155
  81. package/build/src/database/drivers/base-columns-index.js +78 -69
  82. package/build/src/database/drivers/base-foreign-key.js +101 -89
  83. package/build/src/database/drivers/base-table.js +149 -124
  84. package/build/src/database/drivers/base.js +1489 -1306
  85. package/build/src/database/drivers/mssql/column.js +50 -39
  86. package/build/src/database/drivers/mssql/columns-index.js +3 -2
  87. package/build/src/database/drivers/mssql/connect-connection.js +9 -11
  88. package/build/src/database/drivers/mssql/foreign-key.js +9 -8
  89. package/build/src/database/drivers/mssql/index.js +587 -507
  90. package/build/src/database/drivers/mssql/options.js +75 -68
  91. package/build/src/database/drivers/mssql/query-parser.js +3 -2
  92. package/build/src/database/drivers/mssql/sql/alter-table.js +2 -2
  93. package/build/src/database/drivers/mssql/sql/create-database.js +31 -24
  94. package/build/src/database/drivers/mssql/sql/create-index.js +2 -2
  95. package/build/src/database/drivers/mssql/sql/create-table.js +2 -2
  96. package/build/src/database/drivers/mssql/sql/delete.js +16 -14
  97. package/build/src/database/drivers/mssql/sql/drop-database.js +31 -24
  98. package/build/src/database/drivers/mssql/sql/drop-table.js +2 -2
  99. package/build/src/database/drivers/mssql/sql/insert.js +2 -2
  100. package/build/src/database/drivers/mssql/sql/update.js +28 -24
  101. package/build/src/database/drivers/mssql/sql/upsert.js +20 -18
  102. package/build/src/database/drivers/mssql/structure-sql.js +114 -102
  103. package/build/src/database/drivers/mssql/table.js +96 -81
  104. package/build/src/database/drivers/mysql/column.js +92 -75
  105. package/build/src/database/drivers/mysql/columns-index.js +19 -16
  106. package/build/src/database/drivers/mysql/foreign-key.js +9 -8
  107. package/build/src/database/drivers/mysql/index.js +457 -396
  108. package/build/src/database/drivers/mysql/options.js +30 -26
  109. package/build/src/database/drivers/mysql/query-parser.js +3 -2
  110. package/build/src/database/drivers/mysql/query.js +29 -26
  111. package/build/src/database/drivers/mysql/sql/alter-table.js +3 -2
  112. package/build/src/database/drivers/mysql/sql/create-database.js +28 -23
  113. package/build/src/database/drivers/mysql/sql/create-index.js +3 -2
  114. package/build/src/database/drivers/mysql/sql/create-table.js +3 -2
  115. package/build/src/database/drivers/mysql/sql/delete.js +17 -14
  116. package/build/src/database/drivers/mysql/sql/drop-database.js +3 -2
  117. package/build/src/database/drivers/mysql/sql/drop-table.js +3 -2
  118. package/build/src/database/drivers/mysql/sql/insert.js +3 -2
  119. package/build/src/database/drivers/mysql/sql/update.js +29 -24
  120. package/build/src/database/drivers/mysql/sql/upsert.js +10 -8
  121. package/build/src/database/drivers/mysql/structure-sql.js +88 -79
  122. package/build/src/database/drivers/mysql/table.js +98 -83
  123. package/build/src/database/drivers/pgsql/column.js +72 -56
  124. package/build/src/database/drivers/pgsql/columns-index.js +3 -2
  125. package/build/src/database/drivers/pgsql/foreign-key.js +9 -8
  126. package/build/src/database/drivers/pgsql/index.js +438 -377
  127. package/build/src/database/drivers/pgsql/options.js +28 -25
  128. package/build/src/database/drivers/pgsql/query-parser.js +3 -2
  129. package/build/src/database/drivers/pgsql/sql/alter-table.js +3 -2
  130. package/build/src/database/drivers/pgsql/sql/create-database.js +23 -19
  131. package/build/src/database/drivers/pgsql/sql/create-index.js +3 -2
  132. package/build/src/database/drivers/pgsql/sql/create-table.js +3 -2
  133. package/build/src/database/drivers/pgsql/sql/delete.js +17 -14
  134. package/build/src/database/drivers/pgsql/sql/drop-database.js +3 -2
  135. package/build/src/database/drivers/pgsql/sql/drop-table.js +3 -2
  136. package/build/src/database/drivers/pgsql/sql/insert.js +3 -2
  137. package/build/src/database/drivers/pgsql/sql/update.js +29 -24
  138. package/build/src/database/drivers/pgsql/sql/upsert.js +11 -9
  139. package/build/src/database/drivers/pgsql/structure-sql.js +120 -108
  140. package/build/src/database/drivers/pgsql/table.js +77 -60
  141. package/build/src/database/drivers/sqlite/base.js +478 -405
  142. package/build/src/database/drivers/sqlite/column.js +69 -54
  143. package/build/src/database/drivers/sqlite/columns-index.js +27 -22
  144. package/build/src/database/drivers/sqlite/connection-sql-js.js +42 -35
  145. package/build/src/database/drivers/sqlite/foreign-key.js +21 -18
  146. package/build/src/database/drivers/sqlite/index.js +373 -330
  147. package/build/src/database/drivers/sqlite/index.native.js +64 -55
  148. package/build/src/database/drivers/sqlite/index.web.js +87 -69
  149. package/build/src/database/drivers/sqlite/options.js +28 -25
  150. package/build/src/database/drivers/sqlite/query-parser.js +3 -2
  151. package/build/src/database/drivers/sqlite/query.js +24 -21
  152. package/build/src/database/drivers/sqlite/query.native.js +25 -20
  153. package/build/src/database/drivers/sqlite/query.web.js +37 -30
  154. package/build/src/database/drivers/sqlite/sql/alter-table.js +179 -159
  155. package/build/src/database/drivers/sqlite/sql/create-index.js +3 -2
  156. package/build/src/database/drivers/sqlite/sql/create-table.js +3 -2
  157. package/build/src/database/drivers/sqlite/sql/delete.js +22 -17
  158. package/build/src/database/drivers/sqlite/sql/drop-table.js +3 -2
  159. package/build/src/database/drivers/sqlite/sql/insert.js +3 -2
  160. package/build/src/database/drivers/sqlite/sql/update.js +29 -24
  161. package/build/src/database/drivers/sqlite/sql/upsert.js +11 -9
  162. package/build/src/database/drivers/sqlite/structure-sql.js +52 -49
  163. package/build/src/database/drivers/sqlite/table-rebuilder.js +75 -62
  164. package/build/src/database/drivers/sqlite/table.js +125 -102
  165. package/build/src/database/drivers/structure-sql/utils.js +17 -14
  166. package/build/src/database/handler.js +10 -9
  167. package/build/src/database/initializer-from-require-context.js +87 -76
  168. package/build/src/database/migration/index.js +395 -332
  169. package/build/src/database/migrator/files-finder.js +50 -40
  170. package/build/src/database/migrator/types.js +30 -2
  171. package/build/src/database/migrator.js +526 -454
  172. package/build/src/database/pool/async-tracked-multi-connection.js +1147 -997
  173. package/build/src/database/pool/base-methods-forward.js +43 -40
  174. package/build/src/database/pool/base.js +343 -298
  175. package/build/src/database/pool/single-multi-use.js +110 -93
  176. package/build/src/database/query/alter-table-base.js +99 -84
  177. package/build/src/database/query/base.js +46 -39
  178. package/build/src/database/query/create-database-base.js +30 -25
  179. package/build/src/database/query/create-index-base.js +94 -75
  180. package/build/src/database/query/create-table-base.js +193 -151
  181. package/build/src/database/query/delete-base.js +16 -14
  182. package/build/src/database/query/drop-database-base.js +28 -23
  183. package/build/src/database/query/drop-table-base.js +53 -42
  184. package/build/src/database/query/from-base.js +33 -30
  185. package/build/src/database/query/from-plain.js +13 -11
  186. package/build/src/database/query/from-table.js +15 -13
  187. package/build/src/database/query/index.js +472 -410
  188. package/build/src/database/query/insert-base.js +164 -143
  189. package/build/src/database/query/join-base.js +40 -35
  190. package/build/src/database/query/join-object.js +153 -128
  191. package/build/src/database/query/join-plain.js +15 -13
  192. package/build/src/database/query/join-tracker.js +90 -76
  193. package/build/src/database/query/model-class-query.js +1370 -1134
  194. package/build/src/database/query/order-base.js +30 -27
  195. package/build/src/database/query/order-column.js +53 -44
  196. package/build/src/database/query/order-plain.js +24 -20
  197. package/build/src/database/query/preloader/belongs-to.js +258 -210
  198. package/build/src/database/query/preloader/ensure-model-class-initialized.js +9 -8
  199. package/build/src/database/query/preloader/has-many.js +301 -240
  200. package/build/src/database/query/preloader/has-one.js +117 -91
  201. package/build/src/database/query/preloader/selection.js +129 -117
  202. package/build/src/database/query/preloader.js +185 -160
  203. package/build/src/database/query/query-data.js +201 -157
  204. package/build/src/database/query/select-base.js +27 -25
  205. package/build/src/database/query/select-plain.js +15 -13
  206. package/build/src/database/query/select-table-and-column.js +25 -21
  207. package/build/src/database/query/update-base.js +38 -35
  208. package/build/src/database/query/upsert-base.js +100 -93
  209. package/build/src/database/query/where-base.js +35 -32
  210. package/build/src/database/query/where-combinator.d.ts.map +1 -1
  211. package/build/src/database/query/where-combinator.js +28 -26
  212. package/build/src/database/query/where-hash.js +68 -61
  213. package/build/src/database/query/where-model-class-hash.js +469 -414
  214. package/build/src/database/query/where-not.js +20 -18
  215. package/build/src/database/query/where-plain.js +17 -15
  216. package/build/src/database/query/with-count.js +159 -125
  217. package/build/src/database/query-parser/base-query-parser.js +37 -32
  218. package/build/src/database/query-parser/from-parser.js +45 -36
  219. package/build/src/database/query-parser/group-parser.js +50 -42
  220. package/build/src/database/query-parser/joins-parser.js +33 -28
  221. package/build/src/database/query-parser/limit-parser.js +70 -67
  222. package/build/src/database/query-parser/options.js +82 -75
  223. package/build/src/database/query-parser/order-parser.js +40 -36
  224. package/build/src/database/query-parser/select-parser.js +60 -49
  225. package/build/src/database/query-parser/where-parser.js +41 -36
  226. package/build/src/database/record/acts-as-list.d.ts.map +1 -1
  227. package/build/src/database/record/acts-as-list.js +273 -229
  228. package/build/src/database/record/attachments/download.js +45 -44
  229. package/build/src/database/record/attachments/handle.js +161 -141
  230. package/build/src/database/record/attachments/normalize-input.js +138 -128
  231. package/build/src/database/record/attachments/storage-drivers/filesystem.js +91 -77
  232. package/build/src/database/record/attachments/storage-drivers/native.js +121 -112
  233. package/build/src/database/record/attachments/storage-drivers/s3.js +208 -177
  234. package/build/src/database/record/attachments/store.d.ts +1 -1
  235. package/build/src/database/record/attachments/store.d.ts.map +1 -1
  236. package/build/src/database/record/attachments/store.js +540 -468
  237. package/build/src/database/record/index.d.ts +23 -15
  238. package/build/src/database/record/index.d.ts.map +1 -1
  239. package/build/src/database/record/index.js +3894 -3350
  240. package/build/src/database/record/instance-relationships/base.js +268 -234
  241. package/build/src/database/record/instance-relationships/belongs-to.js +73 -58
  242. package/build/src/database/record/instance-relationships/has-many.js +264 -225
  243. package/build/src/database/record/instance-relationships/has-one.js +105 -85
  244. package/build/src/database/record/record-not-found-error.js +2 -3
  245. package/build/src/database/record/relationships/base.d.ts +2 -2
  246. package/build/src/database/record/relationships/base.d.ts.map +1 -1
  247. package/build/src/database/record/relationships/base.js +167 -145
  248. package/build/src/database/record/relationships/belongs-to.js +51 -44
  249. package/build/src/database/record/relationships/has-many.js +40 -32
  250. package/build/src/database/record/relationships/has-one.js +40 -32
  251. package/build/src/database/record/state-machine.js +208 -156
  252. package/build/src/database/record/user-module.js +38 -32
  253. package/build/src/database/record/validators/base.js +24 -22
  254. package/build/src/database/record/validators/format.js +46 -36
  255. package/build/src/database/record/validators/presence.js +20 -18
  256. package/build/src/database/record/validators/uniqueness.js +117 -99
  257. package/build/src/database/table-data/index.js +231 -199
  258. package/build/src/database/table-data/table-column.js +382 -338
  259. package/build/src/database/table-data/table-foreign-key.js +66 -57
  260. package/build/src/database/table-data/table-index.js +36 -29
  261. package/build/src/database/table-data/table-reference.js +10 -10
  262. package/build/src/database/use-database.js +40 -32
  263. package/build/src/environment-handlers/base.js +544 -484
  264. package/build/src/environment-handlers/browser.js +294 -241
  265. package/build/src/environment-handlers/node/cli/commands/background-jobs-main.js +19 -16
  266. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.js +21 -18
  267. package/build/src/environment-handlers/node/cli/commands/background-jobs-worker.js +29 -22
  268. package/build/src/environment-handlers/node/cli/commands/beacon.js +19 -16
  269. package/build/src/environment-handlers/node/cli/commands/cli-command-context.js +15 -14
  270. package/build/src/environment-handlers/node/cli/commands/console.js +120 -99
  271. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.js +39 -34
  272. package/build/src/environment-handlers/node/cli/commands/db/schema/load.js +63 -57
  273. package/build/src/environment-handlers/node/cli/commands/db/seed.js +63 -51
  274. package/build/src/environment-handlers/node/cli/commands/destroy/migration.js +40 -32
  275. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
  276. package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +353 -298
  277. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +844 -729
  278. package/build/src/environment-handlers/node/cli/commands/generate/migration.js +38 -34
  279. package/build/src/environment-handlers/node/cli/commands/generate/model.js +38 -34
  280. package/build/src/environment-handlers/node/cli/commands/init.js +61 -56
  281. package/build/src/environment-handlers/node/cli/commands/routes.js +59 -51
  282. package/build/src/environment-handlers/node/cli/commands/run-script.js +68 -54
  283. package/build/src/environment-handlers/node/cli/commands/runner.js +74 -56
  284. package/build/src/environment-handlers/node/cli/commands/server.js +106 -93
  285. package/build/src/environment-handlers/node/cli/commands/test.js +113 -97
  286. package/build/src/environment-handlers/node.js +874 -753
  287. package/build/src/error-logger.js +21 -22
  288. package/build/src/frontend-model-controller.d.ts +6 -6
  289. package/build/src/frontend-model-controller.d.ts.map +1 -1
  290. package/build/src/frontend-model-controller.js +3288 -2788
  291. package/build/src/frontend-model-resource/base-resource.d.ts +18 -17
  292. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  293. package/build/src/frontend-model-resource/base-resource.js +869 -759
  294. package/build/src/frontend-models/base.d.ts +19 -12
  295. package/build/src/frontend-models/base.d.ts.map +1 -1
  296. package/build/src/frontend-models/base.js +3602 -3114
  297. package/build/src/frontend-models/clear-pending-debounced-callback.js +8 -7
  298. package/build/src/frontend-models/event-hook-models.js +21 -16
  299. package/build/src/frontend-models/model-registry.js +11 -9
  300. package/build/src/frontend-models/outgoing-event-buffer.js +17 -10
  301. package/build/src/frontend-models/preloader.d.ts +6 -6
  302. package/build/src/frontend-models/preloader.d.ts.map +1 -1
  303. package/build/src/frontend-models/preloader.js +149 -131
  304. package/build/src/frontend-models/query.d.ts.map +1 -1
  305. package/build/src/frontend-models/query.js +1855 -1560
  306. package/build/src/frontend-models/resource-config-validation.js +37 -27
  307. package/build/src/frontend-models/resource-definition.js +288 -234
  308. package/build/src/frontend-models/transport-serialization.js +266 -203
  309. package/build/src/frontend-models/use-created-event.js +7 -5
  310. package/build/src/frontend-models/use-destroyed-event.js +93 -80
  311. package/build/src/frontend-models/use-model-class-event.js +91 -79
  312. package/build/src/frontend-models/use-updated-event.js +97 -84
  313. package/build/src/frontend-models/websocket-channel.js +441 -381
  314. package/build/src/frontend-models/websocket-publishers.js +173 -140
  315. package/build/src/http-client/header.js +14 -13
  316. package/build/src/http-client/index.js +132 -116
  317. package/build/src/http-client/request.js +87 -71
  318. package/build/src/http-client/response.js +140 -122
  319. package/build/src/http-client/websocket-client.js +17 -15
  320. package/build/src/http-server/client/index.js +465 -409
  321. package/build/src/http-server/client/params-to-object.js +135 -124
  322. package/build/src/http-server/client/request-buffer/form-data-part.js +132 -111
  323. package/build/src/http-server/client/request-buffer/header.js +16 -15
  324. package/build/src/http-server/client/request-buffer/index.js +506 -446
  325. package/build/src/http-server/client/request-parser.js +186 -163
  326. package/build/src/http-server/client/request-runner.js +259 -226
  327. package/build/src/http-server/client/request-timing.js +151 -132
  328. package/build/src/http-server/client/request.js +108 -96
  329. package/build/src/http-server/client/response.js +235 -213
  330. package/build/src/http-server/client/uploaded-file/memory-uploaded-file.js +29 -25
  331. package/build/src/http-server/client/uploaded-file/temporary-uploaded-file.js +29 -25
  332. package/build/src/http-server/client/uploaded-file/uploaded-file.js +33 -33
  333. package/build/src/http-server/client/websocket-request.js +137 -114
  334. package/build/src/http-server/client/websocket-session.js +1657 -1452
  335. package/build/src/http-server/cookie.js +236 -216
  336. package/build/src/http-server/development-reloader.js +221 -190
  337. package/build/src/http-server/index.js +525 -451
  338. package/build/src/http-server/remote-address.js +50 -38
  339. package/build/src/http-server/server-client.js +208 -181
  340. package/build/src/http-server/server-lock.js +167 -153
  341. package/build/src/http-server/websocket-channel-subscribers.js +93 -81
  342. package/build/src/http-server/websocket-channel.js +117 -104
  343. package/build/src/http-server/websocket-connection.js +104 -96
  344. package/build/src/http-server/websocket-event-log-store.js +404 -350
  345. package/build/src/http-server/websocket-events-host.js +164 -145
  346. package/build/src/http-server/websocket-events.js +47 -47
  347. package/build/src/http-server/worker-handler/channel-subscriber-dispatch.js +14 -13
  348. package/build/src/http-server/worker-handler/in-process.js +141 -123
  349. package/build/src/http-server/worker-handler/index.js +349 -313
  350. package/build/src/http-server/worker-handler/worker-script.js +5 -4
  351. package/build/src/http-server/worker-handler/worker-thread.js +269 -240
  352. package/build/src/initializer.js +36 -31
  353. package/build/src/jobs/mail-delivery.js +15 -13
  354. package/build/src/logger/base-logger.js +26 -24
  355. package/build/src/logger/console-logger.js +23 -21
  356. package/build/src/logger/file-logger.js +31 -29
  357. package/build/src/logger/outputs/array-output.js +42 -37
  358. package/build/src/logger/outputs/console-output.js +24 -20
  359. package/build/src/logger/outputs/file-output.js +48 -43
  360. package/build/src/logger/outputs/stdout-output.js +48 -39
  361. package/build/src/logger.js +394 -338
  362. package/build/src/mailer/backends/smtp.js +163 -134
  363. package/build/src/mailer/base.js +251 -211
  364. package/build/src/mailer/delivery.js +64 -56
  365. package/build/src/mailer/index.js +22 -4
  366. package/build/src/mailer.js +13 -4
  367. package/build/src/plugins/sqljs-wasm-route-controller.js +52 -42
  368. package/build/src/plugins/sqljs-wasm-route.js +38 -28
  369. package/build/src/record-payload-values.js +28 -25
  370. package/build/src/routes/app-routes.js +14 -12
  371. package/build/src/routes/base-route.js +130 -112
  372. package/build/src/routes/basic-route.js +102 -83
  373. package/build/src/routes/built-in/debug/controller.js +10 -10
  374. package/build/src/routes/built-in/errors/controller.js +5 -5
  375. package/build/src/routes/get-route.js +63 -50
  376. package/build/src/routes/hooks/frontend-model-command-route-hook.js +80 -66
  377. package/build/src/routes/index.js +43 -36
  378. package/build/src/routes/namespace-route.js +47 -38
  379. package/build/src/routes/plugin-routes.js +124 -107
  380. package/build/src/routes/post-route.js +62 -51
  381. package/build/src/routes/resolver.js +494 -422
  382. package/build/src/routes/resource-route.js +143 -124
  383. package/build/src/routes/root-route.js +8 -7
  384. package/build/src/testing/base-expect.js +14 -13
  385. package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +405 -329
  386. package/build/src/testing/browser-test-app.js +29 -23
  387. package/build/src/testing/expect-to-change.js +50 -41
  388. package/build/src/testing/expect-utils.js +184 -139
  389. package/build/src/testing/expect.js +731 -638
  390. package/build/src/testing/request-client.js +85 -70
  391. package/build/src/testing/test-files-finder.js +339 -285
  392. package/build/src/testing/test-filter-parser.js +155 -124
  393. package/build/src/testing/test-runner.js +1020 -883
  394. package/build/src/testing/test-suite-splitter.js +142 -114
  395. package/build/src/testing/test.js +256 -216
  396. package/build/src/utils/backtrace-cleaner-node.js +69 -62
  397. package/build/src/utils/backtrace-cleaner.js +216 -188
  398. package/build/src/utils/ensure-error.js +7 -7
  399. package/build/src/utils/event-emitter.js +6 -4
  400. package/build/src/utils/file-exists.js +10 -9
  401. package/build/src/utils/format-value.js +76 -67
  402. package/build/src/utils/model-scope.js +31 -27
  403. package/build/src/utils/nest-callbacks.js +13 -10
  404. package/build/src/utils/plain-object.js +6 -5
  405. package/build/src/utils/ransack.d.ts.map +1 -1
  406. package/build/src/utils/ransack.js +563 -449
  407. package/build/src/utils/rest-args-error.js +6 -5
  408. package/build/src/utils/singularize-model-name.js +11 -9
  409. package/build/src/utils/split-sql-statements.js +79 -68
  410. package/build/src/utils/to-import-specifier.js +30 -24
  411. package/build/src/utils/with-tracked-stack-async-hooks.js +74 -60
  412. package/build/src/utils/with-tracked-stack.js +18 -14
  413. package/build/src/velocious-error.js +30 -27
  414. package/index.js +1 -0
  415. package/package.json +10 -4
  416. package/scripts/clean-build.js +8 -0
  417. package/scripts/ensure-bin-executable.js +13 -0
  418. package/scripts/run-tests.js +37 -0
  419. package/scripts/test-browser.js +486 -0
  420. package/src/application.js +229 -0
  421. package/src/authorization/ability.js +329 -0
  422. package/src/authorization/base-resource.js +143 -0
  423. package/src/background-jobs/client.js +50 -0
  424. package/src/background-jobs/cron-expression.js +277 -0
  425. package/src/background-jobs/forked-runner-child.js +86 -0
  426. package/src/background-jobs/job-record.js +13 -0
  427. package/src/background-jobs/job-registry.js +92 -0
  428. package/src/background-jobs/job-runner.js +107 -0
  429. package/src/background-jobs/job.js +77 -0
  430. package/src/background-jobs/json-socket.js +78 -0
  431. package/src/background-jobs/main.js +926 -0
  432. package/src/background-jobs/normalize-error.js +26 -0
  433. package/src/background-jobs/scheduler.js +274 -0
  434. package/src/background-jobs/socket-request.js +68 -0
  435. package/src/background-jobs/status-reporter.js +101 -0
  436. package/src/background-jobs/store.js +994 -0
  437. package/src/background-jobs/types.js +70 -0
  438. package/src/background-jobs/web/authorization.js +89 -0
  439. package/src/background-jobs/web/controller.js +280 -0
  440. package/src/background-jobs/web/index.js +57 -0
  441. package/src/background-jobs/web/path-matcher.js +74 -0
  442. package/src/background-jobs/web/registry.js +49 -0
  443. package/src/background-jobs/worker.js +683 -0
  444. package/src/beacon/client.js +330 -0
  445. package/src/beacon/in-process-broker.js +71 -0
  446. package/src/beacon/in-process-client.js +139 -0
  447. package/src/beacon/server.js +148 -0
  448. package/src/beacon/types.js +55 -0
  449. package/src/cli/base-command.js +67 -0
  450. package/src/cli/browser-cli.js +45 -0
  451. package/src/cli/commands/background-jobs-main.js +7 -0
  452. package/src/cli/commands/background-jobs-runner.js +7 -0
  453. package/src/cli/commands/background-jobs-worker.js +7 -0
  454. package/src/cli/commands/beacon.js +7 -0
  455. package/src/cli/commands/console.js +12 -0
  456. package/src/cli/commands/db/base-command.js +82 -0
  457. package/src/cli/commands/db/create.js +64 -0
  458. package/src/cli/commands/db/drop.js +75 -0
  459. package/src/cli/commands/db/migrate.js +17 -0
  460. package/src/cli/commands/db/reset.js +22 -0
  461. package/src/cli/commands/db/rollback.js +15 -0
  462. package/src/cli/commands/db/schema/dump.js +12 -0
  463. package/src/cli/commands/db/schema/load.js +12 -0
  464. package/src/cli/commands/db/seed.js +12 -0
  465. package/src/cli/commands/db/tenants/check.js +38 -0
  466. package/src/cli/commands/db/tenants/create.js +33 -0
  467. package/src/cli/commands/db/tenants/migrate.js +49 -0
  468. package/src/cli/commands/destroy/migration.js +7 -0
  469. package/src/cli/commands/generate/base-models.js +7 -0
  470. package/src/cli/commands/generate/frontend-models.js +12 -0
  471. package/src/cli/commands/generate/migration.js +7 -0
  472. package/src/cli/commands/generate/model.js +7 -0
  473. package/src/cli/commands/init.js +11 -0
  474. package/src/cli/commands/routes.js +7 -0
  475. package/src/cli/commands/run-script.js +12 -0
  476. package/src/cli/commands/runner.js +12 -0
  477. package/src/cli/commands/server.js +7 -0
  478. package/src/cli/commands/test.js +9 -0
  479. package/src/cli/index.js +152 -0
  480. package/src/cli/tenant-database-command-helper.js +198 -0
  481. package/src/cli/use-browser-cli.js +30 -0
  482. package/src/configuration-resolver.js +65 -0
  483. package/src/configuration-types.js +429 -0
  484. package/src/configuration.js +2590 -0
  485. package/src/controller.js +421 -0
  486. package/src/current-configuration.js +31 -0
  487. package/src/current.js +80 -0
  488. package/src/database/annotations-async-hooks.js +47 -0
  489. package/src/database/annotations.js +40 -0
  490. package/src/database/drivers/base-column.js +182 -0
  491. package/src/database/drivers/base-columns-index.js +81 -0
  492. package/src/database/drivers/base-foreign-key.js +104 -0
  493. package/src/database/drivers/base-table.js +156 -0
  494. package/src/database/drivers/base.js +1609 -0
  495. package/src/database/drivers/mssql/column.js +74 -0
  496. package/src/database/drivers/mssql/columns-index.js +6 -0
  497. package/src/database/drivers/mssql/connect-connection.js +16 -0
  498. package/src/database/drivers/mssql/foreign-key.js +12 -0
  499. package/src/database/drivers/mssql/index.js +590 -0
  500. package/src/database/drivers/mssql/options.js +79 -0
  501. package/src/database/drivers/mssql/query-parser.js +6 -0
  502. package/src/database/drivers/mssql/sql/alter-table.js +4 -0
  503. package/src/database/drivers/mssql/sql/create-database.js +36 -0
  504. package/src/database/drivers/mssql/sql/create-index.js +4 -0
  505. package/src/database/drivers/mssql/sql/create-table.js +4 -0
  506. package/src/database/drivers/mssql/sql/delete.js +19 -0
  507. package/src/database/drivers/mssql/sql/drop-database.js +36 -0
  508. package/src/database/drivers/mssql/sql/drop-table.js +4 -0
  509. package/src/database/drivers/mssql/sql/insert.js +4 -0
  510. package/src/database/drivers/mssql/sql/update.js +31 -0
  511. package/src/database/drivers/mssql/sql/upsert.js +23 -0
  512. package/src/database/drivers/mssql/structure-sql.js +120 -0
  513. package/src/database/drivers/mssql/table.js +145 -0
  514. package/src/database/drivers/mysql/column.js +112 -0
  515. package/src/database/drivers/mysql/columns-index.js +22 -0
  516. package/src/database/drivers/mysql/foreign-key.js +12 -0
  517. package/src/database/drivers/mysql/index.js +473 -0
  518. package/src/database/drivers/mysql/options.js +34 -0
  519. package/src/database/drivers/mysql/query-parser.js +6 -0
  520. package/src/database/drivers/mysql/query.js +37 -0
  521. package/src/database/drivers/mysql/sql/alter-table.js +6 -0
  522. package/src/database/drivers/mysql/sql/create-database.js +39 -0
  523. package/src/database/drivers/mysql/sql/create-index.js +6 -0
  524. package/src/database/drivers/mysql/sql/create-table.js +6 -0
  525. package/src/database/drivers/mysql/sql/delete.js +21 -0
  526. package/src/database/drivers/mysql/sql/drop-database.js +6 -0
  527. package/src/database/drivers/mysql/sql/drop-table.js +6 -0
  528. package/src/database/drivers/mysql/sql/insert.js +6 -0
  529. package/src/database/drivers/mysql/sql/update.js +33 -0
  530. package/src/database/drivers/mysql/sql/upsert.js +13 -0
  531. package/src/database/drivers/mysql/structure-sql.js +93 -0
  532. package/src/database/drivers/mysql/table.js +121 -0
  533. package/src/database/drivers/pgsql/column.js +90 -0
  534. package/src/database/drivers/pgsql/columns-index.js +6 -0
  535. package/src/database/drivers/pgsql/foreign-key.js +12 -0
  536. package/src/database/drivers/pgsql/index.js +441 -0
  537. package/src/database/drivers/pgsql/options.js +32 -0
  538. package/src/database/drivers/pgsql/query-parser.js +6 -0
  539. package/src/database/drivers/pgsql/sql/alter-table.js +6 -0
  540. package/src/database/drivers/pgsql/sql/create-database.js +38 -0
  541. package/src/database/drivers/pgsql/sql/create-index.js +6 -0
  542. package/src/database/drivers/pgsql/sql/create-table.js +6 -0
  543. package/src/database/drivers/pgsql/sql/delete.js +21 -0
  544. package/src/database/drivers/pgsql/sql/drop-database.js +6 -0
  545. package/src/database/drivers/pgsql/sql/drop-table.js +6 -0
  546. package/src/database/drivers/pgsql/sql/insert.js +6 -0
  547. package/src/database/drivers/pgsql/sql/update.js +33 -0
  548. package/src/database/drivers/pgsql/sql/upsert.js +14 -0
  549. package/src/database/drivers/pgsql/structure-sql.js +126 -0
  550. package/src/database/drivers/pgsql/table.js +135 -0
  551. package/src/database/drivers/sqlite/base.js +509 -0
  552. package/src/database/drivers/sqlite/column.js +75 -0
  553. package/src/database/drivers/sqlite/columns-index.js +30 -0
  554. package/src/database/drivers/sqlite/connection-sql-js.js +46 -0
  555. package/src/database/drivers/sqlite/foreign-key.js +24 -0
  556. package/src/database/drivers/sqlite/index.js +394 -0
  557. package/src/database/drivers/sqlite/index.native.js +72 -0
  558. package/src/database/drivers/sqlite/index.web.js +99 -0
  559. package/src/database/drivers/sqlite/options.js +32 -0
  560. package/src/database/drivers/sqlite/query-parser.js +6 -0
  561. package/src/database/drivers/sqlite/query.js +35 -0
  562. package/src/database/drivers/sqlite/query.native.js +35 -0
  563. package/src/database/drivers/sqlite/query.web.js +49 -0
  564. package/src/database/drivers/sqlite/sql/alter-table.js +187 -0
  565. package/src/database/drivers/sqlite/sql/create-index.js +6 -0
  566. package/src/database/drivers/sqlite/sql/create-table.js +6 -0
  567. package/src/database/drivers/sqlite/sql/delete.js +26 -0
  568. package/src/database/drivers/sqlite/sql/drop-table.js +6 -0
  569. package/src/database/drivers/sqlite/sql/insert.js +6 -0
  570. package/src/database/drivers/sqlite/sql/update.js +33 -0
  571. package/src/database/drivers/sqlite/sql/upsert.js +14 -0
  572. package/src/database/drivers/sqlite/structure-sql.js +56 -0
  573. package/src/database/drivers/sqlite/table-rebuilder.js +96 -0
  574. package/src/database/drivers/sqlite/table.js +131 -0
  575. package/src/database/drivers/structure-sql/utils.js +35 -0
  576. package/src/database/handler.js +13 -0
  577. package/src/database/initializer-from-require-context.js +101 -0
  578. package/src/database/migration/index.js +438 -0
  579. package/src/database/migrator/files-finder.js +55 -0
  580. package/src/database/migrator/types.js +31 -0
  581. package/src/database/migrator.js +557 -0
  582. package/src/database/pool/async-tracked-multi-connection.js +1164 -0
  583. package/src/database/pool/base-methods-forward.js +52 -0
  584. package/src/database/pool/base.js +380 -0
  585. package/src/database/pool/single-multi-use.js +118 -0
  586. package/src/database/query/alter-table-base.js +104 -0
  587. package/src/database/query/base.js +49 -0
  588. package/src/database/query/create-database-base.js +42 -0
  589. package/src/database/query/create-index-base.js +117 -0
  590. package/src/database/query/create-table-base.js +205 -0
  591. package/src/database/query/delete-base.js +19 -0
  592. package/src/database/query/drop-database-base.js +38 -0
  593. package/src/database/query/drop-table-base.js +58 -0
  594. package/src/database/query/from-base.js +36 -0
  595. package/src/database/query/from-plain.js +16 -0
  596. package/src/database/query/from-table.js +18 -0
  597. package/src/database/query/index.js +533 -0
  598. package/src/database/query/insert-base.js +172 -0
  599. package/src/database/query/join-base.js +43 -0
  600. package/src/database/query/join-object.js +167 -0
  601. package/src/database/query/join-plain.js +18 -0
  602. package/src/database/query/join-tracker.js +93 -0
  603. package/src/database/query/model-class-query.js +1577 -0
  604. package/src/database/query/order-base.js +33 -0
  605. package/src/database/query/order-column.js +77 -0
  606. package/src/database/query/order-plain.js +28 -0
  607. package/src/database/query/preloader/belongs-to.js +267 -0
  608. package/src/database/query/preloader/ensure-model-class-initialized.js +18 -0
  609. package/src/database/query/preloader/has-many.js +316 -0
  610. package/src/database/query/preloader/has-one.js +123 -0
  611. package/src/database/query/preloader/selection.js +152 -0
  612. package/src/database/query/preloader.js +201 -0
  613. package/src/database/query/query-data.js +305 -0
  614. package/src/database/query/select-base.js +30 -0
  615. package/src/database/query/select-plain.js +18 -0
  616. package/src/database/query/select-table-and-column.js +28 -0
  617. package/src/database/query/update-base.js +41 -0
  618. package/src/database/query/upsert-base.js +103 -0
  619. package/src/database/query/where-base.js +38 -0
  620. package/src/database/query/where-combinator.js +31 -0
  621. package/src/database/query/where-hash.js +77 -0
  622. package/src/database/query/where-model-class-hash.js +505 -0
  623. package/src/database/query/where-not.js +23 -0
  624. package/src/database/query/where-plain.js +20 -0
  625. package/src/database/query/with-count.js +219 -0
  626. package/src/database/query-parser/base-query-parser.js +40 -0
  627. package/src/database/query-parser/from-parser.js +49 -0
  628. package/src/database/query-parser/group-parser.js +55 -0
  629. package/src/database/query-parser/joins-parser.js +37 -0
  630. package/src/database/query-parser/limit-parser.js +77 -0
  631. package/src/database/query-parser/options.js +94 -0
  632. package/src/database/query-parser/order-parser.js +45 -0
  633. package/src/database/query-parser/select-parser.js +67 -0
  634. package/src/database/query-parser/where-parser.js +46 -0
  635. package/src/database/record/acts-as-list.js +374 -0
  636. package/src/database/record/attachments/download.js +49 -0
  637. package/src/database/record/attachments/handle.js +188 -0
  638. package/src/database/record/attachments/normalize-input.js +213 -0
  639. package/src/database/record/attachments/storage-drivers/filesystem.js +114 -0
  640. package/src/database/record/attachments/storage-drivers/native.js +146 -0
  641. package/src/database/record/attachments/storage-drivers/s3.js +245 -0
  642. package/src/database/record/attachments/store.js +591 -0
  643. package/src/database/record/index.js +3970 -0
  644. package/src/database/record/instance-relationships/base.js +289 -0
  645. package/src/database/record/instance-relationships/belongs-to.js +84 -0
  646. package/src/database/record/instance-relationships/has-many.js +284 -0
  647. package/src/database/record/instance-relationships/has-one.js +117 -0
  648. package/src/database/record/record-not-found-error.js +3 -0
  649. package/src/database/record/relationships/base.js +195 -0
  650. package/src/database/record/relationships/belongs-to.js +57 -0
  651. package/src/database/record/relationships/has-many.js +46 -0
  652. package/src/database/record/relationships/has-one.js +46 -0
  653. package/src/database/record/state-machine.js +278 -0
  654. package/src/database/record/user-module.js +43 -0
  655. package/src/database/record/validators/base.js +27 -0
  656. package/src/database/record/validators/format.js +50 -0
  657. package/src/database/record/validators/presence.js +24 -0
  658. package/src/database/record/validators/uniqueness.js +124 -0
  659. package/src/database/table-data/index.js +241 -0
  660. package/src/database/table-data/table-column.js +416 -0
  661. package/src/database/table-data/table-foreign-key.js +69 -0
  662. package/src/database/table-data/table-index.js +46 -0
  663. package/src/database/table-data/table-reference.js +13 -0
  664. package/src/database/use-database.js +48 -0
  665. package/src/environment-handlers/base.js +561 -0
  666. package/src/environment-handlers/browser.js +338 -0
  667. package/src/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
  668. package/src/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
  669. package/src/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
  670. package/src/environment-handlers/node/cli/commands/beacon.js +21 -0
  671. package/src/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
  672. package/src/environment-handlers/node/cli/commands/console.js +149 -0
  673. package/src/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
  674. package/src/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
  675. package/src/environment-handlers/node/cli/commands/db/seed.js +79 -0
  676. package/src/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
  677. package/src/environment-handlers/node/cli/commands/generate/base-models.js +367 -0
  678. package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
  679. package/src/environment-handlers/node/cli/commands/generate/migration.js +45 -0
  680. package/src/environment-handlers/node/cli/commands/generate/model.js +45 -0
  681. package/src/environment-handlers/node/cli/commands/init.js +68 -0
  682. package/src/environment-handlers/node/cli/commands/routes.js +63 -0
  683. package/src/environment-handlers/node/cli/commands/run-script.js +85 -0
  684. package/src/environment-handlers/node/cli/commands/runner.js +84 -0
  685. package/src/environment-handlers/node/cli/commands/server.js +151 -0
  686. package/src/environment-handlers/node/cli/commands/test.js +118 -0
  687. package/src/environment-handlers/node.js +887 -0
  688. package/src/error-logger.js +30 -0
  689. package/src/frontend-model-controller.js +3491 -0
  690. package/src/frontend-model-resource/base-resource.js +935 -0
  691. package/src/frontend-models/base.js +4004 -0
  692. package/src/frontend-models/clear-pending-debounced-callback.js +16 -0
  693. package/src/frontend-models/event-hook-models.js +49 -0
  694. package/src/frontend-models/model-registry.js +28 -0
  695. package/src/frontend-models/outgoing-event-buffer.js +51 -0
  696. package/src/frontend-models/preloader.js +169 -0
  697. package/src/frontend-models/query.js +2245 -0
  698. package/src/frontend-models/resource-config-validation.js +56 -0
  699. package/src/frontend-models/resource-definition.js +399 -0
  700. package/src/frontend-models/transport-serialization.js +369 -0
  701. package/src/frontend-models/use-created-event.js +21 -0
  702. package/src/frontend-models/use-destroyed-event.js +148 -0
  703. package/src/frontend-models/use-model-class-event.js +164 -0
  704. package/src/frontend-models/use-updated-event.js +152 -0
  705. package/src/frontend-models/websocket-channel.js +494 -0
  706. package/src/frontend-models/websocket-publishers.js +224 -0
  707. package/src/http-client/header.js +17 -0
  708. package/src/http-client/index.js +139 -0
  709. package/src/http-client/request.js +94 -0
  710. package/src/http-client/response.js +151 -0
  711. package/src/http-client/websocket-client.js +27 -0
  712. package/src/http-server/client/index.js +507 -0
  713. package/src/http-server/client/params-to-object.js +152 -0
  714. package/src/http-server/client/request-buffer/form-data-part.js +139 -0
  715. package/src/http-server/client/request-buffer/header.js +19 -0
  716. package/src/http-server/client/request-buffer/index.js +535 -0
  717. package/src/http-server/client/request-parser.js +195 -0
  718. package/src/http-server/client/request-runner.js +321 -0
  719. package/src/http-server/client/request-timing.js +171 -0
  720. package/src/http-server/client/request.js +114 -0
  721. package/src/http-server/client/response.js +251 -0
  722. package/src/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
  723. package/src/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
  724. package/src/http-server/client/uploaded-file/uploaded-file.js +36 -0
  725. package/src/http-server/client/websocket-request.js +147 -0
  726. package/src/http-server/client/websocket-session.js +1755 -0
  727. package/src/http-server/cookie.js +245 -0
  728. package/src/http-server/development-reloader.js +240 -0
  729. package/src/http-server/index.js +561 -0
  730. package/src/http-server/remote-address.js +77 -0
  731. package/src/http-server/server-client.js +222 -0
  732. package/src/http-server/server-lock.js +178 -0
  733. package/src/http-server/websocket-channel-subscribers.js +110 -0
  734. package/src/http-server/websocket-channel.js +137 -0
  735. package/src/http-server/websocket-connection.js +118 -0
  736. package/src/http-server/websocket-event-log-store.js +433 -0
  737. package/src/http-server/websocket-events-host.js +170 -0
  738. package/src/http-server/websocket-events.js +50 -0
  739. package/src/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
  740. package/src/http-server/worker-handler/in-process.js +155 -0
  741. package/src/http-server/worker-handler/index.js +370 -0
  742. package/src/http-server/worker-handler/worker-script.js +6 -0
  743. package/src/http-server/worker-handler/worker-thread.js +286 -0
  744. package/src/initializer.js +39 -0
  745. package/src/jobs/.gitkeep +1 -0
  746. package/src/jobs/mail-delivery.js +22 -0
  747. package/src/logger/base-logger.js +34 -0
  748. package/src/logger/console-logger.js +28 -0
  749. package/src/logger/file-logger.js +36 -0
  750. package/src/logger/outputs/array-output.js +50 -0
  751. package/src/logger/outputs/console-output.js +32 -0
  752. package/src/logger/outputs/file-output.js +55 -0
  753. package/src/logger/outputs/stdout-output.js +64 -0
  754. package/src/logger.js +507 -0
  755. package/src/mailer/backends/smtp.js +197 -0
  756. package/src/mailer/base.js +337 -0
  757. package/src/mailer/delivery.js +70 -0
  758. package/src/mailer/index.js +24 -0
  759. package/src/mailer.js +15 -0
  760. package/src/plugins/sqljs-wasm-route-controller.js +70 -0
  761. package/src/plugins/sqljs-wasm-route.js +71 -0
  762. package/src/record-payload-values.js +83 -0
  763. package/src/routes/app-routes.js +17 -0
  764. package/src/routes/base-route.js +133 -0
  765. package/src/routes/basic-route.js +109 -0
  766. package/src/routes/built-in/debug/controller.js +12 -0
  767. package/src/routes/built-in/errors/controller.js +7 -0
  768. package/src/routes/built-in/errors/not-found.ejs +1 -0
  769. package/src/routes/get-route.js +75 -0
  770. package/src/routes/hooks/frontend-model-command-route-hook.js +100 -0
  771. package/src/routes/index.js +50 -0
  772. package/src/routes/namespace-route.js +51 -0
  773. package/src/routes/plugin-routes.js +141 -0
  774. package/src/routes/post-route.js +74 -0
  775. package/src/routes/resolver.js +535 -0
  776. package/src/routes/resource-route.js +154 -0
  777. package/src/routes/root-route.js +11 -0
  778. package/src/templates/configuration.js +61 -0
  779. package/src/templates/generate-migration.js +11 -0
  780. package/src/templates/generate-model.js +6 -0
  781. package/src/templates/routes.js +11 -0
  782. package/src/testing/base-expect.js +17 -0
  783. package/src/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
  784. package/src/testing/browser-test-app.js +32 -0
  785. package/src/testing/expect-to-change.js +55 -0
  786. package/src/testing/expect-utils.js +269 -0
  787. package/src/testing/expect.js +763 -0
  788. package/src/testing/request-client.js +90 -0
  789. package/src/testing/test-files-finder.js +364 -0
  790. package/src/testing/test-filter-parser.js +198 -0
  791. package/src/testing/test-runner.js +1168 -0
  792. package/src/testing/test-suite-splitter.js +177 -0
  793. package/src/testing/test.js +370 -0
  794. package/src/types/external-modules.d.ts +57 -0
  795. package/src/utils/backtrace-cleaner-node.js +87 -0
  796. package/src/utils/backtrace-cleaner.js +266 -0
  797. package/src/utils/ensure-error.js +15 -0
  798. package/src/utils/event-emitter.js +8 -0
  799. package/src/utils/file-exists.js +18 -0
  800. package/src/utils/format-value.js +101 -0
  801. package/src/utils/model-scope.js +56 -0
  802. package/src/utils/nest-callbacks.js +22 -0
  803. package/src/utils/plain-object.js +14 -0
  804. package/src/utils/ransack.js +859 -0
  805. package/src/utils/rest-args-error.js +14 -0
  806. package/src/utils/singularize-model-name.js +18 -0
  807. package/src/utils/split-sql-statements.js +88 -0
  808. package/src/utils/to-import-specifier.js +53 -0
  809. package/src/utils/with-tracked-stack-async-hooks.js +103 -0
  810. package/src/utils/with-tracked-stack.js +38 -0
  811. package/src/velocious-error.js +34 -0
  812. package/tsconfig.json +16 -0
@@ -0,0 +1,1168 @@
1
+ // @ts-check
2
+
3
+ import {addTrackedStackToError} from "../utils/with-tracked-stack.js"
4
+ import fs from "node:fs/promises"
5
+ import path from "path"
6
+ import {format} from "node:util"
7
+ import Application from "../../src/application.js"
8
+ import BacktraceCleaner from "../utils/backtrace-cleaner-node.js"
9
+ import RequestClient from "./request-client.js"
10
+ import picocolors from "picocolors"
11
+ import restArgsError from "../utils/rest-args-error.js"
12
+ import {testConfig, testEvents, tests} from "./test.js"
13
+ import {pathToFileURL} from "url"
14
+ import {clearDeliveries} from "../mailer.js"
15
+
16
+ /**
17
+ * Runs run with timeout.
18
+ * @param {Promise<?> | ?} promise - Promise or value.
19
+ * @param {number} timeoutMs - Timeout in milliseconds.
20
+ * @param {string} testDescription - Test description.
21
+ * @returns {Promise<?>} - Resolves or rejects based on timeout or promise result.
22
+ */
23
+ function runWithTimeout(promise, timeoutMs, testDescription) {
24
+ const timeoutSeconds = (timeoutMs / 1000).toFixed(3).replace(/\.?0+$/, "")
25
+ const timeoutError = new Error(`Timed out after ${timeoutSeconds}s: ${testDescription}`)
26
+
27
+ return new Promise((resolve, reject) => {
28
+ const timeout = setTimeout(() => reject(timeoutError), timeoutMs)
29
+
30
+ Promise.resolve(promise).then((result) => {
31
+ clearTimeout(timeout)
32
+ resolve(result)
33
+ }).catch((error) => {
34
+ clearTimeout(timeout)
35
+ reject(error)
36
+ })
37
+ })
38
+ }
39
+
40
+ /**
41
+ * ConsoleMethodName type.
42
+ @typedef {"log" | "info" | "warn" | "error" | "debug"} ConsoleMethodName */
43
+
44
+ /**
45
+ * Captured console methods.
46
+ @type {ConsoleMethodName[]} */
47
+ const CAPTURED_CONSOLE_METHODS = ["log", "info", "warn", "error", "debug"]
48
+
49
+ /**
50
+ * AttemptConsoleOutput type.
51
+ * @typedef {object} AttemptConsoleOutput
52
+ * @property {number} attemptNumber - Attempt number.
53
+ * @property {string} output - Captured console output.
54
+ */
55
+
56
+ /**
57
+ * Runs to file slug.
58
+ * @param {string} value - Value to sanitize.
59
+ * @returns {string} - Slug-safe value.
60
+ */
61
+ function toFileSlug(value) {
62
+ return value
63
+ .toLowerCase()
64
+ .replace(/[^a-z0-9]+/g, "-")
65
+ .replace(/^-+|-+$/g, "")
66
+ .slice(0, 80) || "failed-test"
67
+ }
68
+
69
+ /**
70
+ * TestArgs type.
71
+ * @typedef {object} TestArgs
72
+ * @property {Application} [application] - Application instance for integration tests.
73
+ * @property {RequestClient} [client] - HTTP client for request tests.
74
+ * @property {object} [databaseCleaning] - Database cleanup options for tests.
75
+ * @property {boolean} [databaseCleaning.transaction] - Use transactions to rollback between tests.
76
+ * @property {boolean} [databaseCleaning.truncate] - Truncate tables between tests.
77
+ * @property {boolean} [focus] - Whether this test is focused.
78
+ * @property {() => (void|Promise<void>)} [function] - Test callback function.
79
+ * @property {number} [retry] - Number of retries when a test fails.
80
+ * @property {string[] | string} [tags] - Tags for filtering.
81
+ * @property {number} [timeoutSeconds] - Timeout in seconds for the test.
82
+ * @property {string} [type] - Test type identifier.
83
+ */
84
+
85
+ /**
86
+ * TestData type.
87
+ * @typedef {object} TestData
88
+ * @property {TestArgs} args - Arguments passed to the test.
89
+ * @property {string} [filePath] - Source file path.
90
+ * @property {number} [line] - Source line number.
91
+ * @property {function(TestArgs) : (void|Promise<void>)} function - Test callback to execute.
92
+ */
93
+
94
+ /**
95
+ * FailedTestDetail type.
96
+ * @typedef {object} FailedTestDetail
97
+ * @property {string} fullDescription - Full test description.
98
+ * @property {string} [filePath] - Source file path.
99
+ * @property {number} [line] - Source line number.
100
+ * @property {?} error - Failure error.
101
+ * @property {string} [consoleOutput] - Captured console output while test ran.
102
+ * @property {string} [consoleLogPath] - Saved console log path.
103
+ */
104
+
105
+ /**
106
+ * ActiveAfterAllScopeEntry type.
107
+ * @typedef {object} ActiveAfterAllScopeEntry
108
+ * @property {TestsArgument} tests - Scope test tree.
109
+ * @property {boolean} afterAllsRun - Whether cleanup hooks have run.
110
+ */
111
+
112
+ /**
113
+ * Defines this typedef.
114
+ * @typedef {function({configuration: import("../configuration.js").default, testArgs: TestArgs, testData: TestData}) : (void|Promise<void>)} AfterBeforeEachCallbackType
115
+ */
116
+
117
+ /**
118
+ * AfterBeforeEachCallbackObjectType type.
119
+ * @typedef {object} AfterBeforeEachCallbackObjectType
120
+ * @property {AfterBeforeEachCallbackType} callback - Hook callback to execute.
121
+ */
122
+
123
+ /**
124
+ * Defines this typedef.
125
+ * @typedef {function({configuration: import("../configuration.js").default}) : (void|Promise<void>)} BeforeAfterAllCallbackType
126
+ */
127
+
128
+ /**
129
+ * BeforeAfterAllCallbackObjectType type.
130
+ * @typedef {object} BeforeAfterAllCallbackObjectType
131
+ * @property {BeforeAfterAllCallbackType} callback - Hook callback to execute.
132
+ */
133
+
134
+ /**
135
+ * TestsArgument type.
136
+ * @typedef {object} TestsArgument
137
+ * @property {Record<string, TestData>} args - Arguments keyed by test description.
138
+ * @property {boolean} [anyTestsFocussed] - Whether any tests in the tree are focused.
139
+ * @property {AfterBeforeEachCallbackObjectType[]} afterEaches - After-each hooks for this scope.
140
+ * @property {BeforeAfterAllCallbackObjectType[]} afterAlls - After-all hooks for this scope.
141
+ * @property {BeforeAfterAllCallbackObjectType[]} beforeAlls - Before-all hooks for this scope.
142
+ * @property {AfterBeforeEachCallbackObjectType[]} beforeEaches - Before-each hooks for this scope.
143
+ * @property {string} [filePath] - Source file path.
144
+ * @property {number} [line] - Source line number.
145
+ * @property {Record<string, TestData>} tests - A unique identifier for the node.
146
+ * @property {Record<string, TestsArgument>} subs - Optional child nodes. Each item is another `Node`, allowing recursion.
147
+ */
148
+
149
+ export default class TestRunner {
150
+ /**
151
+ * Narrows the runtime value to the documented type.
152
+ @type {ActiveAfterAllScopeEntry[]} */
153
+ _activeAfterAllScopes
154
+
155
+ /**
156
+ * Narrows the runtime value to the documented type.
157
+ @type {FailedTestDetail[]} */
158
+ _failedTestDetails
159
+
160
+ /**
161
+ * Runs constructor.
162
+ * @param {object} args - Options object.
163
+ * @param {import("../configuration.js").default} args.configuration - Configuration instance.
164
+ * @param {string[] | string} [args.excludeTags] - Tags to exclude.
165
+ * @param {string[] | string} [args.includeTags] - Tags to include.
166
+ * @param {Array<string>} args.testFiles - Test files.
167
+ * @param {Record<string, number[]>} [args.lineFilters] - Line filters by file.
168
+ * @param {RegExp[]} [args.examplePatterns] - Example patterns.
169
+ */
170
+ constructor({configuration, excludeTags, includeTags, testFiles, lineFilters, examplePatterns, ...restArgs}) {
171
+ restArgsError(restArgs)
172
+
173
+ if (!configuration) throw new Error("configuration is required")
174
+
175
+ this._configuration = configuration
176
+ this._excludeTags = this.normalizeTags(excludeTags)
177
+ this._excludeTagSet = new Set(this._excludeTags)
178
+ this._includeTags = this.normalizeTags(includeTags)
179
+ this._includeTagSet = new Set(this._includeTags)
180
+ this._testFiles = testFiles
181
+ this._lineFilters = lineFilters || {}
182
+ this._examplePatterns = examplePatterns || []
183
+
184
+ this._failedTests = 0
185
+ this._successfulTests = 0
186
+ this._testsCount = 0
187
+ this._activeAfterAllScopes = []
188
+ this._failedTestDetails = []
189
+ }
190
+
191
+ /**
192
+ * Runs get configuration.
193
+ * @returns {import("../configuration.js").default} - The configuration.
194
+ */
195
+ getConfiguration() { return this._configuration }
196
+
197
+ /**
198
+ * Runs get test files.
199
+ * @returns {string[]} - The test files.
200
+ */
201
+ getTestFiles() { return this._testFiles }
202
+
203
+ /**
204
+ * Runs get line filters.
205
+ * @returns {Record<string, number[]>} - Line filters.
206
+ */
207
+ getLineFilters() { return this._lineFilters }
208
+
209
+ /**
210
+ * Runs get example patterns.
211
+ * @returns {RegExp[]} - Example patterns.
212
+ */
213
+ getExamplePatterns() { return this._examplePatterns }
214
+
215
+ /**
216
+ * Runs normalize tags.
217
+ * @param {string[] | string | undefined} tags - Tags.
218
+ * @returns {string[]} - Normalized tags.
219
+ */
220
+ normalizeTags(tags) {
221
+ if (!tags) return []
222
+
223
+ const values = []
224
+ const rawTags = Array.isArray(tags) ? tags : [tags]
225
+
226
+ for (const rawTag of rawTags) {
227
+ if (rawTag === undefined || rawTag === null) continue
228
+
229
+ const parts = String(rawTag).split(",")
230
+
231
+ for (const part of parts) {
232
+ const trimmed = part.trim()
233
+
234
+ if (trimmed) values.push(trimmed)
235
+ }
236
+ }
237
+
238
+ return Array.from(new Set(values))
239
+ }
240
+
241
+ /**
242
+ * Runs has tag.
243
+ * @param {TestArgs} testArgs - Test args.
244
+ * @param {string} tag - Tag to check for.
245
+ * @returns {boolean} - Whether tag is present.
246
+ */
247
+ hasTag(testArgs, tag) {
248
+ return this.normalizeTags(testArgs?.tags).includes(tag)
249
+ }
250
+
251
+ /**
252
+ * Runs is browser test mode.
253
+ * @returns {boolean} - Whether running browser tests.
254
+ */
255
+ isBrowserTestMode() {
256
+ return process.env.VELOCIOUS_BROWSER_TESTS === "true"
257
+ }
258
+
259
+ /**
260
+ * Runs run with dummy if needed.
261
+ * @param {TestArgs} testArgs - Test args.
262
+ * @param {() => Promise<void>} callback - Callback to run.
263
+ * @returns {Promise<void>} - Resolves when complete.
264
+ */
265
+ async runWithDummyIfNeeded(testArgs, callback) {
266
+ if (!this.hasTag(testArgs, "dummy")) {
267
+ await callback()
268
+ return
269
+ }
270
+
271
+ if (this.isBrowserTestMode()) {
272
+ await this.runBrowserDummy(callback)
273
+ return
274
+ }
275
+
276
+ await this.runNodeDummy(callback)
277
+ }
278
+
279
+ /**
280
+ * Runs run node dummy.
281
+ * @param {() => Promise<void>} callback - Callback to run.
282
+ * @returns {Promise<void>} - Resolves when complete.
283
+ */
284
+ async runNodeDummy(callback) {
285
+ const dummyPath = process.env.VELOCIOUS_DUMMY_PATH || this.defaultDummyPath()
286
+ const dummyImport = await import(pathToFileURL(dummyPath).href)
287
+ const Dummy = dummyImport.default
288
+
289
+ if (!Dummy?.run) {
290
+ throw new Error(`Dummy helper not found at ${dummyPath}`)
291
+ }
292
+
293
+ await Dummy.run(callback)
294
+ }
295
+
296
+ /**
297
+ * Runs default dummy path.
298
+ * @returns {string} - Default dummy helper path.
299
+ */
300
+ defaultDummyPath() {
301
+ const cwd = path.resolve(process.cwd())
302
+ const normalized = cwd.split(path.sep).join("/")
303
+
304
+ if (normalized.endsWith("/spec/dummy")) {
305
+ return path.join(cwd, "index.js")
306
+ }
307
+
308
+ return path.join(cwd, "spec/dummy/index.js")
309
+ }
310
+
311
+ /**
312
+ * Runs run browser dummy.
313
+ * @param {() => Promise<void>} callback - Callback to run.
314
+ * @returns {Promise<void>} - Resolves when complete.
315
+ */
316
+ async runBrowserDummy(callback) {
317
+ await this.getConfiguration().ensureConnections({name: "Test runner browser dummy"}, async (dbs) => {
318
+ await this.truncateDatabases(dbs)
319
+
320
+ try {
321
+ await callback()
322
+ } finally {
323
+ await this.truncateDatabases(dbs)
324
+ }
325
+ })
326
+ }
327
+
328
+ /**
329
+ * Runs truncate databases.
330
+ * @param {Record<string, import("../database/drivers/base.js").default>} dbs - Database connections.
331
+ * @returns {Promise<void>} - Resolves when complete.
332
+ */
333
+ async truncateDatabases(dbs) {
334
+ for (const identifier of Object.keys(dbs)) {
335
+ await dbs[identifier].truncateAllTables()
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Runs get exclude tag set.
341
+ * @returns {Set<string>} - Exclude tag set.
342
+ */
343
+ getExcludeTagSet() {
344
+ /**
345
+ * Config tags.
346
+ @type {string[]} */
347
+ const configTags = Array.isArray(testConfig.excludeTags) ? testConfig.excludeTags : []
348
+
349
+ return new Set([...this._excludeTags, ...configTags])
350
+ }
351
+
352
+ /**
353
+ * Runs has matching tag.
354
+ * @param {string[] | string | undefined} testTags - Test tags.
355
+ * @param {Set<string>} tagSet - Tag set.
356
+ * @returns {boolean} - Whether any tags match.
357
+ */
358
+ hasMatchingTag(testTags, tagSet) {
359
+ if (!tagSet.size) return false
360
+
361
+ const normalized = this.normalizeTags(testTags)
362
+
363
+ for (const tag of normalized) {
364
+ if (tagSet.has(tag)) return true
365
+ }
366
+
367
+ return false
368
+ }
369
+
370
+ /**
371
+ * Runs has runnable tests.
372
+ * @param {TestsArgument} tests - Tests.
373
+ * @param {string[]} [descriptions] - Description stack.
374
+ * @param {boolean} [lineMatchedInScope] - Whether line matched in scope.
375
+ * @returns {boolean} - Whether any tests in this scope will run.
376
+ */
377
+ hasRunnableTests(tests, descriptions = [], lineMatchedInScope = false) {
378
+ for (const testDescription in tests.tests) {
379
+ const testData = tests.tests[testDescription]
380
+ const testArgs = /**
381
+ * Narrows the runtime value to the documented type.
382
+ @type {TestArgs} */ (Object.assign({}, testData.args))
383
+ const includeByLine = lineMatchedInScope || this.matchesLineFilter(testData)
384
+
385
+ if (this._onlyFocussed && !testArgs.focus) continue
386
+ if (this.shouldSkipTest(testArgs, testData, testDescription, descriptions, includeByLine)) continue
387
+
388
+ return true
389
+ }
390
+
391
+ for (const subDescription in tests.subs) {
392
+ const subTest = tests.subs[subDescription]
393
+ const scopeLineMatch = lineMatchedInScope || this.matchesLineFilter(subTest)
394
+ const nextDescriptions = descriptions.concat([subDescription])
395
+
396
+ if (this._onlyFocussed && !subTest.anyTestsFocussed) continue
397
+ if (this.hasRunnableTests(subTest, nextDescriptions, scopeLineMatch)) return true
398
+ }
399
+
400
+ return false
401
+ }
402
+
403
+ /**
404
+ * Runs should skip test.
405
+ * @param {TestArgs} testArgs - Test args.
406
+ * @param {TestData} testData - Test data.
407
+ * @param {string} testDescription - Test description.
408
+ * @param {string[]} descriptions - Description stack.
409
+ * @param {boolean} lineMatchedInScope - Whether line matched in scope.
410
+ * @returns {boolean} - Whether the test should be skipped.
411
+ */
412
+ shouldSkipTest(testArgs, testData, testDescription, descriptions, lineMatchedInScope) {
413
+ if (this.hasMatchingTag(testArgs.tags, this.getExcludeTagSet())) return true
414
+
415
+ if (this._includeTagSet.size > 0 && !testArgs.focus) {
416
+ if (!this.hasMatchingTag(testArgs.tags, this._includeTagSet)) return true
417
+ }
418
+
419
+ if (this.getExamplePatterns().length > 0) {
420
+ const fullDescription = this.buildFullDescription(descriptions, testDescription)
421
+ const matches = this.getExamplePatterns().some((pattern) => {
422
+ pattern.lastIndex = 0
423
+ return pattern.test(fullDescription)
424
+ })
425
+
426
+ if (!matches) return true
427
+ }
428
+
429
+ const lineFilters = this.getLineFilters()
430
+
431
+ if (Object.keys(lineFilters).length > 0) {
432
+ if (!lineMatchedInScope && !this.matchesLineFilter(testData)) return true
433
+ }
434
+
435
+ return false
436
+ }
437
+
438
+ /**
439
+ * Runs matches line filter.
440
+ * @param {TestData | TestsArgument} entry - Test entry.
441
+ * @returns {boolean} - Whether line filter matches entry.
442
+ */
443
+ matchesLineFilter(entry) {
444
+ if (!entry || !entry.filePath || !entry.line) return false
445
+
446
+ const filePath = path.resolve(entry.filePath)
447
+ const lines = this.getLineFilters()[filePath]
448
+
449
+ if (!lines || lines.length === 0) return false
450
+
451
+ return lines.includes(entry.line)
452
+ }
453
+
454
+ /**
455
+ * Runs build full description.
456
+ * @param {string[]} descriptions - Description stack.
457
+ * @param {string} testDescription - Test description.
458
+ * @returns {string} - Full description.
459
+ */
460
+ buildFullDescription(descriptions, testDescription) {
461
+ const parts = descriptions.concat([testDescription])
462
+
463
+ return parts.join(" ").trim()
464
+ }
465
+
466
+ /**
467
+ * Runs application.
468
+ * @returns {Promise<Application>} - Resolves with the application.
469
+ */
470
+ async application() {
471
+ if (!this._application) {
472
+ this._application = new Application({
473
+ configuration: this.getConfiguration(),
474
+ httpServer: {port: 31006},
475
+ type: "test-runner"
476
+ })
477
+
478
+ await this._application.initialize()
479
+ await this._application.startHttpServer()
480
+ }
481
+
482
+ return this._application
483
+ }
484
+
485
+ /**
486
+ * Runs request client.
487
+ * @returns {Promise<RequestClient>} - Resolves with the request client.
488
+ */
489
+ async requestClient() {
490
+ if (!this._requestClient) {
491
+ this._requestClient = new RequestClient()
492
+ }
493
+
494
+ return this._requestClient
495
+ }
496
+
497
+ /**
498
+ * Runs import test files.
499
+ * @returns {Promise<void>} - Resolves when complete.
500
+ */
501
+ async importTestFiles() {
502
+ await this.getConfiguration().getEnvironmentHandler().importTestFiles(this.getTestFiles())
503
+ }
504
+
505
+ /**
506
+ * Runs is failed.
507
+ * @returns {boolean} - Whether failed.
508
+ */
509
+ isFailed() { return this._failedTests !== undefined && this._failedTests > 0 }
510
+
511
+ /**
512
+ * Runs get failed tests.
513
+ * @returns {number} - The failed tests.
514
+ */
515
+ getFailedTests() {
516
+ if (this._failedTests === undefined) throw new Error("Tests hasn't been run yet")
517
+
518
+ return this._failedTests
519
+ }
520
+
521
+ /**
522
+ * Runs get failed test details.
523
+ * @returns {FailedTestDetail[]} - Failed test details.
524
+ */
525
+ getFailedTestDetails() {
526
+ return this._failedTestDetails
527
+ }
528
+
529
+ /**
530
+ * Runs persist failed test console outputs to assets.
531
+ * @param {object} [args] - Options object.
532
+ * @param {string} [args.assetsPath] - Assets directory path.
533
+ * @returns {Promise<string[]>} - Written log file paths.
534
+ */
535
+ async persistFailedTestConsoleOutputsToAssets({assetsPath = path.join(process.cwd(), "tmp/screenshots")} = {}) {
536
+ const failedTestDetails = this.getFailedTestDetails()
537
+ const writtenLogPaths = []
538
+ let createdDirectory = false
539
+
540
+ for (let index = 0; index < failedTestDetails.length; index++) {
541
+ const failedTestDetail = failedTestDetails[index]
542
+ const consoleOutput = failedTestDetail.consoleOutput
543
+
544
+ if (!consoleOutput) continue
545
+
546
+ if (!createdDirectory) {
547
+ await fs.mkdir(assetsPath, {recursive: true})
548
+ createdDirectory = true
549
+ }
550
+
551
+ const now = new Date()
552
+ const timestamp = [
553
+ String(now.getFullYear()),
554
+ String(now.getMonth() + 1).padStart(2, "0"),
555
+ String(now.getDate()).padStart(2, "0"),
556
+ String(now.getHours()).padStart(2, "0"),
557
+ String(now.getMinutes()).padStart(2, "0"),
558
+ String(now.getSeconds()).padStart(2, "0"),
559
+ String(now.getMilliseconds()).padStart(3, "0")
560
+ ].join("")
561
+ const slug = toFileSlug(failedTestDetail.fullDescription)
562
+ const fileName = `${timestamp}-${String(index + 1).padStart(2, "0")}-${slug}.console.log`
563
+ const filePath = path.join(assetsPath, fileName)
564
+
565
+ await fs.writeFile(filePath, consoleOutput, "utf8")
566
+ failedTestDetail.consoleLogPath = filePath
567
+ writtenLogPaths.push(filePath)
568
+ }
569
+
570
+ return writtenLogPaths
571
+ }
572
+
573
+ /**
574
+ * Runs get successful tests.
575
+ * @returns {number} - The successful tests.
576
+ */
577
+ getSuccessfulTests() {
578
+ if (this._successfulTests === undefined) throw new Error("Tests hasn't been run yet")
579
+
580
+ return this._successfulTests
581
+ }
582
+
583
+ /**
584
+ * Runs get tests count.
585
+ * @returns {number} - The tests count.
586
+ */
587
+ getTestsCount() {
588
+ if (this._testsCount === undefined) throw new Error("Tests hasn't been run yet")
589
+
590
+ return this._testsCount
591
+ }
592
+
593
+ /**
594
+ * Runs get executed tests count.
595
+ * @returns {number} - The executed tests count.
596
+ */
597
+ getExecutedTestsCount() {
598
+ if (this._successfulTests === undefined || this._failedTests === undefined) {
599
+ throw new Error("Tests hasn't been run yet")
600
+ }
601
+
602
+ return this._successfulTests + this._failedTests
603
+ }
604
+
605
+ /**
606
+ * Runs prepare.
607
+ * @returns {Promise<void>} - Resolves when complete.
608
+ */
609
+ async prepare() {
610
+ this.anyTestsFocussed = false
611
+ this._failedTests = 0
612
+ this._successfulTests = 0
613
+ this._testsCount = 0
614
+ this._failedTestDetails = []
615
+ await this.importTestFiles()
616
+ await this.analyzeTests(tests)
617
+ this._onlyFocussed = this.anyTestsFocussed
618
+
619
+ const testingConfigPath = this.getConfiguration().getTesting()
620
+
621
+ if (testingConfigPath) {
622
+ await this.getConfiguration().getEnvironmentHandler().importTestingConfigPath()
623
+ }
624
+ }
625
+
626
+ /**
627
+ * Runs are any tests focussed.
628
+ * @returns {boolean} - Whether any tests focussed.
629
+ */
630
+ areAnyTestsFocussed() {
631
+ if (this.anyTestsFocussed === undefined) {
632
+ throw new Error("Hasn't been detected yet")
633
+ }
634
+
635
+ return this.anyTestsFocussed
636
+ }
637
+
638
+ /**
639
+ * Runs run.
640
+ * @returns {Promise<void>} - Resolves when complete.
641
+ */
642
+ async run() {
643
+ await this.getConfiguration().ensureConnections({name: "Test runner suite"}, async () => {
644
+ await this.runTests({
645
+ afterEaches: [],
646
+ beforeEaches: [],
647
+ tests,
648
+ descriptions: [],
649
+ indentLevel: 0
650
+ })
651
+ })
652
+ }
653
+
654
+ /**
655
+ * Runs run after alls for active scopes.
656
+ * @returns {Promise<void>} - Resolves when cleanup hooks finish.
657
+ */
658
+ async runAfterAllsForActiveScopes() {
659
+ const scopes = [...this._activeAfterAllScopes].reverse()
660
+
661
+ for (const scope of scopes) {
662
+ await this.runAfterAllsForScope(scope)
663
+ }
664
+
665
+ this._activeAfterAllScopes = []
666
+ }
667
+
668
+ /**
669
+ * Runs analyze tests.
670
+ * @param {TestsArgument} tests - Tests.
671
+ * @returns {{anyTestsFocussed: boolean}} - Whether any tests in the tree are focused.
672
+ */
673
+ analyzeTests(tests) {
674
+ let anyTestsFocussedFound = false
675
+
676
+ for (const testDescription in tests.tests) {
677
+ const testData = tests.tests[testDescription]
678
+ const testArgs = Object.assign({}, testData.args)
679
+
680
+ this._testsCount++
681
+
682
+ if (testArgs.focus) {
683
+ anyTestsFocussedFound = true
684
+ this.anyTestsFocussed = true
685
+ }
686
+ }
687
+
688
+ for (const subDescription in tests.subs) {
689
+ const subTest = tests.subs[subDescription]
690
+ const {anyTestsFocussed} = this.analyzeTests(subTest)
691
+
692
+ if (anyTestsFocussed) {
693
+ anyTestsFocussedFound = true
694
+ }
695
+
696
+ subTest.anyTestsFocussed = anyTestsFocussed
697
+ }
698
+
699
+ return {anyTestsFocussed: anyTestsFocussedFound}
700
+ }
701
+
702
+ /**
703
+ * Runs run tests.
704
+ * @param {object} args - Options object.
705
+ * @param {Array<AfterBeforeEachCallbackObjectType>} args.afterEaches - After eaches.
706
+ * @param {Array<AfterBeforeEachCallbackObjectType>} args.beforeEaches - Before eaches.
707
+ * @param {TestsArgument} args.tests - Tests.
708
+ * @param {string[]} args.descriptions - Descriptions.
709
+ * @param {number} args.indentLevel - Indent level.
710
+ * @param {boolean} [args.lineMatchedInScope] - Whether line matched in scope.
711
+ * @returns {Promise<void>} - Resolves when complete.
712
+ */
713
+ async runTests({afterEaches, beforeEaches, tests, descriptions, indentLevel, lineMatchedInScope = false}) {
714
+ const leftPadding = " ".repeat(indentLevel * 2)
715
+ const newAfterEaches = [...afterEaches, ...tests.afterEaches]
716
+ const newBeforeEaches = [...beforeEaches, ...tests.beforeEaches]
717
+ const scopeLineMatch = lineMatchedInScope || this.matchesLineFilter(tests)
718
+ const shouldRunAnyTests = this.hasRunnableTests(tests, descriptions, scopeLineMatch)
719
+
720
+ if (!shouldRunAnyTests) return
721
+
722
+ /** Scope entry. @type {ActiveAfterAllScopeEntry} */
723
+ const scopeEntry = {tests, afterAllsRun: false}
724
+ this._activeAfterAllScopes.push(scopeEntry)
725
+
726
+ try {
727
+ for (const beforeAllData of tests.beforeAlls || []) {
728
+ await beforeAllData.callback({configuration: this.getConfiguration()})
729
+ }
730
+
731
+ for (const testDescription in tests.tests) {
732
+ const testData = tests.tests[testDescription]
733
+ const testArgs = /**
734
+ * Narrows the runtime value to the documented type.
735
+ @type {TestArgs} */ (Object.assign({}, testData.args))
736
+ const includeByLine = scopeLineMatch || this.matchesLineFilter(testData)
737
+
738
+ if (this._onlyFocussed && !testArgs.focus) continue
739
+ if (this.shouldSkipTest(testArgs, testData, testDescription, descriptions, includeByLine)) continue
740
+
741
+ if (testArgs.type == "model" || testArgs.type == "request") {
742
+ testArgs.application = await this.application()
743
+ }
744
+
745
+ if (testArgs.type == "request") {
746
+ testArgs.client = await this.requestClient()
747
+ }
748
+
749
+ const retryCount = typeof testArgs.retry === "number" && Number.isFinite(testArgs.retry)
750
+ ? Math.max(0, Math.floor(testArgs.retry))
751
+ : 0
752
+ const configTimeoutSeconds = typeof testConfig.defaultTimeoutSeconds === "number" ? testConfig.defaultTimeoutSeconds : undefined
753
+ const timeoutSeconds = typeof testArgs.timeoutSeconds === "number" ? testArgs.timeoutSeconds : configTimeoutSeconds
754
+ const useTimeout = typeof timeoutSeconds === "number" && Number.isFinite(timeoutSeconds) && timeoutSeconds > 0
755
+ const timeoutMs = useTimeout ? timeoutSeconds * 1000 : undefined
756
+ let retriesUsed = 0
757
+ let attemptNumber = 1
758
+ /**
759
+ * Attempt console outputs.
760
+ @type {AttemptConsoleOutput[]} */
761
+ const attemptConsoleOutputs = []
762
+
763
+ console.log(`${leftPadding}it ${testDescription}`)
764
+
765
+ while (true) {
766
+ let shouldRetry = false
767
+ /**
768
+ * Defines caughtError.
769
+ @type {?} */
770
+ let caughtError
771
+ /**
772
+ * Defines failedError.
773
+ @type {?} */
774
+ let failedError
775
+ /**
776
+ * Defines lastError.
777
+ @type {?} */
778
+ let lastError
779
+ let willRetry = false
780
+ const stopConsoleCapture = this.startConsoleCapture({
781
+ passthrough: testConfig.consoleOutput === "live"
782
+ })
783
+
784
+ try {
785
+ // Run the whole per-test lifecycle (dummy/server startup, connection
786
+ // acquisition, beforeEach hooks, the test body and afterEach hooks) as
787
+ // one promise so the timeout below can cover all of it.
788
+ const testLifecycle = this.runWithDummyIfNeeded(testArgs, async () => {
789
+ // Pin one connection per test so beforeEach, the test body and afterEach
790
+ // all run on the SAME connection. This is required for transaction-based
791
+ // database cleaning (beforeEach starts a transaction, afterEach rolls it
792
+ // back). ensureConnections reuses the suite-level pinned connection while
793
+ // it is healthy and transparently re-establishes a per-test pin if an
794
+ // earlier spec closed the suite connection (which would otherwise leave a
795
+ // stale async-context pin and force every later test onto a fresh checkout,
796
+ // breaking isolation).
797
+ await this.getConfiguration().ensureConnections({name: `Test: ${testDescription}`}, async () => {
798
+ try {
799
+ clearDeliveries()
800
+ for (const beforeEachData of newBeforeEaches) {
801
+ await beforeEachData.callback({configuration: this.getConfiguration(), testArgs, testData})
802
+ }
803
+
804
+ await testData.function(testArgs)
805
+ this._successfulTests++
806
+ } finally {
807
+ for (const afterEachData of newAfterEaches) {
808
+ await afterEachData.callback({configuration: this.getConfiguration(), testArgs, testData})
809
+ }
810
+ }
811
+ })
812
+ })
813
+
814
+ // Time out the ENTIRE lifecycle, not just the test body. A hang in any
815
+ // phase — a connection checkout that never resolves, a beforeEach/afterEach
816
+ // waiting on a lock, or dummy server startup — would otherwise stall the
817
+ // whole run indefinitely (until CI kills the build) instead of failing the
818
+ // single offending test.
819
+ if (useTimeout && timeoutMs !== undefined) {
820
+ await runWithTimeout(testLifecycle, timeoutMs, testDescription)
821
+ } else {
822
+ await testLifecycle
823
+ }
824
+ } catch (error) {
825
+ caughtError = error
826
+ lastError = error
827
+ willRetry = retriesUsed < retryCount
828
+
829
+ if (willRetry) {
830
+ retriesUsed++
831
+ }
832
+
833
+ if (willRetry) {
834
+ shouldRetry = true
835
+ } else {
836
+ failedError = error
837
+ }
838
+ } finally {
839
+ const consoleOutput = stopConsoleCapture()
840
+
841
+ if (consoleOutput) {
842
+ attemptConsoleOutputs.push({attemptNumber, output: consoleOutput})
843
+ }
844
+ }
845
+
846
+ if (caughtError !== undefined) {
847
+ await this.emitEvent("testAttemptFailed", {
848
+ configuration: this.getConfiguration(),
849
+ descriptions,
850
+ error: caughtError,
851
+ attemptNumber,
852
+ nextAttempt: willRetry ? attemptNumber + 1 : undefined,
853
+ retriesUsed,
854
+ retryCount,
855
+ testArgs,
856
+ testData,
857
+ testDescription,
858
+ testRunner: this,
859
+ willRetry
860
+ })
861
+ }
862
+
863
+ if (shouldRetry) {
864
+ console.warn(picocolors.red(`${leftPadding} Retrying (${retriesUsed}/${retryCount}) after error: ${lastError instanceof Error ? lastError.message : String(lastError)}`))
865
+ await this.emitEvent("testRetrying", {
866
+ configuration: this.getConfiguration(),
867
+ descriptions,
868
+ error: lastError,
869
+ nextAttempt: attemptNumber + 1,
870
+ retriesUsed,
871
+ retryCount,
872
+ testArgs,
873
+ testData,
874
+ testDescription,
875
+ testRunner: this
876
+ })
877
+ }
878
+
879
+ if (attemptNumber > 1) {
880
+ await this.emitEvent("testRetried", {
881
+ configuration: this.getConfiguration(),
882
+ descriptions,
883
+ error: lastError,
884
+ attemptNumber,
885
+ retriesUsed,
886
+ retryCount,
887
+ testArgs,
888
+ testData,
889
+ testDescription,
890
+ testRunner: this
891
+ })
892
+ }
893
+
894
+ attemptNumber++
895
+
896
+ if (shouldRetry) continue
897
+
898
+ if (failedError) {
899
+ const consoleOutput = this.buildConsoleOutput(attemptConsoleOutputs)
900
+
901
+ if (failedError instanceof Error) {
902
+ console.error(picocolors.red(`${leftPadding} Test failed: ${failedError.message}`))
903
+ addTrackedStackToError(failedError)
904
+
905
+ const backtraceCleaner = new BacktraceCleaner(failedError)
906
+ const cleanedStack = backtraceCleaner.getCleanedStack()
907
+ const stackLines = cleanedStack?.split("\n")
908
+
909
+ if (stackLines) {
910
+ for (const stackLine of stackLines) {
911
+ console.error(picocolors.red(`${leftPadding} ${stackLine}`))
912
+ }
913
+ }
914
+ } else {
915
+ console.error(picocolors.red(`${leftPadding} Test failed with a ${typeof failedError}: ${String(failedError)}`))
916
+ }
917
+
918
+ this.printFailedConsoleOutput({consoleOutput, leftPadding})
919
+ this._failedTests++
920
+ this._failedTestDetails.push({
921
+ fullDescription: this.buildFullDescription(descriptions, testDescription),
922
+ filePath: testData.filePath,
923
+ line: testData.line,
924
+ error: failedError,
925
+ consoleOutput: consoleOutput || undefined
926
+ })
927
+
928
+ await this.emitEvent("testFailed", {
929
+ configuration: this.getConfiguration(),
930
+ descriptions,
931
+ error: failedError,
932
+ testArgs,
933
+ testData,
934
+ testDescription,
935
+ testRunner: this
936
+ })
937
+
938
+ this.printRerunCommand({descriptions, testDescription, testData, leftPadding})
939
+ }
940
+
941
+ break
942
+ }
943
+ }
944
+
945
+ for (const subDescription in tests.subs) {
946
+ const subTest = tests.subs[subDescription]
947
+ const newDecriptions = descriptions.concat([subDescription])
948
+ const childScopeLineMatch = scopeLineMatch || this.matchesLineFilter(subTest)
949
+
950
+ if (!this._onlyFocussed || subTest.anyTestsFocussed) {
951
+ console.log(`${leftPadding}${subDescription}`)
952
+ await this.runTests({
953
+ afterEaches: newAfterEaches,
954
+ beforeEaches: newBeforeEaches,
955
+ tests: subTest,
956
+ descriptions: newDecriptions,
957
+ indentLevel: indentLevel + 1,
958
+ lineMatchedInScope: childScopeLineMatch
959
+ })
960
+ }
961
+ }
962
+ } finally {
963
+ await this.runAfterAllsForScope(scopeEntry)
964
+ const scopeIndex = this._activeAfterAllScopes.indexOf(scopeEntry)
965
+
966
+ if (scopeIndex >= 0) {
967
+ this._activeAfterAllScopes.splice(scopeIndex, 1)
968
+ }
969
+ }
970
+ }
971
+
972
+ /**
973
+ * Runs run after alls for scope.
974
+ * @param {ActiveAfterAllScopeEntry} scopeEntry - Scope entry.
975
+ * @returns {Promise<void>} - Resolves when scope cleanup finishes.
976
+ */
977
+ async runAfterAllsForScope(scopeEntry) {
978
+ if (scopeEntry.afterAllsRun) return
979
+
980
+ scopeEntry.afterAllsRun = true
981
+
982
+ for (const afterAllData of scopeEntry.tests.afterAlls || []) {
983
+ await afterAllData.callback({configuration: this.getConfiguration()})
984
+ }
985
+ }
986
+
987
+ /**
988
+ * Runs emit event.
989
+ * @param {string} eventName - Event name.
990
+ * @param {object} payload - Event payload.
991
+ * @returns {Promise<void>} - Resolves when all listeners complete.
992
+ */
993
+ async emitEvent(eventName, payload) {
994
+ const listeners = testEvents.listeners(eventName)
995
+
996
+ for (const listener of listeners) {
997
+ await listener(payload)
998
+ }
999
+ }
1000
+
1001
+ /**
1002
+ * Runs print rerun command.
1003
+ * @param {object} args - Options object.
1004
+ * @param {string[]} args.descriptions - Description stack.
1005
+ * @param {string} args.testDescription - Test description.
1006
+ * @param {TestData} args.testData - Test data.
1007
+ * @param {string} args.leftPadding - Left padding.
1008
+ * @returns {void} - No return value.
1009
+ */
1010
+ printRerunCommand({descriptions, testDescription, testData, leftPadding}) {
1011
+ const rerun = this.buildRerunCommand({descriptions, testDescription, testData})
1012
+
1013
+ if (rerun) {
1014
+ console.error(`${leftPadding} Re-run: ${rerun}`)
1015
+ }
1016
+ }
1017
+
1018
+ /**
1019
+ * Runs build rerun command.
1020
+ * @param {object} args - Options object.
1021
+ * @param {string[]} args.descriptions - Description stack.
1022
+ * @param {string} args.testDescription - Test description.
1023
+ * @param {TestData} args.testData - Test data.
1024
+ * @returns {string | undefined} - Rerun command.
1025
+ */
1026
+ buildRerunCommand({descriptions, testDescription, testData}) {
1027
+ const baseCommand = "npx velocious test"
1028
+ const filePath = testData.filePath
1029
+ const line = testData.line
1030
+
1031
+ if (filePath && line) {
1032
+ const relativePath = path.relative(process.cwd(), filePath)
1033
+ return `${baseCommand} ${relativePath}:${line}`
1034
+ }
1035
+
1036
+ const fullDescription = this.buildFullDescription(descriptions, testDescription)
1037
+
1038
+ if (fullDescription) {
1039
+ return `${baseCommand} --example ${JSON.stringify(fullDescription)}`
1040
+ }
1041
+
1042
+ return undefined
1043
+ }
1044
+
1045
+ /**
1046
+ * Runs build console output.
1047
+ * @param {AttemptConsoleOutput[]} attemptConsoleOutputs - Attempt output entries.
1048
+ * @returns {string} - Combined console output.
1049
+ */
1050
+ buildConsoleOutput(attemptConsoleOutputs) {
1051
+ if (attemptConsoleOutputs.length === 0) return ""
1052
+ if (attemptConsoleOutputs.length === 1) return attemptConsoleOutputs[0].output
1053
+
1054
+ return attemptConsoleOutputs.map((attemptConsoleOutput) => {
1055
+ return `--- Attempt ${attemptConsoleOutput.attemptNumber} ---\n${attemptConsoleOutput.output}`
1056
+ }).join("\n")
1057
+ }
1058
+
1059
+ /**
1060
+ * Runs get failed console output max lines.
1061
+ * @returns {number} - Maximum failed console lines.
1062
+ */
1063
+ getFailedConsoleOutputMaxLines() {
1064
+ const maxLines = testConfig.failedConsoleOutputMaxLines
1065
+
1066
+ if (typeof maxLines !== "number" || !Number.isFinite(maxLines)) return 200
1067
+
1068
+ return Math.max(0, Math.floor(maxLines))
1069
+ }
1070
+
1071
+ /**
1072
+ * Runs truncate failed console output lines.
1073
+ * @param {string} consoleOutput - Console output.
1074
+ * @returns {string[]} - Lines for inline output.
1075
+ */
1076
+ truncateFailedConsoleOutputLines(consoleOutput) {
1077
+ const lines = consoleOutput.split("\n")
1078
+ const maxLines = this.getFailedConsoleOutputMaxLines()
1079
+
1080
+ if (maxLines === 0) return []
1081
+ if (lines.length <= maxLines) return lines
1082
+
1083
+ const omittedLines = lines.length - maxLines
1084
+ const plural = omittedLines === 1 ? "" : "s"
1085
+
1086
+ return [
1087
+ `... ${omittedLines} console output line${plural} omitted ...`,
1088
+ ...lines.slice(-maxLines)
1089
+ ]
1090
+ }
1091
+
1092
+ /**
1093
+ * Runs print failed console output.
1094
+ * @param {object} args - Options object.
1095
+ * @param {string} args.consoleOutput - Console output.
1096
+ * @param {string} args.leftPadding - Left padding.
1097
+ * @returns {void} - No return value.
1098
+ */
1099
+ printFailedConsoleOutput({consoleOutput, leftPadding}) {
1100
+ if (testConfig.consoleOutput !== "failure") return
1101
+ if (!consoleOutput) return
1102
+
1103
+ const lines = this.truncateFailedConsoleOutputLines(consoleOutput)
1104
+
1105
+ if (lines.length === 0) return
1106
+
1107
+ console.error(picocolors.red(`${leftPadding} Console output:`))
1108
+
1109
+ for (const line of lines) {
1110
+ console.error(picocolors.red(`${leftPadding} ${line}`))
1111
+ }
1112
+ }
1113
+
1114
+ /**
1115
+ * Runs start console capture.
1116
+ * @param {object} [args] - Options object.
1117
+ * @param {boolean} [args.passthrough] - Whether to pass through to the original console.
1118
+ * @returns {() => string} - Stops the capture and returns captured text.
1119
+ */
1120
+ startConsoleCapture({passthrough = false} = {}) {
1121
+ /**
1122
+ * Lines.
1123
+ @type {string[]} */
1124
+ const lines = []
1125
+ /**
1126
+ * Console object.
1127
+ @type {Record<ConsoleMethodName, (...args: Array<?>) => void>} */
1128
+ const consoleObject = /**
1129
+ * Narrows the runtime value to the documented type.
1130
+ @type {Record<ConsoleMethodName, (...args: Array<?>) => void>} */ (console)
1131
+ /**
1132
+ * Original console methods.
1133
+ @type {Record<ConsoleMethodName, (...args: Array<?>) => void>} */
1134
+ const originalConsoleMethods = {
1135
+ debug: consoleObject.debug.bind(console),
1136
+ error: consoleObject.error.bind(console),
1137
+ info: consoleObject.info.bind(console),
1138
+ log: consoleObject.log.bind(console),
1139
+ warn: consoleObject.warn.bind(console)
1140
+ }
1141
+ let stopped = false
1142
+ let outputText = ""
1143
+
1144
+ for (const methodName of CAPTURED_CONSOLE_METHODS) {
1145
+ consoleObject[methodName] = (...args) => {
1146
+ lines.push(`[${new Date().toISOString()}] [${methodName}] ${format(...args)}`)
1147
+
1148
+ if (passthrough) {
1149
+ originalConsoleMethods[methodName](...args)
1150
+ }
1151
+ }
1152
+ }
1153
+
1154
+ return () => {
1155
+ if (!stopped) {
1156
+ stopped = true
1157
+
1158
+ for (const methodName of CAPTURED_CONSOLE_METHODS) {
1159
+ consoleObject[methodName] = originalConsoleMethods[methodName]
1160
+ }
1161
+
1162
+ outputText = lines.join("\n")
1163
+ }
1164
+
1165
+ return outputText
1166
+ }
1167
+ }
1168
+ }