velocious 1.0.430 → 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 (811) 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.js +273 -235
  227. package/build/src/database/record/attachments/download.js +45 -44
  228. package/build/src/database/record/attachments/handle.js +161 -141
  229. package/build/src/database/record/attachments/normalize-input.js +138 -128
  230. package/build/src/database/record/attachments/storage-drivers/filesystem.js +91 -77
  231. package/build/src/database/record/attachments/storage-drivers/native.js +121 -112
  232. package/build/src/database/record/attachments/storage-drivers/s3.js +208 -177
  233. package/build/src/database/record/attachments/store.d.ts +1 -1
  234. package/build/src/database/record/attachments/store.d.ts.map +1 -1
  235. package/build/src/database/record/attachments/store.js +540 -468
  236. package/build/src/database/record/index.d.ts +17 -15
  237. package/build/src/database/record/index.d.ts.map +1 -1
  238. package/build/src/database/record/index.js +3894 -3361
  239. package/build/src/database/record/instance-relationships/base.js +268 -234
  240. package/build/src/database/record/instance-relationships/belongs-to.js +73 -58
  241. package/build/src/database/record/instance-relationships/has-many.js +264 -225
  242. package/build/src/database/record/instance-relationships/has-one.js +105 -85
  243. package/build/src/database/record/record-not-found-error.js +2 -3
  244. package/build/src/database/record/relationships/base.d.ts +2 -2
  245. package/build/src/database/record/relationships/base.d.ts.map +1 -1
  246. package/build/src/database/record/relationships/base.js +167 -145
  247. package/build/src/database/record/relationships/belongs-to.js +51 -44
  248. package/build/src/database/record/relationships/has-many.js +40 -32
  249. package/build/src/database/record/relationships/has-one.js +40 -32
  250. package/build/src/database/record/state-machine.js +208 -156
  251. package/build/src/database/record/user-module.js +38 -32
  252. package/build/src/database/record/validators/base.js +24 -22
  253. package/build/src/database/record/validators/format.js +46 -36
  254. package/build/src/database/record/validators/presence.js +20 -18
  255. package/build/src/database/record/validators/uniqueness.js +117 -99
  256. package/build/src/database/table-data/index.js +231 -199
  257. package/build/src/database/table-data/table-column.js +382 -338
  258. package/build/src/database/table-data/table-foreign-key.js +66 -57
  259. package/build/src/database/table-data/table-index.js +36 -29
  260. package/build/src/database/table-data/table-reference.js +10 -10
  261. package/build/src/database/use-database.js +40 -32
  262. package/build/src/environment-handlers/base.js +544 -484
  263. package/build/src/environment-handlers/browser.js +294 -241
  264. package/build/src/environment-handlers/node/cli/commands/background-jobs-main.js +19 -16
  265. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.js +21 -18
  266. package/build/src/environment-handlers/node/cli/commands/background-jobs-worker.js +29 -22
  267. package/build/src/environment-handlers/node/cli/commands/beacon.js +19 -16
  268. package/build/src/environment-handlers/node/cli/commands/cli-command-context.js +15 -14
  269. package/build/src/environment-handlers/node/cli/commands/console.js +120 -99
  270. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.js +39 -34
  271. package/build/src/environment-handlers/node/cli/commands/db/schema/load.js +63 -57
  272. package/build/src/environment-handlers/node/cli/commands/db/seed.js +63 -51
  273. package/build/src/environment-handlers/node/cli/commands/destroy/migration.js +40 -32
  274. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
  275. package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +353 -298
  276. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +844 -729
  277. package/build/src/environment-handlers/node/cli/commands/generate/migration.js +38 -34
  278. package/build/src/environment-handlers/node/cli/commands/generate/model.js +38 -34
  279. package/build/src/environment-handlers/node/cli/commands/init.js +61 -56
  280. package/build/src/environment-handlers/node/cli/commands/routes.js +59 -51
  281. package/build/src/environment-handlers/node/cli/commands/run-script.js +68 -54
  282. package/build/src/environment-handlers/node/cli/commands/runner.js +74 -56
  283. package/build/src/environment-handlers/node/cli/commands/server.js +106 -93
  284. package/build/src/environment-handlers/node/cli/commands/test.js +113 -97
  285. package/build/src/environment-handlers/node.js +874 -753
  286. package/build/src/error-logger.js +21 -22
  287. package/build/src/frontend-model-controller.d.ts +6 -6
  288. package/build/src/frontend-model-controller.d.ts.map +1 -1
  289. package/build/src/frontend-model-controller.js +3288 -2788
  290. package/build/src/frontend-model-resource/base-resource.d.ts +18 -17
  291. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  292. package/build/src/frontend-model-resource/base-resource.js +869 -759
  293. package/build/src/frontend-models/base.d.ts +19 -12
  294. package/build/src/frontend-models/base.d.ts.map +1 -1
  295. package/build/src/frontend-models/base.js +3602 -3114
  296. package/build/src/frontend-models/clear-pending-debounced-callback.js +8 -7
  297. package/build/src/frontend-models/event-hook-models.js +21 -16
  298. package/build/src/frontend-models/model-registry.js +11 -9
  299. package/build/src/frontend-models/outgoing-event-buffer.js +17 -10
  300. package/build/src/frontend-models/preloader.d.ts +6 -6
  301. package/build/src/frontend-models/preloader.d.ts.map +1 -1
  302. package/build/src/frontend-models/preloader.js +149 -131
  303. package/build/src/frontend-models/query.d.ts.map +1 -1
  304. package/build/src/frontend-models/query.js +1855 -1560
  305. package/build/src/frontend-models/resource-config-validation.js +37 -27
  306. package/build/src/frontend-models/resource-definition.js +288 -234
  307. package/build/src/frontend-models/transport-serialization.js +266 -203
  308. package/build/src/frontend-models/use-created-event.js +7 -5
  309. package/build/src/frontend-models/use-destroyed-event.js +93 -80
  310. package/build/src/frontend-models/use-model-class-event.js +91 -79
  311. package/build/src/frontend-models/use-updated-event.js +97 -84
  312. package/build/src/frontend-models/websocket-channel.js +441 -381
  313. package/build/src/frontend-models/websocket-publishers.js +173 -140
  314. package/build/src/http-client/header.js +14 -13
  315. package/build/src/http-client/index.js +132 -116
  316. package/build/src/http-client/request.js +87 -71
  317. package/build/src/http-client/response.js +140 -122
  318. package/build/src/http-client/websocket-client.js +17 -15
  319. package/build/src/http-server/client/index.js +465 -409
  320. package/build/src/http-server/client/params-to-object.js +135 -124
  321. package/build/src/http-server/client/request-buffer/form-data-part.js +132 -111
  322. package/build/src/http-server/client/request-buffer/header.js +16 -15
  323. package/build/src/http-server/client/request-buffer/index.js +506 -446
  324. package/build/src/http-server/client/request-parser.js +186 -163
  325. package/build/src/http-server/client/request-runner.js +259 -226
  326. package/build/src/http-server/client/request-timing.js +151 -132
  327. package/build/src/http-server/client/request.js +108 -96
  328. package/build/src/http-server/client/response.js +235 -213
  329. package/build/src/http-server/client/uploaded-file/memory-uploaded-file.js +29 -25
  330. package/build/src/http-server/client/uploaded-file/temporary-uploaded-file.js +29 -25
  331. package/build/src/http-server/client/uploaded-file/uploaded-file.js +33 -33
  332. package/build/src/http-server/client/websocket-request.js +137 -114
  333. package/build/src/http-server/client/websocket-session.js +1657 -1452
  334. package/build/src/http-server/cookie.js +236 -216
  335. package/build/src/http-server/development-reloader.js +221 -190
  336. package/build/src/http-server/index.js +525 -451
  337. package/build/src/http-server/remote-address.js +50 -38
  338. package/build/src/http-server/server-client.js +208 -181
  339. package/build/src/http-server/server-lock.js +167 -153
  340. package/build/src/http-server/websocket-channel-subscribers.js +93 -81
  341. package/build/src/http-server/websocket-channel.js +117 -104
  342. package/build/src/http-server/websocket-connection.js +104 -96
  343. package/build/src/http-server/websocket-event-log-store.js +404 -350
  344. package/build/src/http-server/websocket-events-host.js +164 -145
  345. package/build/src/http-server/websocket-events.js +47 -47
  346. package/build/src/http-server/worker-handler/channel-subscriber-dispatch.js +14 -13
  347. package/build/src/http-server/worker-handler/in-process.js +141 -123
  348. package/build/src/http-server/worker-handler/index.js +349 -313
  349. package/build/src/http-server/worker-handler/worker-script.js +5 -4
  350. package/build/src/http-server/worker-handler/worker-thread.js +269 -240
  351. package/build/src/initializer.js +36 -31
  352. package/build/src/jobs/mail-delivery.js +15 -13
  353. package/build/src/logger/base-logger.js +26 -24
  354. package/build/src/logger/console-logger.js +23 -21
  355. package/build/src/logger/file-logger.js +31 -29
  356. package/build/src/logger/outputs/array-output.js +42 -37
  357. package/build/src/logger/outputs/console-output.js +24 -20
  358. package/build/src/logger/outputs/file-output.js +48 -43
  359. package/build/src/logger/outputs/stdout-output.js +48 -39
  360. package/build/src/logger.js +394 -338
  361. package/build/src/mailer/backends/smtp.js +163 -134
  362. package/build/src/mailer/base.js +251 -211
  363. package/build/src/mailer/delivery.js +64 -56
  364. package/build/src/mailer/index.js +22 -4
  365. package/build/src/mailer.js +13 -4
  366. package/build/src/plugins/sqljs-wasm-route-controller.js +52 -42
  367. package/build/src/plugins/sqljs-wasm-route.js +38 -28
  368. package/build/src/record-payload-values.js +28 -25
  369. package/build/src/routes/app-routes.js +14 -12
  370. package/build/src/routes/base-route.js +130 -112
  371. package/build/src/routes/basic-route.js +102 -83
  372. package/build/src/routes/built-in/debug/controller.js +10 -10
  373. package/build/src/routes/built-in/errors/controller.js +5 -5
  374. package/build/src/routes/get-route.js +63 -50
  375. package/build/src/routes/hooks/frontend-model-command-route-hook.js +80 -66
  376. package/build/src/routes/index.js +43 -36
  377. package/build/src/routes/namespace-route.js +47 -38
  378. package/build/src/routes/plugin-routes.js +124 -107
  379. package/build/src/routes/post-route.js +62 -51
  380. package/build/src/routes/resolver.js +494 -422
  381. package/build/src/routes/resource-route.js +143 -124
  382. package/build/src/routes/root-route.js +8 -7
  383. package/build/src/testing/base-expect.js +14 -13
  384. package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +405 -329
  385. package/build/src/testing/browser-test-app.js +29 -23
  386. package/build/src/testing/expect-to-change.js +50 -41
  387. package/build/src/testing/expect-utils.js +184 -139
  388. package/build/src/testing/expect.js +731 -638
  389. package/build/src/testing/request-client.js +85 -70
  390. package/build/src/testing/test-files-finder.js +339 -285
  391. package/build/src/testing/test-filter-parser.js +155 -124
  392. package/build/src/testing/test-runner.js +1020 -883
  393. package/build/src/testing/test-suite-splitter.js +142 -114
  394. package/build/src/testing/test.js +256 -216
  395. package/build/src/utils/backtrace-cleaner-node.js +69 -62
  396. package/build/src/utils/backtrace-cleaner.js +216 -188
  397. package/build/src/utils/ensure-error.js +7 -7
  398. package/build/src/utils/event-emitter.js +6 -4
  399. package/build/src/utils/file-exists.js +10 -9
  400. package/build/src/utils/format-value.js +76 -67
  401. package/build/src/utils/model-scope.js +31 -27
  402. package/build/src/utils/nest-callbacks.js +13 -10
  403. package/build/src/utils/plain-object.js +6 -5
  404. package/build/src/utils/ransack.d.ts.map +1 -1
  405. package/build/src/utils/ransack.js +563 -449
  406. package/build/src/utils/rest-args-error.js +6 -5
  407. package/build/src/utils/singularize-model-name.js +11 -9
  408. package/build/src/utils/split-sql-statements.js +79 -68
  409. package/build/src/utils/to-import-specifier.js +30 -24
  410. package/build/src/utils/with-tracked-stack-async-hooks.js +74 -60
  411. package/build/src/utils/with-tracked-stack.js +18 -14
  412. package/build/src/velocious-error.js +30 -27
  413. package/index.js +1 -0
  414. package/package.json +10 -4
  415. package/scripts/clean-build.js +8 -0
  416. package/scripts/ensure-bin-executable.js +13 -0
  417. package/scripts/run-tests.js +37 -0
  418. package/scripts/test-browser.js +486 -0
  419. package/src/application.js +229 -0
  420. package/src/authorization/ability.js +329 -0
  421. package/src/authorization/base-resource.js +143 -0
  422. package/src/background-jobs/client.js +50 -0
  423. package/src/background-jobs/cron-expression.js +277 -0
  424. package/src/background-jobs/forked-runner-child.js +86 -0
  425. package/src/background-jobs/job-record.js +13 -0
  426. package/src/background-jobs/job-registry.js +92 -0
  427. package/src/background-jobs/job-runner.js +107 -0
  428. package/src/background-jobs/job.js +77 -0
  429. package/src/background-jobs/json-socket.js +78 -0
  430. package/src/background-jobs/main.js +926 -0
  431. package/src/background-jobs/normalize-error.js +26 -0
  432. package/src/background-jobs/scheduler.js +274 -0
  433. package/src/background-jobs/socket-request.js +68 -0
  434. package/src/background-jobs/status-reporter.js +101 -0
  435. package/src/background-jobs/store.js +994 -0
  436. package/src/background-jobs/types.js +70 -0
  437. package/src/background-jobs/web/authorization.js +89 -0
  438. package/src/background-jobs/web/controller.js +280 -0
  439. package/src/background-jobs/web/index.js +57 -0
  440. package/src/background-jobs/web/path-matcher.js +74 -0
  441. package/src/background-jobs/web/registry.js +49 -0
  442. package/src/background-jobs/worker.js +683 -0
  443. package/src/beacon/client.js +330 -0
  444. package/src/beacon/in-process-broker.js +71 -0
  445. package/src/beacon/in-process-client.js +139 -0
  446. package/src/beacon/server.js +148 -0
  447. package/src/beacon/types.js +55 -0
  448. package/src/cli/base-command.js +67 -0
  449. package/src/cli/browser-cli.js +45 -0
  450. package/src/cli/commands/background-jobs-main.js +7 -0
  451. package/src/cli/commands/background-jobs-runner.js +7 -0
  452. package/src/cli/commands/background-jobs-worker.js +7 -0
  453. package/src/cli/commands/beacon.js +7 -0
  454. package/src/cli/commands/console.js +12 -0
  455. package/src/cli/commands/db/base-command.js +82 -0
  456. package/src/cli/commands/db/create.js +64 -0
  457. package/src/cli/commands/db/drop.js +75 -0
  458. package/src/cli/commands/db/migrate.js +17 -0
  459. package/src/cli/commands/db/reset.js +22 -0
  460. package/src/cli/commands/db/rollback.js +15 -0
  461. package/src/cli/commands/db/schema/dump.js +12 -0
  462. package/src/cli/commands/db/schema/load.js +12 -0
  463. package/src/cli/commands/db/seed.js +12 -0
  464. package/src/cli/commands/db/tenants/check.js +38 -0
  465. package/src/cli/commands/db/tenants/create.js +33 -0
  466. package/src/cli/commands/db/tenants/migrate.js +49 -0
  467. package/src/cli/commands/destroy/migration.js +7 -0
  468. package/src/cli/commands/generate/base-models.js +7 -0
  469. package/src/cli/commands/generate/frontend-models.js +12 -0
  470. package/src/cli/commands/generate/migration.js +7 -0
  471. package/src/cli/commands/generate/model.js +7 -0
  472. package/src/cli/commands/init.js +11 -0
  473. package/src/cli/commands/routes.js +7 -0
  474. package/src/cli/commands/run-script.js +12 -0
  475. package/src/cli/commands/runner.js +12 -0
  476. package/src/cli/commands/server.js +7 -0
  477. package/src/cli/commands/test.js +9 -0
  478. package/src/cli/index.js +152 -0
  479. package/src/cli/tenant-database-command-helper.js +198 -0
  480. package/src/cli/use-browser-cli.js +30 -0
  481. package/src/configuration-resolver.js +65 -0
  482. package/src/configuration-types.js +429 -0
  483. package/src/configuration.js +2590 -0
  484. package/src/controller.js +421 -0
  485. package/src/current-configuration.js +31 -0
  486. package/src/current.js +80 -0
  487. package/src/database/annotations-async-hooks.js +47 -0
  488. package/src/database/annotations.js +40 -0
  489. package/src/database/drivers/base-column.js +182 -0
  490. package/src/database/drivers/base-columns-index.js +81 -0
  491. package/src/database/drivers/base-foreign-key.js +104 -0
  492. package/src/database/drivers/base-table.js +156 -0
  493. package/src/database/drivers/base.js +1609 -0
  494. package/src/database/drivers/mssql/column.js +74 -0
  495. package/src/database/drivers/mssql/columns-index.js +6 -0
  496. package/src/database/drivers/mssql/connect-connection.js +16 -0
  497. package/src/database/drivers/mssql/foreign-key.js +12 -0
  498. package/src/database/drivers/mssql/index.js +590 -0
  499. package/src/database/drivers/mssql/options.js +79 -0
  500. package/src/database/drivers/mssql/query-parser.js +6 -0
  501. package/src/database/drivers/mssql/sql/alter-table.js +4 -0
  502. package/src/database/drivers/mssql/sql/create-database.js +36 -0
  503. package/src/database/drivers/mssql/sql/create-index.js +4 -0
  504. package/src/database/drivers/mssql/sql/create-table.js +4 -0
  505. package/src/database/drivers/mssql/sql/delete.js +19 -0
  506. package/src/database/drivers/mssql/sql/drop-database.js +36 -0
  507. package/src/database/drivers/mssql/sql/drop-table.js +4 -0
  508. package/src/database/drivers/mssql/sql/insert.js +4 -0
  509. package/src/database/drivers/mssql/sql/update.js +31 -0
  510. package/src/database/drivers/mssql/sql/upsert.js +23 -0
  511. package/src/database/drivers/mssql/structure-sql.js +120 -0
  512. package/src/database/drivers/mssql/table.js +145 -0
  513. package/src/database/drivers/mysql/column.js +112 -0
  514. package/src/database/drivers/mysql/columns-index.js +22 -0
  515. package/src/database/drivers/mysql/foreign-key.js +12 -0
  516. package/src/database/drivers/mysql/index.js +473 -0
  517. package/src/database/drivers/mysql/options.js +34 -0
  518. package/src/database/drivers/mysql/query-parser.js +6 -0
  519. package/src/database/drivers/mysql/query.js +37 -0
  520. package/src/database/drivers/mysql/sql/alter-table.js +6 -0
  521. package/src/database/drivers/mysql/sql/create-database.js +39 -0
  522. package/src/database/drivers/mysql/sql/create-index.js +6 -0
  523. package/src/database/drivers/mysql/sql/create-table.js +6 -0
  524. package/src/database/drivers/mysql/sql/delete.js +21 -0
  525. package/src/database/drivers/mysql/sql/drop-database.js +6 -0
  526. package/src/database/drivers/mysql/sql/drop-table.js +6 -0
  527. package/src/database/drivers/mysql/sql/insert.js +6 -0
  528. package/src/database/drivers/mysql/sql/update.js +33 -0
  529. package/src/database/drivers/mysql/sql/upsert.js +13 -0
  530. package/src/database/drivers/mysql/structure-sql.js +93 -0
  531. package/src/database/drivers/mysql/table.js +121 -0
  532. package/src/database/drivers/pgsql/column.js +90 -0
  533. package/src/database/drivers/pgsql/columns-index.js +6 -0
  534. package/src/database/drivers/pgsql/foreign-key.js +12 -0
  535. package/src/database/drivers/pgsql/index.js +441 -0
  536. package/src/database/drivers/pgsql/options.js +32 -0
  537. package/src/database/drivers/pgsql/query-parser.js +6 -0
  538. package/src/database/drivers/pgsql/sql/alter-table.js +6 -0
  539. package/src/database/drivers/pgsql/sql/create-database.js +38 -0
  540. package/src/database/drivers/pgsql/sql/create-index.js +6 -0
  541. package/src/database/drivers/pgsql/sql/create-table.js +6 -0
  542. package/src/database/drivers/pgsql/sql/delete.js +21 -0
  543. package/src/database/drivers/pgsql/sql/drop-database.js +6 -0
  544. package/src/database/drivers/pgsql/sql/drop-table.js +6 -0
  545. package/src/database/drivers/pgsql/sql/insert.js +6 -0
  546. package/src/database/drivers/pgsql/sql/update.js +33 -0
  547. package/src/database/drivers/pgsql/sql/upsert.js +14 -0
  548. package/src/database/drivers/pgsql/structure-sql.js +126 -0
  549. package/src/database/drivers/pgsql/table.js +135 -0
  550. package/src/database/drivers/sqlite/base.js +509 -0
  551. package/src/database/drivers/sqlite/column.js +75 -0
  552. package/src/database/drivers/sqlite/columns-index.js +30 -0
  553. package/src/database/drivers/sqlite/connection-sql-js.js +46 -0
  554. package/src/database/drivers/sqlite/foreign-key.js +24 -0
  555. package/src/database/drivers/sqlite/index.js +394 -0
  556. package/src/database/drivers/sqlite/index.native.js +72 -0
  557. package/src/database/drivers/sqlite/index.web.js +99 -0
  558. package/src/database/drivers/sqlite/options.js +32 -0
  559. package/src/database/drivers/sqlite/query-parser.js +6 -0
  560. package/src/database/drivers/sqlite/query.js +35 -0
  561. package/src/database/drivers/sqlite/query.native.js +35 -0
  562. package/src/database/drivers/sqlite/query.web.js +49 -0
  563. package/src/database/drivers/sqlite/sql/alter-table.js +187 -0
  564. package/src/database/drivers/sqlite/sql/create-index.js +6 -0
  565. package/src/database/drivers/sqlite/sql/create-table.js +6 -0
  566. package/src/database/drivers/sqlite/sql/delete.js +26 -0
  567. package/src/database/drivers/sqlite/sql/drop-table.js +6 -0
  568. package/src/database/drivers/sqlite/sql/insert.js +6 -0
  569. package/src/database/drivers/sqlite/sql/update.js +33 -0
  570. package/src/database/drivers/sqlite/sql/upsert.js +14 -0
  571. package/src/database/drivers/sqlite/structure-sql.js +56 -0
  572. package/src/database/drivers/sqlite/table-rebuilder.js +96 -0
  573. package/src/database/drivers/sqlite/table.js +131 -0
  574. package/src/database/drivers/structure-sql/utils.js +35 -0
  575. package/src/database/handler.js +13 -0
  576. package/src/database/initializer-from-require-context.js +101 -0
  577. package/src/database/migration/index.js +438 -0
  578. package/src/database/migrator/files-finder.js +55 -0
  579. package/src/database/migrator/types.js +31 -0
  580. package/src/database/migrator.js +557 -0
  581. package/src/database/pool/async-tracked-multi-connection.js +1164 -0
  582. package/src/database/pool/base-methods-forward.js +52 -0
  583. package/src/database/pool/base.js +380 -0
  584. package/src/database/pool/single-multi-use.js +118 -0
  585. package/src/database/query/alter-table-base.js +104 -0
  586. package/src/database/query/base.js +49 -0
  587. package/src/database/query/create-database-base.js +42 -0
  588. package/src/database/query/create-index-base.js +117 -0
  589. package/src/database/query/create-table-base.js +205 -0
  590. package/src/database/query/delete-base.js +19 -0
  591. package/src/database/query/drop-database-base.js +38 -0
  592. package/src/database/query/drop-table-base.js +58 -0
  593. package/src/database/query/from-base.js +36 -0
  594. package/src/database/query/from-plain.js +16 -0
  595. package/src/database/query/from-table.js +18 -0
  596. package/src/database/query/index.js +533 -0
  597. package/src/database/query/insert-base.js +172 -0
  598. package/src/database/query/join-base.js +43 -0
  599. package/src/database/query/join-object.js +167 -0
  600. package/src/database/query/join-plain.js +18 -0
  601. package/src/database/query/join-tracker.js +93 -0
  602. package/src/database/query/model-class-query.js +1577 -0
  603. package/src/database/query/order-base.js +33 -0
  604. package/src/database/query/order-column.js +77 -0
  605. package/src/database/query/order-plain.js +28 -0
  606. package/src/database/query/preloader/belongs-to.js +267 -0
  607. package/src/database/query/preloader/ensure-model-class-initialized.js +18 -0
  608. package/src/database/query/preloader/has-many.js +316 -0
  609. package/src/database/query/preloader/has-one.js +123 -0
  610. package/src/database/query/preloader/selection.js +152 -0
  611. package/src/database/query/preloader.js +201 -0
  612. package/src/database/query/query-data.js +305 -0
  613. package/src/database/query/select-base.js +30 -0
  614. package/src/database/query/select-plain.js +18 -0
  615. package/src/database/query/select-table-and-column.js +28 -0
  616. package/src/database/query/update-base.js +41 -0
  617. package/src/database/query/upsert-base.js +103 -0
  618. package/src/database/query/where-base.js +38 -0
  619. package/src/database/query/where-combinator.js +31 -0
  620. package/src/database/query/where-hash.js +77 -0
  621. package/src/database/query/where-model-class-hash.js +505 -0
  622. package/src/database/query/where-not.js +23 -0
  623. package/src/database/query/where-plain.js +20 -0
  624. package/src/database/query/with-count.js +219 -0
  625. package/src/database/query-parser/base-query-parser.js +40 -0
  626. package/src/database/query-parser/from-parser.js +49 -0
  627. package/src/database/query-parser/group-parser.js +55 -0
  628. package/src/database/query-parser/joins-parser.js +37 -0
  629. package/src/database/query-parser/limit-parser.js +77 -0
  630. package/src/database/query-parser/options.js +94 -0
  631. package/src/database/query-parser/order-parser.js +45 -0
  632. package/src/database/query-parser/select-parser.js +67 -0
  633. package/src/database/query-parser/where-parser.js +46 -0
  634. package/src/database/record/acts-as-list.js +374 -0
  635. package/src/database/record/attachments/download.js +49 -0
  636. package/src/database/record/attachments/handle.js +188 -0
  637. package/src/database/record/attachments/normalize-input.js +213 -0
  638. package/src/database/record/attachments/storage-drivers/filesystem.js +114 -0
  639. package/src/database/record/attachments/storage-drivers/native.js +146 -0
  640. package/src/database/record/attachments/storage-drivers/s3.js +245 -0
  641. package/src/database/record/attachments/store.js +591 -0
  642. package/src/database/record/index.js +3970 -0
  643. package/src/database/record/instance-relationships/base.js +289 -0
  644. package/src/database/record/instance-relationships/belongs-to.js +84 -0
  645. package/src/database/record/instance-relationships/has-many.js +284 -0
  646. package/src/database/record/instance-relationships/has-one.js +117 -0
  647. package/src/database/record/record-not-found-error.js +3 -0
  648. package/src/database/record/relationships/base.js +195 -0
  649. package/src/database/record/relationships/belongs-to.js +57 -0
  650. package/src/database/record/relationships/has-many.js +46 -0
  651. package/src/database/record/relationships/has-one.js +46 -0
  652. package/src/database/record/state-machine.js +278 -0
  653. package/src/database/record/user-module.js +43 -0
  654. package/src/database/record/validators/base.js +27 -0
  655. package/src/database/record/validators/format.js +50 -0
  656. package/src/database/record/validators/presence.js +24 -0
  657. package/src/database/record/validators/uniqueness.js +124 -0
  658. package/src/database/table-data/index.js +241 -0
  659. package/src/database/table-data/table-column.js +416 -0
  660. package/src/database/table-data/table-foreign-key.js +69 -0
  661. package/src/database/table-data/table-index.js +46 -0
  662. package/src/database/table-data/table-reference.js +13 -0
  663. package/src/database/use-database.js +48 -0
  664. package/src/environment-handlers/base.js +561 -0
  665. package/src/environment-handlers/browser.js +338 -0
  666. package/src/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
  667. package/src/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
  668. package/src/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
  669. package/src/environment-handlers/node/cli/commands/beacon.js +21 -0
  670. package/src/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
  671. package/src/environment-handlers/node/cli/commands/console.js +149 -0
  672. package/src/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
  673. package/src/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
  674. package/src/environment-handlers/node/cli/commands/db/seed.js +79 -0
  675. package/src/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
  676. package/src/environment-handlers/node/cli/commands/generate/base-models.js +367 -0
  677. package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
  678. package/src/environment-handlers/node/cli/commands/generate/migration.js +45 -0
  679. package/src/environment-handlers/node/cli/commands/generate/model.js +45 -0
  680. package/src/environment-handlers/node/cli/commands/init.js +68 -0
  681. package/src/environment-handlers/node/cli/commands/routes.js +63 -0
  682. package/src/environment-handlers/node/cli/commands/run-script.js +85 -0
  683. package/src/environment-handlers/node/cli/commands/runner.js +84 -0
  684. package/src/environment-handlers/node/cli/commands/server.js +151 -0
  685. package/src/environment-handlers/node/cli/commands/test.js +118 -0
  686. package/src/environment-handlers/node.js +887 -0
  687. package/src/error-logger.js +30 -0
  688. package/src/frontend-model-controller.js +3491 -0
  689. package/src/frontend-model-resource/base-resource.js +935 -0
  690. package/src/frontend-models/base.js +4004 -0
  691. package/src/frontend-models/clear-pending-debounced-callback.js +16 -0
  692. package/src/frontend-models/event-hook-models.js +49 -0
  693. package/src/frontend-models/model-registry.js +28 -0
  694. package/src/frontend-models/outgoing-event-buffer.js +51 -0
  695. package/src/frontend-models/preloader.js +169 -0
  696. package/src/frontend-models/query.js +2245 -0
  697. package/src/frontend-models/resource-config-validation.js +56 -0
  698. package/src/frontend-models/resource-definition.js +399 -0
  699. package/src/frontend-models/transport-serialization.js +369 -0
  700. package/src/frontend-models/use-created-event.js +21 -0
  701. package/src/frontend-models/use-destroyed-event.js +148 -0
  702. package/src/frontend-models/use-model-class-event.js +164 -0
  703. package/src/frontend-models/use-updated-event.js +152 -0
  704. package/src/frontend-models/websocket-channel.js +494 -0
  705. package/src/frontend-models/websocket-publishers.js +224 -0
  706. package/src/http-client/header.js +17 -0
  707. package/src/http-client/index.js +139 -0
  708. package/src/http-client/request.js +94 -0
  709. package/src/http-client/response.js +151 -0
  710. package/src/http-client/websocket-client.js +27 -0
  711. package/src/http-server/client/index.js +507 -0
  712. package/src/http-server/client/params-to-object.js +152 -0
  713. package/src/http-server/client/request-buffer/form-data-part.js +139 -0
  714. package/src/http-server/client/request-buffer/header.js +19 -0
  715. package/src/http-server/client/request-buffer/index.js +535 -0
  716. package/src/http-server/client/request-parser.js +195 -0
  717. package/src/http-server/client/request-runner.js +321 -0
  718. package/src/http-server/client/request-timing.js +171 -0
  719. package/src/http-server/client/request.js +114 -0
  720. package/src/http-server/client/response.js +251 -0
  721. package/src/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
  722. package/src/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
  723. package/src/http-server/client/uploaded-file/uploaded-file.js +36 -0
  724. package/src/http-server/client/websocket-request.js +147 -0
  725. package/src/http-server/client/websocket-session.js +1755 -0
  726. package/src/http-server/cookie.js +245 -0
  727. package/src/http-server/development-reloader.js +240 -0
  728. package/src/http-server/index.js +561 -0
  729. package/src/http-server/remote-address.js +77 -0
  730. package/src/http-server/server-client.js +222 -0
  731. package/src/http-server/server-lock.js +178 -0
  732. package/src/http-server/websocket-channel-subscribers.js +110 -0
  733. package/src/http-server/websocket-channel.js +137 -0
  734. package/src/http-server/websocket-connection.js +118 -0
  735. package/src/http-server/websocket-event-log-store.js +433 -0
  736. package/src/http-server/websocket-events-host.js +170 -0
  737. package/src/http-server/websocket-events.js +50 -0
  738. package/src/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
  739. package/src/http-server/worker-handler/in-process.js +155 -0
  740. package/src/http-server/worker-handler/index.js +370 -0
  741. package/src/http-server/worker-handler/worker-script.js +6 -0
  742. package/src/http-server/worker-handler/worker-thread.js +286 -0
  743. package/src/initializer.js +39 -0
  744. package/src/jobs/.gitkeep +1 -0
  745. package/src/jobs/mail-delivery.js +22 -0
  746. package/src/logger/base-logger.js +34 -0
  747. package/src/logger/console-logger.js +28 -0
  748. package/src/logger/file-logger.js +36 -0
  749. package/src/logger/outputs/array-output.js +50 -0
  750. package/src/logger/outputs/console-output.js +32 -0
  751. package/src/logger/outputs/file-output.js +55 -0
  752. package/src/logger/outputs/stdout-output.js +64 -0
  753. package/src/logger.js +507 -0
  754. package/src/mailer/backends/smtp.js +197 -0
  755. package/src/mailer/base.js +337 -0
  756. package/src/mailer/delivery.js +70 -0
  757. package/src/mailer/index.js +24 -0
  758. package/src/mailer.js +15 -0
  759. package/src/plugins/sqljs-wasm-route-controller.js +70 -0
  760. package/src/plugins/sqljs-wasm-route.js +71 -0
  761. package/src/record-payload-values.js +83 -0
  762. package/src/routes/app-routes.js +17 -0
  763. package/src/routes/base-route.js +133 -0
  764. package/src/routes/basic-route.js +109 -0
  765. package/src/routes/built-in/debug/controller.js +12 -0
  766. package/src/routes/built-in/errors/controller.js +7 -0
  767. package/src/routes/built-in/errors/not-found.ejs +1 -0
  768. package/src/routes/get-route.js +75 -0
  769. package/src/routes/hooks/frontend-model-command-route-hook.js +100 -0
  770. package/src/routes/index.js +50 -0
  771. package/src/routes/namespace-route.js +51 -0
  772. package/src/routes/plugin-routes.js +141 -0
  773. package/src/routes/post-route.js +74 -0
  774. package/src/routes/resolver.js +535 -0
  775. package/src/routes/resource-route.js +154 -0
  776. package/src/routes/root-route.js +11 -0
  777. package/src/templates/configuration.js +61 -0
  778. package/src/templates/generate-migration.js +11 -0
  779. package/src/templates/generate-model.js +6 -0
  780. package/src/templates/routes.js +11 -0
  781. package/src/testing/base-expect.js +17 -0
  782. package/src/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
  783. package/src/testing/browser-test-app.js +32 -0
  784. package/src/testing/expect-to-change.js +55 -0
  785. package/src/testing/expect-utils.js +269 -0
  786. package/src/testing/expect.js +763 -0
  787. package/src/testing/request-client.js +90 -0
  788. package/src/testing/test-files-finder.js +364 -0
  789. package/src/testing/test-filter-parser.js +198 -0
  790. package/src/testing/test-runner.js +1168 -0
  791. package/src/testing/test-suite-splitter.js +177 -0
  792. package/src/testing/test.js +370 -0
  793. package/src/types/external-modules.d.ts +57 -0
  794. package/src/utils/backtrace-cleaner-node.js +87 -0
  795. package/src/utils/backtrace-cleaner.js +266 -0
  796. package/src/utils/ensure-error.js +15 -0
  797. package/src/utils/event-emitter.js +8 -0
  798. package/src/utils/file-exists.js +18 -0
  799. package/src/utils/format-value.js +101 -0
  800. package/src/utils/model-scope.js +56 -0
  801. package/src/utils/nest-callbacks.js +22 -0
  802. package/src/utils/plain-object.js +14 -0
  803. package/src/utils/ransack.js +859 -0
  804. package/src/utils/rest-args-error.js +14 -0
  805. package/src/utils/singularize-model-name.js +18 -0
  806. package/src/utils/split-sql-statements.js +88 -0
  807. package/src/utils/to-import-specifier.js +53 -0
  808. package/src/utils/with-tracked-stack-async-hooks.js +103 -0
  809. package/src/utils/with-tracked-stack.js +38 -0
  810. package/src/velocious-error.js +34 -0
  811. package/tsconfig.json +16 -0
