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
@@ -1,519 +1,591 @@
1
1
  // @ts-check
2
- import UUID from "pure-uuid";
3
- import TableData from "../../table-data/index.js";
4
- import normalizeRecordAttachmentInput from "./normalize-input.js";
5
- const ATTACHMENTS_TABLE = "velocious_attachments";
2
+
3
+ import UUID from "pure-uuid"
4
+ import TableData from "../../table-data/index.js"
5
+ import normalizeRecordAttachmentInput from "./normalize-input.js"
6
+
7
+ const ATTACHMENTS_TABLE = "velocious_attachments"
8
+
6
9
  /**
7
10
  * AttachmentDriverConstructor type.
8
- @typedef {new (...args: Array<?>) => Record<string, ?>} AttachmentDriverConstructor */
11
+ @typedef {import("../../../configuration-types.js").AttachmentDriverConstructor} AttachmentDriverConstructor */
9
12
  /**
10
13
  * Stores by configuration.
11
14
  @type {WeakMap<import("../../../configuration.js").default, Map<string, RecordAttachmentsStore>>} */
12
- const storesByConfiguration = new WeakMap();
15
+ const storesByConfiguration = new WeakMap()
16
+
13
17
  /**
14
18
  * Runs generate uuid.
15
19
  * @returns {string} - Generated UUID v4 value.
16
20
  */
17
21
  function generateUUID() {
18
- return new UUID(4).format();
22
+ return new UUID(4).format()
19
23
  }
24
+
20
25
  /**
21
26
  * Runs store key for model.
22
27
  * @param {import("../index.js").default} model - Model instance.
23
28
  * @returns {string} - Store key.
24
29
  */
25
30
  function storeKeyForModel(model) {
26
- return `${model.getModelClass().getDatabaseIdentifier()}`;
31
+ return `${model.getModelClass().getDatabaseIdentifier()}`
27
32
  }
33
+
28
34
  /**
29
35
  * Runs the recordAttachmentsStoreForModel helper.
30
36
  * @param {import("../index.js").default} model - Model instance.
31
37
  * @returns {RecordAttachmentsStore} - Store instance.
32
38
  */
33
39
  export function recordAttachmentsStoreForModel(model) {
34
- const configuration = model._getConfiguration();
35
- let storesByDatabaseIdentifier = storesByConfiguration.get(configuration);
36
- if (!storesByDatabaseIdentifier) {
37
- storesByDatabaseIdentifier = new Map();
38
- storesByConfiguration.set(configuration, storesByDatabaseIdentifier);
39
- }
40
- const key = storeKeyForModel(model);
41
- let store = storesByDatabaseIdentifier.get(key);
42
- if (store)
43
- return store;
44
- store = new RecordAttachmentsStore({
45
- configuration,
46
- databaseIdentifier: model.getModelClass().getDatabaseIdentifier()
47
- });
48
- storesByDatabaseIdentifier.set(key, store);
49
- return store;
40
+ const configuration = model._getConfiguration()
41
+ let storesByDatabaseIdentifier = storesByConfiguration.get(configuration)
42
+
43
+ if (!storesByDatabaseIdentifier) {
44
+ storesByDatabaseIdentifier = new Map()
45
+ storesByConfiguration.set(configuration, storesByDatabaseIdentifier)
46
+ }
47
+
48
+ const key = storeKeyForModel(model)
49
+ let store = storesByDatabaseIdentifier.get(key)
50
+
51
+ if (store) return store
52
+
53
+ store = new RecordAttachmentsStore({
54
+ configuration,
55
+ databaseIdentifier: model.getModelClass().getDatabaseIdentifier()
56
+ })
57
+
58
+ storesByDatabaseIdentifier.set(key, store)
59
+
60
+ return store
50
61
  }
62
+
51
63
  /**
52
64
  * Attachment persistence store.
53
65
  */