@@ -1,25 +1,31 @@
1
1
  // @ts-check
2
- import * as inflection from "inflection";
3
- import { isPlainObject } from "is-plain-object";
4
- import { resolveFrontendModelClass } from "../frontend-models/model-registry.js";
2
+
3
+ import * as inflection from "inflection"
4
+ import {isPlainObject} from "is-plain-object"
5
+ import {resolveFrontendModelClass} from "../frontend-models/model-registry.js"
6
+
5
7
  /**
6
8
  * RansackPredicate type.
7
9
  * @typedef {"cont" | "end" | "eq" | "gt" | "gteq" | "in" | "lt" | "lteq" | "not_eq" | "not_in" | "null" | "start"} RansackPredicate
8
10
  */
11
+
9
12
  /**
10
13
  * RansackCombinator type.
11
14
  * @typedef {"and" | "or"} RansackCombinator
12
15
  */
16
+
13
17
  /**
14
18
  * RansackModelClass type.
15
19
  * @typedef {typeof import("../database/record/index.js").default | typeof import("../frontend-models/base.js").default} RansackModelClass
16
20
  */
21
+
17
22
  /**
18
23
  * RansackAttribute type.
19
24
  * @typedef {object} RansackAttribute
20
25
  * @property {string} attributeName - Resolved attribute name.
21
26
  * @property {string[]} path - Resolved relationship path.
22
27
  */
28
+
23
29
  /**
24
30
  * RansackCondition type.
25
31
  * @typedef {object} RansackCondition
@@ -28,6 +34,7 @@ import { resolveFrontendModelClass } from "../frontend-models/model-registry.js"
28
34
  * @property {RansackPredicate} predicate - Parsed Ransack predicate.
29
35
  * @property {?} value - Normalized value.
30
36
  */
37
+
31
38
  /**
32
39
  * RansackGroup type.
33
40
  * @typedef {object} RansackGroup
@@ -35,30 +42,32 @@ import { resolveFrontendModelClass } from "../frontend-models/model-registry.js"
35
42
  * @property {RansackCondition[]} conditions - Conditions in this group.
36
43
  * @property {RansackGroup[]} groupings - Nested groups.
37
44
  */
45
+
38
46
  const supportedPredicates = [
39
- "not_in",
40
- "not_eq",
41
- "gteq",
42
- "lteq",
43
- "start",
44
- "cont",
45
- "null",
46
- "end",
47
- "eq",
48
- "gt",
49
- "lt",
50
- "in"
51
- ];
47
+ "not_in",
48
+ "not_eq",
49
+ "gteq",
50
+ "lteq",
51
+ "start",
52
+ "cont",
53
+ "null",
54
+ "end",
55
+ "eq",
56
+ "gt",
57
+ "lt",
58
+ "in"
59
+ ]
60
+
52
61
  /**
53
62
  * Runs the normalizeRansackParams helper.
54
63
  * @param {RansackModelClass} modelClass - Model class.
55
64
  * @param {Record<string, ?>} params - Ransack-style params hash.
56
65
  * @returns {RansackCondition[]} - Normalized conditions.
57
66
  */
58
- // fallow-ignore-next-line unused-export
59
67
  export function normalizeRansackParams(modelClass, params) {
60
- return normalizeRansackGroup(modelClass, params).conditions;
68
+ return normalizeRansackGroup(modelClass, params).conditions
61
69
  }
70
+
62
71
  /**
63
72
  * Runs the normalizeRansackGroup helper.
64
73
  * @param {RansackModelClass} modelClass - Model class.
@@ -66,36 +75,43 @@ export function normalizeRansackParams(modelClass, params) {
66
75
  * @returns {RansackGroup} - Normalized group.
67
76
  */
68
77
  export function normalizeRansackGroup(modelClass, params) {
69
- if (!isPlainObject(params)) {
70
- throw new Error(`ransack params must be a plain object, got: ${typeof params}`);
71
- }
72
- /**
73
- * Normalized.
74
- @type {RansackGroup} */
75
- const normalized = {
76
- combinator: normalizeRansackCombinator(params.m, "and"),
77
- conditions: [],
78
- groupings: []
79
- };
80
- for (const [key, rawValue] of Object.entries(params)) {
81
- if (key === "m") {
82
- continue;
83
- }
84
- if (key === "c") {
85
- normalized.conditions.push(...normalizeAdvancedRansackConditions({ modelClass, value: rawValue }));
86
- continue;
87
- }
88
- if (key === "g") {
89
- normalized.groupings.push(...normalizeAdvancedRansackGroups({ modelClass, value: rawValue }));
90
- continue;
91
- }
92
- const condition = normalizeSimpleRansackCondition({ key, modelClass, rawValue });
93
- if (condition)
94
- normalized.conditions.push(condition);
95
- }
96
- return normalized;
97
- }
98
- const SKIP_RANSACK_CONDITION = Symbol("skip-ransack-condition");
78
+ if (!isPlainObject(params)) {
79
+ throw new Error(`ransack params must be a plain object, got: ${typeof params}`)
80
+ }
81
+
82
+ /**
83
+ * Normalized.
84
+ @type {RansackGroup} */
85
+ const normalized = {
86
+ combinator: normalizeRansackCombinator(params.m, "and"),
87
+ conditions: [],
88
+ groupings: []
89
+ }
90
+
91
+ for (const [key, rawValue] of Object.entries(params)) {
92
+ if (key === "m") {
93
+ continue
94
+ }
95
+
96
+ if (key === "c") {
97
+ normalized.conditions.push(...normalizeAdvancedRansackConditions({modelClass, value: rawValue}))
98
+ continue
99
+ }
100
+
101
+ if (key === "g") {
102
+ normalized.groupings.push(...normalizeAdvancedRansackGroups({modelClass, value: rawValue}))
103
+ continue
104
+ }
105
+
106
+ const condition = normalizeSimpleRansackCondition({key, modelClass, rawValue})
107
+ if (condition) normalized.conditions.push(condition)
108
+ }
109
+
110
+ return normalized
111
+ }
112
+
113
+ const SKIP_RANSACK_CONDITION = Symbol("skip-ransack-condition")
114
+
99
115
  /**
100
116
  * Runs normalize simple ransack condition.
101
117
  * @param {object} args - Options.
@@ -104,25 +120,30 @@ const SKIP_RANSACK_CONDITION = Symbol("skip-ransack-condition");
104
120
  * @param {?} args.rawValue - Raw condition value.
105
121
  * @returns {RansackCondition | null} - Normalized condition, or null when skipped.
106
122
  */
107
- function normalizeSimpleRansackCondition({ key, modelClass, rawValue }) {
108
- const parsedKey = parseRansackKey(key);
109
- if (!parsedKey) {
110
- throw new Error(`Unsupported ransack predicate in key: ${key}`);
111
- }
112
- const value = normalizeRansackValue({
113
- predicate: parsedKey.predicate,
114
- value: rawValue
115
- });
116
- if (value === SKIP_RANSACK_CONDITION)
117
- return null;
118
- const attributes = resolveRansackAttributes({ modelClass, value: parsedKey.pathValue });
119
- return {
120
- attributes,
121
- combinator: attributes.length > 1 ? "or" : "and",
122
- predicate: parsedKey.predicate,
123
- value
124
- };
125
- }
123
+ function normalizeSimpleRansackCondition({key, modelClass, rawValue}) {
124
+ const parsedKey = parseRansackKey(key)
125
+
126
+ if (!parsedKey) {
127
+ throw new Error(`Unsupported ransack predicate in key: ${key}`)
128
+ }
129
+
130
+ const value = normalizeRansackValue({
131
+ predicate: parsedKey.predicate,
132
+ value: rawValue
133
+ })
134
+
135
+ if (value === SKIP_RANSACK_CONDITION) return null
136
+
137
+ const attributes = resolveRansackAttributes({modelClass, value: parsedKey.pathValue})
138
+
139
+ return {
140
+ attributes,
141
+ combinator: attributes.length > 1 ? "or" : "and",
142
+ predicate: parsedKey.predicate,
143
+ value
144
+ }
145
+ }
146
+
126
147
  /**
127
148
  * Runs normalize advanced ransack conditions.
128
149
  * @param {object} args - Options.
@@ -130,39 +151,48 @@ function normalizeSimpleRansackCondition({ key, modelClass, rawValue }) {
130
151
  * @param {?} args.value - Advanced conditions collection.
131
152
  * @returns {RansackCondition[]} - Normalized conditions.
132
153
  */
133
- function normalizeAdvancedRansackConditions({ modelClass, value }) {
134
- /**
135
- * Conditions.
136
- @type {RansackCondition[]} */
137
- const conditions = [];
138
- for (const entry of normalizeRansackCollection(value, "conditions")) {
139
- if (!isPlainObject(entry)) {
140
- throw new Error(`Ransack condition entries must be plain objects, got: ${typeof entry}`);
141
- }
142
- const predicateValue = entry.p;
143
- if (typeof predicateValue !== "string") {
144
- throw new Error("Ransack condition predicate must be a string");
145
- }
146
- if (!supportedPredicates.includes(predicateValue)) {
147
- throw new Error(`Unsupported ransack predicate in condition: ${predicateValue}`);
148
- }
149
- const predicate = /**
150
- * Narrows the runtime value to the documented type.
151
- @type {RansackPredicate} */ (predicateValue);
152
- const rawValue = advancedRansackConditionValue({ predicate, value: entry.v });
153
- const normalizedValue = normalizeRansackValue({ predicate, value: rawValue });
154
- if (normalizedValue === SKIP_RANSACK_CONDITION)
155
- continue;
156
- const attributes = resolveRansackAttributesFromAdvancedValue({ modelClass, value: entry.a });
157
- conditions.push({
158
- attributes,
159
- combinator: normalizeRansackCombinator(entry.m, attributes.length > 1 ? "or" : "and"),
160
- predicate,
161
- value: normalizedValue
162
- });
163
- }
164
- return conditions;
165
- }
154
+ function normalizeAdvancedRansackConditions({modelClass, value}) {
155
+ /**
156
+ * Conditions.
157
+ @type {RansackCondition[]} */
158
+ const conditions = []
159
+
160
+ for (const entry of normalizeRansackCollection(value, "conditions")) {
161
+ if (!isPlainObject(entry)) {
162
+ throw new Error(`Ransack condition entries must be plain objects, got: ${typeof entry}`)
163
+ }
164
+
165
+ const predicateValue = entry.p
166
+
167
+ if (typeof predicateValue !== "string") {
168
+ throw new Error("Ransack condition predicate must be a string")
169
+ }
170
+
171
+ if (!supportedPredicates.includes(predicateValue)) {
172
+ throw new Error(`Unsupported ransack predicate in condition: ${predicateValue}`)
173
+ }
174
+
175
+ const predicate = /**
176
+ * Narrows the runtime value to the documented type.
177
+ @type {RansackPredicate} */ (predicateValue)
178
+ const rawValue = advancedRansackConditionValue({predicate, value: entry.v})
179
+ const normalizedValue = normalizeRansackValue({predicate, value: rawValue})
180
+
181
+ if (normalizedValue === SKIP_RANSACK_CONDITION) continue
182
+
183
+ const attributes = resolveRansackAttributesFromAdvancedValue({modelClass, value: entry.a})
184
+
185
+ conditions.push({
186
+ attributes,
187
+ combinator: normalizeRansackCombinator(entry.m, attributes.length > 1 ? "or" : "and"),
188
+ predicate,
189
+ value: normalizedValue
190
+ })
191
+ }
192
+
193
+ return conditions
194
+ }
195
+
166
196
  /**
167
197
  * Runs normalize advanced ransack groups.
168
198
  * @param {object} args - Options.
@@ -170,19 +200,23 @@ function normalizeAdvancedRansackConditions({ modelClass, value }) {
170
200
  * @param {?} args.value - Advanced groups collection.
171
201
  * @returns {RansackGroup[]} - Normalized groups.
172
202
  */
173
- function normalizeAdvancedRansackGroups({ modelClass, value }) {
174
- /**
175
- * Groupings.
176
- @type {RansackGroup[]} */
177
- const groupings = [];
178
- for (const entry of normalizeRansackCollection(value, "groupings")) {
179
- if (!isPlainObject(entry)) {
180
- throw new Error(`Ransack grouping entries must be plain objects, got: ${typeof entry}`);
181
- }
182
- groupings.push(normalizeRansackGroup(modelClass, entry));
203
+ function normalizeAdvancedRansackGroups({modelClass, value}) {
204
+ /**
205
+ * Groupings.
206
+ @type {RansackGroup[]} */
207
+ const groupings = []
208
+
209
+ for (const entry of normalizeRansackCollection(value, "groupings")) {
210
+ if (!isPlainObject(entry)) {
211
+ throw new Error(`Ransack grouping entries must be plain objects, got: ${typeof entry}`)
183
212
  }
184
- return groupings;
213
+
214
+ groupings.push(normalizeRansackGroup(modelClass, entry))
215
+ }
216
+
217
+ return groupings
185
218
  }
219
+
186
220
  /**
187
221
  * Runs normalize ransack combinator.
188
222
  * @param {?} value - Candidate combinator.
@@ -190,12 +224,12 @@ function normalizeAdvancedRansackGroups({ modelClass, value }) {
190
224
  * @returns {RansackCombinator} - Normalized combinator.
191
225
  */
192
226
  function normalizeRansackCombinator(value, defaultValue) {
193
- if (value === undefined || value === null || value === "")
194
- return defaultValue;
195
- if (value === "and" || value === "or")
196
- return value;
197
- throw new Error(`Invalid ransack combinator: ${String(value)}`);
227
+ if (value === undefined || value === null || value === "") return defaultValue
228
+ if (value === "and" || value === "or") return value
229
+
230
+ throw new Error(`Invalid ransack combinator: ${String(value)}`)
198
231
  }
232
+
199
233
  /**
200
234
  * Runs normalize ransack collection.
201
235
  * @param {?} value - Candidate collection.
@@ -203,24 +237,27 @@ function normalizeRansackCombinator(value, defaultValue) {
203
237
  * @returns {Array<?>} - Collection values in stable order.
204
238
  */
205
239
  function normalizeRansackCollection(value, name) {
206
- if (value === undefined || value === null || value === "")
207
- return [];
208
- if (Array.isArray(value))
209
- return value;
210
- if (isPlainObject(value)) {
211
- return Object.keys(value)
212
- .sort((left, right) => {
213
- const leftNumber = Number(left);
214
- const rightNumber = Number(right);
215
- if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) {
216
- return leftNumber - rightNumber;
217
- }
218
- return left.localeCompare(right);
219
- })
220
- .map((key) => value[key]);
221
- }
222
- throw new Error(`Ransack ${name} must be an array or object, got: ${typeof value}`);
240
+ if (value === undefined || value === null || value === "") return []
241
+ if (Array.isArray(value)) return value
242
+
243
+ if (isPlainObject(value)) {
244
+ return Object.keys(value)
245
+ .sort((left, right) => {
246
+ const leftNumber = Number(left)
247
+ const rightNumber = Number(right)
248
+
249
+ if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) {
250
+ return leftNumber - rightNumber
251
+ }
252
+
253
+ return left.localeCompare(right)
254
+ })
255
+ .map((key) => value[key])
256
+ }
257
+
258
+ throw new Error(`Ransack ${name} must be an array or object, got: ${typeof value}`)
223
259
  }
260
+
224
261
  /**
225
262
  * Runs advanced ransack condition value.
226
263
  * @param {object} args - Options.
@@ -228,14 +265,16 @@ function normalizeRansackCollection(value, name) {
228
265
  * @param {?} args.value - Advanced condition value.
229
266
  * @returns {?} - Value passed to predicate normalization.
230
267
  */
231
- function advancedRansackConditionValue({ predicate, value }) {
232
- if (predicate === "in" || predicate === "not_in")
233
- return value;
234
- if (Array.isArray(value)) {
235
- return value.find((entry) => entry !== undefined && entry !== null && entry !== "");
236
- }
237
- return value;
268
+ function advancedRansackConditionValue({predicate, value}) {
269
+ if (predicate === "in" || predicate === "not_in") return value
270
+
271
+ if (Array.isArray(value)) {
272
+ return value.find((entry) => entry !== undefined && entry !== null && entry !== "")
273
+ }
274
+
275
+ return value
238
276
  }
277
+
239
278
  /**
240
279
  * Runs resolve ransack attributes from advanced value.
241
280
  * @param {object} args - Options.
@@ -243,49 +282,58 @@ function advancedRansackConditionValue({ predicate, value }) {
243
282
  * @param {?} args.value - Advanced attribute value.
244
283
  * @returns {RansackAttribute[]} - Resolved attributes.
245
284
  */
246
- function resolveRansackAttributesFromAdvancedValue({ modelClass, value }) {
247
- const values = normalizeAdvancedAttributeValues(value);
248
- /**
249
- * Attributes.
250
- @type {RansackAttribute[]} */
251
- const attributes = [];
252
- for (const attributeValue of values) {
253
- attributes.push(...resolveRansackAttributes({ modelClass, value: attributeValue }));
254
- }
255
- if (attributes.length < 1) {
256
- throw new Error("Ransack condition must include at least one attribute");
257
- }
258
- return attributes;
259
- }
285
+ function resolveRansackAttributesFromAdvancedValue({modelClass, value}) {
286
+ const values = normalizeAdvancedAttributeValues(value)
287
+ /**
288
+ * Attributes.
289
+ @type {RansackAttribute[]} */
290
+ const attributes = []
291
+
292
+ for (const attributeValue of values) {
293
+ attributes.push(...resolveRansackAttributes({modelClass, value: attributeValue}))
294
+ }
295
+
296
+ if (attributes.length < 1) {
297
+ throw new Error("Ransack condition must include at least one attribute")
298
+ }
299
+
300
+ return attributes
301
+ }
302
+
260
303
  /**
261
304
  * Runs normalize advanced attribute values.
262
305
  * @param {?} value - Advanced attribute value.
263
306
  * @returns {string[]} - Attribute path strings.
264
307
  */
265
308
  function normalizeAdvancedAttributeValues(value) {
266
- if (typeof value === "string")
267
- return [value];
268
- if (Array.isArray(value)) {
269
- return value.map((entry) => normalizeAdvancedAttributeValue(entry));
270
- }
271
- if (isPlainObject(value)) {
272
- return normalizeRansackCollection(value, "attributes").map((entry) => normalizeAdvancedAttributeValue(entry));
273
- }
274
- throw new Error(`Ransack condition attributes must be strings, arrays, or objects, got: ${typeof value}`);
275
- }
309
+ if (typeof value === "string") return [value]
310
+
311
+ if (Array.isArray(value)) {
312
+ return value.map((entry) => normalizeAdvancedAttributeValue(entry))
313
+ }
314
+
315
+ if (isPlainObject(value)) {
316
+ return normalizeRansackCollection(value, "attributes").map((entry) => normalizeAdvancedAttributeValue(entry))
317
+ }
318
+
319
+ throw new Error(`Ransack condition attributes must be strings, arrays, or objects, got: ${typeof value}`)
320
+ }
321
+
276
322
  /**
277
323
  * Runs normalize advanced attribute value.
278
324
  * @param {?} value - Advanced attribute entry.
279
325
  * @returns {string} - Attribute path string.
280
326
  */
281
327
  function normalizeAdvancedAttributeValue(value) {
282
- if (typeof value === "string")
283
- return value;
284
- if (isPlainObject(value) && typeof value.name === "string") {
285
- return value.name;
286
- }
287
- throw new Error(`Ransack condition attribute entries must be strings or {name}, got: ${typeof value}`);
328
+ if (typeof value === "string") return value
329
+
330
+ if (isPlainObject(value) && typeof value.name === "string") {
331
+ return value.name
332
+ }
333
+
334
+ throw new Error(`Ransack condition attribute entries must be strings or {name}, got: ${typeof value}`)
288
335
  }
336
+
289
337
  /**
290
338
  * Runs resolve ransack attributes.
291
339
  * @param {object} args - Options.
@@ -293,20 +341,23 @@ function normalizeAdvancedAttributeValue(value) {
293
341
  * @param {string} args.value - Attribute path value.
294
342
  * @returns {RansackAttribute[]} - Resolved attributes.
295
343
  */