54
66
  export default class RecordAttachmentsStore {
67
+ /**
68
+ * Runs constructor.
69
+ * @param {object} args - Options.
70
+ * @param {import("../../../configuration.js").default} args.configuration - Configuration instance.
71
+ * @param {string} args.databaseIdentifier - Database identifier.
72
+ */
73
+ constructor({configuration, databaseIdentifier}) {
74
+ this.configuration = configuration
75
+ this.databaseIdentifier = databaseIdentifier
76
+ this._readyPromise = null
77
+ this._driverColumnsAvailable = false
78
+ this._contentBase64Nullable = true
55
79
  /**
56
- * Runs constructor.
57
- * @param {object} args - Options.
58
- * @param {import("../../../configuration.js").default} args.configuration - Configuration instance.
59
- * @param {string} args.databaseIdentifier - Database identifier.
60
- */
61
- constructor({ configuration, databaseIdentifier }) {
62
- this.configuration = configuration;
63
- this.databaseIdentifier = databaseIdentifier;
64
- this._readyPromise = null;
65
- this._driverColumnsAvailable = false;
66
- this._contentBase64Nullable = true;
67
- /**
68
- * Narrows the runtime value to the documented type.
69
- @type {Map<string, Record<string, ?>>} */
70
- this._attachmentDriversByName = new Map();
71
- /**
72
- * Narrows the runtime value to the documented type.
73
- @type {Map<AttachmentDriverConstructor | Record<string, ?>, Record<string, ?>>} */
74
- this._attachmentDriversByReference = new Map();
75
- }
80
+ * Narrows the runtime value to the documented type.
81
+ @type {Map<string, Record<string, ?>>} */
82
+ this._attachmentDriversByName = new Map()
76
83
  /**
77
- * Runs ensure ready.
78
- * @returns {Promise<void>} - Resolves when schema is ready.
79
- */
80
- async ensureReady() {
81
- if (this._readyPromise) {
82
- await this._readyPromise;
83
- return;
84
- }
85
- this._readyPromise = (async () => {
86
- await this._withDb(async (db) => {
87
- if (await db.tableExists(ATTACHMENTS_TABLE)) {
88
- await this.ensureAttachmentStoreSchema({ db });
89
- return;
90
- }
91
- const table = new TableData(ATTACHMENTS_TABLE, { ifNotExists: true });
92
- table.string("id", { null: false, primaryKey: true });
93
- table.string("record_type", { null: false, index: true });
94
- table.string("record_id", { null: false, index: true });
95
- table.string("name", { null: false, index: true });
96
- table.integer("position", { null: false });
97
- table.string("filename", { null: false });
98
- table.string("content_type", { null: true });
99
- table.bigint("byte_size", { null: false });
100
- table.string("driver", { null: true });
101
- table.string("storage_key", { null: true });
102
- table.text("content_base64", { null: true });
103
- table.bigint("created_at_ms", { null: false });
104
- table.bigint("updated_at_ms", { null: false });
105
- await db.createTable(table);
106
- this._driverColumnsAvailable = true;
107
- this._contentBase64Nullable = true;
108
- });
109
- })();
110
- try {
111
- await this._readyPromise;
84
+ * Narrows the runtime value to the documented type.
85
+ @type {Map<AttachmentDriverConstructor | Record<string, ?>, Record<string, ?>>} */
86
+ this._attachmentDriversByReference = new Map()
87
+ }
88
+
89
+ /**
90
+ * Runs ensure ready.
91
+ * @returns {Promise<void>} - Resolves when schema is ready.
92
+ */
93
+ async ensureReady() {
94
+ if (this._readyPromise) {
95
+ await this._readyPromise
96
+ return
97
+ }
98
+
99
+ this._readyPromise = (async () => {
100
+ await this._withDb(async (db) => {
101
+ if (await db.tableExists(ATTACHMENTS_TABLE)) {
102
+ await this.ensureAttachmentStoreSchema({db})
103
+ return
112
104
  }
113
- finally {
114
- this._readyPromise = null;
105
+
106
+ const table = new TableData(ATTACHMENTS_TABLE, {ifNotExists: true})
107
+
108
+ table.string("id", {null: false, primaryKey: true})
109
+ table.string("record_type", {null: false, index: true})
110
+ table.string("record_id", {null: false, index: true})
111
+ table.string("name", {null: false, index: true})
112
+ table.integer("position", {null: false})
113
+ table.string("filename", {null: false})
114
+ table.string("content_type", {null: true})
115
+ table.bigint("byte_size", {null: false})
116
+ table.string("driver", {null: true})
117
+ table.string("storage_key", {null: true})
118
+ table.text("content_base64", {null: true})
119
+ table.bigint("created_at_ms", {null: false})
120
+ table.bigint("updated_at_ms", {null: false})
121
+
122
+ await db.createTable(table)
123
+ this._driverColumnsAvailable = true
124
+ this._contentBase64Nullable = true
125
+ })
126
+ })()
127
+
128
+ try {
129
+ await this._readyPromise
130
+ } finally {
131
+ this._readyPromise = null
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Runs attach.
137
+ * @param {object} args - Options.
138
+ * @param {import("../index.js").default} args.model - Model instance.
139
+ * @param {string} args.name - Attachment name.
140
+ * @param {?} args.input - Attachment input.
141
+ * @param {boolean} args.replace - Whether to replace existing attachments.
142
+ * @returns {Promise<void>} - Resolves when complete.
143
+ */
144
+ async attach({input, model, name, replace}) {
145
+ await this.ensureReady()
146
+ const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {}
147
+ const allowPathInput = attachmentsConfiguration.allowPathInput === true
148
+ const allowedPathPrefixes = Array.isArray(attachmentsConfiguration.allowedPathPrefixes)
149
+ ? attachmentsConfiguration.allowedPathPrefixes
150
+ : undefined
151
+
152
+ const normalizedInput = await normalizeRecordAttachmentInput(input, {
153
+ allowPathInput,
154
+ allowedPathPrefixes,
155
+ environmentHandler: this.configuration.getEnvironmentHandler()
156
+ })
157
+ const attachmentDriver = await this.resolveAttachmentDriver({model, name})
158
+ const attachmentDriverName = this._attachmentDriverNameFor({model, name})
159
+ const now = Date.now()
160
+ const recordType = model.getModelClass().getModelName()
161
+ const recordId = String(model.id())
162
+ const attachmentId = generateUUID()
163
+ const {storageKey} = await attachmentDriver.write({
164
+ attachmentId,
165
+ input: normalizedInput,
166
+ model,
167
+ name
168
+ })
169
+
170
+ await this._withDb(async (db) => {
171
+ if (replace) {
172
+ const existingRows = await db
173
+ .newQuery()
174
+ .from(ATTACHMENTS_TABLE)
175
+ .where({name, record_id: recordId, record_type: recordType})
176
+ .results()
177
+
178
+ for (const existingRow of existingRows) {
179
+ await this.deleteAttachmentRowStorage({model, name, row: existingRow})
115
180
  }
181
+
182
+ await db.delete({
183
+ conditions: {name, record_id: recordId, record_type: recordType},
184
+ tableName: ATTACHMENTS_TABLE
185
+ })
186
+ }
187
+
188
+ const position = replace ? 0 : await this._nextPosition({db, name, recordId, recordType})
189
+ /**
190
+ * Insert data.
191
+ @type {Record<string, ?>} */
192
+ const insertData = {
193
+ byte_size: normalizedInput.byteSize,
194
+ content_base64: this._contentBase64Nullable ? null : normalizedInput.contentBase64,
195
+ content_type: normalizedInput.contentType,
196
+ created_at_ms: now,
197
+ filename: normalizedInput.filename,
198
+ id: attachmentId,
199
+ name,
200
+ position,
201
+ record_id: recordId,
202
+ record_type: recordType,
203
+ updated_at_ms: now
204
+ }
205
+
206
+ if (this._driverColumnsAvailable) {
207
+ insertData.driver = attachmentDriverName
208
+ insertData.storage_key = storageKey
209
+ }
210
+
211
+ await db.insert({
212
+ data: insertData,
213
+ tableName: ATTACHMENTS_TABLE
214
+ })
215
+ })
216
+ }
217
+
218
+ /**
219
+ * Runs ensure attachment store schema.
220
+ * @param {object} args - Options.
221
+ * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
222
+ * @returns {Promise<void>} - Resolves when schema columns are ensured.
223
+ */
224
+ async ensureAttachmentStoreSchema({db}) {
225
+ const table = await db.getTableByNameOrFail(ATTACHMENTS_TABLE)
226
+ const columns = await table.getColumns()
227
+ const hasDriverColumn = columns.some((column) => column.getName() === "driver")
228
+ const hasStorageKeyColumn = columns.some((column) => column.getName() === "storage_key")
229
+ const contentBase64Column = columns.find((column) => column.getName() === "content_base64")
230
+ const alterTable = new TableData(ATTACHMENTS_TABLE)
231
+ let shouldAlter = false
232
+
233
+ if (!hasDriverColumn) {
234
+ alterTable.string("driver", {null: true})
235
+ shouldAlter = true
116
236
  }
117
- /**
118
- * Runs attach.
119
- * @param {object} args - Options.
120
- * @param {import("../index.js").default} args.model - Model instance.
121
- * @param {string} args.name - Attachment name.
122
- * @param {?} args.input - Attachment input.
123
- * @param {boolean} args.replace - Whether to replace existing attachments.
124
- * @returns {Promise<void>} - Resolves when complete.
125
- */
126
- async attach({ input, model, name, replace }) {
127
- await this.ensureReady();
128
- const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {};
129
- const allowPathInput = attachmentsConfiguration.allowPathInput === true;
130
- const allowedPathPrefixes = Array.isArray(attachmentsConfiguration.allowedPathPrefixes)
131
- ? attachmentsConfiguration.allowedPathPrefixes
132
- : undefined;
133
- const normalizedInput = await normalizeRecordAttachmentInput(input, {
134
- allowPathInput,
135
- allowedPathPrefixes,
136
- environmentHandler: this.configuration.getEnvironmentHandler()
137
- });
138
- const attachmentDriver = await this.resolveAttachmentDriver({ model, name });
139
- const attachmentDriverName = this._attachmentDriverNameFor({ model, name });
140
- const now = Date.now();
141
- const recordType = model.getModelClass().getModelName();
142
- const recordId = String(model.id());
143
- const attachmentId = generateUUID();
144
- const { storageKey } = await attachmentDriver.write({
145
- attachmentId,
146
- input: normalizedInput,
147
- model,
148
- name
149
- });
150
- await this._withDb(async (db) => {
151
- if (replace) {
152
- const existingRows = await db
153
- .newQuery()
154
- .from(ATTACHMENTS_TABLE)
155
- .where({ name, record_id: recordId, record_type: recordType })
156
- .results();
157
- for (const existingRow of existingRows) {
158
- await this.deleteAttachmentRowStorage({ model, name, row: existingRow });
159
- }
160
- await db.delete({
161
- conditions: { name, record_id: recordId, record_type: recordType },
162
- tableName: ATTACHMENTS_TABLE
163
- });
164
- }
165
- const position = replace ? 0 : await this._nextPosition({ db, name, recordId, recordType });
166
- /**
167
- * Insert data.
168
- @type {Record<string, ?>} */
169
- const insertData = {
170
- byte_size: normalizedInput.byteSize,
171
- content_base64: this._contentBase64Nullable ? null : normalizedInput.contentBase64,
172
- content_type: normalizedInput.contentType,
173
- created_at_ms: now,
174
- filename: normalizedInput.filename,
175
- id: attachmentId,
176
- name,
177
- position,
178
- record_id: recordId,
179
- record_type: recordType,
180
- updated_at_ms: now
181
- };
182
- if (this._driverColumnsAvailable) {
183
- insertData.driver = attachmentDriverName;
184
- insertData.storage_key = storageKey;
185
- }
186
- await db.insert({
187
- data: insertData,
188
- tableName: ATTACHMENTS_TABLE
189
- });
190
- });
237
+
238
+ if (!hasStorageKeyColumn) {
239
+ alterTable.string("storage_key", {null: true})
240
+ shouldAlter = true
191
241
  }
192
- /**
193
- * Runs ensure attachment store schema.
194
- * @param {object} args - Options.
195
- * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
196
- * @returns {Promise<void>} - Resolves when schema columns are ensured.
197
- */
198
- async ensureAttachmentStoreSchema({ db }) {
199
- const table = await db.getTableByNameOrFail(ATTACHMENTS_TABLE);
200
- const columns = await table.getColumns();
201
- const hasDriverColumn = columns.some((column) => column.getName() === "driver");
202
- const hasStorageKeyColumn = columns.some((column) => column.getName() === "storage_key");
203
- const contentBase64Column = columns.find((column) => column.getName() === "content_base64");
204
- const alterTable = new TableData(ATTACHMENTS_TABLE);
205
- let shouldAlter = false;
206
- if (!hasDriverColumn) {
207
- alterTable.string("driver", { null: true });
208
- shouldAlter = true;
209
- }
210
- if (!hasStorageKeyColumn) {
211
- alterTable.string("storage_key", { null: true });
212
- shouldAlter = true;
213
- }
214
- if (shouldAlter) {
215
- const alterTableSQLs = await db.alterTableSQLs(alterTable);
216
- for (const sql of alterTableSQLs) {
217
- await db.query(sql);
218
- }
219
- }
220
- this._driverColumnsAvailable = true;
221
- this._contentBase64Nullable = contentBase64Column ? contentBase64Column.getNull() : true;
242
+
243
+ if (shouldAlter) {
244
+ const alterTableSQLs = await db.alterTableSQLs(alterTable)
245
+
246
+ for (const sql of alterTableSQLs) {
247
+ await db.query(sql)
248
+ }
222
249
  }
223
- /**
224
- * Runs read attachment row.
225
- * @param {object} args - Options.
226
- * @param {import("../index.js").default} args.model - Model instance.
227
- * @param {string} args.name - Attachment name.
228
- * @param {Record<string, ?>} args.row - Attachment row.
229
- * @returns {Promise<Buffer>} - Attachment bytes.
230
- */
231
- async readAttachmentRow({ model, name, row }) {
232
- if (typeof row.content_base64 === "string" && row.content_base64.length > 0) {
233
- return Buffer.from(row.content_base64, "base64");
234
- }
235
- const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null;
236
- if (!storageKey) {
237
- throw new Error(`Attachment row ${String(row.id)} is missing storage key`);
238
- }
239
- const attachmentDriver = await this.resolveAttachmentDriver({ model, name, row });
240
- return await attachmentDriver.read({
241
- model,
242
- name,
243
- row,
244
- storageKey
245
- });
250
+
251
+ this._driverColumnsAvailable = true
252
+ this._contentBase64Nullable = contentBase64Column ? contentBase64Column.getNull() : true
253
+ }
254
+
255
+ /**
256
+ * Runs read attachment row.
257
+ * @param {object} args - Options.
258
+ * @param {import("../index.js").default} args.model - Model instance.
259
+ * @param {string} args.name - Attachment name.
260
+ * @param {Record<string, ?>} args.row - Attachment row.
261
+ * @returns {Promise<Buffer>} - Attachment bytes.
262
+ */
263
+ async readAttachmentRow({model, name, row}) {
264
+ if (typeof row.content_base64 === "string" && row.content_base64.length > 0) {
265
+ return Buffer.from(row.content_base64, "base64")
246
266
  }
247
- /**
248
- * Runs attachment row url.
249
- * @param {object} args - Options.
250
- * @param {import("../index.js").default} args.model - Model instance.
251
- * @param {string} args.name - Attachment name.
252
- * @param {Record<string, ?>} args.row - Attachment row.
253
- * @returns {Promise<string | null>} - Attachment URL.
254
- */
255
- async attachmentRowUrl({ model, name, row }) {
256
- const attachmentDriver = await this.resolveAttachmentDriver({ model, name, row });
257
- if (typeof attachmentDriver.url !== "function")
258
- return null;
259
- const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0
260
- ? row.storage_key
261
- : (typeof row.id === "string" ? row.id : "");
262
- if (!storageKey)
263
- return null;
264
- return await attachmentDriver.url({
265
- model,
266
- name,
267
- row,
268
- storageKey
269
- });
267
+
268
+ const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null
269
+
270
+ if (!storageKey) {
271
+ throw new Error(`Attachment row ${String(row.id)} is missing storage key`)
270
272
  }
271
- /**
272
- * Runs find one.
273
- * @param {object} args - Options.
274
- * @param {import("../index.js").default} args.model - Model instance.
275
- * @param {string} args.name - Attachment name.
276
- * @param {string} [args.id] - Optional attachment id.
277
- * @returns {Promise<Record<string, ?> | null>} - Attachment row.
278
- */
279
- async findOne({ id, model, name }) {
280
- await this.ensureReady();
281
- return await this._withDb(async (db) => {
282
- const recordType = model.getModelClass().getModelName();
283
- const recordId = String(model.id());
284
- let query = db
285
- .newQuery()
286
- .from(ATTACHMENTS_TABLE)
287
- .where({ name, record_id: recordId, record_type: recordType })
288
- .order("position ASC")
289
- .order("created_at_ms DESC")
290
- .limit(1);
291
- if (id) {
292
- query = query.where({ id });
293
- }
294
- const rows = await query.results();
295
- return rows[0] || null;
296
- });
273
+
274
+ const attachmentDriver = await this.resolveAttachmentDriver({model, name, row})
275
+
276
+ return await attachmentDriver.read({
277
+ model,
278
+ name,
279
+ row,
280
+ storageKey
281
+ })
282
+ }
283
+
284
+ /**
285
+ * Runs attachment row url.
286
+ * @param {object} args - Options.
287
+ * @param {import("../index.js").default} args.model - Model instance.
288
+ * @param {string} args.name - Attachment name.
289
+ * @param {Record<string, ?>} args.row - Attachment row.
290
+ * @returns {Promise<string | null>} - Attachment URL.
291
+ */
292
+ async attachmentRowUrl({model, name, row}) {
293
+ const attachmentDriver = await this.resolveAttachmentDriver({model, name, row})
294
+
295
+ if (typeof attachmentDriver.url !== "function") return null
296
+
297
+ const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0
298
+ ? row.storage_key
299
+ : (typeof row.id === "string" ? row.id : "")
300
+
301
+ if (!storageKey) return null
302
+
303
+ return await attachmentDriver.url({
304
+ model,
305
+ name,
306
+ row,
307
+ storageKey
308
+ })
309
+ }
310
+
311
+ /**
312
+ * Runs find one.
313
+ * @param {object} args - Options.
314
+ * @param {import("../index.js").default} args.model - Model instance.
315
+ * @param {string} args.name - Attachment name.
316
+ * @param {string} [args.id] - Optional attachment id.
317
+ * @returns {Promise<Record<string, ?> | null>} - Attachment row.
318
+ */
319
+ async findOne({id, model, name}) {
320
+ await this.ensureReady()
321
+
322
+ return await this._withDb(async (db) => {
323
+ const recordType = model.getModelClass().getModelName()
324
+ const recordId = String(model.id())
325
+ let query = db
326
+ .newQuery()
327
+ .from(ATTACHMENTS_TABLE)
328
+ .where({name, record_id: recordId, record_type: recordType})
329
+ .order("position ASC")
330
+ .order("created_at_ms DESC")
331
+ .limit(1)
332
+
333
+ if (id) {
334
+ query = query.where({id})
335
+ }
336
+
337
+ const rows = await query.results()
338
+
339
+ return rows[0] || null
340
+ })
341
+ }
342
+
343
+ /**
344
+ * Runs find many.
345
+ * @param {object} args - Options.
346
+ * @param {import("../index.js").default} args.model - Model instance.
347
+ * @param {string} args.name - Attachment name.
348
+ * @returns {Promise<Array<Record<string, ?>>>} - Attachment rows.
349
+ */
350
+ async findMany({model, name}) {
351
+ await this.ensureReady()
352
+
353
+ return await this._withDb(async (db) => {
354
+ const recordType = model.getModelClass().getModelName()
355
+ const recordId = String(model.id())
356
+ const query = db
357
+ .newQuery()
358
+ .from(ATTACHMENTS_TABLE)
359
+ .where({name, record_id: recordId, record_type: recordType})
360
+ .order("position ASC")
361
+ .order("created_at_ms ASC")
362
+
363
+ return await query.results()
364
+ })
365
+ }
366
+
367
+ /**
368
+ * Runs delete attachment row storage.
369
+ * @param {object} args - Options.
370
+ * @param {import("../index.js").default} args.model - Model instance.
371
+ * @param {string} args.name - Attachment name.
372
+ * @param {Record<string, ?>} args.row - Attachment row.
373
+ * @returns {Promise<void>} - Resolves when row storage has been deleted.
374
+ */
375
+ async deleteAttachmentRowStorage({model, name, row}) {
376
+ const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null
377
+
378
+ if (!storageKey) return
379
+
380
+ const attachmentDriver = await this.resolveAttachmentDriver({model, name, row})
381
+
382
+ if (typeof attachmentDriver.delete !== "function") return
383
+
384
+ await attachmentDriver.delete({
385
+ model,
386
+ name,
387
+ row,
388
+ storageKey
389
+ })
390
+ }
391
+
392
+ /**
393
+ * Runs attachment driver by name.
394
+ * @param {string} driverName - Driver name.
395
+ * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
396
+ */
397
+ async attachmentDriverByName(driverName) {
398
+ if (this._attachmentDriversByName.has(driverName)) {
399
+ return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByName.get(driverName))
297
400
  }
401
+
402
+ const attachmentConfiguration = this.configuration.getAttachmentsConfiguration?.() || {}
403
+ const configuredDriver = attachmentConfiguration.drivers?.[driverName]
298
404
  /**
299
- * Runs find many.
300
- * @param {object} args - Options.
301
- * @param {import("../index.js").default} args.model - Model instance.
302
- * @param {string} args.name - Attachment name.
303
- * @returns {Promise<Array<Record<string, ?>>>} - Attachment rows.
304
- */
305
- async findMany({ model, name }) {
306
- await this.ensureReady();
307
- return await this._withDb(async (db) => {
308
- const recordType = model.getModelClass().getModelName();
309
- const recordId = String(model.id());
310
- const query = db
311
- .newQuery()
312
- .from(ATTACHMENTS_TABLE)
313
- .where({ name, record_id: recordId, record_type: recordType })
314
- .order("position ASC")
315
- .order("created_at_ms ASC");
316
- return await query.results();
317
- });
405
+ * Defines attachmentDriver.
406
+ @type {Record<string, ?>} */
407
+ let attachmentDriver
408
+
409
+ if (!configuredDriver) {
410
+ throw new Error(`No configured attachment storage driver named "${driverName}"`)
411
+ } else if (configuredDriver.instance && typeof configuredDriver.instance === "object") {
412
+ attachmentDriver = configuredDriver.instance
413
+ } else if (typeof configuredDriver.driverClass === "function") {
414
+ attachmentDriver = new configuredDriver.driverClass({
415
+ configuration: this.configuration,
416
+ name: driverName,
417
+ options: configuredDriver
418
+ })
419
+ } else if (typeof configuredDriver.create === "function") {
420
+ attachmentDriver = configuredDriver.create({
421
+ configuration: this.configuration,
422
+ name: driverName,
423
+ options: configuredDriver
424
+ })
425
+ } else {
426
+ throw new Error(`Attachment storage driver "${driverName}" must define instance, driverClass, or create`)
318
427
  }
319
- /**
320
- * Runs delete attachment row storage.
321
- * @param {object} args - Options.
322
- * @param {import("../index.js").default} args.model - Model instance.
323
- * @param {string} args.name - Attachment name.
324
- * @param {Record<string, ?>} args.row - Attachment row.
325
- * @returns {Promise<void>} - Resolves when row storage has been deleted.
326
- */
327
- async deleteAttachmentRowStorage({ model, name, row }) {
328
- const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null;
329
- if (!storageKey)
330
- return;
331
- const attachmentDriver = await this.resolveAttachmentDriver({ model, name, row });
332
- if (typeof attachmentDriver.delete !== "function")
333
- return;
334
- await attachmentDriver.delete({
335
- model,
336
- name,
337
- row,
338
- storageKey
339
- });
428
+
429
+ if (!attachmentDriver || typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
430
+ throw new Error(`Attachment storage driver "${driverName}" must implement write/read`)
340
431
  }
341
- /**
342
- * Runs attachment driver by name.
343
- * @param {string} driverName - Driver name.
344
- * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
345
- */
346
- async attachmentDriverByName(driverName) {
347
- if (this._attachmentDriversByName.has(driverName)) {
348
- return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByName.get(driverName));
349
- }
350
- const attachmentConfiguration = this.configuration.getAttachmentsConfiguration?.() || {};
351
- const configuredDriver = attachmentConfiguration.drivers?.[driverName];
352
- /**
353
- * Defines attachmentDriver.
354
- @type {Record<string, ?>} */
355
- let attachmentDriver;
356
- if (!configuredDriver) {
357
- throw new Error(`No configured attachment storage driver named "${driverName}"`);
358
- }
359
- else if (configuredDriver.instance && typeof configuredDriver.instance === "object") {
360
- attachmentDriver = configuredDriver.instance;
361
- }
362
- else if (typeof configuredDriver.driverClass === "function") {
363
- attachmentDriver = new configuredDriver.driverClass({
364
- configuration: this.configuration,
365
- name: driverName,
366
- options: configuredDriver
367
- });
368
- }
369
- else if (typeof configuredDriver.create === "function") {
370
- attachmentDriver = configuredDriver.create({
371
- configuration: this.configuration,
372
- name: driverName,
373
- options: configuredDriver
374
- });
375
- }
376
- else {
377
- throw new Error(`Attachment storage driver "${driverName}" must define instance, driverClass, or create`);
378
- }
379
- if (!attachmentDriver || typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
380
- throw new Error(`Attachment storage driver "${driverName}" must implement write/read`);
381
- }
382
- this._attachmentDriversByName.set(driverName, attachmentDriver);
383
- return attachmentDriver;
432
+
433
+ this._attachmentDriversByName.set(driverName, attachmentDriver)
434
+
435
+ return attachmentDriver
436
+ }
437
+
438
+ /**
439
+ * Runs attachment driver by reference.
440
+ * @param {object} args - Options.
441
+ * @param {AttachmentDriverConstructor | Record<string, ?>} args.driverReference - Driver class or instance.
442
+ * @param {string} args.attachmentName - Attachment name.
443
+ * @param {typeof import("../index.js").default} args.modelClass - Model class.
444
+ * @returns {Record<string, ?>} - Attachment driver instance.
445
+ */
446
+ attachmentDriverByReference({attachmentName, driverReference, modelClass}) {
447
+ if (this._attachmentDriversByReference.has(driverReference)) {
448
+ return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByReference.get(driverReference))
384
449
  }
450
+
385
451
  /**
386
- * Runs attachment driver by reference.
387
- * @param {object} args - Options.
388
- * @param {AttachmentDriverConstructor | Record<string, ?>} args.driverReference - Driver class or instance.
389
- * @param {string} args.attachmentName - Attachment name.
390
- * @param {typeof import("../index.js").default} args.modelClass - Model class.
391
- * @returns {Record<string, ?>} - Attachment driver instance.
392
- */
393
- attachmentDriverByReference({ attachmentName, driverReference, modelClass }) {
394
- if (this._attachmentDriversByReference.has(driverReference)) {
395
- return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByReference.get(driverReference));
396
- }
397
- /**
398
- * Defines attachmentDriver.
399
- @type {Record<string, ?>} */
400
- let attachmentDriver;
401
- if (typeof driverReference === "function") {
402
- const DriverClass = /**
403
- * Narrows the runtime value to the documented type.
404
- @type {AttachmentDriverConstructor} */ (driverReference);
405
- attachmentDriver = new DriverClass({
406
- attachmentName,
407
- configuration: this.configuration,
408
- modelClass
409
- });
410
- }
411
- else if (driverReference && typeof driverReference === "object") {
412
- attachmentDriver = driverReference;
413
- }
414
- else {
415
- throw new Error(`Invalid attachment driver reference for ${modelClass.name}#${attachmentName}`);
416
- }
417
- if (typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
418
- throw new Error(`Attachment driver for ${modelClass.name}#${attachmentName} must implement write/read`);
419
- }
420
- this._attachmentDriversByReference.set(driverReference, attachmentDriver);
421
- return attachmentDriver;
452
+ * Defines attachmentDriver.
453
+ @type {Record<string, ?>} */
454
+ let attachmentDriver
455
+
456
+ if (typeof driverReference === "function") {
457
+ const DriverClass = /**
458
+ * Narrows the runtime value to the documented type.
459
+ @type {AttachmentDriverConstructor} */ (driverReference)
460
+
461
+ attachmentDriver = new DriverClass({
462
+ attachmentName,
463
+ configuration: this.configuration,
464
+ modelClass
465
+ })
466
+ } else if (driverReference && typeof driverReference === "object") {
467
+ attachmentDriver = driverReference
468
+ } else {
469
+ throw new Error(`Invalid attachment driver reference for ${modelClass.name}#${attachmentName}`)
422
470
  }
423
- /**
424
- * Runs attachment driver name for.
425
- * @param {object} args - Options.
426
- * @param {import("../index.js").default} args.model - Model instance.
427
- * @param {string} args.name - Attachment name.
428
- * @returns {string} - Attachment driver name.
429
- */
430
- _attachmentDriverNameFor({ model, name }) {
431
- const attachmentDefinition = model.getModelClass().getAttachmentByName(name);
432
- const configuredDriver = attachmentDefinition.driver;
433
- const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {};
434
- const defaultDriver = attachmentsConfiguration.defaultDriver;
435
- if (typeof configuredDriver === "string" && configuredDriver.length > 0) {
436
- return configuredDriver;
437
- }
438
- if (typeof configuredDriver === "function") {
439
- return configuredDriver.name || "custom";
440
- }
441
- if (configuredDriver && typeof configuredDriver === "object") {
442
- const constructorName = configuredDriver.constructor?.name;
443
- if (typeof constructorName === "string" && constructorName.length > 0 && constructorName !== "Object") {
444
- return constructorName;
445
- }
446
- return "custom";
447
- }
448
- if (typeof defaultDriver === "string" && defaultDriver.length > 0) {
449
- return defaultDriver;
450
- }
451
- throw new Error(`No attachment driver configured for ${model.getModelClass().name}#${name}`);
471
+
472
+ if (typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
473
+ throw new Error(`Attachment driver for ${modelClass.name}#${attachmentName} must implement write/read`)
452
474
  }
453
- /**
454
- * Runs resolve attachment driver.
455
- * @param {object} args - Options.
456
- * @param {import("../index.js").default} args.model - Model instance.
457
- * @param {string} args.name - Attachment name.
458
- * @param {Record<string, ?>} [args.row] - Attachment row.
459
- * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
460
- */
461
- async resolveAttachmentDriver({ model, name, row }) {
462
- const attachmentDefinition = model.getModelClass().getAttachmentByName(name);
463
- const configuredDriver = attachmentDefinition.driver;
464
- if (typeof configuredDriver === "function" || (configuredDriver && typeof configuredDriver === "object")) {
465
- return this.attachmentDriverByReference({
466
- attachmentName: name,
467
- driverReference: configuredDriver,
468
- modelClass: model.getModelClass()
469
- });
470
- }
471
- const fallbackDriverName = typeof row?.driver === "string" && row.driver.length > 0
472
- ? row.driver
473
- : this._attachmentDriverNameFor({ model, name });
474
- return await this.attachmentDriverByName(fallbackDriverName);
475
+
476
+ this._attachmentDriversByReference.set(driverReference, attachmentDriver)
477
+
478
+ return attachmentDriver
479
+ }
480
+
481
+ /**
482
+ * Runs attachment driver name for.
483
+ * @param {object} args - Options.
484
+ * @param {import("../index.js").default} args.model - Model instance.
485
+ * @param {string} args.name - Attachment name.
486
+ * @returns {string} - Attachment driver name.
487
+ */
488
+ _attachmentDriverNameFor({model, name}) {
489
+ const attachmentDefinition = model.getModelClass().getAttachmentByName(name)
490
+ const configuredDriver = attachmentDefinition.driver
491
+ const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {}
492
+ const defaultDriver = attachmentsConfiguration.defaultDriver
493
+
494
+ if (typeof configuredDriver === "string" && configuredDriver.length > 0) {
495
+ return configuredDriver
475
496
  }
476
- /**
477
- * Runs next position.
478
- * @param {object} args - Options.
479
- * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
480
- * @param {string} args.name - Attachment name.
481
- * @param {string} args.recordId - Record id.
482
- * @param {string} args.recordType - Record type.
483
- * @returns {Promise<number>} - Next position.
484
- */
485
- async _nextPosition({ db, name, recordId, recordType }) {
486
- const query = db
487
- .newQuery()
488
- .from(ATTACHMENTS_TABLE)
489
- .where({ name, record_id: recordId, record_type: recordType })
490
- .order("position DESC")
491
- .limit(1);
492
- const rows = await query.results();
493
- const currentRow = /**
494
- * Narrows the runtime value to the documented type.
495
- @type {{position?: string | number | null} | undefined} */ (rows[0]);
496
- const current = Number(currentRow?.position);
497
- if (!Number.isFinite(current))
498
- return 0;
499
- return current + 1;
497
+
498
+ if (typeof configuredDriver === "function") {
499
+ return configuredDriver.name || "custom"
500
500
  }
501
- /**
502
- * Runs with db.
503
- * @template T
504
- * @param {(db: import("../../../database/drivers/base.js").default) => Promise<T>} callback - Callback.
505
- * @returns {Promise<T>} - Callback result.
506
- */
507
- async _withDb(callback) {
508
- const pool = this.configuration.getDatabasePool(this.databaseIdentifier);
509
- /**
510
- * Defines result.
511
- @type {T | undefined} */
512
- let result;
513
- await pool.withConnection({ name: "Record attachment store" }, async (db) => {
514
- result = await callback(db);
515
- });
516
- return /** Narrows the runtime value to the documented type. @type {T} */ (result);
501
+
502
+ if (configuredDriver && typeof configuredDriver === "object") {
503
+ const constructorName = configuredDriver.constructor?.name
504
+
505
+ if (typeof constructorName === "string" && constructorName.length > 0 && constructorName !== "Object") {
506
+ return constructorName
507
+ }
508
+
509
+ return "custom"
510
+ }
511
+
512
+ if (typeof defaultDriver === "string" && defaultDriver.length > 0) {
513
+ return defaultDriver
517
514
  }
515
+
516
+ throw new Error(`No attachment driver configured for ${model.getModelClass().name}#${name}`)
517
+ }
518
+
519
+ /**
520
+ * Runs resolve attachment driver.
521
+ * @param {object} args - Options.
522
+ * @param {import("../index.js").default} args.model - Model instance.
523
+ * @param {string} args.name - Attachment name.
524
+ * @param {Record<string, ?>} [args.row] - Attachment row.
525
+ * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
526
+ */
527
+ async resolveAttachmentDriver({model, name, row}) {
528
+ const attachmentDefinition = model.getModelClass().getAttachmentByName(name)
529
+ const configuredDriver = attachmentDefinition.driver
530
+ if (typeof configuredDriver === "function" || (configuredDriver && typeof configuredDriver === "object")) {
531
+ return this.attachmentDriverByReference({
532
+ attachmentName: name,
533
+ driverReference: configuredDriver,
534
+ modelClass: model.getModelClass()
535
+ })
536
+ }
537
+
538
+ const fallbackDriverName = typeof row?.driver === "string" && row.driver.length > 0
539
+ ? row.driver
540
+ : this._attachmentDriverNameFor({model, name})
541
+
542
+ return await this.attachmentDriverByName(fallbackDriverName)
543
+ }
544
+
545
+ /**
546
+ * Runs next position.
547
+ * @param {object} args - Options.
548
+ * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
549
+ * @param {string} args.name - Attachment name.
550
+ * @param {string} args.recordId - Record id.
551
+ * @param {string} args.recordType - Record type.
552
+ * @returns {Promise<number>} - Next position.
553
+ */
554
+ async _nextPosition({db, name, recordId, recordType}) {
555
+ const query = db
556
+ .newQuery()
557
+ .from(ATTACHMENTS_TABLE)
558
+ .where({name, record_id: recordId, record_type: recordType})
559
+ .order("position DESC")
560
+ .limit(1)
561
+ const rows = await query.results()
562
+ const currentRow = /**
563
+ * Narrows the runtime value to the documented type.
564
+ @type {{position?: string | number | null} | undefined} */ (rows[0])
565
+ const current = Number(currentRow?.position)
566
+
567
+ if (!Number.isFinite(current)) return 0
568
+
569
+ return current + 1
570
+ }
571
+
572
+ /**
573
+ * Runs with db.
574
+ * @template T
575
+ * @param {(db: import("../../../database/drivers/base.js").default) => Promise<T>} callback - Callback.
576
+ * @returns {Promise<T>} - Callback result.
577
+ */
578
+ async _withDb(callback) {
579
+ const pool = this.configuration.getDatabasePool(this.databaseIdentifier)
580
+ /**
581
+ * Defines result.
582
+ @type {T | undefined} */
583
+ let result
584
+
585
+ await pool.withConnection({name: "Record attachment store"}, async (db) => {
586
+ result = await callback(db)
587
+ })
588
+
589
+ return /** Narrows the runtime value to the documented type. @type {T} */ (result)
590
+ }
518
591
  }
519
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvZGF0YWJhc2UvcmVjb3JkL2F0dGFjaG1lbnRzL3N0b3JlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLElBQUksTUFBTSxXQUFXLENBQUE7QUFDNUIsT0FBTyxTQUFTLE1BQU0sMkJBQTJCLENBQUE7QUFDakQsT0FBTyw4QkFBOEIsTUFBTSxzQkFBc0IsQ0FBQTtBQUVqRSxNQUFNLGlCQUFpQixHQUFHLHVCQUF1QixDQUFBO0FBRWpEOzt3RkFFd0Y7QUFDeEY7O3NHQUVzRztBQUN0RyxNQUFNLHFCQUFxQixHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7QUFFM0M7OztHQUdHO0FBQ0gsU0FBUyxZQUFZO0lBQ25CLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUE7QUFDN0IsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGdCQUFnQixDQUFDLEtBQUs7SUFDN0IsT0FBTyxHQUFHLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLENBQUE7QUFDM0QsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsOEJBQThCLENBQUMsS0FBSztJQUNsRCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtJQUMvQyxJQUFJLDBCQUEwQixHQUFHLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQTtJQUV6RSxJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUNoQywwQkFBMEIsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO1FBQ3RDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsMEJBQTBCLENBQUMsQ0FBQTtJQUN0RSxDQUFDO0lBRUQsTUFBTSxHQUFHLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUE7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Q0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztZQUFFLE9BQU8sQ0FBQyxDQUFBO1FBRXZDLE9BQU8sT0FBTyxHQUFHLENBQUMsQ0FBQTtJQUNwQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVE7UUFDcEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUE7UUFDeEU7O2tDQUUwQjtRQUMxQixJQUFJLE1BQU0sQ0FBQTtRQUVWLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFDLElBQUksRUFBRSx5QkFBeUIsRUFBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUN4RSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDN0IsQ0FBQyxDQUFDLENBQUE7UUFFRixPQUFPLGtFQUFrRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDcEYsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBVVUlEIGZyb20gXCJwdXJlLXV1aWRcIlxuaW1wb3J0IFRhYmxlRGF0YSBmcm9tIFwiLi4vLi4vdGFibGUtZGF0YS9pbmRleC5qc1wiXG5pbXBvcnQgbm9ybWFsaXplUmVjb3JkQXR0YWNobWVudElucHV0IGZyb20gXCIuL25vcm1hbGl6ZS1pbnB1dC5qc1wiXG5cbmNvbnN0IEFUVEFDSE1FTlRTX1RBQkxFID0gXCJ2ZWxvY2lvdXNfYXR0YWNobWVudHNcIlxuXG4vKipcbiAqIEF0dGFjaG1lbnREcml2ZXJDb25zdHJ1Y3RvciB0eXBlLlxuICBAdHlwZWRlZiB7bmV3ICguLi5hcmdzOiBBcnJheTw/PikgPT4gUmVjb3JkPHN0cmluZywgPz59IEF0dGFjaG1lbnREcml2ZXJDb25zdHJ1Y3RvciAqL1xuLyoqXG4gKiBTdG9yZXMgYnkgY29uZmlndXJhdGlvbi5cbiAgQHR5cGUge1dlYWtNYXA8aW1wb3J0KFwiLi4vLi4vLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0LCBNYXA8c3RyaW5nLCBSZWNvcmRBdHRhY2htZW50c1N0b3JlPj59ICovXG5jb25zdCBzdG9yZXNCeUNvbmZpZ3VyYXRpb24gPSBuZXcgV2Vha01hcCgpXG5cbi8qKlxuICogUnVucyBnZW5lcmF0ZSB1dWlkLlxuICogQHJldHVybnMge3N0cmluZ30gLSBHZW5lcmF0ZWQgVVVJRCB2NCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVVVUlEKCkge1xuICByZXR1cm4gbmV3IFVVSUQoNCkuZm9ybWF0KClcbn1cblxuLyoqXG4gKiBSdW5zIHN0b3JlIGtleSBmb3IgbW9kZWwuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2luZGV4LmpzXCIpLmRlZmF1bHR9IG1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIFN0b3JlIGtleS5cbiAqL1xuZnVuY3Rpb24gc3RvcmVLZXlGb3JNb2RlbChtb2RlbCkge1xuICByZXR1cm4gYCR7bW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldERhdGFiYXNlSWRlbnRpZmllcigpfWBcbn1cblxuLyoqXG4gKiBSdW5zIHRoZSByZWNvcmRBdHRhY2htZW50c1N0b3JlRm9yTW9kZWwgaGVscGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBtb2RlbCAtIE1vZGVsIGluc3RhbmNlLlxuICogQHJldHVybnMge1JlY29yZEF0dGFjaG1lbnRzU3RvcmV9IC0gU3RvcmUgaW5zdGFuY2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWNvcmRBdHRhY2htZW50c1N0b3JlRm9yTW9kZWwobW9kZWwpIHtcbiAgY29uc3QgY29uZmlndXJhdGlvbiA9IG1vZGVsLl9nZXRDb25maWd1cmF0aW9uKClcbiAgbGV0IHN0b3Jlc0J5RGF0YWJhc2VJZGVudGlmaWVyID0gc3RvcmVzQnlDb25maWd1cmF0aW9uLmdldChjb25maWd1cmF0aW9uKVxuXG4gIGlmICghc3RvcmVzQnlEYXRhYmFzZUlkZW50aWZpZXIpIHtcbiAgICBzdG9yZXNCeURhdGFiYXNlSWRlbnRpZmllciA9IG5ldyBNYXAoKVxuICAgIHN0b3Jlc0J5Q29uZmlndXJhdGlvbi5zZXQoY29uZmlndXJhdGlvbiwgc3RvcmVzQnlEYXRhYmFzZUlkZW50aWZpZXIpXG4gIH1cblxuICBjb25zdCBrZXkgPSBzdG9yZUtleUZvck1vZGVsKG1vZGVsKVxuICBsZXQgc3RvcmUgPSBzdG9yZXNCeURhdGFiYXNlSWRlbnRpZmllci5nZXQoa2V5KVxuXG4gIGlmIChzdG9yZSkgcmV0dXJuIHN0b3JlXG5cbiAgc3RvcmUgPSBuZXcgUmVjb3JkQXR0YWNobWVudHNTdG9yZSh7XG4gICAgY29uZmlndXJhdGlvbixcbiAgICBkYXRhYmFzZUlkZW50aWZpZXI6IG1vZGVsLmdldE1vZGVsQ2xhc3MoKS5nZXREYXRhYmFzZUlkZW50aWZpZXIoKVxuICB9KVxuXG4gIHN0b3Jlc0J5RGF0YWJhc2VJZGVudGlmaWVyLnNldChrZXksIHN0b3JlKVxuXG4gIHJldHVybiBzdG9yZVxufVxuXG4vKipcbiAqIEF0dGFjaG1lbnQgcGVyc2lzdGVuY2Ugc3RvcmUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlY29yZEF0dGFjaG1lbnRzU3RvcmUge1xuICAvKipcbiAgICogUnVucyBjb25zdHJ1Y3Rvci5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uLy4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gYXJncy5jb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuZGF0YWJhc2VJZGVudGlmaWVyIC0gRGF0YWJhc2UgaWRlbnRpZmllci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb25maWd1cmF0aW9uLCBkYXRhYmFzZUlkZW50aWZpZXJ9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIHRoaXMuZGF0YWJhc2VJZGVudGlmaWVyID0gZGF0YWJhc2VJZGVudGlmaWVyXG4gICAgdGhpcy5fcmVhZHlQcm9taXNlID0gbnVsbFxuICAgIHRoaXMuX2RyaXZlckNvbHVtbnNBdmFpbGFibGUgPSBmYWxzZVxuICAgIHRoaXMuX2NvbnRlbnRCYXNlNjROdWxsYWJsZSA9IHRydWVcbiAgICAvKipcbiAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICBAdHlwZSB7TWFwPHN0cmluZywgUmVjb3JkPHN0cmluZywgPz4+fSAqL1xuICAgIHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlOYW1lID0gbmV3IE1hcCgpXG4gICAgLyoqXG4gICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgQHR5cGUge01hcDxBdHRhY2htZW50RHJpdmVyQ29uc3RydWN0b3IgfCBSZWNvcmQ8c3RyaW5nLCA/PiwgUmVjb3JkPHN0cmluZywgPz4+fSAqL1xuICAgIHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlSZWZlcmVuY2UgPSBuZXcgTWFwKClcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGVuc3VyZSByZWFkeS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBzY2hlbWEgaXMgcmVhZHkuXG4gICAqL1xuICBhc3luYyBlbnN1cmVSZWFkeSgpIHtcbiAgICBpZiAodGhpcy5fcmVhZHlQcm9taXNlKSB7XG4gICAgICBhd2FpdCB0aGlzLl9yZWFkeVByb21pc2VcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHRoaXMuX3JlYWR5UHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiB7XG4gICAgICAgIGlmIChhd2FpdCBkYi50YWJsZUV4aXN0cyhBVFRBQ0hNRU5UU19UQUJMRSkpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmVuc3VyZUF0dGFjaG1lbnRTdG9yZVNjaGVtYSh7ZGJ9KVxuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGFibGUgPSBuZXcgVGFibGVEYXRhKEFUVEFDSE1FTlRTX1RBQkxFLCB7aWZOb3RFeGlzdHM6IHRydWV9KVxuXG4gICAgICAgIHRhYmxlLnN0cmluZyhcImlkXCIsIHtudWxsOiBmYWxzZSwgcHJpbWFyeUtleTogdHJ1ZX0pXG4gICAgICAgIHRhYmxlLnN0cmluZyhcInJlY29yZF90eXBlXCIsIHtudWxsOiBmYWxzZSwgaW5kZXg6IHRydWV9KVxuICAgICAgICB0YWJsZS5zdHJpbmcoXCJyZWNvcmRfaWRcIiwge251bGw6IGZhbHNlLCBpbmRleDogdHJ1ZX0pXG4gICAgICAgIHRhYmxlLnN0cmluZyhcIm5hbWVcIiwge251bGw6IGZhbHNlLCBpbmRleDogdHJ1ZX0pXG4gICAgICAgIHRhYmxlLmludGVnZXIoXCJwb3NpdGlvblwiLCB7bnVsbDogZmFsc2V9KVxuICAgICAgICB0YWJsZS5zdHJpbmcoXCJmaWxlbmFtZVwiLCB7bnVsbDogZmFsc2V9KVxuICAgICAgICB0YWJsZS5zdHJpbmcoXCJjb250ZW50X3R5cGVcIiwge251bGw6IHRydWV9KVxuICAgICAgICB0YWJsZS5iaWdpbnQoXCJieXRlX3NpemVcIiwge251bGw6IGZhbHNlfSlcbiAgICAgICAgdGFibGUuc3RyaW5nKFwiZHJpdmVyXCIsIHtudWxsOiB0cnVlfSlcbiAgICAgICAgdGFibGUuc3RyaW5nKFwic3RvcmFnZV9rZXlcIiwge251bGw6IHRydWV9KVxuICAgICAgICB0YWJsZS50ZXh0KFwiY29udGVudF9iYXNlNjRcIiwge251bGw6IHRydWV9KVxuICAgICAgICB0YWJsZS5iaWdpbnQoXCJjcmVhdGVkX2F0X21zXCIsIHtudWxsOiBmYWxzZX0pXG4gICAgICAgIHRhYmxlLmJpZ2ludChcInVwZGF0ZWRfYXRfbXNcIiwge251bGw6IGZhbHNlfSlcblxuICAgICAgICBhd2FpdCBkYi5jcmVhdGVUYWJsZSh0YWJsZSlcbiAgICAgICAgdGhpcy5fZHJpdmVyQ29sdW1uc0F2YWlsYWJsZSA9IHRydWVcbiAgICAgICAgdGhpcy5fY29udGVudEJhc2U2NE51bGxhYmxlID0gdHJ1ZVxuICAgICAgfSlcbiAgICB9KSgpXG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5fcmVhZHlQcm9taXNlXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuX3JlYWR5UHJvbWlzZSA9IG51bGxcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBhdHRhY2guXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7P30gYXJncy5pbnB1dCAtIEF0dGFjaG1lbnQgaW5wdXQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXJncy5yZXBsYWNlIC0gV2hldGhlciB0byByZXBsYWNlIGV4aXN0aW5nIGF0dGFjaG1lbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgYXR0YWNoKHtpbnB1dCwgbW9kZWwsIG5hbWUsIHJlcGxhY2V9KSB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpXG4gICAgY29uc3QgYXR0YWNobWVudHNDb25maWd1cmF0aW9uID0gdGhpcy5jb25maWd1cmF0aW9uLmdldEF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbj8uKCkgfHwge31cbiAgICBjb25zdCBhbGxvd1BhdGhJbnB1dCA9IGF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbi5hbGxvd1BhdGhJbnB1dCA9PT0gdHJ1ZVxuICAgIGNvbnN0IGFsbG93ZWRQYXRoUHJlZml4ZXMgPSBBcnJheS5pc0FycmF5KGF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbi5hbGxvd2VkUGF0aFByZWZpeGVzKVxuICAgICAgPyBhdHRhY2htZW50c0NvbmZpZ3VyYXRpb24uYWxsb3dlZFBhdGhQcmVmaXhlc1xuICAgICAgOiB1bmRlZmluZWRcblxuICAgIGNvbnN0IG5vcm1hbGl6ZWRJbnB1dCA9IGF3YWl0IG5vcm1hbGl6ZVJlY29yZEF0dGFjaG1lbnRJbnB1dChpbnB1dCwge1xuICAgICAgYWxsb3dQYXRoSW5wdXQsXG4gICAgICBhbGxvd2VkUGF0aFByZWZpeGVzLFxuICAgICAgZW52aXJvbm1lbnRIYW5kbGVyOiB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RW52aXJvbm1lbnRIYW5kbGVyKClcbiAgICB9KVxuICAgIGNvbnN0IGF0dGFjaG1lbnREcml2ZXIgPSBhd2FpdCB0aGlzLnJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZX0pXG4gICAgY29uc3QgYXR0YWNobWVudERyaXZlck5hbWUgPSB0aGlzLl9hdHRhY2htZW50RHJpdmVyTmFtZUZvcih7bW9kZWwsIG5hbWV9KVxuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KClcbiAgICBjb25zdCByZWNvcmRUeXBlID0gbW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldE1vZGVsTmFtZSgpXG4gICAgY29uc3QgcmVjb3JkSWQgPSBTdHJpbmcobW9kZWwuaWQoKSlcbiAgICBjb25zdCBhdHRhY2htZW50SWQgPSBnZW5lcmF0ZVVVSUQoKVxuICAgIGNvbnN0IHtzdG9yYWdlS2V5fSA9IGF3YWl0IGF0dGFjaG1lbnREcml2ZXIud3JpdGUoe1xuICAgICAgYXR0YWNobWVudElkLFxuICAgICAgaW5wdXQ6IG5vcm1hbGl6ZWRJbnB1dCxcbiAgICAgIG1vZGVsLFxuICAgICAgbmFtZVxuICAgIH0pXG5cbiAgICBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiB7XG4gICAgICBpZiAocmVwbGFjZSkge1xuICAgICAgICBjb25zdCBleGlzdGluZ1Jvd3MgPSBhd2FpdCBkYlxuICAgICAgICAgIC5uZXdRdWVyeSgpXG4gICAgICAgICAgLmZyb20oQVRUQUNITUVOVFNfVEFCTEUpXG4gICAgICAgICAgLndoZXJlKHtuYW1lLCByZWNvcmRfaWQ6IHJlY29yZElkLCByZWNvcmRfdHlwZTogcmVjb3JkVHlwZX0pXG4gICAgICAgICAgLnJlc3VsdHMoKVxuXG4gICAgICAgIGZvciAoY29uc3QgZXhpc3RpbmdSb3cgb2YgZXhpc3RpbmdSb3dzKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5kZWxldGVBdHRhY2htZW50Um93U3RvcmFnZSh7bW9kZWwsIG5hbWUsIHJvdzogZXhpc3RpbmdSb3d9KVxuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgZGIuZGVsZXRlKHtcbiAgICAgICAgICBjb25kaXRpb25zOiB7bmFtZSwgcmVjb3JkX2lkOiByZWNvcmRJZCwgcmVjb3JkX3R5cGU6IHJlY29yZFR5cGV9LFxuICAgICAgICAgIHRhYmxlTmFtZTogQVRUQUNITUVOVFNfVEFCTEVcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgY29uc3QgcG9zaXRpb24gPSByZXBsYWNlID8gMCA6IGF3YWl0IHRoaXMuX25leHRQb3NpdGlvbih7ZGIsIG5hbWUsIHJlY29yZElkLCByZWNvcmRUeXBlfSlcbiAgICAgIC8qKlxuICAgICAgICogSW5zZXJ0IGRhdGEuXG4gICAgICAgIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICAgIGNvbnN0IGluc2VydERhdGEgPSB7XG4gICAgICAgIGJ5dGVfc2l6ZTogbm9ybWFsaXplZElucHV0LmJ5dGVTaXplLFxuICAgICAgICBjb250ZW50X2Jhc2U2NDogdGhpcy5fY29udGVudEJhc2U2NE51bGxhYmxlID8gbnVsbCA6IG5vcm1hbGl6ZWRJbnB1dC5jb250ZW50QmFzZTY0LFxuICAgICAgICBjb250ZW50X3R5cGU6IG5vcm1hbGl6ZWRJbnB1dC5jb250ZW50VHlwZSxcbiAgICAgICAgY3JlYXRlZF9hdF9tczogbm93LFxuICAgICAgICBmaWxlbmFtZTogbm9ybWFsaXplZElucHV0LmZpbGVuYW1lLFxuICAgICAgICBpZDogYXR0YWNobWVudElkLFxuICAgICAgICBuYW1lLFxuICAgICAgICBwb3NpdGlvbixcbiAgICAgICAgcmVjb3JkX2lkOiByZWNvcmRJZCxcbiAgICAgICAgcmVjb3JkX3R5cGU6IHJlY29yZFR5cGUsXG4gICAgICAgIHVwZGF0ZWRfYXRfbXM6IG5vd1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fZHJpdmVyQ29sdW1uc0F2YWlsYWJsZSkge1xuICAgICAgICBpbnNlcnREYXRhLmRyaXZlciA9IGF0dGFjaG1lbnREcml2ZXJOYW1lXG4gICAgICAgIGluc2VydERhdGEuc3RvcmFnZV9rZXkgPSBzdG9yYWdlS2V5XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGRiLmluc2VydCh7XG4gICAgICAgIGRhdGE6IGluc2VydERhdGEsXG4gICAgICAgIHRhYmxlTmFtZTogQVRUQUNITUVOVFNfVEFCTEVcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGVuc3VyZSBhdHRhY2htZW50IHN0b3JlIHNjaGVtYS5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uLy4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBhcmdzLmRiIC0gREIgY29ubmVjdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBzY2hlbWEgY29sdW1ucyBhcmUgZW5zdXJlZC5cbiAgICovXG4gIGFzeW5jIGVuc3VyZUF0dGFjaG1lbnRTdG9yZVNjaGVtYSh7ZGJ9KSB7XG4gICAgY29uc3QgdGFibGUgPSBhd2FpdCBkYi5nZXRUYWJsZUJ5TmFtZU9yRmFpbChBVFRBQ0hNRU5UU19UQUJMRSlcbiAgICBjb25zdCBjb2x1bW5zID0gYXdhaXQgdGFibGUuZ2V0Q29sdW1ucygpXG4gICAgY29uc3QgaGFzRHJpdmVyQ29sdW1uID0gY29sdW1ucy5zb21lKChjb2x1bW4pID0+IGNvbHVtbi5nZXROYW1lKCkgPT09IFwiZHJpdmVyXCIpXG4gICAgY29uc3QgaGFzU3RvcmFnZUtleUNvbHVtbiA9IGNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiBjb2x1bW4uZ2V0TmFtZSgpID09PSBcInN0b3JhZ2Vfa2V5XCIpXG4gICAgY29uc3QgY29udGVudEJhc2U2NENvbHVtbiA9IGNvbHVtbnMuZmluZCgoY29sdW1uKSA9PiBjb2x1bW4uZ2V0TmFtZSgpID09PSBcImNvbnRlbnRfYmFzZTY0XCIpXG4gICAgY29uc3QgYWx0ZXJUYWJsZSA9IG5ldyBUYWJsZURhdGEoQVRUQUNITUVOVFNfVEFCTEUpXG4gICAgbGV0IHNob3VsZEFsdGVyID0gZmFsc2VcblxuICAgIGlmICghaGFzRHJpdmVyQ29sdW1uKSB7XG4gICAgICBhbHRlclRhYmxlLnN0cmluZyhcImRyaXZlclwiLCB7bnVsbDogdHJ1ZX0pXG4gICAgICBzaG91bGRBbHRlciA9IHRydWVcbiAgICB9XG5cbiAgICBpZiAoIWhhc1N0b3JhZ2VLZXlDb2x1bW4pIHtcbiAgICAgIGFsdGVyVGFibGUuc3RyaW5nKFwic3RvcmFnZV9rZXlcIiwge251bGw6IHRydWV9KVxuICAgICAgc2hvdWxkQWx0ZXIgPSB0cnVlXG4gICAgfVxuXG4gICAgaWYgKHNob3VsZEFsdGVyKSB7XG4gICAgICBjb25zdCBhbHRlclRhYmxlU1FMcyA9IGF3YWl0IGRiLmFsdGVyVGFibGVTUUxzKGFsdGVyVGFibGUpXG5cbiAgICAgIGZvciAoY29uc3Qgc3FsIG9mIGFsdGVyVGFibGVTUUxzKSB7XG4gICAgICAgIGF3YWl0IGRiLnF1ZXJ5KHNxbClcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl9kcml2ZXJDb2x1bW5zQXZhaWxhYmxlID0gdHJ1ZVxuICAgIHRoaXMuX2NvbnRlbnRCYXNlNjROdWxsYWJsZSA9IGNvbnRlbnRCYXNlNjRDb2x1bW4gPyBjb250ZW50QmFzZTY0Q29sdW1uLmdldE51bGwoKSA6IHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHJlYWQgYXR0YWNobWVudCByb3cuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgPz59IGFyZ3Mucm93IC0gQXR0YWNobWVudCByb3cuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEJ1ZmZlcj59IC0gQXR0YWNobWVudCBieXRlcy5cbiAgICovXG4gIGFzeW5jIHJlYWRBdHRhY2htZW50Um93KHttb2RlbCwgbmFtZSwgcm93fSkge1xuICAgIGlmICh0eXBlb2Ygcm93LmNvbnRlbnRfYmFzZTY0ID09PSBcInN0cmluZ1wiICYmIHJvdy5jb250ZW50X2Jhc2U2NC5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20ocm93LmNvbnRlbnRfYmFzZTY0LCBcImJhc2U2NFwiKVxuICAgIH1cblxuICAgIGNvbnN0IHN0b3JhZ2VLZXkgPSB0eXBlb2Ygcm93LnN0b3JhZ2Vfa2V5ID09PSBcInN0cmluZ1wiICYmIHJvdy5zdG9yYWdlX2tleS5sZW5ndGggPiAwID8gcm93LnN0b3JhZ2Vfa2V5IDogbnVsbFxuXG4gICAgaWYgKCFzdG9yYWdlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEF0dGFjaG1lbnQgcm93ICR7U3RyaW5nKHJvdy5pZCl9IGlzIG1pc3Npbmcgc3RvcmFnZSBrZXlgKVxuICAgIH1cblxuICAgIGNvbnN0IGF0dGFjaG1lbnREcml2ZXIgPSBhd2FpdCB0aGlzLnJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZSwgcm93fSlcblxuICAgIHJldHVybiBhd2FpdCBhdHRhY2htZW50RHJpdmVyLnJlYWQoe1xuICAgICAgbW9kZWwsXG4gICAgICBuYW1lLFxuICAgICAgcm93LFxuICAgICAgc3RvcmFnZUtleVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBhdHRhY2htZW50IHJvdyB1cmwuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgPz59IGFyZ3Mucm93IC0gQXR0YWNobWVudCByb3cuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZyB8IG51bGw+fSAtIEF0dGFjaG1lbnQgVVJMLlxuICAgKi9cbiAgYXN5bmMgYXR0YWNobWVudFJvd1VybCh7bW9kZWwsIG5hbWUsIHJvd30pIHtcbiAgICBjb25zdCBhdHRhY2htZW50RHJpdmVyID0gYXdhaXQgdGhpcy5yZXNvbHZlQXR0YWNobWVudERyaXZlcih7bW9kZWwsIG5hbWUsIHJvd30pXG5cbiAgICBpZiAodHlwZW9mIGF0dGFjaG1lbnREcml2ZXIudXJsICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBudWxsXG5cbiAgICBjb25zdCBzdG9yYWdlS2V5ID0gdHlwZW9mIHJvdy5zdG9yYWdlX2tleSA9PT0gXCJzdHJpbmdcIiAmJiByb3cuc3RvcmFnZV9rZXkubGVuZ3RoID4gMFxuICAgICAgPyByb3cuc3RvcmFnZV9rZXlcbiAgICAgIDogKHR5cGVvZiByb3cuaWQgPT09IFwic3RyaW5nXCIgPyByb3cuaWQgOiBcIlwiKVxuXG4gICAgaWYgKCFzdG9yYWdlS2V5KSByZXR1cm4gbnVsbFxuXG4gICAgcmV0dXJuIGF3YWl0IGF0dGFjaG1lbnREcml2ZXIudXJsKHtcbiAgICAgIG1vZGVsLFxuICAgICAgbmFtZSxcbiAgICAgIHJvdyxcbiAgICAgIHN0b3JhZ2VLZXlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgZmluZCBvbmUuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5pZF0gLSBPcHRpb25hbCBhdHRhY2htZW50IGlkLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCA/PiB8IG51bGw+fSAtIEF0dGFjaG1lbnQgcm93LlxuICAgKi9cbiAgYXN5bmMgZmluZE9uZSh7aWQsIG1vZGVsLCBuYW1lfSkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZFR5cGUgPSBtb2RlbC5nZXRNb2RlbENsYXNzKCkuZ2V0TW9kZWxOYW1lKClcbiAgICAgIGNvbnN0IHJlY29yZElkID0gU3RyaW5nKG1vZGVsLmlkKCkpXG4gICAgICBsZXQgcXVlcnkgPSBkYlxuICAgICAgICAubmV3UXVlcnkoKVxuICAgICAgICAuZnJvbShBVFRBQ0hNRU5UU19UQUJMRSlcbiAgICAgICAgLndoZXJlKHtuYW1lLCByZWNvcmRfaWQ6IHJlY29yZElkLCByZWNvcmRfdHlwZTogcmVjb3JkVHlwZX0pXG4gICAgICAgIC5vcmRlcihcInBvc2l0aW9uIEFTQ1wiKVxuICAgICAgICAub3JkZXIoXCJjcmVhdGVkX2F0X21zIERFU0NcIilcbiAgICAgICAgLmxpbWl0KDEpXG5cbiAgICAgIGlmIChpZCkge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKHtpZH0pXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJvd3MgPSBhd2FpdCBxdWVyeS5yZXN1bHRzKClcblxuICAgICAgcmV0dXJuIHJvd3NbMF0gfHwgbnVsbFxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBmaW5kIG1hbnkuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEFycmF5PFJlY29yZDxzdHJpbmcsID8+Pj59IC0gQXR0YWNobWVudCByb3dzLlxuICAgKi9cbiAgYXN5bmMgZmluZE1hbnkoe21vZGVsLCBuYW1lfSkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZFR5cGUgPSBtb2RlbC5nZXRNb2RlbENsYXNzKCkuZ2V0TW9kZWxOYW1lKClcbiAgICAgIGNvbnN0IHJlY29yZElkID0gU3RyaW5nKG1vZGVsLmlkKCkpXG4gICAgICBjb25zdCBxdWVyeSA9IGRiXG4gICAgICAgIC5uZXdRdWVyeSgpXG4gICAgICAgIC5mcm9tKEFUVEFDSE1FTlRTX1RBQkxFKVxuICAgICAgICAud2hlcmUoe25hbWUsIHJlY29yZF9pZDogcmVjb3JkSWQsIHJlY29yZF90eXBlOiByZWNvcmRUeXBlfSlcbiAgICAgICAgLm9yZGVyKFwicG9zaXRpb24gQVNDXCIpXG4gICAgICAgIC5vcmRlcihcImNyZWF0ZWRfYXRfbXMgQVNDXCIpXG5cbiAgICAgIHJldHVybiBhd2FpdCBxdWVyeS5yZXN1bHRzKClcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgZGVsZXRlIGF0dGFjaG1lbnQgcm93IHN0b3JhZ2UuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgPz59IGFyZ3Mucm93IC0gQXR0YWNobWVudCByb3cuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gcm93IHN0b3JhZ2UgaGFzIGJlZW4gZGVsZXRlZC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZUF0dGFjaG1lbnRSb3dTdG9yYWdlKHttb2RlbCwgbmFtZSwgcm93fSkge1xuICAgIGNvbnN0IHN0b3JhZ2VLZXkgPSB0eXBlb2Ygcm93LnN0b3JhZ2Vfa2V5ID09PSBcInN0cmluZ1wiICYmIHJvdy5zdG9yYWdlX2tleS5sZW5ndGggPiAwID8gcm93LnN0b3JhZ2Vfa2V5IDogbnVsbFxuXG4gICAgaWYgKCFzdG9yYWdlS2V5KSByZXR1cm5cblxuICAgIGNvbnN0IGF0dGFjaG1lbnREcml2ZXIgPSBhd2FpdCB0aGlzLnJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZSwgcm93fSlcblxuICAgIGlmICh0eXBlb2YgYXR0YWNobWVudERyaXZlci5kZWxldGUgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuXG5cbiAgICBhd2FpdCBhdHRhY2htZW50RHJpdmVyLmRlbGV0ZSh7XG4gICAgICBtb2RlbCxcbiAgICAgIG5hbWUsXG4gICAgICByb3csXG4gICAgICBzdG9yYWdlS2V5XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGF0dGFjaG1lbnQgZHJpdmVyIGJ5IG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkcml2ZXJOYW1lIC0gRHJpdmVyIG5hbWUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+Pn0gLSBBdHRhY2htZW50IHN0b3JhZ2UgZHJpdmVyIGluc3RhbmNlLlxuICAgKi9cbiAgYXN5bmMgYXR0YWNobWVudERyaXZlckJ5TmFtZShkcml2ZXJOYW1lKSB7XG4gICAgaWYgKHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlOYW1lLmhhcyhkcml2ZXJOYW1lKSkge1xuICAgICAgcmV0dXJuIC8qKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi8gKHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlOYW1lLmdldChkcml2ZXJOYW1lKSlcbiAgICB9XG5cbiAgICBjb25zdCBhdHRhY2htZW50Q29uZmlndXJhdGlvbiA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRBdHRhY2htZW50c0NvbmZpZ3VyYXRpb24/LigpIHx8IHt9XG4gICAgY29uc3QgY29uZmlndXJlZERyaXZlciA9IGF0dGFjaG1lbnRDb25maWd1cmF0aW9uLmRyaXZlcnM/Lltkcml2ZXJOYW1lXVxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYXR0YWNobWVudERyaXZlci5cbiAgICAgIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICBsZXQgYXR0YWNobWVudERyaXZlclxuXG4gICAgaWYgKCFjb25maWd1cmVkRHJpdmVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGNvbmZpZ3VyZWQgYXR0YWNobWVudCBzdG9yYWdlIGRyaXZlciBuYW1lZCBcIiR7ZHJpdmVyTmFtZX1cImApXG4gICAgfSBlbHNlIGlmIChjb25maWd1cmVkRHJpdmVyLmluc3RhbmNlICYmIHR5cGVvZiBjb25maWd1cmVkRHJpdmVyLmluc3RhbmNlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBhdHRhY2htZW50RHJpdmVyID0gY29uZmlndXJlZERyaXZlci5pbnN0YW5jZVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbmZpZ3VyZWREcml2ZXIuZHJpdmVyQ2xhc3MgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgYXR0YWNobWVudERyaXZlciA9IG5ldyBjb25maWd1cmVkRHJpdmVyLmRyaXZlckNsYXNzKHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICBuYW1lOiBkcml2ZXJOYW1lLFxuICAgICAgICBvcHRpb25zOiBjb25maWd1cmVkRHJpdmVyXG4gICAgICB9KVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbmZpZ3VyZWREcml2ZXIuY3JlYXRlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGF0dGFjaG1lbnREcml2ZXIgPSBjb25maWd1cmVkRHJpdmVyLmNyZWF0ZSh7XG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgbmFtZTogZHJpdmVyTmFtZSxcbiAgICAgICAgb3B0aW9uczogY29uZmlndXJlZERyaXZlclxuICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBdHRhY2htZW50IHN0b3JhZ2UgZHJpdmVyIFwiJHtkcml2ZXJOYW1lfVwiIG11c3QgZGVmaW5lIGluc3RhbmNlLCBkcml2ZXJDbGFzcywgb3IgY3JlYXRlYClcbiAgICB9XG5cbiAgICBpZiAoIWF0dGFjaG1lbnREcml2ZXIgfHwgdHlwZW9mIGF0dGFjaG1lbnREcml2ZXIud3JpdGUgIT09IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgYXR0YWNobWVudERyaXZlci5yZWFkICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQXR0YWNobWVudCBzdG9yYWdlIGRyaXZlciBcIiR7ZHJpdmVyTmFtZX1cIiBtdXN0IGltcGxlbWVudCB3cml0ZS9yZWFkYClcbiAgICB9XG5cbiAgICB0aGlzLl9hdHRhY2htZW50RHJpdmVyc0J5TmFtZS5zZXQoZHJpdmVyTmFtZSwgYXR0YWNobWVudERyaXZlcilcblxuICAgIHJldHVybiBhdHRhY2htZW50RHJpdmVyXG4gIH1cblxuICAvKipcbiAgICogUnVucyBhdHRhY2htZW50IGRyaXZlciBieSByZWZlcmVuY2UuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtBdHRhY2htZW50RHJpdmVyQ29uc3RydWN0b3IgfCBSZWNvcmQ8c3RyaW5nLCA/Pn0gYXJncy5kcml2ZXJSZWZlcmVuY2UgLSBEcml2ZXIgY2xhc3Mgb3IgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmF0dGFjaG1lbnROYW1lIC0gQXR0YWNobWVudCBuYW1lLlxuICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsID8+fSAtIEF0dGFjaG1lbnQgZHJpdmVyIGluc3RhbmNlLlxuICAgKi9cbiAgYXR0YWNobWVudERyaXZlckJ5UmVmZXJlbmNlKHthdHRhY2htZW50TmFtZSwgZHJpdmVyUmVmZXJlbmNlLCBtb2RlbENsYXNzfSkge1xuICAgIGlmICh0aGlzLl9hdHRhY2htZW50RHJpdmVyc0J5UmVmZXJlbmNlLmhhcyhkcml2ZXJSZWZlcmVuY2UpKSB7XG4gICAgICByZXR1cm4gLyoqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS4gQHR5cGUge1JlY29yZDxzdHJpbmcsID8+fSAqLyAodGhpcy5fYXR0YWNobWVudERyaXZlcnNCeVJlZmVyZW5jZS5nZXQoZHJpdmVyUmVmZXJlbmNlKSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGF0dGFjaG1lbnREcml2ZXIuXG4gICAgICBAdHlwZSB7UmVjb3JkPHN0cmluZywgPz59ICovXG4gICAgbGV0IGF0dGFjaG1lbnREcml2ZXJcblxuICAgIGlmICh0eXBlb2YgZHJpdmVyUmVmZXJlbmNlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGNvbnN0IERyaXZlckNsYXNzID0gLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAdHlwZSB7QXR0YWNobWVudERyaXZlckNvbnN0cnVjdG9yfSAqLyAoZHJpdmVyUmVmZXJlbmNlKVxuXG4gICAgICBhdHRhY2htZW50RHJpdmVyID0gbmV3IERyaXZlckNsYXNzKHtcbiAgICAgICAgYXR0YWNobWVudE5hbWUsXG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgbW9kZWxDbGFzc1xuICAgICAgfSlcbiAgICB9IGVsc2UgaWYgKGRyaXZlclJlZmVyZW5jZSAmJiB0eXBlb2YgZHJpdmVyUmVmZXJlbmNlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBhdHRhY2htZW50RHJpdmVyID0gZHJpdmVyUmVmZXJlbmNlXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhdHRhY2htZW50IGRyaXZlciByZWZlcmVuY2UgZm9yICR7bW9kZWxDbGFzcy5uYW1lfSMke2F0dGFjaG1lbnROYW1lfWApXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBhdHRhY2htZW50RHJpdmVyLndyaXRlICE9PSBcImZ1bmN0aW9uXCIgfHwgdHlwZW9mIGF0dGFjaG1lbnREcml2ZXIucmVhZCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEF0dGFjaG1lbnQgZHJpdmVyIGZvciAke21vZGVsQ2xhc3MubmFtZX0jJHthdHRhY2htZW50TmFtZX0gbXVzdCBpbXBsZW1lbnQgd3JpdGUvcmVhZGApXG4gICAgfVxuXG4gICAgdGhpcy5fYXR0YWNobWVudERyaXZlcnNCeVJlZmVyZW5jZS5zZXQoZHJpdmVyUmVmZXJlbmNlLCBhdHRhY2htZW50RHJpdmVyKVxuXG4gICAgcmV0dXJuIGF0dGFjaG1lbnREcml2ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGF0dGFjaG1lbnQgZHJpdmVyIG5hbWUgZm9yLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vaW5kZXguanNcIikuZGVmYXVsdH0gYXJncy5tb2RlbCAtIE1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5uYW1lIC0gQXR0YWNobWVudCBuYW1lLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIEF0dGFjaG1lbnQgZHJpdmVyIG5hbWUuXG4gICAqL1xuICBfYXR0YWNobWVudERyaXZlck5hbWVGb3Ioe21vZGVsLCBuYW1lfSkge1xuICAgIGNvbnN0IGF0dGFjaG1lbnREZWZpbml0aW9uID0gbW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldEF0dGFjaG1lbnRCeU5hbWUobmFtZSlcbiAgICBjb25zdCBjb25maWd1cmVkRHJpdmVyID0gYXR0YWNobWVudERlZmluaXRpb24uZHJpdmVyXG4gICAgY29uc3QgYXR0YWNobWVudHNDb25maWd1cmF0aW9uID0gdGhpcy5jb25maWd1cmF0aW9uLmdldEF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbj8uKCkgfHwge31cbiAgICBjb25zdCBkZWZhdWx0RHJpdmVyID0gYXR0YWNobWVudHNDb25maWd1cmF0aW9uLmRlZmF1bHREcml2ZXJcblxuICAgIGlmICh0eXBlb2YgY29uZmlndXJlZERyaXZlciA9PT0gXCJzdHJpbmdcIiAmJiBjb25maWd1cmVkRHJpdmVyLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBjb25maWd1cmVkRHJpdmVyXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBjb25maWd1cmVkRHJpdmVyID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiBjb25maWd1cmVkRHJpdmVyLm5hbWUgfHwgXCJjdXN0b21cIlxuICAgIH1cblxuICAgIGlmIChjb25maWd1cmVkRHJpdmVyICYmIHR5cGVvZiBjb25maWd1cmVkRHJpdmVyID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBjb25zdCBjb25zdHJ1Y3Rvck5hbWUgPSBjb25maWd1cmVkRHJpdmVyLmNvbnN0cnVjdG9yPy5uYW1lXG5cbiAgICAgIGlmICh0eXBlb2YgY29uc3RydWN0b3JOYW1lID09PSBcInN0cmluZ1wiICYmIGNvbnN0cnVjdG9yTmFtZS5sZW5ndGggPiAwICYmIGNvbnN0cnVjdG9yTmFtZSAhPT0gXCJPYmplY3RcIikge1xuICAgICAgICByZXR1cm4gY29uc3RydWN0b3JOYW1lXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBcImN1c3RvbVwiXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBkZWZhdWx0RHJpdmVyID09PSBcInN0cmluZ1wiICYmIGRlZmF1bHREcml2ZXIubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIGRlZmF1bHREcml2ZXJcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGF0dGFjaG1lbnQgZHJpdmVyIGNvbmZpZ3VyZWQgZm9yICR7bW9kZWwuZ2V0TW9kZWxDbGFzcygpLm5hbWV9IyR7bmFtZX1gKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgcmVzb2x2ZSBhdHRhY2htZW50IGRyaXZlci5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2luZGV4LmpzXCIpLmRlZmF1bHR9IGFyZ3MubW9kZWwgLSBNb2RlbCBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MubmFtZSAtIEF0dGFjaG1lbnQgbmFtZS5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gW2FyZ3Mucm93XSAtIEF0dGFjaG1lbnQgcm93LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCA/Pj59IC0gQXR0YWNobWVudCBzdG9yYWdlIGRyaXZlciBpbnN0YW5jZS5cbiAgICovXG4gIGFzeW5jIHJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZSwgcm93fSkge1xuICAgIGNvbnN0IGF0dGFjaG1lbnREZWZpbml0aW9uID0gbW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldEF0dGFjaG1lbnRCeU5hbWUobmFtZSlcbiAgICBjb25zdCBjb25maWd1cmVkRHJpdmVyID0gYXR0YWNobWVudERlZmluaXRpb24uZHJpdmVyXG4gICAgaWYgKHR5cGVvZiBjb25maWd1cmVkRHJpdmVyID09PSBcImZ1bmN0aW9uXCIgfHwgKGNvbmZpZ3VyZWREcml2ZXIgJiYgdHlwZW9mIGNvbmZpZ3VyZWREcml2ZXIgPT09IFwib2JqZWN0XCIpKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdHRhY2htZW50RHJpdmVyQnlSZWZlcmVuY2Uoe1xuICAgICAgICBhdHRhY2htZW50TmFtZTogbmFtZSxcbiAgICAgICAgZHJpdmVyUmVmZXJlbmNlOiBjb25maWd1cmVkRHJpdmVyLFxuICAgICAgICBtb2RlbENsYXNzOiBtb2RlbC5nZXRNb2RlbENsYXNzKClcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgY29uc3QgZmFsbGJhY2tEcml2ZXJOYW1lID0gdHlwZW9mIHJvdz8uZHJpdmVyID09PSBcInN0cmluZ1wiICYmIHJvdy5kcml2ZXIubGVuZ3RoID4gMFxuICAgICAgPyByb3cuZHJpdmVyXG4gICAgICA6IHRoaXMuX2F0dGFjaG1lbnREcml2ZXJOYW1lRm9yKHttb2RlbCwgbmFtZX0pXG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5hdHRhY2htZW50RHJpdmVyQnlOYW1lKGZhbGxiYWNrRHJpdmVyTmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIG5leHQgcG9zaXRpb24uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi8uLi9kYXRhYmFzZS9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdH0gYXJncy5kYiAtIERCIGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnJlY29yZElkIC0gUmVjb3JkIGlkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5yZWNvcmRUeXBlIC0gUmVjb3JkIHR5cGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59IC0gTmV4dCBwb3NpdGlvbi5cbiAgICovXG4gIGFzeW5jIF9uZXh0UG9zaXRpb24oe2RiLCBuYW1lLCByZWNvcmRJZCwgcmVjb3JkVHlwZX0pIHtcbiAgICBjb25zdCBxdWVyeSA9IGRiXG4gICAgICAubmV3UXVlcnkoKVxuICAgICAgLmZyb20oQVRUQUNITUVOVFNfVEFCTEUpXG4gICAgICAud2hlcmUoe25hbWUsIHJlY29yZF9pZDogcmVjb3JkSWQsIHJlY29yZF90eXBlOiByZWNvcmRUeXBlfSlcbiAgICAgIC5vcmRlcihcInBvc2l0aW9uIERFU0NcIilcbiAgICAgIC5saW1pdCgxKVxuICAgIGNvbnN0IHJvd3MgPSBhd2FpdCBxdWVyeS5yZXN1bHRzKClcbiAgICBjb25zdCBjdXJyZW50Um93ID0gLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICBAdHlwZSB7e3Bvc2l0aW9uPzogc3RyaW5nIHwgbnVtYmVyIHwgbnVsbH0gfCB1bmRlZmluZWR9ICovIChyb3dzWzBdKVxuICAgIGNvbnN0IGN1cnJlbnQgPSBOdW1iZXIoY3VycmVudFJvdz8ucG9zaXRpb24pXG5cbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShjdXJyZW50KSkgcmV0dXJuIDBcblxuICAgIHJldHVybiBjdXJyZW50ICsgMVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgd2l0aCBkYi5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHsoZGI6IGltcG9ydChcIi4uLy4uLy4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0KSA9PiBQcm9taXNlPFQ+fSBjYWxsYmFjayAtIENhbGxiYWNrLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUPn0gLSBDYWxsYmFjayByZXN1bHQuXG4gICAqL1xuICBhc3luYyBfd2l0aERiKGNhbGxiYWNrKSB7XG4gICAgY29uc3QgcG9vbCA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXREYXRhYmFzZVBvb2wodGhpcy5kYXRhYmFzZUlkZW50aWZpZXIpXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyByZXN1bHQuXG4gICAgICBAdHlwZSB7VCB8IHVuZGVmaW5lZH0gKi9cbiAgICBsZXQgcmVzdWx0XG5cbiAgICBhd2FpdCBwb29sLndpdGhDb25uZWN0aW9uKHtuYW1lOiBcIlJlY29yZCBhdHRhY2htZW50IHN0b3JlXCJ9LCBhc3luYyAoZGIpID0+IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IGNhbGxiYWNrKGRiKVxuICAgIH0pXG5cbiAgICByZXR1cm4gLyoqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS4gQHR5cGUge1R9ICovIChyZXN1bHQpXG4gIH1cbn1cbiJdfQ==