296
- function resolveRansackAttributes({ modelClass, value }) {
297
- return value.split("_or_").map((attributeValue) => {
298
- const resolvedPath = resolveRansackPath({ modelClass, value: attributeValue });
299
- const targetModelClass = modelClassAtPath({ modelClass, path: resolvedPath.path });
300
- const attributeName = resolveAttributeName({ modelClass: targetModelClass, value: resolvedPath.attributeValue });
301
- if (!attributeName) {
302
- throw new Error(`Unknown ransack attribute "${resolvedPath.attributeValue}" for ${targetModelClass.name}`);
303
- }
304
- return {
305
- attributeName,
306
- path: resolvedPath.path
307
- };
308
- });
344
+ function resolveRansackAttributes({modelClass, value}) {
345
+ return value.split("_or_").map((attributeValue) => {
346
+ const resolvedPath = resolveRansackPath({modelClass, value: attributeValue})
347
+ const targetModelClass = modelClassAtPath({modelClass, path: resolvedPath.path})
348
+ const attributeName = resolveAttributeName({modelClass: targetModelClass, value: resolvedPath.attributeValue})
349
+
350
+ if (!attributeName) {
351
+ throw new Error(`Unknown ransack attribute "${resolvedPath.attributeValue}" for ${targetModelClass.name}`)
352
+ }
353
+
354
+ return {
355
+ attributeName,
356
+ path: resolvedPath.path
357
+ }
358
+ })
309
359
  }
360
+
310
361
  /**
311
362
  * Runs model class at path.
312
363
  * @param {object} args - Options.
@@ -314,17 +365,22 @@ function resolveRansackAttributes({ modelClass, value }) {
314
365
  * @param {string[]} args.path - Relationship path.
315
366
  * @returns {RansackModelClass} - Target model class.
316
367
  */
317
- function modelClassAtPath({ modelClass, path }) {
318
- let currentModelClass = modelClass;
319
- for (const relationshipName of path) {
320
- const relationship = relationshipEntries(currentModelClass)[relationshipName];
321
- if (!relationship) {
322
- throw new Error(`Unknown ransack relationship "${relationshipName}" for ${currentModelClass.name}`);
323
- }
324
- currentModelClass = relationship.targetModelClass;
368
+ function modelClassAtPath({modelClass, path}) {
369
+ let currentModelClass = modelClass
370
+
371
+ for (const relationshipName of path) {
372
+ const relationship = relationshipEntries(currentModelClass)[relationshipName]
373
+
374
+ if (!relationship) {
375
+ throw new Error(`Unknown ransack relationship "${relationshipName}" for ${currentModelClass.name}`)
325
376
  }
326
- return currentModelClass;
377
+
378
+ currentModelClass = relationship.targetModelClass
379
+ }
380
+
381
+ return currentModelClass
327
382
  }
383
+
328
384
  /**
329
385
  * Runs resolve ransack path.
330
386
  * @param {object} args - Options.
@@ -332,35 +388,41 @@ function modelClassAtPath({ modelClass, path }) {
332
388
  * @param {string} args.value - Remaining path value.
333
389
  * @returns {{attributeValue: string, path: string[]}} - Resolved relationship path and remaining attribute value.
334
390
  */
335
- function resolveRansackPath({ modelClass, value }) {
336
- /**
337
- * Path.
338
- @type {string[]} */
339
- const path = [];
340
- let currentModelClass = modelClass;
341
- let remainingValue = value;
342
- while (true) {
343
- if (resolveAttributeName({ modelClass: currentModelClass, value: remainingValue })) {
344
- break;
345
- }
346
- const match = findRelationshipPrefix({
347
- modelClass: currentModelClass,
348
- value: remainingValue
349
- });
350
- if (!match)
351
- break;
352
- path.push(match.relationshipName);
353
- currentModelClass = match.targetModelClass;
354
- remainingValue = match.remainingValue;
355
- }
356
- if (remainingValue.length < 1) {
357
- throw new Error(`Invalid ransack key path: ${value}`);
358
- }
359
- return {
360
- attributeValue: remainingValue,
361
- path
362
- };
363
- }
391
+ function resolveRansackPath({modelClass, value}) {
392
+ /**
393
+ * Path.
394
+ @type {string[]} */
395
+ const path = []
396
+ let currentModelClass = modelClass
397
+ let remainingValue = value
398
+
399
+ while (true) {
400
+ if (resolveAttributeName({modelClass: currentModelClass, value: remainingValue})) {
401
+ break
402
+ }
403
+
404
+ const match = findRelationshipPrefix({
405
+ modelClass: currentModelClass,
406
+ value: remainingValue
407
+ })
408
+
409
+ if (!match) break
410
+
411
+ path.push(match.relationshipName)
412
+ currentModelClass = match.targetModelClass
413
+ remainingValue = match.remainingValue
414
+ }
415
+
416
+ if (remainingValue.length < 1) {
417
+ throw new Error(`Invalid ransack key path: ${value}`)
418
+ }
419
+
420
+ return {
421
+ attributeValue: remainingValue,
422
+ path
423
+ }
424
+ }
425
+
364
426
  /**
365
427
  * Runs find relationship prefix.
366
428
  * @param {object} args - Options.
@@ -368,34 +430,37 @@ function resolveRansackPath({ modelClass, value }) {
368
430
  * @param {string} args.value - Remaining value to match.
369
431
  * @returns {{relationshipName: string, remainingValue: string, targetModelClass: RansackModelClass} | null} - Matching relationship prefix.
370
432
  */
371
- function findRelationshipPrefix({ modelClass, value }) {
372
- let bestMatch = null;
373
- for (const relationshipName of Object.keys(relationshipEntries(modelClass))) {
374
- const relationship = relationshipEntries(modelClass)[relationshipName];
375
- for (const candidate of relationshipCandidates(relationshipName)) {
376
- const remainingValue = stripRelationshipCandidate(value, candidate);
377
- if (remainingValue === null)
378
- continue;
379
- if (remainingValue.length < 1)
380
- continue;
381
- if (bestMatch && candidate.length <= bestMatch.candidateLength)
382
- continue;
383
- bestMatch = {
384
- candidateLength: candidate.length,
385
- relationshipName,
386
- remainingValue,
387
- targetModelClass: relationship.targetModelClass
388
- };
389
- }
390
- }
391
- if (!bestMatch)
392
- return null;
393
- return {
394
- relationshipName: bestMatch.relationshipName,
395
- remainingValue: bestMatch.remainingValue,
396
- targetModelClass: bestMatch.targetModelClass
397
- };
398
- }
433
+ function findRelationshipPrefix({modelClass, value}) {
434
+ let bestMatch = null
435
+
436
+ for (const relationshipName of Object.keys(relationshipEntries(modelClass))) {
437
+ const relationship = relationshipEntries(modelClass)[relationshipName]
438
+
439
+ for (const candidate of relationshipCandidates(relationshipName)) {
440
+ const remainingValue = stripRelationshipCandidate(value, candidate)
441
+
442
+ if (remainingValue === null) continue
443
+ if (remainingValue.length < 1) continue
444
+ if (bestMatch && candidate.length <= bestMatch.candidateLength) continue
445
+
446
+ bestMatch = {
447
+ candidateLength: candidate.length,
448
+ relationshipName,
449
+ remainingValue,
450
+ targetModelClass: relationship.targetModelClass
451
+ }
452
+ }
453
+ }
454
+
455
+ if (!bestMatch) return null
456
+
457
+ return {
458
+ relationshipName: bestMatch.relationshipName,
459
+ remainingValue: bestMatch.remainingValue,
460
+ targetModelClass: bestMatch.targetModelClass
461
+ }
462
+ }
463
+
399
464
  /**
400
465
  * Returns the portion of `value` after `candidate` when `candidate`
401
466
  * sits at a relationship-path boundary, or null when there's no
@@ -412,26 +477,29 @@ function findRelationshipPrefix({ modelClass, value }) {
412
477
  * @returns {string | null} - Remainder after the candidate, or null.
413
478
  */
414
479
  function stripRelationshipCandidate(value, candidate) {
415
- if (value.startsWith(`${candidate}_`)) {
416
- return value.slice(candidate.length + 1);
417
- }
418
- if (value.length <= candidate.length)
419
- return null;
420
- if (!value.startsWith(candidate))
421
- return null;
422
- const nextChar = value.charAt(candidate.length);
423
- if (nextChar < "A" || nextChar > "Z")
424
- return null;
425
- return nextChar.toLowerCase() + value.slice(candidate.length + 1);
426
- }
480
+ if (value.startsWith(`${candidate}_`)) {
481
+ return value.slice(candidate.length + 1)
482
+ }
483
+
484
+ if (value.length <= candidate.length) return null
485
+ if (!value.startsWith(candidate)) return null
486
+
487
+ const nextChar = value.charAt(candidate.length)
488
+
489
+ if (nextChar < "A" || nextChar > "Z") return null
490
+
491
+ return nextChar.toLowerCase() + value.slice(candidate.length + 1)
492
+ }
493
+
427
494
  /**
428
495
  * Runs relationship candidates.
429
496
  * @param {string} relationshipName - Relationship name.
430
497
  * @returns {string[]} - Candidate tokens for matching.
431
498
  */
432
499
  function relationshipCandidates(relationshipName) {
433
- return uniqunize([relationshipName, inflection.underscore(relationshipName)]);
500
+ return uniqunize([relationshipName, inflection.underscore(relationshipName)])
434
501
  }
502
+
435
503
  /**
436
504
  * Runs resolve attribute name.
437
505
  * @param {object} args - Options.
@@ -439,123 +507,139 @@ function relationshipCandidates(relationshipName) {
439
507
  * @param {string} args.value - Attribute candidate.
440
508
  * @returns {string | undefined} - Resolved attribute name.
441
509
  */
442
- function resolveAttributeName({ modelClass, value }) {
443
- for (const [attributeName, columnName] of Object.entries(attributeEntries(modelClass))) {
444
- if (matchesAttributeValue({ attributeName, columnName, value })) {
445
- return attributeName;
446
- }
510
+ function resolveAttributeName({modelClass, value}) {
511
+ for (const [attributeName, columnName] of Object.entries(attributeEntries(modelClass))) {
512
+ if (matchesAttributeValue({attributeName, columnName, value})) {
513
+ return attributeName
447
514
  }
448
- return undefined;
515
+ }
516
+
517
+ return undefined
449
518
  }
519
+
450
520
  /**
451
521
  * Runs relationship entries.
452
522
  * @param {RansackModelClass} modelClass - Model class.
453
523
  * @returns {Record<string, {targetModelClass: RansackModelClass}>} - Relationship entries keyed by name.
454
524
  */
455
525
  function relationshipEntries(modelClass) {
456
- if (typeof /**
457
- * Narrows the runtime value to the documented type.
458
- @type {?} */ (modelClass).getRelationshipsMap === "function") {
459
- return backendRelationshipEntries(modelClass);
460
- }
461
- if (typeof /**
462
- * Narrows the runtime value to the documented type.
463
- @type {?} */ (modelClass).relationshipDefinitions === "function" &&
464
- typeof /**
465
- * Narrows the runtime value to the documented type.
466
- @type {?} */ (modelClass).relationshipModelClasses === "function") {
467
- return frontendRelationshipEntries(modelClass);
468
- }
469
- return {};
470
- }
526
+ if (typeof /**
527
+ * Narrows the runtime value to the documented type.
528
+ @type {?} */ (modelClass).getRelationshipsMap === "function") {
529
+ return backendRelationshipEntries(modelClass)
530
+ }
531
+
532
+ if (typeof /**
533
+ * Narrows the runtime value to the documented type.
534
+ @type {?} */ (modelClass).relationshipDefinitions === "function" &&
535
+ typeof /**
536
+ * Narrows the runtime value to the documented type.
537
+ @type {?} */ (modelClass).relationshipModelClasses === "function") {
538
+ return frontendRelationshipEntries(modelClass)
539
+ }
540
+
541
+ return {}
542
+ }
543
+
471
544
  /**
472
545
  * Runs backend relationship entries.
473
546
  * @param {RansackModelClass} modelClass - Backend model class.
474
547
  * @returns {Record<string, {targetModelClass: RansackModelClass}>} - Relationship entries keyed by name.
475
548
  */
476
549
  function backendRelationshipEntries(modelClass) {
477
- /**
478
- * Entries.
479
- @type {Record<string, {targetModelClass: RansackModelClass}>} */
480
- const entries = {};
481
- const relationshipsMap = /**
482
- * Narrows the runtime value to the documented type.
483
- @type {?} */ (modelClass).getRelationshipsMap();
484
- for (const relationshipName of Object.keys(relationshipsMap)) {
485
- const relationship = relationshipsMap[relationshipName];
486
- if (typeof relationship.isPolymorphic === "function" && relationship.isPolymorphic())
487
- continue;
488
- const targetModelClass = relationship.getTargetModelClass();
489
- if (!targetModelClass)
490
- continue;
491
- entries[relationshipName] = { targetModelClass };
492
- }
493
- return entries;
494
- }
550
+ /**
551
+ * Entries.
552
+ @type {Record<string, {targetModelClass: RansackModelClass}>} */
553
+ const entries = {}
554
+ const relationshipsMap = /**
555
+ * Narrows the runtime value to the documented type.
556
+ @type {?} */ (modelClass).getRelationshipsMap()
557
+
558
+ for (const relationshipName of Object.keys(relationshipsMap)) {
559
+ const relationship = relationshipsMap[relationshipName]
560
+
561
+ if (typeof relationship.isPolymorphic === "function" && relationship.isPolymorphic()) continue
562
+
563
+ const targetModelClass = relationship.getTargetModelClass()
564
+
565
+ if (!targetModelClass) continue
566
+
567
+ entries[relationshipName] = {targetModelClass}
568
+ }
569
+
570
+ return entries
571
+ }
572
+
495
573
  /**
496
574
  * Runs frontend relationship entries.
497
575
  * @param {RansackModelClass} modelClass - Frontend model class.
498
576
  * @returns {Record<string, {targetModelClass: RansackModelClass}>} - Relationship entries keyed by name.
499
577
  */
500
578
  function frontendRelationshipEntries(modelClass) {
501
- /**
502
- * Entries.
503
- @type {Record<string, {targetModelClass: RansackModelClass}>} */
504
- const entries = {};
505
- const definitions = /**
506
- * Narrows the runtime value to the documented type.
507
- @type {?} */ (modelClass).relationshipDefinitions();
508
- const relationshipModelClasses = /**
509
- * Narrows the runtime value to the documented type.
510
- @type {?} */ (modelClass).relationshipModelClasses();
511
- for (const relationshipName of Object.keys(definitions)) {
512
- const targetModelClass = resolveFrontendModelClass(relationshipModelClasses[relationshipName]);
513
- if (!targetModelClass)
514
- continue;
515
- entries[relationshipName] = { targetModelClass };
516
- }
517
- return entries;
518
- }
579
+ /**
580
+ * Entries.
581
+ @type {Record<string, {targetModelClass: RansackModelClass}>} */
582
+ const entries = {}
583
+ const definitions = /**
584
+ * Narrows the runtime value to the documented type.
585
+ @type {?} */ (modelClass).relationshipDefinitions()
586
+ const relationshipModelClasses = /**
587
+ * Narrows the runtime value to the documented type.
588
+ @type {?} */ (modelClass).relationshipModelClasses()
589
+
590
+ for (const relationshipName of Object.keys(definitions)) {
591
+ const targetModelClass = resolveFrontendModelClass(relationshipModelClasses[relationshipName])
592
+
593
+ if (!targetModelClass) continue
594
+
595
+ entries[relationshipName] = {targetModelClass}
596
+ }
597
+
598
+ return entries
599
+ }
600
+
519
601
  /**
520
602
  * Runs attribute entries.
521
603
  * @param {RansackModelClass} modelClass - Model class.
522
604
  * @returns {Record<string, string>} - Attribute-to-column entries keyed by attribute name.
523
605
  */
524
606
  function attributeEntries(modelClass) {
525
- if (typeof /**
526
- * Narrows the runtime value to the documented type.
527
- @type {?} */ (modelClass).getAttributeNameToColumnNameMap === "function") {
528
- return /** Narrows the runtime value to the documented type. @type {Record<string, string>} */ (( /**
529
- * Narrows the runtime value to the documented type.
530
- @type {?} */(modelClass).getAttributeNameToColumnNameMap()));
531
- }
532
- const resourceConfig = typeof /**
533
- * Narrows the runtime value to the documented type.
534
- @type {?} */ (modelClass).resourceConfig === "function"
535
- ? /**
536
- * Narrows the runtime value to the documented type.
537
- @type {?} */
538
- (modelClass).resourceConfig()
539
- : {};
540
- const attributes = resourceConfig.attributes;
541
- /**
542
- * Entries.
543
- @type {Record<string, string>} */
544
- const entries = {};
545
- if (Array.isArray(attributes)) {
546
- for (const attributeName of attributes) {
547
- if (typeof attributeName !== "string")
548
- continue;
549
- entries[attributeName] = attributeName;
550
- }
551
- }
552
- else if (isPlainObject(attributes)) {
553
- for (const attributeName of Object.keys(attributes)) {
554
- entries[attributeName] = attributeName;
555
- }
556
- }
557
- return entries;
558
- }
607
+ if (typeof /**
608
+ * Narrows the runtime value to the documented type.
609
+ @type {?} */ (modelClass).getAttributeNameToColumnNameMap === "function") {
610
+ return /** Narrows the runtime value to the documented type. @type {Record<string, string>} */ ((/**
611
+ * Narrows the runtime value to the documented type.
612
+ @type {?} */ (modelClass).getAttributeNameToColumnNameMap()))
613
+ }
614
+
615
+ const resourceConfig = typeof /**
616
+ * Narrows the runtime value to the documented type.
617
+ @type {?} */ (modelClass).resourceConfig === "function"
618
+ ? /**
619
+ * Narrows the runtime value to the documented type.
620
+ @type {?} */ (modelClass).resourceConfig()
621
+ : {}
622
+ const attributes = resourceConfig.attributes
623
+ /**
624
+ * Entries.
625
+ @type {Record<string, string>} */
626
+ const entries = {}
627
+
628
+ if (Array.isArray(attributes)) {
629
+ for (const attributeName of attributes) {
630
+ if (typeof attributeName !== "string") continue
631
+
632
+ entries[attributeName] = attributeName
633
+ }
634
+ } else if (isPlainObject(attributes)) {
635
+ for (const attributeName of Object.keys(attributes)) {
636
+ entries[attributeName] = attributeName
637
+ }
638
+ }
639
+
640
+ return entries
641
+ }
642
+
559
643
  /**
560
644
  * Runs matches attribute value.
561
645
  * @param {object} args - Options.
@@ -564,61 +648,72 @@ function attributeEntries(modelClass) {
564
648
  * @param {string} args.value - Candidate value.
565
649
  * @returns {boolean} - Whether the candidate resolves to the attribute.
566
650
  */
567
- function matchesAttributeValue({ attributeName, columnName, value }) {
568
- return uniqunize([
569
- attributeName,
570
- columnName,
571
- inflection.underscore(attributeName),
572
- inflection.underscore(columnName)
573
- ]).includes(value);
651
+ function matchesAttributeValue({attributeName, columnName, value}) {
652
+ return uniqunize([
653
+ attributeName,
654
+ columnName,
655
+ inflection.underscore(attributeName),
656
+ inflection.underscore(columnName)
657
+ ]).includes(value)
574
658
  }
659
+
575
660
  /**
576
661
  * Runs parse ransack key.
577
662
  * @param {string} key - Ransack key.
578
663
  * @returns {{pathValue: string, predicate: RansackPredicate} | null} - Parsed key.
579
664
  */
580
665
  function parseRansackKey(key) {
581
- for (const predicate of supportedPredicates) {
582
- const suffix = `_${predicate}`;
583
- if (!key.endsWith(suffix))
584
- continue;
585
- const pathValue = key.slice(0, key.length - suffix.length);
586
- if (pathValue.length < 1) {
587
- throw new Error(`Invalid ransack key: ${key}`);
588
- }
589
- return {
590
- pathValue,
591
- predicate: /**
592
- * Narrows the runtime value to the documented type.
593
- @type {RansackPredicate} */ (predicate)
594
- };
595
- }
596
- for (const predicate of supportedPredicates) {
597
- const camelSuffix = snakeToCamelSuffix(predicate);
598
- if (!key.endsWith(camelSuffix))
599
- continue;
600
- const pathValue = key.slice(0, key.length - camelSuffix.length);
601
- if (pathValue.length < 1) {
602
- throw new Error(`Invalid ransack key: ${key}`);
603
- }
604
- return {
605
- pathValue,
606
- predicate: /**
607
- * Narrows the runtime value to the documented type.
608
- @type {RansackPredicate} */ (predicate)
609
- };
666
+ for (const predicate of supportedPredicates) {
667
+ const suffix = `_${predicate}`
668
+ if (!key.endsWith(suffix)) continue
669
+
670
+ const pathValue = key.slice(0, key.length - suffix.length)
671
+
672
+ if (pathValue.length < 1) {
673
+ throw new Error(`Invalid ransack key: ${key}`)
674
+ }
675
+
676
+ return {
677
+ pathValue,
678
+ predicate: /**
679
+ * Narrows the runtime value to the documented type.
680
+ @type {RansackPredicate} */ (predicate)
681
+ }
682
+ }
683
+
684
+ for (const predicate of supportedPredicates) {
685
+ const camelSuffix = snakeToCamelSuffix(predicate)
686
+
687
+ if (!key.endsWith(camelSuffix)) continue
688
+
689
+ const pathValue = key.slice(0, key.length - camelSuffix.length)
690
+
691
+ if (pathValue.length < 1) {
692
+ throw new Error(`Invalid ransack key: ${key}`)
693
+ }
694
+
695
+ return {
696
+ pathValue,
697
+ predicate: /**
698
+ * Narrows the runtime value to the documented type.
699
+ @type {RansackPredicate} */ (predicate)
610
700
  }
611
- return null;
701
+ }
702
+
703
+ return null
612
704
  }
705
+
613
706
  /**
614
707
  * Runs snake to camel suffix.
615
708
  * @param {string} value - Snake-case predicate.
616
709
  * @returns {string} - CamelCase predicate suffix used in ransack keys.
617
710
  */
618
711
  function snakeToCamelSuffix(value) {
619
- const segments = value.split("_");
620
- return segments.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join("");
712
+ const segments = value.split("_")
713
+
714
+ return segments.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)).join("")
621
715
  }
716
+
622
717
  /**
623
718
  * Runs normalize ransack value.
624
719
  * @param {object} args - Options.
@@ -626,87 +721,99 @@ function snakeToCamelSuffix(value) {
626
721
  * @param {?} args.value - Raw value.
627
722
  * @returns {?} - Normalized value.
628
723
  */
629
- function normalizeRansackValue({ predicate, value }) {
630
- if (predicate === "null") {
631
- return normalizeRansackNullValue(value);
632
- }
633
- if (predicate === "in" || predicate === "not_in") {
634
- return normalizeRansackListValue(value);
635
- }
636
- if (ransackValueIsBlank(value))
637
- return SKIP_RANSACK_CONDITION;
638
- return value;
639
- }
724
+ function normalizeRansackValue({predicate, value}) {
725
+ if (predicate === "null") {
726
+ return normalizeRansackNullValue(value)
727
+ }
728
+
729
+ if (predicate === "in" || predicate === "not_in") {
730
+ return normalizeRansackListValue(value)
731
+ }
732
+
733
+ if (ransackValueIsBlank(value)) return SKIP_RANSACK_CONDITION
734
+
735
+ return value
736
+ }
737
+
640
738
  /**
641
739
  * Runs normalize ransack null value.
642
740
  * @param {?} value - Candidate null predicate value.
643
741
  * @returns {boolean | typeof SKIP_RANSACK_CONDITION} - Normalized value.
644
742
  */
645
743
  function normalizeRansackNullValue(value) {
646
- const booleanValue = normalizeRansackBoolean(value);
647
- return booleanValue === null ? SKIP_RANSACK_CONDITION : booleanValue;
744
+ const booleanValue = normalizeRansackBoolean(value)
745
+
746
+ return booleanValue === null ? SKIP_RANSACK_CONDITION : booleanValue
648
747
  }
748
+
649
749
  /**
650
750
  * Runs normalize ransack list value.
651
751
  * @param {?} value - Candidate list predicate value.
652
752
  * @returns {Array<?> | typeof SKIP_RANSACK_CONDITION} - Normalized value.
653
753
  */
654
754
  function normalizeRansackListValue(value) {
655
- const normalizedArray = normalizeRansackArray(value);
656
- return normalizedArray.length < 1 ? SKIP_RANSACK_CONDITION : normalizedArray;
755
+ const normalizedArray = normalizeRansackArray(value)
756
+
757
+ return normalizedArray.length < 1 ? SKIP_RANSACK_CONDITION : normalizedArray
657
758
  }
759
+
658
760
  /**
659
761
  * Ransack true values.
660
762
  @type {Set<?>} */
661
- const ransackTrueValues = new Set([true, 1, "1", "true"]);
763
+ const ransackTrueValues = new Set([true, 1, "1", "true"])
662
764
  /**
663
765
  * Ransack false values.
664
766
  @type {Set<?>} */
665
- const ransackFalseValues = new Set([false, 0, "0", "false"]);
767
+ const ransackFalseValues = new Set([false, 0, "0", "false"])
768
+
666
769
  /**
667
770
  * Runs normalize ransack boolean.
668
771
  * @param {?} value - Candidate boolean.
669
772
  * @returns {boolean | null} - Normalized boolean or null when blank.
670
773
  */
671
774
  function normalizeRansackBoolean(value) {
672
- if (ransackTrueValues.has(value))
673
- return true;
674
- if (ransackFalseValues.has(value))
675
- return false;
676
- if (ransackValueIsBlank(value))
677
- return null;
678
- throw new Error(`Invalid ransack boolean value: ${String(value)}`);
775
+ if (ransackTrueValues.has(value)) return true
776
+ if (ransackFalseValues.has(value)) return false
777
+ if (ransackValueIsBlank(value)) return null
778
+
779
+ throw new Error(`Invalid ransack boolean value: ${String(value)}`)
679
780
  }
781
+
680
782
  /**
681
783
  * Runs ransack value is blank.
682
784
  * @param {?} value - Candidate value.
683
785
  * @returns {boolean} - Whether value should be ignored as blank.
684
786
  */
685
787
  function ransackValueIsBlank(value) {
686
- return value === undefined || value === null || value === "";
788
+ return value === undefined || value === null || value === ""
687
789
  }
790
+
688
791
  /**
689
792
  * Runs normalize ransack array.
690
793
  * @param {?} value - Candidate array-ish value.
691
794
  * @returns {Array<?>} - Normalized array values.
692
795
  */
693
796
  function normalizeRansackArray(value) {
694
- if (Array.isArray(value)) {
695
- return value.filter((entry) => entry !== undefined && entry !== null && entry !== "");
696
- }
697
- if (typeof value === "string") {
698
- return value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
699
- }
700
- if (value === undefined || value === null || value === "")
701
- return [];
702
- return [value];
703
- }
797
+ if (Array.isArray(value)) {
798
+ return value.filter((entry) => entry !== undefined && entry !== null && entry !== "")
799
+ }
800
+
801
+ if (typeof value === "string") {
802
+ return value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0)
803
+ }
804
+
805
+ if (value === undefined || value === null || value === "") return []
806
+
807
+ return [value]
808
+ }
809
+
704
810
  /**
705
811
  * RansackSort type.
706
812
  * @typedef {object} RansackSort
707
813
  * @property {string} attribute - Resolved attribute name.
708
814
  * @property {"asc" | "desc"} direction - Sort direction.
709
815
  */
816
+
710
817
  /**
711
818
  * Parses and validates a ransack `s` sort string against model attributes.
712
819
  * @param {RansackModelClass} modelClass - Model class for attribute validation.
@@ -714,32 +821,39 @@ function normalizeRansackArray(value) {
714
821
  * @returns {RansackSort[]} - Validated sort definitions.
715
822
  */
716
823
  export function parseRansackSort(modelClass, sortString) {
717
- const segments = sortString.split(",").map((segment) => segment.trim()).filter((segment) => segment.length > 0);
718
- /**
719
- * Sorts.
720
- @type {RansackSort[]} */
721
- const sorts = [];
722
- for (const segment of segments) {
723
- const parts = segment.split(/\s+/);
724
- const columnCandidate = parts[0];
725
- const directionCandidate = parts.length > 1 ? parts[1].toLowerCase() : "asc";
726
- if (directionCandidate !== "asc" && directionCandidate !== "desc") {
727
- throw new Error(`Invalid ransack sort direction "${directionCandidate}" in: ${segment}`);
728
- }
729
- const resolvedAttribute = resolveAttributeName({ modelClass, value: columnCandidate });
730
- if (!resolvedAttribute) {
731
- throw new Error(`Unknown ransack sort attribute "${columnCandidate}" for ${modelClass.name}`);
732
- }
733
- sorts.push({ attribute: resolvedAttribute, direction: directionCandidate });
734
- }
735
- return sorts;
736
- }
824
+ const segments = sortString.split(",").map((segment) => segment.trim()).filter((segment) => segment.length > 0)
825
+
826
+ /**
827
+ * Sorts.
828
+ @type {RansackSort[]} */
829
+ const sorts = []
830
+
831
+ for (const segment of segments) {
832
+ const parts = segment.split(/\s+/)
833
+ const columnCandidate = parts[0]
834
+ const directionCandidate = parts.length > 1 ? parts[1].toLowerCase() : "asc"
835
+
836
+ if (directionCandidate !== "asc" && directionCandidate !== "desc") {
837
+ throw new Error(`Invalid ransack sort direction "${directionCandidate}" in: ${segment}`)
838
+ }
839
+
840
+ const resolvedAttribute = resolveAttributeName({modelClass, value: columnCandidate})
841
+
842
+ if (!resolvedAttribute) {
843
+ throw new Error(`Unknown ransack sort attribute "${columnCandidate}" for ${modelClass.name}`)
844
+ }
845
+
846
+ sorts.push({attribute: resolvedAttribute, direction: directionCandidate})
847
+ }
848
+
849
+ return sorts
850
+ }
851
+
737
852
  /**
738
853
  * Runs uniqunize.
739
854
  * @param {string[]} values - Input values.
740
855
  * @returns {string[]} - Unique values in original order.
741
856
  */
742
857
  function uniqunize(values) {
743
- return Array.from(new Set(values));
858
+ return Array.from(new Set(values))
744
859
  }
745
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFuc2Fjay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9yYW5zYWNrLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEtBQUssVUFBVSxNQUFNLFlBQVksQ0FBQTtBQUN4QyxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0saUJBQWlCLENBQUE7QUFDN0MsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0sc0NBQXNDLENBQUE7QUFFOUU7OztHQUdHO0FBRUg7OztHQUdHO0FBRUg7OztHQUdHO0FBRUg7Ozs7O0dBS0c7QUFFSDs7Ozs7OztHQU9HO0FBRUg7Ozs7OztHQU1HO0FBRUgsTUFBTSxtQkFBbUIsR0FBRztJQUMxQixRQUFRO0lBQ1IsUUFBUTtJQUNSLE1BQU07SUFDTixNQUFNO0lBQ04sT0FBTztJQUNQLE1BQU07SUFDTixNQUFNO0lBQ04sS0FBSztJQUNMLElBQUk7SUFDSixJQUFJO0lBQ0osSUFBSTtJQUNKLElBQUk7Q0FDTCxDQUFBO0FBRUQ7Ozs7O0dBS0c7QUFDSCx3Q0FBd0M7QUFDeEMsTUFBTSxVQUFVLHNCQUFzQixDQUFDLFVBQVUsRUFBRSxNQUFNO0lBQ3ZELE9BQU8scUJBQXFCLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDLFVBQVUsQ0FBQTtBQUM3RCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQUMsVUFBVSxFQUFFLE1BQU07SUFDdEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLE9BQU8sTUFBTSxFQUFFLENBQUMsQ0FBQTtJQUNqRixDQUFDO0lBRUQ7OzZCQUV5QjtJQUN6QixNQUFNLFVBQVUsR0FBRztRQUNqQixVQUFVLEVBQUUsMEJBQTBCLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUM7UUFDdkQsVUFBVSxFQUFF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TUFBTSxJQUFJLEtBQUssQ0FBQyxtQ0FBbUMsa0JBQWtCLFNBQVMsT0FBTyxFQUFFLENBQUMsQ0FBQTtRQUMxRixDQUFDO1FBRUQsTUFBTSxpQkFBaUIsR0FBRyxvQkFBb0IsQ0FBQyxFQUFDLFVBQVUsRUFBRSxLQUFLLEVBQUUsZUFBZSxFQUFDLENBQUMsQ0FBQTtRQUVwRixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxlQUFlLFNBQVMsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUE7UUFDL0YsQ0FBQztRQUVELEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBQyxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFDLENBQUMsQ0FBQTtJQUMzRSxDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUE7QUFDZCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsU0FBUyxDQUFDLE1BQU07SUFDdkIsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUE7QUFDcEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgKiBhcyBpbmZsZWN0aW9uIGZyb20gXCJpbmZsZWN0aW9uXCJcbmltcG9ydCB7aXNQbGFpbk9iamVjdH0gZnJvbSBcImlzLXBsYWluLW9iamVjdFwiXG5pbXBvcnQge3Jlc29sdmVGcm9udGVuZE1vZGVsQ2xhc3N9IGZyb20gXCIuLi9mcm9udGVuZC1tb2RlbHMvbW9kZWwtcmVnaXN0cnkuanNcIlxuXG4vKipcbiAqIFJhbnNhY2tQcmVkaWNhdGUgdHlwZS5cbiAqIEB0eXBlZGVmIHtcImNvbnRcIiB8IFwiZW5kXCIgfCBcImVxXCIgfCBcImd0XCIgfCBcImd0ZXFcIiB8IFwiaW5cIiB8IFwibHRcIiB8IFwibHRlcVwiIHwgXCJub3RfZXFcIiB8IFwibm90X2luXCIgfCBcIm51bGxcIiB8IFwic3RhcnRcIn0gUmFuc2Fja1ByZWRpY2F0ZVxuICovXG5cbi8qKlxuICogUmFuc2Fja0NvbWJpbmF0b3IgdHlwZS5cbiAqIEB0eXBlZGVmIHtcImFuZFwiIHwgXCJvclwifSBSYW5zYWNrQ29tYmluYXRvclxuICovXG5cbi8qKlxuICogUmFuc2Fja01vZGVsQ2xhc3MgdHlwZS5cbiAqIEB0eXBlZGVmIHt0eXBlb2YgaW1wb3J0KFwiLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHQgfCB0eXBlb2YgaW1wb3J0KFwiLi4vZnJvbnRlbmQtbW9kZWxzL2Jhc2UuanNcIikuZGVmYXVsdH0gUmFuc2Fja01vZGVsQ2xhc3NcbiAqL1xuXG4vKipcbiAqIFJhbnNhY2tBdHRyaWJ1dGUgdHlwZS5cbiAqIEB0eXBlZGVmIHtvYmplY3R9IFJhbnNhY2tBdHRyaWJ1dGVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBhdHRyaWJ1dGVOYW1lIC0gUmVzb2x2ZWQgYXR0cmlidXRlIG5hbWUuXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBwYXRoIC0gUmVzb2x2ZWQgcmVsYXRpb25zaGlwIHBhdGguXG4gKi9cblxuLyoqXG4gKiBSYW5zYWNrQ29uZGl0aW9uIHR5cGUuXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBSYW5zYWNrQ29uZGl0aW9uXG4gKiBAcHJvcGVydHkge1JhbnNhY2tBdHRyaWJ1dGVbXX0gYXR0cmlidXRlcyAtIFJlc29sdmVkIGF0dHJpYnV0ZXMgdG8gdGVzdC5cbiAqIEBwcm9wZXJ0eSB7UmFuc2Fja0NvbWJpbmF0b3J9IGNvbWJpbmF0b3IgLSBIb3cgbXVsdGlwbGUgYXR0cmlidXRlcyBhcmUgY29tYmluZWQuXG4gKiBAcHJvcGVydHkge1JhbnNhY2tQcmVkaWNhdGV9IHByZWRpY2F0ZSAtIFBhcnNlZCBSYW5zYWNrIHByZWRpY2F0ZS5cbiAqIEBwcm9wZXJ0eSB7P30gdmFsdWUgLSBOb3JtYWxpemVkIHZhbHVlLlxuICovXG5cbi8qKlxuICogUmFuc2Fja0dyb3VwIHR5cGUuXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBSYW5zYWNrR3JvdXBcbiAqIEBwcm9wZXJ0eSB7UmFuc2Fja0NvbWJpbmF0b3J9IGNvbWJpbmF0b3IgLSBIb3cgZW50cmllcyBpbnNpZGUgdGhpcyBncm91cCBhcmUgY29tYmluZWQuXG4gKiBAcHJvcGVydHkge1JhbnNhY2tDb25kaXRpb25bXX0gY29uZGl0aW9ucyAtIENvbmRpdGlvbnMgaW4gdGhpcyBncm91cC5cbiAqIEBwcm9wZXJ0eSB7UmFuc2Fja0dyb3VwW119IGdyb3VwaW5ncyAtIE5lc3RlZCBncm91cHMuXG4gKi9cblxuY29uc3Qgc3VwcG9ydGVkUHJlZGljYXRlcyA9IFtcbiAgXCJub3RfaW5cIixcbiAgXCJub3RfZXFcIixcbiAgXCJndGVxXCIsXG4gIFwibHRlcVwiLFxuICBcInN0YXJ0XCIsXG4gIFwiY29udFwiLFxuICBcIm51bGxcIixcbiAgXCJlbmRcIixcbiAgXCJlcVwiLFxuICBcImd0XCIsXG4gIFwibHRcIixcbiAgXCJpblwiXG5dXG5cbi8qKlxuICogUnVucyB0aGUgbm9ybWFsaXplUmFuc2Fja1BhcmFtcyBoZWxwZXIuXG4gKiBAcGFyYW0ge1JhbnNhY2tNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBwYXJhbXMgLSBSYW5zYWNrLXN0eWxlIHBhcmFtcyBoYXNoLlxuICogQHJldHVybnMge1JhbnNhY2tDb25kaXRpb25bXX0gLSBOb3JtYWxpemVkIGNvbmRpdGlvbnMuXG4gKi9cbi8vIGZhbGxvdy1pZ25vcmUtbmV4dC1saW5lIHVudXNlZC1leHBvcnRcbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVSYW5zYWNrUGFyYW1zKG1vZGVsQ2xhc3MsIHBhcmFtcykge1xuICByZXR1cm4gbm9ybWFsaXplUmFuc2Fja0dyb3VwKG1vZGVsQ2xhc3MsIHBhcmFtcykuY29uZGl0aW9uc1xufVxuXG4vKipcbiAqIFJ1bnMgdGhlIG5vcm1hbGl6ZVJhbnNhY2tHcm91cCBoZWxwZXIuXG4gKiBAcGFyYW0ge1JhbnNhY2tNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBwYXJhbXMgLSBSYW5zYWNrLXN0eWxlIHBhcmFtcyBoYXNoLlxuICogQHJldHVybnMge1JhbnNhY2tHcm91cH0gLSBOb3JtYWxpemVkIGdyb3VwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplUmFuc2Fja0dyb3VwKG1vZGVsQ2xhc3MsIHBhcmFtcykge1xuICBpZiAoIWlzUGxhaW5PYmplY3QocGFyYW1zKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgcmFuc2FjayBwYXJhbXMgbXVzdCBiZSBhIHBsYWluIG9iamVjdCwgZ290OiAke3R5cGVvZiBwYXJhbXN9YClcbiAgfVxuXG4gIC8qKlxuICAgKiBOb3JtYWxpemVkLlxuICAgIEB0eXBlIHtSYW5zYWNrR3JvdXB9ICovXG4gIGNvbnN0IG5vcm1hbGl6ZWQgPSB7XG4gICAgY29tYmluYXRvcjogbm9ybWFsaXplUmFuc2Fja0NvbWJpbmF0b3IocGFyYW1zLm0sIFwiYW5kXCIpLFxuICAgIGNvbmRpdGlvbnM6IFtdLFxuICAgIGdyb3VwaW5nczogW11cbiAgfVxuXG4gIGZvciAoY29uc3QgW2tleSwgcmF3VmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHBhcmFtcykpIHtcbiAgICBpZiAoa2V5ID09PSBcIm1cIikge1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICBpZiAoa2V5ID09PSBcImNcIikge1xuICAgICAgbm9ybWFsaXplZC5jb25kaXRpb25zLnB1c2goLi4ubm9ybWFsaXplQWR2YW5jZWRSYW5zYWNrQ29uZGl0aW9ucyh7bW9kZWxDbGFzcywgdmFsdWU6IHJhd1ZhbHVlfSkpXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGlmIChrZXkgPT09IFwiZ1wiKSB7XG4gICAgICBub3JtYWxpemVkLmdyb3VwaW5ncy5wdXNoKC4uLm5vcm1hbGl6ZUFkdmFuY2VkUmFuc2Fja0dyb3Vwcyh7bW9kZWxDbGFzcywgdmFsdWU6IHJhd1ZhbHVlfSkpXG4gICAgICBjb250aW51ZVxuICAgIH1cblxuICAgIGNvbnN0IGNvbmRpdGlvbiA9IG5vcm1hbGl6ZVNpbXBsZVJhbnNhY2tDb25kaXRpb24oe2tleSwgbW9kZWxDbGFzcywgcmF3VmFsdWV9KVxuICAgIGlmIChjb25kaXRpb24pIG5vcm1hbGl6ZWQuY29uZGl0aW9ucy5wdXNoKGNvbmRpdGlvbilcbiAgfVxuXG4gIHJldHVybiBub3JtYWxpemVkXG59XG5cbmNvbnN0IFNLSVBfUkFOU0FDS19DT05ESVRJT04gPSBTeW1ib2woXCJza2lwLXJhbnNhY2stY29uZGl0aW9uXCIpXG5cbi8qKlxuICogUnVucyBub3JtYWxpemUgc2ltcGxlIHJhbnNhY2sgY29uZGl0aW9uLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Mua2V5IC0gU2ltcGxlIFJhbnNhY2sga2V5LlxuICogQHBhcmFtIHtSYW5zYWNrTW9kZWxDbGFzc30gYXJncy5tb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0gez99IGFyZ3MucmF3VmFsdWUgLSBSYXcgY29uZGl0aW9uIHZhbHVlLlxuICogQHJldHVybnMge1JhbnNhY2tDb25kaXRpb24gfCBudWxsfSAtIE5vcm1hbGl6ZWQgY29uZGl0aW9uLCBvciBudWxsIHdoZW4gc2tpcHBlZC5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplU2ltcGxlUmFuc2Fja0NvbmRpdGlvbih7a2V5LCBtb2RlbENsYXNzLCByYXdWYWx1ZX0pIHtcbiAgY29uc3QgcGFyc2VkS2V5ID0gcGFyc2VSYW5zYWNrS2V5KGtleSlcblxuICBpZiAoIXBhcnNlZEtleSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgcmFuc2FjayBwcmVkaWNhdGUgaW4ga2V5OiAke2tleX1gKVxuICB9XG5cbiAgY29uc3QgdmFsdWUgPSBub3JtYWxpemVSYW5zYWNrVmFsdWUoe1xuICAgIHByZWRpY2F0ZTogcGFyc2VkS2V5LnByZWRpY2F0ZSxcbiAgICB2YWx1ZTogcmF3VmFsdWVcbiAgfSlcblxuICBpZiAodmFsdWUgPT09IFNLSVBfUkFOU0FDS19DT05ESVRJT04pIHJldHVybiBudWxsXG5cbiAgY29uc3QgYXR0cmlidXRlcyA9IHJlc29sdmVSYW5zYWNrQXR0cmlidXRlcyh7bW9kZWxDbGFzcywgdmFsdWU6IHBhcnNlZEtleS5wYXRoVmFsdWV9KVxuXG4gIHJldHVybiB7XG4gICAgYXR0cmlidXRlcyxcbiAgICBjb21iaW5hdG9yOiBhdHRyaWJ1dGVzLmxlbmd0aCA+IDEgPyBcIm9yXCIgOiBcImFuZFwiLFxuICAgIHByZWRpY2F0ZTogcGFyc2VkS2V5LnByZWRpY2F0ZSxcbiAgICB2YWx1ZVxuICB9XG59XG5cbi8qKlxuICogUnVucyBub3JtYWxpemUgYWR2YW5jZWQgcmFuc2FjayBjb25kaXRpb25zLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtSYW5zYWNrTW9kZWxDbGFzc30gYXJncy5tb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0gez99IGFyZ3MudmFsdWUgLSBBZHZhbmNlZCBjb25kaXRpb25zIGNvbGxlY3Rpb24uXG4gKiBAcmV0dXJucyB7UmFuc2Fja0NvbmRpdGlvbltdfSAtIE5vcm1hbGl6ZWQgY29uZGl0aW9ucy5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplQWR2YW5jZWRSYW5zYWNrQ29uZGl0aW9ucyh7bW9kZWxDbGFzcywgdmFsdWV9KSB7XG4gIC8qKlxuICAgKiBDb25kaXRpb25zLlxuICAgIEB0eXBlIHtSYW5zYWNrQ29uZGl0aW9uW119ICovXG4gIGNvbnN0IGNvbmRpdGlvbnMgPSBbXVxuXG4gIGZvciAoY29uc3QgZW50cnkgb2Ygbm9ybWFsaXplUmFuc2Fja0NvbGxlY3Rpb24odmFsdWUsIFwiY29uZGl0aW9uc1wiKSkge1xuICAgIGlmICghaXNQbGFpbk9iamVjdChlbnRyeSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUmFuc2FjayBjb25kaXRpb24gZW50cmllcyBtdXN0IGJlIHBsYWluIG9iamVjdHMsIGdvdDogJHt0eXBlb2YgZW50cnl9YClcbiAgICB9XG5cbiAgICBjb25zdCBwcmVkaWNhdGVWYWx1ZSA9IGVudHJ5LnBcblxuICAgIGlmICh0eXBlb2YgcHJlZGljYXRlVmFsdWUgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlJhbnNhY2sgY29uZGl0aW9uIHByZWRpY2F0ZSBtdXN0IGJlIGEgc3RyaW5nXCIpXG4gICAgfVxuXG4gICAgaWYgKCFzdXBwb3J0ZWRQcmVkaWNhdGVzLmluY2x1ZGVzKHByZWRpY2F0ZVZhbHVlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCByYW5zYWNrIHByZWRpY2F0ZSBpbiBjb25kaXRpb246ICR7cHJlZGljYXRlVmFsdWV9YClcbiAgICB9XG5cbiAgICBjb25zdCBwcmVkaWNhdGUgPSAvKipcbiAgICAgICAgICAgICAgICAgICAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICAgICAgICAgICAgICAgICAgICBAdHlwZSB7UmFuc2Fja1ByZWRpY2F0ZX0gKi8gKHByZWRpY2F0ZVZhbHVlKVxuICAgIGNvbnN0IHJhd1ZhbHVlID0gYWR2YW5jZWRSYW5zYWNrQ29uZGl0aW9uVmFsdWUoe3ByZWRpY2F0ZSwgdmFsdWU6IGVudHJ5LnZ9KVxuICAgIGNvbnN0IG5vcm1hbGl6ZWRWYWx1ZSA9IG5vcm1hbGl6ZVJhbnNhY2tWYWx1ZSh7cHJlZGljYXRlLCB2YWx1ZTogcmF3VmFsdWV9KVxuXG4gICAgaWYgKG5vcm1hbGl6ZWRWYWx1ZSA9PT0gU0tJUF9SQU5TQUNLX0NPTkRJVElPTikgY29udGludWVcblxuICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSByZXNvbHZlUmFuc2Fja0F0dHJpYnV0ZXNGcm9tQWR2YW5jZWRWYWx1ZSh7bW9kZWxDbGFzcywgdmFsdWU6IGVudHJ5LmF9KVxuXG4gICAgY29uZGl0aW9ucy5wdXNoKHtcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICBjb21iaW5hdG9yOiBub3JtYWxpemVSYW5zYWNrQ29tYmluYXRvcihlbnRyeS5tLCBhdHRyaWJ1dGVzLmxlbmd0aCA+IDEgPyBcIm9yXCIgOiBcImFuZFwiKSxcbiAgICAgIHByZWRpY2F0ZSxcbiAgICAgIHZhbHVlOiBub3JtYWxpemVkVmFsdWVcbiAgICB9KVxuICB9XG5cbiAgcmV0dXJuIGNvbmRpdGlvbnNcbn1cblxuLyoqXG4gKiBSdW5zIG5vcm1hbGl6ZSBhZHZhbmNlZCByYW5zYWNrIGdyb3Vwcy5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAqIEBwYXJhbSB7UmFuc2Fja01vZGVsQ2xhc3N9IGFyZ3MubW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHs/fSBhcmdzLnZhbHVlIC0gQWR2YW5jZWQgZ3JvdXBzIGNvbGxlY3Rpb24uXG4gKiBAcmV0dXJucyB7UmFuc2Fja0dyb3VwW119IC0gTm9ybWFsaXplZCBncm91cHMuXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZUFkdmFuY2VkUmFuc2Fja0dyb3Vwcyh7bW9kZWxDbGFzcywgdmFsdWV9KSB7XG4gIC8qKlxuICAgKiBHcm91cGluZ3MuXG4gICAgQHR5cGUge1JhbnNhY2tHcm91cFtdfSAqL1xuICBjb25zdCBncm91cGluZ3MgPSBbXVxuXG4gIGZvciAoY29uc3QgZW50cnkgb2Ygbm9ybWFsaXplUmFuc2Fja0NvbGxlY3Rpb24odmFsdWUsIFwiZ3JvdXBpbmdzXCIpKSB7XG4gICAgaWYgKCFpc1BsYWluT2JqZWN0KGVudHJ5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSYW5zYWNrIGdyb3VwaW5nIGVudHJpZXMgbXVzdCBiZSBwbGFpbiBvYmplY3RzLCBnb3Q6ICR7dHlwZW9mIGVudHJ5fWApXG4gICAgfVxuXG4gICAgZ3JvdXBpbmdzLnB1c2gobm9ybWFsaXplUmFuc2Fja0dyb3VwKG1vZGVsQ2xhc3MsIGVudHJ5KSlcbiAgfVxuXG4gIHJldHVybiBncm91cGluZ3Ncbn1cblxuLyoqXG4gKiBSdW5zIG5vcm1hbGl6ZSByYW5zYWNrIGNvbWJpbmF0b3IuXG4gKiBAcGFyYW0gez99IHZhbHVlIC0gQ2FuZGlkYXRlIGNvbWJpbmF0b3IuXG4gKiBAcGFyYW0ge1JhbnNhY2tDb21iaW5hdG9yfSBkZWZhdWx0VmFsdWUgLSBEZWZhdWx0IGNvbWJpbmF0b3IuXG4gKiBAcmV0dXJucyB7UmFuc2Fja0NvbWJpbmF0b3J9IC0gTm9ybWFsaXplZCBjb21iaW5hdG9yLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSYW5zYWNrQ29tYmluYXRvcih2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSBcIlwiKSByZXR1cm4gZGVmYXVsdFZhbHVlXG4gIGlmICh2YWx1ZSA9PT0gXCJhbmRcIiB8fCB2YWx1ZSA9PT0gXCJvclwiKSByZXR1cm4gdmFsdWVcblxuICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmFuc2FjayBjb21iaW5hdG9yOiAke1N0cmluZyh2YWx1ZSl9YClcbn1cblxuLyoqXG4gKiBSdW5zIG5vcm1hbGl6ZSByYW5zYWNrIGNvbGxlY3Rpb24uXG4gKiBAcGFyYW0gez99IHZhbHVlIC0gQ2FuZGlkYXRlIGNvbGxlY3Rpb24uXG4gKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIENvbGxlY3Rpb24gbmFtZSBmb3IgZXJyb3JzLlxuICogQHJldHVybnMge0FycmF5PD8+fSAtIENvbGxlY3Rpb24gdmFsdWVzIGluIHN0YWJsZSBvcmRlci5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplUmFuc2Fja0NvbGxlY3Rpb24odmFsdWUsIG5hbWUpIHtcbiAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IFwiXCIpIHJldHVybiBbXVxuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiB2YWx1ZVxuXG4gIGlmIChpc1BsYWluT2JqZWN0KHZhbHVlKSkge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyh2YWx1ZSlcbiAgICAgIC5zb3J0KChsZWZ0LCByaWdodCkgPT4ge1xuICAgICAgICBjb25zdCBsZWZ0TnVtYmVyID0gTnVtYmVyKGxlZnQpXG4gICAgICAgIGNvbnN0IHJpZ2h0TnVtYmVyID0gTnVtYmVyKHJpZ2h0KVxuXG4gICAgICAgIGlmIChOdW1iZXIuaXNGaW5pdGUobGVmdE51bWJlcikgJiYgTnVtYmVyLmlzRmluaXRlKHJpZ2h0TnVtYmVyKSkge1xuICAgICAgICAgIHJldHVybiBsZWZ0TnVtYmVyIC0gcmlnaHROdW1iZXJcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBsZWZ0LmxvY2FsZUNvbXBhcmUocmlnaHQpXG4gICAgICB9KVxuICAgICAgLm1hcCgoa2V5KSA9PiB2YWx1ZVtrZXldKVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBSYW5zYWNrICR7bmFtZX0gbXVzdCBiZSBhbiBhcnJheSBvciBvYmplY3QsIGdvdDogJHt0eXBlb2YgdmFsdWV9YClcbn1cblxuLyoqXG4gKiBSdW5zIGFkdmFuY2VkIHJhbnNhY2sgY29uZGl0aW9uIHZhbHVlLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtSYW5zYWNrUHJlZGljYXRlfSBhcmdzLnByZWRpY2F0ZSAtIFBhcnNlZCBwcmVkaWNhdGUuXG4gKiBAcGFyYW0gez99IGFyZ3MudmFsdWUgLSBBZHZhbmNlZCBjb25kaXRpb24gdmFsdWUuXG4gKiBAcmV0dXJucyB7P30gLSBWYWx1ZSBwYXNzZWQgdG8gcHJlZGljYXRlIG5vcm1hbGl6YXRpb24uXG4gKi9cbmZ1bmN0aW9uIGFkdmFuY2VkUmFuc2Fja0NvbmRpdGlvblZhbHVlKHtwcmVkaWNhdGUsIHZhbHVlfSkge1xuICBpZiAocHJlZGljYXRlID09PSBcImluXCIgfHwgcHJlZGljYXRlID09PSBcIm5vdF9pblwiKSByZXR1cm4gdmFsdWVcblxuICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWUuZmluZCgoZW50cnkpID0+IGVudHJ5ICE9PSB1bmRlZmluZWQgJiYgZW50cnkgIT09IG51bGwgJiYgZW50cnkgIT09IFwiXCIpXG4gIH1cblxuICByZXR1cm4gdmFsdWVcbn1cblxuLyoqXG4gKiBSdW5zIHJlc29sdmUgcmFuc2FjayBhdHRyaWJ1dGVzIGZyb20gYWR2YW5jZWQgdmFsdWUuXG4gKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gKiBAcGFyYW0ge1JhbnNhY2tNb2RlbENsYXNzfSBhcmdzLm1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAqIEBwYXJhbSB7P30gYXJncy52YWx1ZSAtIEFkdmFuY2VkIGF0dHJpYnV0ZSB2YWx1ZS5cbiAqIEByZXR1cm5zIHtSYW5zYWNrQXR0cmlidXRlW119IC0gUmVzb2x2ZWQgYXR0cmlidXRlcy5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVJhbnNhY2tBdHRyaWJ1dGVzRnJvbUFkdmFuY2VkVmFsdWUoe21vZGVsQ2xhc3MsIHZhbHVlfSkge1xuICBjb25zdCB2YWx1ZXMgPSBub3JtYWxpemVBZHZhbmNlZEF0dHJpYnV0ZVZhbHVlcyh2YWx1ZSlcbiAgLyoqXG4gICAqIEF0dHJpYnV0ZXMuXG4gICAgQHR5cGUge1JhbnNhY2tBdHRyaWJ1dGVbXX0gKi9cbiAgY29uc3QgYXR0cmlidXRlcyA9IFtdXG5cbiAgZm9yIChjb25zdCBhdHRyaWJ1dGVWYWx1ZSBvZiB2YWx1ZXMpIHtcbiAgICBhdHRyaWJ1dGVzLnB1c2goLi4ucmVzb2x2ZVJhbnNhY2tBdHRyaWJ1dGVzKHttb2RlbENsYXNzLCB2YWx1ZTogYXR0cmlidXRlVmFsdWV9KSlcbiAgfVxuXG4gIGlmIChhdHRyaWJ1dGVzLmxlbmd0aCA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJSYW5zYWNrIGNvbmRpdGlvbiBtdXN0IGluY2x1ZGUgYXQgbGVhc3Qgb25lIGF0dHJpYnV0ZVwiKVxuICB9XG5cbiAgcmV0dXJuIGF0dHJpYnV0ZXNcbn1cblxuLyoqXG4gKiBSdW5zIG5vcm1hbGl6ZSBhZHZhbmNlZCBhdHRyaWJ1dGUgdmFsdWVzLlxuICogQHBhcmFtIHs/fSB2YWx1ZSAtIEFkdmFuY2VkIGF0dHJpYnV0ZSB2YWx1ZS5cbiAqIEByZXR1cm5zIHtzdHJpbmdbXX0gLSBBdHRyaWJ1dGUgcGF0aCBzdHJpbmdzLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVBZHZhbmNlZEF0dHJpYnV0ZVZhbHVlcyh2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSByZXR1cm4gW3ZhbHVlXVxuXG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZS5tYXAoKGVudHJ5KSA9PiBub3JtYWxpemVBZHZhbmNlZEF0dHJpYnV0ZVZhbHVlKGVudHJ5KSlcbiAgfVxuXG4gIGlmIChpc1BsYWluT2JqZWN0KHZhbHVlKSkge1xuICAgIHJldHVybiBub3JtYWxpemVSYW5zYWNrQ29sbGVjdGlvbih2YWx1ZSwgXCJhdHRyaWJ1dGVzXCIpLm1hcCgoZW50cnkpID0+IG5vcm1hbGl6ZUFkdmFuY2VkQXR0cmlidXRlVmFsdWUoZW50cnkpKVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBSYW5zYWNrIGNvbmRpdGlvbiBhdHRyaWJ1dGVzIG11c3QgYmUgc3RyaW5ncywgYXJyYXlzLCBvciBvYmplY3RzLCBnb3Q6ICR7dHlwZW9mIHZhbHVlfWApXG59XG5cbi8qKlxuICogUnVucyBub3JtYWxpemUgYWR2YW5jZWQgYXR0cmlidXRlIHZhbHVlLlxuICogQHBhcmFtIHs/fSB2YWx1ZSAtIEFkdmFuY2VkIGF0dHJpYnV0ZSBlbnRyeS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gQXR0cmlidXRlIHBhdGggc3RyaW5nLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVBZHZhbmNlZEF0dHJpYnV0ZVZhbHVlKHZhbHVlKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHJldHVybiB2YWx1ZVxuXG4gIGlmIChpc1BsYWluT2JqZWN0KHZhbHVlKSAmJiB0eXBlb2YgdmFsdWUubmFtZSA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiB2YWx1ZS5uYW1lXG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFJhbnNhY2sgY29uZGl0aW9uIGF0dHJpYnV0ZSBlbnRyaWVzIG11c3QgYmUgc3RyaW5ncyBvciB7bmFtZX0sIGdvdDogJHt0eXBlb2YgdmFsdWV9YClcbn1cblxuLyoqXG4gKiBSdW5zIHJlc29sdmUgcmFuc2FjayBhdHRyaWJ1dGVzLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtSYW5zYWNrTW9kZWxDbGFzc30gYXJncy5tb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXJncy52YWx1ZSAtIEF0dHJpYnV0ZSBwYXRoIHZhbHVlLlxuICogQHJldHVybnMge1JhbnNhY2tBdHRyaWJ1dGVbXX0gLSBSZXNvbHZlZCBhdHRyaWJ1dGVzLlxuICovXG5mdW5jdGlvbiByZXNvbHZlUmFuc2Fja0F0dHJpYnV0ZXMoe21vZGVsQ2xhc3MsIHZhbHVlfSkge1xuICByZXR1cm4gdmFsdWUuc3BsaXQoXCJfb3JfXCIpLm1hcCgoYXR0cmlidXRlVmFsdWUpID0+IHtcbiAgICBjb25zdCByZXNvbHZlZFBhdGggPSByZXNvbHZlUmFuc2Fja1BhdGgoe21vZGVsQ2xhc3MsIHZhbHVlOiBhdHRyaWJ1dGVWYWx1ZX0pXG4gICAgY29uc3QgdGFyZ2V0TW9kZWxDbGFzcyA9IG1vZGVsQ2xhc3NBdFBhdGgoe21vZGVsQ2xhc3MsIHBhdGg6IHJlc29sdmVkUGF0aC5wYXRofSlcbiAgICBjb25zdCBhdHRyaWJ1dGVOYW1lID0gcmVzb2x2ZUF0dHJpYnV0ZU5hbWUoe21vZGVsQ2xhc3M6IHRhcmdldE1vZGVsQ2xhc3MsIHZhbHVlOiByZXNvbHZlZFBhdGguYXR0cmlidXRlVmFsdWV9KVxuXG4gICAgaWYgKCFhdHRyaWJ1dGVOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gcmFuc2FjayBhdHRyaWJ1dGUgXCIke3Jlc29sdmVkUGF0aC5hdHRyaWJ1dGVWYWx1ZX1cIiBmb3IgJHt0YXJnZXRNb2RlbENsYXNzLm5hbWV9YClcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYXR0cmlidXRlTmFtZSxcbiAgICAgIHBhdGg6IHJlc29sdmVkUGF0aC5wYXRoXG4gICAgfVxuICB9KVxufVxuXG4vKipcbiAqIFJ1bnMgbW9kZWwgY2xhc3MgYXQgcGF0aC5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAqIEBwYXJhbSB7UmFuc2Fja01vZGVsQ2xhc3N9IGFyZ3MubW9kZWxDbGFzcyAtIFJvb3QgbW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBhcmdzLnBhdGggLSBSZWxhdGlvbnNoaXAgcGF0aC5cbiAqIEByZXR1cm5zIHtSYW5zYWNrTW9kZWxDbGFzc30gLSBUYXJnZXQgbW9kZWwgY2xhc3MuXG4gKi9cbmZ1bmN0aW9uIG1vZGVsQ2xhc3NBdFBhdGgoe21vZGVsQ2xhc3MsIHBhdGh9KSB7XG4gIGxldCBjdXJyZW50TW9kZWxDbGFzcyA9IG1vZGVsQ2xhc3NcblxuICBmb3IgKGNvbnN0IHJlbGF0aW9uc2hpcE5hbWUgb2YgcGF0aCkge1xuICAgIGNvbnN0IHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcEVudHJpZXMoY3VycmVudE1vZGVsQ2xhc3MpW3JlbGF0aW9uc2hpcE5hbWVdXG5cbiAgICBpZiAoIXJlbGF0aW9uc2hpcCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHJhbnNhY2sgcmVsYXRpb25zaGlwIFwiJHtyZWxhdGlvbnNoaXBOYW1lfVwiIGZvciAke2N1cnJlbnRNb2RlbENsYXNzLm5hbWV9YClcbiAgICB9XG5cbiAgICBjdXJyZW50TW9kZWxDbGFzcyA9IHJlbGF0aW9uc2hpcC50YXJnZXRNb2RlbENsYXNzXG4gIH1cblxuICByZXR1cm4gY3VycmVudE1vZGVsQ2xhc3Ncbn1cblxuLyoqXG4gKiBSdW5zIHJlc29sdmUgcmFuc2FjayBwYXRoLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICogQHBhcmFtIHtSYW5zYWNrTW9kZWxDbGFzc30gYXJncy5tb2RlbENsYXNzIC0gQ3VycmVudCBtb2RlbCBjbGFzcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnZhbHVlIC0gUmVtYWluaW5nIHBhdGggdmFsdWUuXG4gKiBAcmV0dXJucyB7e2F0dHJpYnV0ZVZhbHVlOiBzdHJpbmcsIHBhdGg6IHN0cmluZ1tdfX0gLSBSZXNvbHZlZCByZWxhdGlvbnNoaXAgcGF0aCBhbmQgcmVtYWluaW5nIGF0dHJpYnV0ZSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZVJhbnNhY2tQYXRoKHttb2RlbENsYXNzLCB2YWx1ZX0pIHtcbiAgLyoqXG4gICAqIFBhdGguXG4gICAgQHR5cGUge3N0cmluZ1tdfSAqL1xuICBjb25zdCBwYXRoID0gW11cbiAgbGV0IGN1cnJlbnRNb2RlbENsYXNzID0gbW9kZWxDbGFzc1xuICBsZXQgcmVtYWluaW5nVmFsdWUgPSB2YWx1ZVxuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgaWYgKHJlc29sdmVBdHRyaWJ1dGVOYW1lKHttb2RlbENsYXNzOiBjdXJyZW50TW9kZWxDbGFzcywgdmFsdWU6IHJlbWFpbmluZ1ZhbHVlfSkpIHtcbiAgICAgIGJyZWFrXG4gICAgfVxuXG4gICAgY29uc3QgbWF0Y2ggPSBmaW5kUmVsYXRpb25zaGlwUHJlZml4KHtcbiAgICAgIG1vZGVsQ2xhc3M6IGN1cnJlbnRNb2RlbENsYXNzLFxuICAgICAgdmFsdWU6IHJlbWFpbmluZ1ZhbHVlXG4gICAgfSlcblxuICAgIGlmICghbWF0Y2gpIGJyZWFrXG5cbiAgICBwYXRoLnB1c2gobWF0Y2gucmVsYXRpb25zaGlwTmFtZSlcbiAgICBjdXJyZW50TW9kZWxDbGFzcyA9IG1hdGNoLnRhcmdldE1vZGVsQ2xhc3NcbiAgICByZW1haW5pbmdWYWx1ZSA9IG1hdGNoLnJlbWFpbmluZ1ZhbHVlXG4gIH1cblxuICBpZiAocmVtYWluaW5nVmFsdWUubGVuZ3RoIDwgMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByYW5zYWNrIGtleSBwYXRoOiAke3ZhbHVlfWApXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGF0dHJpYnV0ZVZhbHVlOiByZW1haW5pbmdWYWx1ZSxcbiAgICBwYXRoXG4gIH1cbn1cblxuLyoqXG4gKiBSdW5zIGZpbmQgcmVsYXRpb25zaGlwIHByZWZpeC5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAqIEBwYXJhbSB7UmFuc2Fja01vZGVsQ2xhc3N9IGFyZ3MubW9kZWxDbGFzcyAtIEN1cnJlbnQgbW9kZWwgY2xhc3MuXG4gKiBAcGFyYW0ge3N0cmluZ30gYXJncy52YWx1ZSAtIFJlbWFpbmluZyB2YWx1ZSB0byBtYXRjaC5cbiAqIEByZXR1cm5zIHt7cmVsYXRpb25zaGlwTmFtZTogc3RyaW5nLCByZW1haW5pbmdWYWx1ZTogc3RyaW5nLCB0YXJnZXRNb2RlbENsYXNzOiBSYW5zYWNrTW9kZWxDbGFzc30gfCBudWxsfSAtIE1hdGNoaW5nIHJlbGF0aW9uc2hpcCBwcmVmaXguXG4gKi9cbmZ1bmN0aW9uIGZpbmRSZWxhdGlvbnNoaXBQcmVmaXgoe21vZGVsQ2xhc3MsIHZhbHVlfSkge1xuICBsZXQgYmVzdE1hdGNoID0gbnVsbFxuXG4gIGZvciAoY29uc3QgcmVsYXRpb25zaGlwTmFtZSBvZiBPYmplY3Qua2V5cyhyZWxhdGlvbnNoaXBFbnRyaWVzKG1vZGVsQ2xhc3MpKSkge1xuICAgIGNvbnN0IHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcEVudHJpZXMobW9kZWxDbGFzcylbcmVsYXRpb25zaGlwTmFtZV1cblxuICAgIGZvciAoY29uc3QgY2FuZGlkYXRlIG9mIHJlbGF0aW9uc2hpcENhbmRpZGF0ZXMocmVsYXRpb25zaGlwTmFtZSkpIHtcbiAgICAgIGNvbnN0IHJlbWFpbmluZ1ZhbHVlID0gc3RyaXBSZWxhdGlvbnNoaXBDYW5kaWRhdGUodmFsdWUsIGNhbmRpZGF0ZSlcblxuICAgICAgaWYgKHJlbWFpbmluZ1ZhbHVlID09PSBudWxsKSBjb250aW51ZVxuICAgICAgaWYgKHJlbWFpbmluZ1ZhbHVlLmxlbmd0aCA8IDEpIGNvbnRpbnVlXG4gICAgICBpZiAoYmVzdE1hdGNoICYmIGNhbmRpZGF0ZS5sZW5ndGggPD0gYmVzdE1hdGNoLmNhbmRpZGF0ZUxlbmd0aCkgY29udGludWVcblxuICAgICAgYmVzdE1hdGNoID0ge1xuICAgICAgICBjYW5kaWRhdGVMZW5ndGg6IGNhbmRpZGF0ZS5sZW5ndGgsXG4gICAgICAgIHJlbGF0aW9uc2hpcE5hbWUsXG4gICAgICAgIHJlbWFpbmluZ1ZhbHVlLFxuICAgICAgICB0YXJnZXRNb2RlbENsYXNzOiByZWxhdGlvbnNoaXAudGFyZ2V0TW9kZWxDbGFzc1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmICghYmVzdE1hdGNoKSByZXR1cm4gbnVsbFxuXG4gIHJldHVybiB7XG4gICAgcmVsYXRpb25zaGlwTmFtZTogYmVzdE1hdGNoLnJlbGF0aW9uc2hpcE5hbWUsXG4gICAgcmVtYWluaW5nVmFsdWU6IGJlc3RNYXRjaC5yZW1haW5pbmdWYWx1ZSxcbiAgICB0YXJnZXRNb2RlbENsYXNzOiBiZXN0TWF0Y2gudGFyZ2V0TW9kZWxDbGFzc1xuICB9XG59XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcG9ydGlvbiBvZiBgdmFsdWVgIGFmdGVyIGBjYW5kaWRhdGVgIHdoZW4gYGNhbmRpZGF0ZWBcbiAqIHNpdHMgYXQgYSByZWxhdGlvbnNoaXAtcGF0aCBib3VuZGFyeSwgb3IgbnVsbCB3aGVuIHRoZXJlJ3Mgbm9cbiAqIGJvdW5kYXJ5IG1hdGNoLiBUd28gYm91bmRhcnkgZm9ybXMgYXJlIGFjY2VwdGVkOlxuICogLSBzbmFrZTogYDxjYW5kaWRhdGU+X2AgZm9sbG93ZWQgYnkgdGhlIHJlc3Qgb2YgdGhlIHBhdGggKGUuZy5cbiAqICAgYHRhc2tfcHJvamVjdF9pZGAgYWdhaW5zdCBjYW5kaWRhdGUgYHRhc2tgIHJldHVybnMgYHByb2plY3RfaWRgKS5cbiAqIC0gY2FtZWw6IGA8Y2FuZGlkYXRlPmAgaW1tZWRpYXRlbHkgZm9sbG93ZWQgYnkgYW4gdXBwZXJjYXNlIGxldHRlcixcbiAqICAgd2hpY2ggbWFya3MgYSBuZXcgd29yZCBpbiBjYW1lbENhc2UgKGUuZy4gYHRhc2tQcm9qZWN0SWRgIGFnYWluc3RcbiAqICAgY2FuZGlkYXRlIGB0YXNrYCByZXR1cm5zIGBwcm9qZWN0SWRgIHdpdGggdGhlIGxlYWRpbmcgYFBgXG4gKiAgIGxvd2VyY2FzZWQgc28gdGhlIHJlbWFpbmRlciBzdGF5cyBpbiBjYWxsZXItZm9ybSBmb3IgdGhlIG5leHRcbiAqICAgYXR0cmlidXRlIC8gcmVsYXRpb25zaGlwIG1hdGNoKS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSAtIFJlbWFpbmluZyByYW5zYWNrIHBhdGguXG4gKiBAcGFyYW0ge3N0cmluZ30gY2FuZGlkYXRlIC0gUmVsYXRpb25zaGlwIG5hbWUgY2FuZGlkYXRlLlxuICogQHJldHVybnMge3N0cmluZyB8IG51bGx9IC0gUmVtYWluZGVyIGFmdGVyIHRoZSBjYW5kaWRhdGUsIG9yIG51bGwuXG4gKi9cbmZ1bmN0aW9uIHN0cmlwUmVsYXRpb25zaGlwQ2FuZGlkYXRlKHZhbHVlLCBjYW5kaWRhdGUpIHtcbiAgaWYgKHZhbHVlLnN0YXJ0c1dpdGgoYCR7Y2FuZGlkYXRlfV9gKSkge1xuICAgIHJldHVybiB2YWx1ZS5zbGljZShjYW5kaWRhdGUubGVuZ3RoICsgMSlcbiAgfVxuXG4gIGlmICh2YWx1ZS5sZW5ndGggPD0gY2FuZGlkYXRlLmxlbmd0aCkgcmV0dXJuIG51bGxcbiAgaWYgKCF2YWx1ZS5zdGFydHNXaXRoKGNhbmRpZGF0ZSkpIHJldHVybiBudWxsXG5cbiAgY29uc3QgbmV4dENoYXIgPSB2YWx1ZS5jaGFyQXQoY2FuZGlkYXRlLmxlbmd0aClcblxuICBpZiAobmV4dENoYXIgPCBcIkFcIiB8fCBuZXh0Q2hhciA+IFwiWlwiKSByZXR1cm4gbnVsbFxuXG4gIHJldHVybiBuZXh0Q2hhci50b0xvd2VyQ2FzZSgpICsgdmFsdWUuc2xpY2UoY2FuZGlkYXRlLmxlbmd0aCArIDEpXG59XG5cbi8qKlxuICogUnVucyByZWxhdGlvbnNoaXAgY2FuZGlkYXRlcy5cbiAqIEBwYXJhbSB7c3RyaW5nfSByZWxhdGlvbnNoaXBOYW1lIC0gUmVsYXRpb25zaGlwIG5hbWUuXG4gKiBAcmV0dXJucyB7c3RyaW5nW119IC0gQ2FuZGlkYXRlIHRva2VucyBmb3IgbWF0Y2hpbmcuXG4gKi9cbmZ1bmN0aW9uIHJlbGF0aW9uc2hpcENhbmRpZGF0ZXMocmVsYXRpb25zaGlwTmFtZSkge1xuICByZXR1cm4gdW5pcXVuaXplKFtyZWxhdGlvbnNoaXBOYW1lLCBpbmZsZWN0aW9uLnVuZGVyc2NvcmUocmVsYXRpb25zaGlwTmFtZSldKVxufVxuXG4vKipcbiAqIFJ1bnMgcmVzb2x2ZSBhdHRyaWJ1dGUgbmFtZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAqIEBwYXJhbSB7UmFuc2Fja01vZGVsQ2xhc3N9IGFyZ3MubW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MudmFsdWUgLSBBdHRyaWJ1dGUgY2FuZGlkYXRlLlxuICogQHJldHVybnMge3N0cmluZyB8IHVuZGVmaW5lZH0gLSBSZXNvbHZlZCBhdHRyaWJ1dGUgbmFtZS5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZUF0dHJpYnV0ZU5hbWUoe21vZGVsQ2xhc3MsIHZhbHVlfSkge1xuICBmb3IgKGNvbnN0IFthdHRyaWJ1dGVOYW1lLCBjb2x1bW5OYW1lXSBvZiBPYmplY3QuZW50cmllcyhhdHRyaWJ1dGVFbnRyaWVzKG1vZGVsQ2xhc3MpKSkge1xuICAgIGlmIChtYXRjaGVzQXR0cmlidXRlVmFsdWUoe2F0dHJpYnV0ZU5hbWUsIGNvbHVtbk5hbWUsIHZhbHVlfSkpIHtcbiAgICAgIHJldHVybiBhdHRyaWJ1dGVOYW1lXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZFxufVxuXG4vKipcbiAqIFJ1bnMgcmVsYXRpb25zaGlwIGVudHJpZXMuXG4gKiBAcGFyYW0ge1JhbnNhY2tNb2RlbENsYXNzfSBtb2RlbENsYXNzIC0gTW9kZWwgY2xhc3MuXG4gKiBAcmV0dXJucyB7UmVjb3JkPHN0cmluZywge3RhcmdldE1vZGVsQ2xhc3M6IFJhbnNhY2tNb2RlbENsYXNzfT59IC0gUmVsYXRpb25zaGlwIGVudHJpZXMga2V5ZWQgYnkgbmFtZS5cbiAqL1xuZnVuY3Rpb24gcmVsYXRpb25zaGlwRW50cmllcyhtb2RlbENsYXNzKSB7XG4gIGlmICh0eXBlb2YgLyoqXG4gICAgICAgICAgICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgICAgICAgICAgQHR5cGUgez99ICovIChtb2RlbENsYXNzKS5nZXRSZWxhdGlvbnNoaXBzTWFwID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICByZXR1cm4gYmFja2VuZFJlbGF0aW9uc2hpcEVudHJpZXMobW9kZWxDbGFzcylcbiAgfVxuXG4gIGlmICh0eXBlb2YgLyoqXG4gICAgICAgICAgICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgICAgICAgICAgQHR5cGUgez99ICovIChtb2RlbENsYXNzKS5yZWxhdGlvbnNoaXBEZWZpbml0aW9ucyA9PT0gXCJmdW5jdGlvblwiICYmXG4gICAgdHlwZW9mIC8qKlxuICAgICAgICAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICAgICAgICAgQHR5cGUgez99ICovIChtb2RlbENsYXNzKS5yZWxhdGlvbnNoaXBNb2RlbENsYXNzZXMgPT09IFwiZnVuY3Rpb25cIikge1xuICAgIHJldHVybiBmcm9udGVuZFJlbGF0aW9uc2hpcEVudHJpZXMobW9kZWxDbGFzcylcbiAgfVxuXG4gIHJldHVybiB7fVxufVxuXG4vKipcbiAqIFJ1bnMgYmFja2VuZCByZWxhdGlvbnNoaXAgZW50cmllcy5cbiAqIEBwYXJhbSB7UmFuc2Fja01vZGVsQ2xhc3N9IG1vZGVsQ2xhc3MgLSBCYWNrZW5kIG1vZGVsIGNsYXNzLlxuICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIHt0YXJnZXRNb2RlbENsYXNzOiBSYW5zYWNrTW9kZWxDbGFzc30+fSAtIFJlbGF0aW9uc2hpcCBlbnRyaWVzIGtleWVkIGJ5IG5hbWUuXG4gKi9cbmZ1bmN0aW9uIGJhY2tlbmRSZWxhdGlvbnNoaXBFbnRyaWVzKG1vZGVsQ2xhc3MpIHtcbiAgLyoqXG4gICAqIEVudHJpZXMuXG4gICAgQHR5cGUge1JlY29yZDxzdHJpbmcsIHt0YXJnZXRNb2RlbENsYXNzOiBSYW5zYWNrTW9kZWxDbGFzc30+fSAqL1xuICBjb25zdCBlbnRyaWVzID0ge31cbiAgY29uc3QgcmVsYXRpb25zaGlwc01hcCA9IC8qKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAdHlwZSB7P30gKi8gKG1vZGVsQ2xhc3MpLmdldFJlbGF0aW9uc2hpcHNNYXAoKVxuXG4gIGZvciAoY29uc3QgcmVsYXRpb25zaGlwTmFtZSBvZiBPYmplY3Qua2V5cyhyZWxhdGlvbnNoaXBzTWFwKSkge1xuICAgIGNvbnN0IHJlbGF0aW9uc2hpcCA9IHJlbGF0aW9uc2hpcHNNYXBbcmVsYXRpb25zaGlwTmFtZV1cblxuICAgIGlmICh0eXBlb2YgcmVsYXRpb25zaGlwLmlzUG9seW1vcnBoaWMgPT09IFwiZnVuY3Rpb25cIiAmJiByZWxhdGlvbnNoaXAuaXNQb2x5bW9ycGhpYygpKSBjb250aW51ZVxuXG4gICAgY29uc3QgdGFyZ2V0TW9kZWxDbGFzcyA9IHJlbGF0aW9uc2hpcC5nZXRUYXJnZXRNb2RlbENsYXNzKClcblxuICAgIGlmICghdGFyZ2V0TW9kZWxDbGFzcykgY29udGludWVcblxuICAgIGVudHJpZXNbcmVsYXRpb25zaGlwTmFtZV0gPSB7dGFyZ2V0TW9kZWxDbGFzc31cbiAgfVxuXG4gIHJldHVybiBlbnRyaWVzXG59XG5cbi8qKlxuICogUnVucyBmcm9udGVuZCByZWxhdGlvbnNoaXAgZW50cmllcy5cbiAqIEBwYXJhbSB7UmFuc2Fja01vZGVsQ2xhc3N9IG1vZGVsQ2xhc3MgLSBGcm9udGVuZCBtb2RlbCBjbGFzcy5cbiAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCB7dGFyZ2V0TW9kZWxDbGFzczogUmFuc2Fja01vZGVsQ2xhc3N9Pn0gLSBSZWxhdGlvbnNoaXAgZW50cmllcyBrZXllZCBieSBuYW1lLlxuICovXG5mdW5jdGlvbiBmcm9udGVuZFJlbGF0aW9uc2hpcEVudHJpZXMobW9kZWxDbGFzcykge1xuICAvKipcbiAgICogRW50cmllcy5cbiAgICBAdHlwZSB7UmVjb3JkPHN0cmluZywge3RhcmdldE1vZGVsQ2xhc3M6IFJhbnNhY2tNb2RlbENsYXNzfT59ICovXG4gIGNvbnN0IGVudHJpZXMgPSB7fVxuICBjb25zdCBkZWZpbml0aW9ucyA9IC8qKlxuICAgICAgICAgICAgICAgICAgICAgICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICAgICAgICAgICAgICAgICAgICAgIEB0eXBlIHs/fSAqLyAobW9kZWxDbGFzcykucmVsYXRpb25zaGlwRGVmaW5pdGlvbnMoKVxuICBjb25zdCByZWxhdGlvbnNoaXBNb2RlbENsYXNzZXMgPSAvKipcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEB0eXBlIHs/fSAqLyAobW9kZWxDbGFzcykucmVsYXRpb25zaGlwTW9kZWxDbGFzc2VzKClcblxuICBmb3IgKGNvbnN0IHJlbGF0aW9uc2hpcE5hbWUgb2YgT2JqZWN0LmtleXMoZGVmaW5pdGlvbnMpKSB7XG4gICAgY29uc3QgdGFyZ2V0TW9kZWxDbGFzcyA9IHJlc29sdmVGcm9udGVuZE1vZGVsQ2xhc3MocmVsYXRpb25zaGlwTW9kZWxDbGFzc2VzW3JlbGF0aW9uc2hpcE5hbWVdKVxuXG4gICAgaWYgKCF0YXJnZXRNb2RlbENsYXNzKSBjb250aW51ZVxuXG4gICAgZW50cmllc1tyZWxhdGlvbnNoaXBOYW1lXSA9IHt0YXJnZXRNb2RlbENsYXNzfVxuICB9XG5cbiAgcmV0dXJuIGVudHJpZXNcbn1cblxuLyoqXG4gKiBSdW5zIGF0dHJpYnV0ZSBlbnRyaWVzLlxuICogQHBhcmFtIHtSYW5zYWNrTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzLlxuICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsIHN0cmluZz59IC0gQXR0cmlidXRlLXRvLWNvbHVtbiBlbnRyaWVzIGtleWVkIGJ5IGF0dHJpYnV0ZSBuYW1lLlxuICovXG5mdW5jdGlvbiBhdHRyaWJ1dGVFbnRyaWVzKG1vZGVsQ2xhc3MpIHtcbiAgaWYgKHR5cGVvZiAvKipcbiAgICAgICAgICAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICAgICAgICAgICBAdHlwZSB7P30gKi8gKG1vZGVsQ2xhc3MpLmdldEF0dHJpYnV0ZU5hbWVUb0NvbHVtbk5hbWVNYXAgPT09IFwiZnVuY3Rpb25cIikge1xuICAgIHJldHVybiAvKiogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLiBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nPn0gKi8gKCgvKipcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEB0eXBlIHs/fSAqLyAobW9kZWxDbGFzcykuZ2V0QXR0cmlidXRlTmFtZVRvQ29sdW1uTmFtZU1hcCgpKSlcbiAgfVxuXG4gIGNvbnN0IHJlc291cmNlQ29uZmlnID0gdHlwZW9mIC8qKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQHR5cGUgez99ICovIChtb2RlbENsYXNzKS5yZXNvdXJjZUNvbmZpZyA9PT0gXCJmdW5jdGlvblwiXG4gICAgPyAvKipcbiAgICAgICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICAgICAgQHR5cGUgez99ICovIChtb2RlbENsYXNzKS5yZXNvdXJjZUNvbmZpZygpXG4gICAgOiB7fVxuICBjb25zdCBhdHRyaWJ1dGVzID0gcmVzb3VyY2VDb25maWcuYXR0cmlidXRlc1xuICAvKipcbiAgICogRW50cmllcy5cbiAgICBAdHlwZSB7UmVjb3JkPHN0cmluZywgc3RyaW5nPn0gKi9cbiAgY29uc3QgZW50cmllcyA9IHt9XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkoYXR0cmlidXRlcykpIHtcbiAgICBmb3IgKGNvbnN0IGF0dHJpYnV0ZU5hbWUgb2YgYXR0cmlidXRlcykge1xuICAgICAgaWYgKHR5cGVvZiBhdHRyaWJ1dGVOYW1lICE9PSBcInN0cmluZ1wiKSBjb250aW51ZVxuXG4gICAgICBlbnRyaWVzW2F0dHJpYnV0ZU5hbWVdID0gYXR0cmlidXRlTmFtZVxuICAgIH1cbiAgfSBlbHNlIGlmIChpc1BsYWluT2JqZWN0KGF0dHJpYnV0ZXMpKSB7XG4gICAgZm9yIChjb25zdCBhdHRyaWJ1dGVOYW1lIG9mIE9iamVjdC5rZXlzKGF0dHJpYnV0ZXMpKSB7XG4gICAgICBlbnRyaWVzW2F0dHJpYnV0ZU5hbWVdID0gYXR0cmlidXRlTmFtZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBlbnRyaWVzXG59XG5cbi8qKlxuICogUnVucyBtYXRjaGVzIGF0dHJpYnV0ZSB2YWx1ZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmF0dHJpYnV0ZU5hbWUgLSBBdHRyaWJ1dGUgbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmNvbHVtbk5hbWUgLSBDb2x1bW4gbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnZhbHVlIC0gQ2FuZGlkYXRlIHZhbHVlLlxuICogQHJldHVybnMge2Jvb2xlYW59IC0gV2hldGhlciB0aGUgY2FuZGlkYXRlIHJlc29sdmVzIHRvIHRoZSBhdHRyaWJ1dGUuXG4gKi9cbmZ1bmN0aW9uIG1hdGNoZXNBdHRyaWJ1dGVWYWx1ZSh7YXR0cmlidXRlTmFtZSwgY29sdW1uTmFtZSwgdmFsdWV9KSB7XG4gIHJldHVybiB1bmlxdW5pemUoW1xuICAgIGF0dHJpYnV0ZU5hbWUsXG4gICAgY29sdW1uTmFtZSxcbiAgICBpbmZsZWN0aW9uLnVuZGVyc2NvcmUoYXR0cmlidXRlTmFtZSksXG4gICAgaW5mbGVjdGlvbi51bmRlcnNjb3JlKGNvbHVtbk5hbWUpXG4gIF0pLmluY2x1ZGVzKHZhbHVlKVxufVxuXG4vKipcbiAqIFJ1bnMgcGFyc2UgcmFuc2FjayBrZXkuXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gUmFuc2FjayBrZXkuXG4gKiBAcmV0dXJucyB7e3BhdGhWYWx1ZTogc3RyaW5nLCBwcmVkaWNhdGU6IFJhbnNhY2tQcmVkaWNhdGV9IHwgbnVsbH0gLSBQYXJzZWQga2V5LlxuICovXG5mdW5jdGlvbiBwYXJzZVJhbnNhY2tLZXkoa2V5KSB7XG4gIGZvciAoY29uc3QgcHJlZGljYXRlIG9mIHN1cHBvcnRlZFByZWRpY2F0ZXMpIHtcbiAgICBjb25zdCBzdWZmaXggPSBgXyR7cHJlZGljYXRlfWBcbiAgICBpZiAoIWtleS5lbmRzV2l0aChzdWZmaXgpKSBjb250aW51ZVxuXG4gICAgY29uc3QgcGF0aFZhbHVlID0ga2V5LnNsaWNlKDAsIGtleS5sZW5ndGggLSBzdWZmaXgubGVuZ3RoKVxuXG4gICAgaWYgKHBhdGhWYWx1ZS5sZW5ndGggPCAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcmFuc2FjayBrZXk6ICR7a2V5fWApXG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHBhdGhWYWx1ZSxcbiAgICAgIHByZWRpY2F0ZTogLyoqXG4gICAgICAgICAgICAgICAgICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICAgICAgICAgICAgICAgICBAdHlwZSB7UmFuc2Fja1ByZWRpY2F0ZX0gKi8gKHByZWRpY2F0ZSlcbiAgICB9XG4gIH1cblxuICBmb3IgKGNvbnN0IHByZWRpY2F0ZSBvZiBzdXBwb3J0ZWRQcmVkaWNhdGVzKSB7XG4gICAgY29uc3QgY2FtZWxTdWZmaXggPSBzbmFrZVRvQ2FtZWxTdWZmaXgocHJlZGljYXRlKVxuXG4gICAgaWYgKCFrZXkuZW5kc1dpdGgoY2FtZWxTdWZmaXgpKSBjb250aW51ZVxuXG4gICAgY29uc3QgcGF0aFZhbHVlID0ga2V5LnNsaWNlKDAsIGtleS5sZW5ndGggLSBjYW1lbFN1ZmZpeC5sZW5ndGgpXG5cbiAgICBpZiAocGF0aFZhbHVlLmxlbmd0aCA8IDEpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByYW5zYWNrIGtleTogJHtrZXl9YClcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcGF0aFZhbHVlLFxuICAgICAgcHJlZGljYXRlOiAvKipcbiAgICAgICAgICAgICAgICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgICAgICAgICAgICAgIEB0eXBlIHtSYW5zYWNrUHJlZGljYXRlfSAqLyAocHJlZGljYXRlKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsXG59XG5cbi8qKlxuICogUnVucyBzbmFrZSB0byBjYW1lbCBzdWZmaXguXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgLSBTbmFrZS1jYXNlIHByZWRpY2F0ZS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IC0gQ2FtZWxDYXNlIHByZWRpY2F0ZSBzdWZmaXggdXNlZCBpbiByYW5zYWNrIGtleXMuXG4gKi9cbmZ1bmN0aW9uIHNuYWtlVG9DYW1lbFN1ZmZpeCh2YWx1ZSkge1xuICBjb25zdCBzZWdtZW50cyA9IHZhbHVlLnNwbGl0KFwiX1wiKVxuXG4gIHJldHVybiBzZWdtZW50cy5tYXAoKHNlZ21lbnQpID0+IHNlZ21lbnQuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzZWdtZW50LnNsaWNlKDEpKS5qb2luKFwiXCIpXG59XG5cbi8qKlxuICogUnVucyBub3JtYWxpemUgcmFuc2FjayB2YWx1ZS5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAqIEBwYXJhbSB7UmFuc2Fja1ByZWRpY2F0ZX0gYXJncy5wcmVkaWNhdGUgLSBQYXJzZWQgcHJlZGljYXRlLlxuICogQHBhcmFtIHs/fSBhcmdzLnZhbHVlIC0gUmF3IHZhbHVlLlxuICogQHJldHVybnMgez99IC0gTm9ybWFsaXplZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplUmFuc2Fja1ZhbHVlKHtwcmVkaWNhdGUsIHZhbHVlfSkge1xuICBpZiAocHJlZGljYXRlID09PSBcIm51bGxcIikge1xuICAgIHJldHVybiBub3JtYWxpemVSYW5zYWNrTnVsbFZhbHVlKHZhbHVlKVxuICB9XG5cbiAgaWYgKHByZWRpY2F0ZSA9PT0gXCJpblwiIHx8IHByZWRpY2F0ZSA9PT0gXCJub3RfaW5cIikge1xuICAgIHJldHVybiBub3JtYWxpemVSYW5zYWNrTGlzdFZhbHVlKHZhbHVlKVxuICB9XG5cbiAgaWYgKHJhbnNhY2tWYWx1ZUlzQmxhbmsodmFsdWUpKSByZXR1cm4gU0tJUF9SQU5TQUNLX0NPTkRJVElPTlxuXG4gIHJldHVybiB2YWx1ZVxufVxuXG4vKipcbiAqIFJ1bnMgbm9ybWFsaXplIHJhbnNhY2sgbnVsbCB2YWx1ZS5cbiAqIEBwYXJhbSB7P30gdmFsdWUgLSBDYW5kaWRhdGUgbnVsbCBwcmVkaWNhdGUgdmFsdWUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbiB8IHR5cGVvZiBTS0lQX1JBTlNBQ0tfQ09ORElUSU9OfSAtIE5vcm1hbGl6ZWQgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIG5vcm1hbGl6ZVJhbnNhY2tOdWxsVmFsdWUodmFsdWUpIHtcbiAgY29uc3QgYm9vbGVhblZhbHVlID0gbm9ybWFsaXplUmFuc2Fja0Jvb2xlYW4odmFsdWUpXG5cbiAgcmV0dXJuIGJvb2xlYW5WYWx1ZSA9PT0gbnVsbCA/IFNLSVBfUkFOU0FDS19DT05ESVRJT04gOiBib29sZWFuVmFsdWVcbn1cblxuLyoqXG4gKiBSdW5zIG5vcm1hbGl6ZSByYW5zYWNrIGxpc3QgdmFsdWUuXG4gKiBAcGFyYW0gez99IHZhbHVlIC0gQ2FuZGlkYXRlIGxpc3QgcHJlZGljYXRlIHZhbHVlLlxuICogQHJldHVybnMge0FycmF5PD8+IHwgdHlwZW9mIFNLSVBfUkFOU0FDS19DT05ESVRJT059IC0gTm9ybWFsaXplZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplUmFuc2Fja0xpc3RWYWx1ZSh2YWx1ZSkge1xuICBjb25zdCBub3JtYWxpemVkQXJyYXkgPSBub3JtYWxpemVSYW5zYWNrQXJyYXkodmFsdWUpXG5cbiAgcmV0dXJuIG5vcm1hbGl6ZWRBcnJheS5sZW5ndGggPCAxID8gU0tJUF9SQU5TQUNLX0NPTkRJVElPTiA6IG5vcm1hbGl6ZWRBcnJheVxufVxuXG4vKipcbiAqIFJhbnNhY2sgdHJ1ZSB2YWx1ZXMuXG4gIEB0eXBlIHtTZXQ8Pz59ICovXG5jb25zdCByYW5zYWNrVHJ1ZVZhbHVlcyA9IG5ldyBTZXQoW3RydWUsIDEsIFwiMVwiLCBcInRydWVcIl0pXG4vKipcbiAqIFJhbnNhY2sgZmFsc2UgdmFsdWVzLlxuICBAdHlwZSB7U2V0PD8+fSAqL1xuY29uc3QgcmFuc2Fja0ZhbHNlVmFsdWVzID0gbmV3IFNldChbZmFsc2UsIDAsIFwiMFwiLCBcImZhbHNlXCJdKVxuXG4vKipcbiAqIFJ1bnMgbm9ybWFsaXplIHJhbnNhY2sgYm9vbGVhbi5cbiAqIEBwYXJhbSB7P30gdmFsdWUgLSBDYW5kaWRhdGUgYm9vbGVhbi5cbiAqIEByZXR1cm5zIHtib29sZWFuIHwgbnVsbH0gLSBOb3JtYWxpemVkIGJvb2xlYW4gb3IgbnVsbCB3aGVuIGJsYW5rLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSYW5zYWNrQm9vbGVhbih2YWx1ZSkge1xuICBpZiAocmFuc2Fja1RydWVWYWx1ZXMuaGFzKHZhbHVlKSkgcmV0dXJuIHRydWVcbiAgaWYgKHJhbnNhY2tGYWxzZVZhbHVlcy5oYXModmFsdWUpKSByZXR1cm4gZmFsc2VcbiAgaWYgKHJhbnNhY2tWYWx1ZUlzQmxhbmsodmFsdWUpKSByZXR1cm4gbnVsbFxuXG4gIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByYW5zYWNrIGJvb2xlYW4gdmFsdWU6ICR7U3RyaW5nKHZhbHVlKX1gKVxufVxuXG4vKipcbiAqIFJ1bnMgcmFuc2FjayB2YWx1ZSBpcyBibGFuay5cbiAqIEBwYXJhbSB7P30gdmFsdWUgLSBDYW5kaWRhdGUgdmFsdWUuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIHZhbHVlIHNob3VsZCBiZSBpZ25vcmVkIGFzIGJsYW5rLlxuICovXG5mdW5jdGlvbiByYW5zYWNrVmFsdWVJc0JsYW5rKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSBcIlwiXG59XG5cbi8qKlxuICogUnVucyBub3JtYWxpemUgcmFuc2FjayBhcnJheS5cbiAqIEBwYXJhbSB7P30gdmFsdWUgLSBDYW5kaWRhdGUgYXJyYXktaXNoIHZhbHVlLlxuICogQHJldHVybnMge0FycmF5PD8+fSAtIE5vcm1hbGl6ZWQgYXJyYXkgdmFsdWVzLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSYW5zYWNrQXJyYXkodmFsdWUpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlLmZpbHRlcigoZW50cnkpID0+IGVudHJ5ICE9PSB1bmRlZmluZWQgJiYgZW50cnkgIT09IG51bGwgJiYgZW50cnkgIT09IFwiXCIpXG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIHZhbHVlLnNwbGl0KFwiLFwiKS5tYXAoKGVudHJ5KSA9PiBlbnRyeS50cmltKCkpLmZpbHRlcigoZW50cnkpID0+IGVudHJ5Lmxlbmd0aCA+IDApXG4gIH1cblxuICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gXCJcIikgcmV0dXJuIFtdXG5cbiAgcmV0dXJuIFt2YWx1ZV1cbn1cblxuLyoqXG4gKiBSYW5zYWNrU29ydCB0eXBlLlxuICogQHR5cGVkZWYge29iamVjdH0gUmFuc2Fja1NvcnRcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBhdHRyaWJ1dGUgLSBSZXNvbHZlZCBhdHRyaWJ1dGUgbmFtZS5cbiAqIEBwcm9wZXJ0eSB7XCJhc2NcIiB8IFwiZGVzY1wifSBkaXJlY3Rpb24gLSBTb3J0IGRpcmVjdGlvbi5cbiAqL1xuXG4vKipcbiAqIFBhcnNlcyBhbmQgdmFsaWRhdGVzIGEgcmFuc2FjayBgc2Agc29ydCBzdHJpbmcgYWdhaW5zdCBtb2RlbCBhdHRyaWJ1dGVzLlxuICogQHBhcmFtIHtSYW5zYWNrTW9kZWxDbGFzc30gbW9kZWxDbGFzcyAtIE1vZGVsIGNsYXNzIGZvciBhdHRyaWJ1dGUgdmFsaWRhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBzb3J0U3RyaW5nIC0gUmFuc2FjayBzb3J0IHN0cmluZyAoZS5nLiwgXCJuYW1lIGFzY1wiIG9yIFwibmFtZSBhc2MsIGNyZWF0ZWRBdCBkZXNjXCIpLlxuICogQHJldHVybnMge1JhbnNhY2tTb3J0W119IC0gVmFsaWRhdGVkIHNvcnQgZGVmaW5pdGlvbnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJhbnNhY2tTb3J0KG1vZGVsQ2xhc3MsIHNvcnRTdHJpbmcpIHtcbiAgY29uc3Qgc2VnbWVudHMgPSBzb3J0U3RyaW5nLnNwbGl0KFwiLFwiKS5tYXAoKHNlZ21lbnQpID0+IHNlZ21lbnQudHJpbSgpKS5maWx0ZXIoKHNlZ21lbnQpID0+IHNlZ21lbnQubGVuZ3RoID4gMClcblxuICAvKipcbiAgICogU29ydHMuXG4gICAgQHR5cGUge1JhbnNhY2tTb3J0W119ICovXG4gIGNvbnN0IHNvcnRzID0gW11cblxuICBmb3IgKGNvbnN0IHNlZ21lbnQgb2Ygc2VnbWVudHMpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHNlZ21lbnQuc3BsaXQoL1xccysvKVxuICAgIGNvbnN0IGNvbHVtbkNhbmRpZGF0ZSA9IHBhcnRzWzBdXG4gICAgY29uc3QgZGlyZWN0aW9uQ2FuZGlkYXRlID0gcGFydHMubGVuZ3RoID4gMSA/IHBhcnRzWzFdLnRvTG93ZXJDYXNlKCkgOiBcImFzY1wiXG5cbiAgICBpZiAoZGlyZWN0aW9uQ2FuZGlkYXRlICE9PSBcImFzY1wiICYmIGRpcmVjdGlvbkNhbmRpZGF0ZSAhPT0gXCJkZXNjXCIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCByYW5zYWNrIHNvcnQgZGlyZWN0aW9uIFwiJHtkaXJlY3Rpb25DYW5kaWRhdGV9XCIgaW46ICR7c2VnbWVudH1gKVxuICAgIH1cblxuICAgIGNvbnN0IHJlc29sdmVkQXR0cmlidXRlID0gcmVzb2x2ZUF0dHJpYnV0ZU5hbWUoe21vZGVsQ2xhc3MsIHZhbHVlOiBjb2x1bW5DYW5kaWRhdGV9KVxuXG4gICAgaWYgKCFyZXNvbHZlZEF0dHJpYnV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIHJhbnNhY2sgc29ydCBhdHRyaWJ1dGUgXCIke2NvbHVtbkNhbmRpZGF0ZX1cIiBmb3IgJHttb2RlbENsYXNzLm5hbWV9YClcbiAgICB9XG5cbiAgICBzb3J0cy5wdXNoKHthdHRyaWJ1dGU6IHJlc29sdmVkQXR0cmlidXRlLCBkaXJlY3Rpb246IGRpcmVjdGlvbkNhbmRpZGF0ZX0pXG4gIH1cblxuICByZXR1cm4gc29ydHNcbn1cblxuLyoqXG4gKiBSdW5zIHVuaXF1bml6ZS5cbiAqIEBwYXJhbSB7c3RyaW5nW119IHZhbHVlcyAtIElucHV0IHZhbHVlcy5cbiAqIEByZXR1cm5zIHtzdHJpbmdbXX0gLSBVbmlxdWUgdmFsdWVzIGluIG9yaWdpbmFsIG9yZGVyLlxuICovXG5mdW5jdGlvbiB1bmlxdW5pemUodmFsdWVzKSB7XG4gIHJldHVybiBBcnJheS5mcm9tKG5ldyBTZXQodmFsdWVzKSlcbn1cbiJdfQ==