velocious 1.0.431 → 1.0.433

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 (794) hide show
  1. package/build/application.js +229 -0
  2. package/build/authorization/ability.js +329 -0
  3. package/build/authorization/base-resource.js +143 -0
  4. package/build/background-jobs/client.js +50 -0
  5. package/build/background-jobs/cron-expression.js +277 -0
  6. package/build/background-jobs/forked-runner-child.js +86 -0
  7. package/build/background-jobs/job-record.js +13 -0
  8. package/build/background-jobs/job-registry.js +92 -0
  9. package/build/background-jobs/job-runner.js +107 -0
  10. package/build/background-jobs/job.js +77 -0
  11. package/build/background-jobs/json-socket.js +78 -0
  12. package/build/background-jobs/main.js +926 -0
  13. package/build/background-jobs/normalize-error.js +26 -0
  14. package/build/background-jobs/scheduler.js +274 -0
  15. package/build/background-jobs/socket-request.js +68 -0
  16. package/build/background-jobs/status-reporter.js +101 -0
  17. package/build/background-jobs/store.js +994 -0
  18. package/build/background-jobs/types.js +70 -0
  19. package/build/background-jobs/web/authorization.js +89 -0
  20. package/build/background-jobs/web/controller.js +280 -0
  21. package/build/background-jobs/web/index.js +57 -0
  22. package/build/background-jobs/web/path-matcher.js +74 -0
  23. package/build/background-jobs/web/registry.js +49 -0
  24. package/build/background-jobs/worker.js +683 -0
  25. package/build/beacon/client.js +330 -0
  26. package/build/beacon/in-process-broker.js +71 -0
  27. package/build/beacon/in-process-client.js +139 -0
  28. package/build/beacon/server.js +148 -0
  29. package/build/beacon/types.js +55 -0
  30. package/build/cli/base-command.js +67 -0
  31. package/build/cli/browser-cli.js +45 -0
  32. package/build/cli/commands/background-jobs-main.js +7 -0
  33. package/build/cli/commands/background-jobs-runner.js +7 -0
  34. package/build/cli/commands/background-jobs-worker.js +7 -0
  35. package/build/cli/commands/beacon.js +7 -0
  36. package/build/cli/commands/console.js +12 -0
  37. package/build/cli/commands/db/base-command.js +82 -0
  38. package/build/cli/commands/db/create.js +64 -0
  39. package/build/cli/commands/db/drop.js +75 -0
  40. package/build/cli/commands/db/migrate.js +17 -0
  41. package/build/cli/commands/db/reset.js +22 -0
  42. package/build/cli/commands/db/rollback.js +15 -0
  43. package/build/cli/commands/db/schema/dump.js +12 -0
  44. package/build/cli/commands/db/schema/load.js +12 -0
  45. package/build/cli/commands/db/seed.js +12 -0
  46. package/build/cli/commands/db/tenants/check.js +38 -0
  47. package/build/cli/commands/db/tenants/create.js +33 -0
  48. package/build/cli/commands/db/tenants/migrate.js +49 -0
  49. package/build/cli/commands/destroy/migration.js +7 -0
  50. package/build/cli/commands/generate/base-models.js +7 -0
  51. package/build/cli/commands/generate/frontend-models.js +12 -0
  52. package/build/cli/commands/generate/migration.js +7 -0
  53. package/build/cli/commands/generate/model.js +7 -0
  54. package/build/cli/commands/init.js +11 -0
  55. package/build/cli/commands/routes.js +7 -0
  56. package/build/cli/commands/run-script.js +12 -0
  57. package/build/cli/commands/runner.js +12 -0
  58. package/build/cli/commands/server.js +7 -0
  59. package/build/cli/commands/test.js +9 -0
  60. package/build/cli/index.js +152 -0
  61. package/build/cli/tenant-database-command-helper.js +198 -0
  62. package/build/cli/use-browser-cli.js +30 -0
  63. package/build/configuration-resolver.js +65 -0
  64. package/build/configuration-types.js +429 -0
  65. package/build/configuration.js +2590 -0
  66. package/build/controller.js +421 -0
  67. package/build/current-configuration.js +31 -0
  68. package/build/current.js +80 -0
  69. package/build/database/annotations-async-hooks.js +47 -0
  70. package/build/database/annotations.js +40 -0
  71. package/build/database/drivers/base-column.js +182 -0
  72. package/build/database/drivers/base-columns-index.js +81 -0
  73. package/build/database/drivers/base-foreign-key.js +104 -0
  74. package/build/database/drivers/base-table.js +156 -0
  75. package/build/database/drivers/base.js +1609 -0
  76. package/build/database/drivers/mssql/column.js +74 -0
  77. package/build/database/drivers/mssql/columns-index.js +6 -0
  78. package/build/database/drivers/mssql/connect-connection.js +16 -0
  79. package/build/database/drivers/mssql/foreign-key.js +12 -0
  80. package/build/database/drivers/mssql/index.js +590 -0
  81. package/build/database/drivers/mssql/options.js +79 -0
  82. package/build/database/drivers/mssql/query-parser.js +6 -0
  83. package/build/database/drivers/mssql/sql/alter-table.js +4 -0
  84. package/build/database/drivers/mssql/sql/create-database.js +36 -0
  85. package/build/database/drivers/mssql/sql/create-index.js +4 -0
  86. package/build/database/drivers/mssql/sql/create-table.js +4 -0
  87. package/build/database/drivers/mssql/sql/delete.js +19 -0
  88. package/build/database/drivers/mssql/sql/drop-database.js +36 -0
  89. package/build/database/drivers/mssql/sql/drop-table.js +4 -0
  90. package/build/database/drivers/mssql/sql/insert.js +4 -0
  91. package/build/database/drivers/mssql/sql/update.js +31 -0
  92. package/build/database/drivers/mssql/sql/upsert.js +23 -0
  93. package/build/database/drivers/mssql/structure-sql.js +120 -0
  94. package/build/database/drivers/mssql/table.js +145 -0
  95. package/build/database/drivers/mysql/column.js +112 -0
  96. package/build/database/drivers/mysql/columns-index.js +22 -0
  97. package/build/database/drivers/mysql/foreign-key.js +12 -0
  98. package/build/database/drivers/mysql/index.js +473 -0
  99. package/build/database/drivers/mysql/options.js +34 -0
  100. package/build/database/drivers/mysql/query-parser.js +6 -0
  101. package/build/database/drivers/mysql/query.js +37 -0
  102. package/build/database/drivers/mysql/sql/alter-table.js +6 -0
  103. package/build/database/drivers/mysql/sql/create-database.js +39 -0
  104. package/build/database/drivers/mysql/sql/create-index.js +6 -0
  105. package/build/database/drivers/mysql/sql/create-table.js +6 -0
  106. package/build/database/drivers/mysql/sql/delete.js +21 -0
  107. package/build/database/drivers/mysql/sql/drop-database.js +6 -0
  108. package/build/database/drivers/mysql/sql/drop-table.js +6 -0
  109. package/build/database/drivers/mysql/sql/insert.js +6 -0
  110. package/build/database/drivers/mysql/sql/update.js +33 -0
  111. package/build/database/drivers/mysql/sql/upsert.js +13 -0
  112. package/build/database/drivers/mysql/structure-sql.js +93 -0
  113. package/build/database/drivers/mysql/table.js +121 -0
  114. package/build/database/drivers/pgsql/column.js +90 -0
  115. package/build/database/drivers/pgsql/columns-index.js +6 -0
  116. package/build/database/drivers/pgsql/foreign-key.js +12 -0
  117. package/build/database/drivers/pgsql/index.js +441 -0
  118. package/build/database/drivers/pgsql/options.js +32 -0
  119. package/build/database/drivers/pgsql/query-parser.js +6 -0
  120. package/build/database/drivers/pgsql/sql/alter-table.js +6 -0
  121. package/build/database/drivers/pgsql/sql/create-database.js +38 -0
  122. package/build/database/drivers/pgsql/sql/create-index.js +6 -0
  123. package/build/database/drivers/pgsql/sql/create-table.js +6 -0
  124. package/build/database/drivers/pgsql/sql/delete.js +21 -0
  125. package/build/database/drivers/pgsql/sql/drop-database.js +6 -0
  126. package/build/database/drivers/pgsql/sql/drop-table.js +6 -0
  127. package/build/database/drivers/pgsql/sql/insert.js +6 -0
  128. package/build/database/drivers/pgsql/sql/update.js +33 -0
  129. package/build/database/drivers/pgsql/sql/upsert.js +14 -0
  130. package/build/database/drivers/pgsql/structure-sql.js +126 -0
  131. package/build/database/drivers/pgsql/table.js +135 -0
  132. package/build/database/drivers/sqlite/base.js +509 -0
  133. package/build/database/drivers/sqlite/column.js +75 -0
  134. package/build/database/drivers/sqlite/columns-index.js +30 -0
  135. package/build/database/drivers/sqlite/connection-sql-js.js +46 -0
  136. package/build/database/drivers/sqlite/foreign-key.js +24 -0
  137. package/build/database/drivers/sqlite/index.js +394 -0
  138. package/build/database/drivers/sqlite/index.native.js +72 -0
  139. package/build/database/drivers/sqlite/index.web.js +99 -0
  140. package/build/database/drivers/sqlite/options.js +32 -0
  141. package/build/database/drivers/sqlite/query-parser.js +6 -0
  142. package/build/database/drivers/sqlite/query.js +35 -0
  143. package/build/database/drivers/sqlite/query.native.js +35 -0
  144. package/build/database/drivers/sqlite/query.web.js +49 -0
  145. package/build/database/drivers/sqlite/sql/alter-table.js +187 -0
  146. package/build/database/drivers/sqlite/sql/create-index.js +6 -0
  147. package/build/database/drivers/sqlite/sql/create-table.js +6 -0
  148. package/build/database/drivers/sqlite/sql/delete.js +26 -0
  149. package/build/database/drivers/sqlite/sql/drop-table.js +6 -0
  150. package/build/database/drivers/sqlite/sql/insert.js +6 -0
  151. package/build/database/drivers/sqlite/sql/update.js +33 -0
  152. package/build/database/drivers/sqlite/sql/upsert.js +14 -0
  153. package/build/database/drivers/sqlite/structure-sql.js +56 -0
  154. package/build/database/drivers/sqlite/table-rebuilder.js +96 -0
  155. package/build/database/drivers/sqlite/table.js +131 -0
  156. package/build/database/drivers/structure-sql/utils.js +35 -0
  157. package/build/database/handler.js +13 -0
  158. package/build/database/initializer-from-require-context.js +101 -0
  159. package/build/database/migration/index.js +438 -0
  160. package/build/database/migrator/files-finder.js +55 -0
  161. package/build/database/migrator/types.js +31 -0
  162. package/build/database/migrator.js +557 -0
  163. package/build/database/pool/async-tracked-multi-connection.js +1164 -0
  164. package/build/database/pool/base-methods-forward.js +52 -0
  165. package/build/database/pool/base.js +380 -0
  166. package/build/database/pool/single-multi-use.js +118 -0
  167. package/build/database/query/alter-table-base.js +104 -0
  168. package/build/database/query/base.js +49 -0
  169. package/build/database/query/create-database-base.js +42 -0
  170. package/build/database/query/create-index-base.js +117 -0
  171. package/build/database/query/create-table-base.js +205 -0
  172. package/build/database/query/delete-base.js +19 -0
  173. package/build/database/query/drop-database-base.js +38 -0
  174. package/build/database/query/drop-table-base.js +58 -0
  175. package/build/database/query/from-base.js +36 -0
  176. package/build/database/query/from-plain.js +16 -0
  177. package/build/database/query/from-table.js +18 -0
  178. package/build/database/query/index.js +533 -0
  179. package/build/database/query/insert-base.js +172 -0
  180. package/build/database/query/join-base.js +43 -0
  181. package/build/database/query/join-object.js +167 -0
  182. package/build/database/query/join-plain.js +18 -0
  183. package/build/database/query/join-tracker.js +93 -0
  184. package/build/database/query/model-class-query.js +1577 -0
  185. package/build/database/query/order-base.js +33 -0
  186. package/build/database/query/order-column.js +77 -0
  187. package/build/database/query/order-plain.js +28 -0
  188. package/build/database/query/preloader/belongs-to.js +267 -0
  189. package/build/database/query/preloader/ensure-model-class-initialized.js +18 -0
  190. package/build/database/query/preloader/has-many.js +316 -0
  191. package/build/database/query/preloader/has-one.js +123 -0
  192. package/build/database/query/preloader/selection.js +152 -0
  193. package/build/database/query/preloader.js +201 -0
  194. package/build/database/query/query-data.js +305 -0
  195. package/build/database/query/select-base.js +30 -0
  196. package/build/database/query/select-plain.js +18 -0
  197. package/build/database/query/select-table-and-column.js +28 -0
  198. package/build/database/query/update-base.js +41 -0
  199. package/build/database/query/upsert-base.js +103 -0
  200. package/build/database/query/where-base.js +38 -0
  201. package/build/database/query/where-combinator.js +31 -0
  202. package/build/database/query/where-hash.js +77 -0
  203. package/build/database/query/where-model-class-hash.js +505 -0
  204. package/build/database/query/where-not.js +23 -0
  205. package/build/database/query/where-plain.js +20 -0
  206. package/build/database/query/with-count.js +219 -0
  207. package/build/database/query-parser/base-query-parser.js +40 -0
  208. package/build/database/query-parser/from-parser.js +49 -0
  209. package/build/database/query-parser/group-parser.js +55 -0
  210. package/build/database/query-parser/joins-parser.js +37 -0
  211. package/build/database/query-parser/limit-parser.js +77 -0
  212. package/build/database/query-parser/options.js +94 -0
  213. package/build/database/query-parser/order-parser.js +45 -0
  214. package/build/database/query-parser/select-parser.js +67 -0
  215. package/build/database/query-parser/where-parser.js +46 -0
  216. package/build/database/record/acts-as-list.js +374 -0
  217. package/build/database/record/attachments/download.js +49 -0
  218. package/build/database/record/attachments/handle.js +188 -0
  219. package/build/database/record/attachments/normalize-input.js +213 -0
  220. package/build/database/record/attachments/storage-drivers/filesystem.js +114 -0
  221. package/build/database/record/attachments/storage-drivers/native.js +146 -0
  222. package/build/database/record/attachments/storage-drivers/s3.js +245 -0
  223. package/build/database/record/attachments/store.js +591 -0
  224. package/build/database/record/index.js +4119 -0
  225. package/build/database/record/instance-relationships/base.js +289 -0
  226. package/build/database/record/instance-relationships/belongs-to.js +84 -0
  227. package/build/database/record/instance-relationships/has-many.js +284 -0
  228. package/build/database/record/instance-relationships/has-one.js +117 -0
  229. package/build/database/record/record-not-found-error.js +3 -0
  230. package/build/database/record/relationships/base.js +195 -0
  231. package/build/database/record/relationships/belongs-to.js +57 -0
  232. package/build/database/record/relationships/has-many.js +46 -0
  233. package/build/database/record/relationships/has-one.js +46 -0
  234. package/build/database/record/state-machine.js +278 -0
  235. package/build/database/record/user-module.js +43 -0
  236. package/build/database/record/validators/base.js +27 -0
  237. package/build/database/record/validators/format.js +50 -0
  238. package/build/database/record/validators/presence.js +24 -0
  239. package/build/database/record/validators/uniqueness.js +124 -0
  240. package/build/database/table-data/index.js +241 -0
  241. package/build/database/table-data/table-column.js +416 -0
  242. package/build/database/table-data/table-foreign-key.js +69 -0
  243. package/build/database/table-data/table-index.js +46 -0
  244. package/build/database/table-data/table-reference.js +13 -0
  245. package/build/database/use-database.js +48 -0
  246. package/build/environment-handlers/base.js +561 -0
  247. package/build/environment-handlers/browser.js +338 -0
  248. package/build/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
  249. package/build/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
  250. package/build/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
  251. package/build/environment-handlers/node/cli/commands/beacon.js +21 -0
  252. package/build/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
  253. package/build/environment-handlers/node/cli/commands/console.js +149 -0
  254. package/build/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
  255. package/build/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
  256. package/build/environment-handlers/node/cli/commands/db/seed.js +79 -0
  257. package/build/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
  258. package/build/environment-handlers/node/cli/commands/generate/base-models.js +396 -0
  259. package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
  260. package/build/environment-handlers/node/cli/commands/generate/migration.js +45 -0
  261. package/build/environment-handlers/node/cli/commands/generate/model.js +45 -0
  262. package/build/environment-handlers/node/cli/commands/init.js +68 -0
  263. package/build/environment-handlers/node/cli/commands/routes.js +63 -0
  264. package/build/environment-handlers/node/cli/commands/run-script.js +85 -0
  265. package/build/environment-handlers/node/cli/commands/runner.js +84 -0
  266. package/build/environment-handlers/node/cli/commands/server.js +151 -0
  267. package/build/environment-handlers/node/cli/commands/test.js +118 -0
  268. package/build/environment-handlers/node.js +887 -0
  269. package/build/error-logger.js +30 -0
  270. package/build/frontend-model-controller.js +3491 -0
  271. package/build/frontend-model-resource/base-resource.js +939 -0
  272. package/build/frontend-models/base.js +4004 -0
  273. package/build/frontend-models/clear-pending-debounced-callback.js +16 -0
  274. package/build/frontend-models/event-hook-models.js +49 -0
  275. package/build/frontend-models/model-registry.js +28 -0
  276. package/build/frontend-models/outgoing-event-buffer.js +51 -0
  277. package/build/frontend-models/preloader.js +169 -0
  278. package/build/frontend-models/query.js +2245 -0
  279. package/build/frontend-models/resource-config-validation.js +56 -0
  280. package/build/frontend-models/resource-definition.js +399 -0
  281. package/build/frontend-models/transport-serialization.js +369 -0
  282. package/build/frontend-models/use-created-event.js +21 -0
  283. package/build/frontend-models/use-destroyed-event.js +148 -0
  284. package/build/frontend-models/use-model-class-event.js +164 -0
  285. package/build/frontend-models/use-updated-event.js +152 -0
  286. package/build/frontend-models/websocket-channel.js +494 -0
  287. package/build/frontend-models/websocket-publishers.js +224 -0
  288. package/build/http-client/header.js +17 -0
  289. package/build/http-client/index.js +139 -0
  290. package/build/http-client/request.js +94 -0
  291. package/build/http-client/response.js +151 -0
  292. package/build/http-client/websocket-client.js +27 -0
  293. package/build/http-server/client/index.js +507 -0
  294. package/build/http-server/client/params-to-object.js +152 -0
  295. package/build/http-server/client/request-buffer/form-data-part.js +139 -0
  296. package/build/http-server/client/request-buffer/header.js +19 -0
  297. package/build/http-server/client/request-buffer/index.js +535 -0
  298. package/build/http-server/client/request-parser.js +195 -0
  299. package/build/http-server/client/request-runner.js +321 -0
  300. package/build/http-server/client/request-timing.js +171 -0
  301. package/build/http-server/client/request.js +114 -0
  302. package/build/http-server/client/response.js +251 -0
  303. package/build/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
  304. package/build/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
  305. package/build/http-server/client/uploaded-file/uploaded-file.js +36 -0
  306. package/build/http-server/client/websocket-request.js +147 -0
  307. package/build/http-server/client/websocket-session.js +1755 -0
  308. package/build/http-server/cookie.js +245 -0
  309. package/build/http-server/development-reloader.js +240 -0
  310. package/build/http-server/index.js +561 -0
  311. package/build/http-server/remote-address.js +77 -0
  312. package/build/http-server/server-client.js +222 -0
  313. package/build/http-server/server-lock.js +178 -0
  314. package/build/http-server/websocket-channel-subscribers.js +110 -0
  315. package/build/http-server/websocket-channel.js +137 -0
  316. package/build/http-server/websocket-connection.js +118 -0
  317. package/build/http-server/websocket-event-log-store.js +433 -0
  318. package/build/http-server/websocket-events-host.js +170 -0
  319. package/build/http-server/websocket-events.js +50 -0
  320. package/build/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
  321. package/build/http-server/worker-handler/in-process.js +155 -0
  322. package/build/http-server/worker-handler/index.js +370 -0
  323. package/build/http-server/worker-handler/worker-script.js +6 -0
  324. package/build/http-server/worker-handler/worker-thread.js +286 -0
  325. package/build/initializer.js +39 -0
  326. package/build/jobs/mail-delivery.js +22 -0
  327. package/build/logger/base-logger.js +34 -0
  328. package/build/logger/console-logger.js +28 -0
  329. package/build/logger/file-logger.js +36 -0
  330. package/build/logger/outputs/array-output.js +50 -0
  331. package/build/logger/outputs/console-output.js +32 -0
  332. package/build/logger/outputs/file-output.js +55 -0
  333. package/build/logger/outputs/stdout-output.js +64 -0
  334. package/build/logger.js +507 -0
  335. package/build/mailer/backends/smtp.js +197 -0
  336. package/build/mailer/base.js +337 -0
  337. package/build/mailer/delivery.js +70 -0
  338. package/build/mailer/index.js +24 -0
  339. package/build/mailer.js +15 -0
  340. package/build/plugins/sqljs-wasm-route-controller.js +70 -0
  341. package/build/plugins/sqljs-wasm-route.js +71 -0
  342. package/build/record-payload-values.js +83 -0
  343. package/build/routes/app-routes.js +17 -0
  344. package/build/routes/base-route.js +133 -0
  345. package/build/routes/basic-route.js +109 -0
  346. package/build/routes/built-in/debug/controller.js +12 -0
  347. package/build/routes/built-in/errors/controller.js +7 -0
  348. package/build/routes/get-route.js +75 -0
  349. package/build/routes/hooks/frontend-model-command-route-hook.js +100 -0
  350. package/build/routes/index.js +50 -0
  351. package/build/routes/namespace-route.js +51 -0
  352. package/build/routes/plugin-routes.js +141 -0
  353. package/build/routes/post-route.js +74 -0
  354. package/build/routes/resolver.js +535 -0
  355. package/build/routes/resource-route.js +154 -0
  356. package/build/routes/root-route.js +11 -0
  357. package/build/src/application.js +187 -214
  358. package/build/src/authorization/ability.js +250 -297
  359. package/build/src/authorization/base-resource.js +120 -136
  360. package/build/src/background-jobs/client.js +43 -47
  361. package/build/src/background-jobs/cron-expression.js +127 -166
  362. package/build/src/background-jobs/forked-runner-child.js +37 -47
  363. package/build/src/background-jobs/job-record.js +8 -10
  364. package/build/src/background-jobs/job-registry.js +72 -84
  365. package/build/src/background-jobs/job-runner.js +74 -81
  366. package/build/src/background-jobs/job.js +62 -72
  367. package/build/src/background-jobs/json-socket.js +65 -70
  368. package/build/src/background-jobs/main.js +841 -900
  369. package/build/src/background-jobs/normalize-error.js +12 -11
  370. package/build/src/background-jobs/scheduler.js +205 -247
  371. package/build/src/background-jobs/socket-request.js +60 -65
  372. package/build/src/background-jobs/status-reporter.js +86 -96
  373. package/build/src/background-jobs/store.js +862 -980
  374. package/build/src/background-jobs/types.js +2 -3
  375. package/build/src/background-jobs/web/authorization.js +38 -50
  376. package/build/src/background-jobs/web/controller.js +232 -268
  377. package/build/src/background-jobs/web/index.js +36 -40
  378. package/build/src/background-jobs/web/path-matcher.js +45 -48
  379. package/build/src/background-jobs/web/registry.js +9 -14
  380. package/build/src/background-jobs/worker.js +585 -639
  381. package/build/src/beacon/client.js +264 -293
  382. package/build/src/beacon/in-process-broker.js +20 -25
  383. package/build/src/beacon/in-process-client.js +104 -116
  384. package/build/src/beacon/server.js +110 -126
  385. package/build/src/beacon/types.js +2 -8
  386. package/build/src/cli/base-command.js +49 -57
  387. package/build/src/cli/browser-cli.js +37 -42
  388. package/build/src/cli/commands/background-jobs-main.js +5 -5
  389. package/build/src/cli/commands/background-jobs-runner.js +5 -5
  390. package/build/src/cli/commands/background-jobs-worker.js +5 -5
  391. package/build/src/cli/commands/beacon.js +5 -5
  392. package/build/src/cli/commands/console.js +10 -10
  393. package/build/src/cli/commands/db/base-command.js +71 -76
  394. package/build/src/cli/commands/db/create.js +53 -61
  395. package/build/src/cli/commands/db/drop.js +62 -71
  396. package/build/src/cli/commands/db/migrate.js +13 -15
  397. package/build/src/cli/commands/db/reset.js +16 -19
  398. package/build/src/cli/commands/db/rollback.js +12 -13
  399. package/build/src/cli/commands/db/schema/dump.js +9 -9
  400. package/build/src/cli/commands/db/schema/load.js +9 -9
  401. package/build/src/cli/commands/db/seed.js +9 -9
  402. package/build/src/cli/commands/db/tenants/check.js +32 -35
  403. package/build/src/cli/commands/db/tenants/create.js +26 -29
  404. package/build/src/cli/commands/db/tenants/migrate.js +40 -44
  405. package/build/src/cli/commands/destroy/migration.js +5 -5
  406. package/build/src/cli/commands/generate/base-models.js +5 -5
  407. package/build/src/cli/commands/generate/frontend-models.js +9 -9
  408. package/build/src/cli/commands/generate/migration.js +5 -5
  409. package/build/src/cli/commands/generate/model.js +5 -5
  410. package/build/src/cli/commands/init.js +7 -9
  411. package/build/src/cli/commands/routes.js +6 -6
  412. package/build/src/cli/commands/run-script.js +9 -9
  413. package/build/src/cli/commands/runner.js +9 -9
  414. package/build/src/cli/commands/server.js +6 -6
  415. package/build/src/cli/commands/test.js +6 -7
  416. package/build/src/cli/index.js +127 -141
  417. package/build/src/cli/tenant-database-command-helper.js +154 -185
  418. package/build/src/cli/use-browser-cli.js +15 -20
  419. package/build/src/configuration-resolver.js +47 -54
  420. package/build/src/configuration-types.d.ts +5 -3
  421. package/build/src/configuration-types.d.ts.map +1 -1
  422. package/build/src/configuration-types.js +3 -54
  423. package/build/src/configuration.js +2240 -2547
  424. package/build/src/controller.js +363 -407
  425. package/build/src/current-configuration.js +9 -12
  426. package/build/src/current.js +70 -75
  427. package/build/src/database/annotations-async-hooks.js +16 -22
  428. package/build/src/database/annotations.js +12 -18
  429. package/build/src/database/drivers/base-column.js +155 -179
  430. package/build/src/database/drivers/base-columns-index.js +69 -78
  431. package/build/src/database/drivers/base-foreign-key.js +89 -101
  432. package/build/src/database/drivers/base-table.js +124 -149
  433. package/build/src/database/drivers/base.js +1306 -1489
  434. package/build/src/database/drivers/mssql/column.js +39 -50
  435. package/build/src/database/drivers/mssql/columns-index.js +2 -3
  436. package/build/src/database/drivers/mssql/connect-connection.js +11 -9
  437. package/build/src/database/drivers/mssql/foreign-key.js +8 -9
  438. package/build/src/database/drivers/mssql/index.js +507 -587
  439. package/build/src/database/drivers/mssql/options.js +68 -75
  440. package/build/src/database/drivers/mssql/query-parser.js +2 -3
  441. package/build/src/database/drivers/mssql/sql/alter-table.js +2 -2
  442. package/build/src/database/drivers/mssql/sql/create-database.js +24 -31
  443. package/build/src/database/drivers/mssql/sql/create-index.js +2 -2
  444. package/build/src/database/drivers/mssql/sql/create-table.js +2 -2
  445. package/build/src/database/drivers/mssql/sql/delete.js +14 -16
  446. package/build/src/database/drivers/mssql/sql/drop-database.js +24 -31
  447. package/build/src/database/drivers/mssql/sql/drop-table.js +2 -2
  448. package/build/src/database/drivers/mssql/sql/insert.js +2 -2
  449. package/build/src/database/drivers/mssql/sql/update.js +24 -28
  450. package/build/src/database/drivers/mssql/sql/upsert.js +18 -20
  451. package/build/src/database/drivers/mssql/structure-sql.js +102 -114
  452. package/build/src/database/drivers/mssql/table.js +81 -96
  453. package/build/src/database/drivers/mysql/column.js +75 -92
  454. package/build/src/database/drivers/mysql/columns-index.js +16 -19
  455. package/build/src/database/drivers/mysql/foreign-key.js +8 -9
  456. package/build/src/database/drivers/mysql/index.js +396 -457
  457. package/build/src/database/drivers/mysql/options.js +26 -30
  458. package/build/src/database/drivers/mysql/query-parser.js +2 -3
  459. package/build/src/database/drivers/mysql/query.js +26 -29
  460. package/build/src/database/drivers/mysql/sql/alter-table.js +2 -3
  461. package/build/src/database/drivers/mysql/sql/create-database.js +23 -28
  462. package/build/src/database/drivers/mysql/sql/create-index.js +2 -3
  463. package/build/src/database/drivers/mysql/sql/create-table.js +2 -3
  464. package/build/src/database/drivers/mysql/sql/delete.js +14 -17
  465. package/build/src/database/drivers/mysql/sql/drop-database.js +2 -3
  466. package/build/src/database/drivers/mysql/sql/drop-table.js +2 -3
  467. package/build/src/database/drivers/mysql/sql/insert.js +2 -3
  468. package/build/src/database/drivers/mysql/sql/update.js +24 -29
  469. package/build/src/database/drivers/mysql/sql/upsert.js +8 -10
  470. package/build/src/database/drivers/mysql/structure-sql.js +79 -88
  471. package/build/src/database/drivers/mysql/table.js +83 -98
  472. package/build/src/database/drivers/pgsql/column.js +56 -72
  473. package/build/src/database/drivers/pgsql/columns-index.js +2 -3
  474. package/build/src/database/drivers/pgsql/foreign-key.js +8 -9
  475. package/build/src/database/drivers/pgsql/index.js +377 -438
  476. package/build/src/database/drivers/pgsql/options.js +25 -28
  477. package/build/src/database/drivers/pgsql/query-parser.js +2 -3
  478. package/build/src/database/drivers/pgsql/sql/alter-table.js +2 -3
  479. package/build/src/database/drivers/pgsql/sql/create-database.js +19 -23
  480. package/build/src/database/drivers/pgsql/sql/create-index.js +2 -3
  481. package/build/src/database/drivers/pgsql/sql/create-table.js +2 -3
  482. package/build/src/database/drivers/pgsql/sql/delete.js +14 -17
  483. package/build/src/database/drivers/pgsql/sql/drop-database.js +2 -3
  484. package/build/src/database/drivers/pgsql/sql/drop-table.js +2 -3
  485. package/build/src/database/drivers/pgsql/sql/insert.js +2 -3
  486. package/build/src/database/drivers/pgsql/sql/update.js +24 -29
  487. package/build/src/database/drivers/pgsql/sql/upsert.js +9 -11
  488. package/build/src/database/drivers/pgsql/structure-sql.js +108 -120
  489. package/build/src/database/drivers/pgsql/table.js +60 -77
  490. package/build/src/database/drivers/sqlite/base.js +405 -478
  491. package/build/src/database/drivers/sqlite/column.js +54 -69
  492. package/build/src/database/drivers/sqlite/columns-index.js +22 -27
  493. package/build/src/database/drivers/sqlite/connection-sql-js.js +35 -42
  494. package/build/src/database/drivers/sqlite/foreign-key.js +18 -21
  495. package/build/src/database/drivers/sqlite/index.js +330 -373
  496. package/build/src/database/drivers/sqlite/index.native.js +55 -64
  497. package/build/src/database/drivers/sqlite/index.web.js +69 -87
  498. package/build/src/database/drivers/sqlite/options.js +25 -28
  499. package/build/src/database/drivers/sqlite/query-parser.js +2 -3
  500. package/build/src/database/drivers/sqlite/query.js +21 -24
  501. package/build/src/database/drivers/sqlite/query.native.js +20 -25
  502. package/build/src/database/drivers/sqlite/query.web.js +30 -37
  503. package/build/src/database/drivers/sqlite/sql/alter-table.js +159 -179
  504. package/build/src/database/drivers/sqlite/sql/create-index.js +2 -3
  505. package/build/src/database/drivers/sqlite/sql/create-table.js +2 -3
  506. package/build/src/database/drivers/sqlite/sql/delete.js +17 -22
  507. package/build/src/database/drivers/sqlite/sql/drop-table.js +2 -3
  508. package/build/src/database/drivers/sqlite/sql/insert.js +2 -3
  509. package/build/src/database/drivers/sqlite/sql/update.js +24 -29
  510. package/build/src/database/drivers/sqlite/sql/upsert.js +9 -11
  511. package/build/src/database/drivers/sqlite/structure-sql.js +49 -52
  512. package/build/src/database/drivers/sqlite/table-rebuilder.js +62 -75
  513. package/build/src/database/drivers/sqlite/table.js +102 -125
  514. package/build/src/database/drivers/structure-sql/utils.js +14 -17
  515. package/build/src/database/handler.js +9 -10
  516. package/build/src/database/initializer-from-require-context.js +76 -87
  517. package/build/src/database/migration/index.js +332 -395
  518. package/build/src/database/migrator/files-finder.js +40 -50
  519. package/build/src/database/migrator/types.js +2 -30
  520. package/build/src/database/migrator.js +454 -526
  521. package/build/src/database/pool/async-tracked-multi-connection.js +997 -1147
  522. package/build/src/database/pool/base-methods-forward.js +40 -43
  523. package/build/src/database/pool/base.js +298 -343
  524. package/build/src/database/pool/single-multi-use.js +93 -110
  525. package/build/src/database/query/alter-table-base.js +84 -99
  526. package/build/src/database/query/base.js +39 -46
  527. package/build/src/database/query/create-database-base.js +25 -30
  528. package/build/src/database/query/create-index-base.js +75 -94
  529. package/build/src/database/query/create-table-base.js +151 -193
  530. package/build/src/database/query/delete-base.js +14 -16
  531. package/build/src/database/query/drop-database-base.js +23 -28
  532. package/build/src/database/query/drop-table-base.js +42 -53
  533. package/build/src/database/query/from-base.js +30 -33
  534. package/build/src/database/query/from-plain.js +11 -13
  535. package/build/src/database/query/from-table.js +13 -15
  536. package/build/src/database/query/index.js +410 -472
  537. package/build/src/database/query/insert-base.js +143 -164
  538. package/build/src/database/query/join-base.js +35 -40
  539. package/build/src/database/query/join-object.js +128 -153
  540. package/build/src/database/query/join-plain.js +13 -15
  541. package/build/src/database/query/join-tracker.js +76 -90
  542. package/build/src/database/query/model-class-query.js +1134 -1370
  543. package/build/src/database/query/order-base.js +27 -30
  544. package/build/src/database/query/order-column.js +44 -53
  545. package/build/src/database/query/order-plain.js +20 -24
  546. package/build/src/database/query/preloader/belongs-to.js +210 -258
  547. package/build/src/database/query/preloader/ensure-model-class-initialized.js +8 -9
  548. package/build/src/database/query/preloader/has-many.js +240 -301
  549. package/build/src/database/query/preloader/has-one.js +91 -117
  550. package/build/src/database/query/preloader/selection.js +117 -129
  551. package/build/src/database/query/preloader.js +160 -185
  552. package/build/src/database/query/query-data.js +157 -201
  553. package/build/src/database/query/select-base.js +25 -27
  554. package/build/src/database/query/select-plain.js +13 -15
  555. package/build/src/database/query/select-table-and-column.js +21 -25
  556. package/build/src/database/query/update-base.js +35 -38
  557. package/build/src/database/query/upsert-base.js +93 -100
  558. package/build/src/database/query/where-base.js +32 -35
  559. package/build/src/database/query/where-combinator.js +25 -28
  560. package/build/src/database/query/where-hash.js +61 -68
  561. package/build/src/database/query/where-model-class-hash.js +414 -469
  562. package/build/src/database/query/where-not.js +18 -20
  563. package/build/src/database/query/where-plain.js +15 -17
  564. package/build/src/database/query/with-count.js +125 -159
  565. package/build/src/database/query-parser/base-query-parser.js +32 -37
  566. package/build/src/database/query-parser/from-parser.js +36 -45
  567. package/build/src/database/query-parser/group-parser.js +42 -50
  568. package/build/src/database/query-parser/joins-parser.js +28 -33
  569. package/build/src/database/query-parser/limit-parser.js +67 -70
  570. package/build/src/database/query-parser/options.js +75 -82
  571. package/build/src/database/query-parser/order-parser.js +36 -40
  572. package/build/src/database/query-parser/select-parser.js +49 -60
  573. package/build/src/database/query-parser/where-parser.js +36 -41
  574. package/build/src/database/record/acts-as-list.js +235 -273
  575. package/build/src/database/record/attachments/download.js +44 -45
  576. package/build/src/database/record/attachments/handle.js +141 -161
  577. package/build/src/database/record/attachments/normalize-input.js +128 -138
  578. package/build/src/database/record/attachments/storage-drivers/filesystem.js +77 -91
  579. package/build/src/database/record/attachments/storage-drivers/native.js +112 -121
  580. package/build/src/database/record/attachments/storage-drivers/s3.js +177 -208
  581. package/build/src/database/record/attachments/store.js +467 -539
  582. package/build/src/database/record/index.d.ts +109 -25
  583. package/build/src/database/record/index.d.ts.map +1 -1
  584. package/build/src/database/record/index.js +3502 -3898
  585. package/build/src/database/record/instance-relationships/base.js +234 -268
  586. package/build/src/database/record/instance-relationships/belongs-to.js +58 -73
  587. package/build/src/database/record/instance-relationships/has-many.js +225 -264
  588. package/build/src/database/record/instance-relationships/has-one.js +85 -105
  589. package/build/src/database/record/record-not-found-error.js +3 -2
  590. package/build/src/database/record/relationships/base.js +144 -166
  591. package/build/src/database/record/relationships/belongs-to.js +44 -51
  592. package/build/src/database/record/relationships/has-many.js +32 -40
  593. package/build/src/database/record/relationships/has-one.js +32 -40
  594. package/build/src/database/record/state-machine.js +156 -208
  595. package/build/src/database/record/user-module.js +32 -38
  596. package/build/src/database/record/validators/base.js +22 -24
  597. package/build/src/database/record/validators/format.js +36 -46
  598. package/build/src/database/record/validators/presence.js +18 -20
  599. package/build/src/database/record/validators/uniqueness.js +99 -117
  600. package/build/src/database/table-data/index.js +199 -231
  601. package/build/src/database/table-data/table-column.js +338 -382
  602. package/build/src/database/table-data/table-foreign-key.js +57 -66
  603. package/build/src/database/table-data/table-index.js +29 -36
  604. package/build/src/database/table-data/table-reference.js +10 -10
  605. package/build/src/database/use-database.js +32 -40
  606. package/build/src/environment-handlers/base.js +484 -544
  607. package/build/src/environment-handlers/browser.js +241 -294
  608. package/build/src/environment-handlers/node/cli/commands/background-jobs-main.js +16 -19
  609. package/build/src/environment-handlers/node/cli/commands/background-jobs-runner.js +18 -21
  610. package/build/src/environment-handlers/node/cli/commands/background-jobs-worker.js +22 -29
  611. package/build/src/environment-handlers/node/cli/commands/beacon.js +16 -19
  612. package/build/src/environment-handlers/node/cli/commands/cli-command-context.js +14 -15
  613. package/build/src/environment-handlers/node/cli/commands/console.js +99 -120
  614. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.js +34 -39
  615. package/build/src/environment-handlers/node/cli/commands/db/schema/load.js +57 -63
  616. package/build/src/environment-handlers/node/cli/commands/db/seed.js +51 -63
  617. package/build/src/environment-handlers/node/cli/commands/destroy/migration.js +32 -40
  618. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts +4 -2
  619. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
  620. package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +326 -358
  621. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +10 -10
  622. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
  623. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +729 -844
  624. package/build/src/environment-handlers/node/cli/commands/generate/migration.js +34 -38
  625. package/build/src/environment-handlers/node/cli/commands/generate/model.js +34 -38
  626. package/build/src/environment-handlers/node/cli/commands/init.js +56 -61
  627. package/build/src/environment-handlers/node/cli/commands/routes.js +51 -59
  628. package/build/src/environment-handlers/node/cli/commands/run-script.js +54 -68
  629. package/build/src/environment-handlers/node/cli/commands/runner.js +56 -74
  630. package/build/src/environment-handlers/node/cli/commands/server.js +93 -106
  631. package/build/src/environment-handlers/node/cli/commands/test.js +97 -113
  632. package/build/src/environment-handlers/node.js +753 -874
  633. package/build/src/error-logger.js +22 -21
  634. package/build/src/frontend-model-controller.js +2791 -3291
  635. package/build/src/frontend-model-resource/base-resource.d.ts +8 -3
  636. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  637. package/build/src/frontend-model-resource/base-resource.js +770 -865
  638. package/build/src/frontend-models/base.js +3136 -3593
  639. package/build/src/frontend-models/clear-pending-debounced-callback.js +7 -8
  640. package/build/src/frontend-models/event-hook-models.js +16 -21
  641. package/build/src/frontend-models/model-registry.js +9 -11
  642. package/build/src/frontend-models/outgoing-event-buffer.js +10 -17
  643. package/build/src/frontend-models/preloader.js +131 -149
  644. package/build/src/frontend-models/query.js +1557 -1855
  645. package/build/src/frontend-models/resource-config-validation.js +27 -37
  646. package/build/src/frontend-models/resource-definition.d.ts +6 -7
  647. package/build/src/frontend-models/resource-definition.d.ts.map +1 -1
  648. package/build/src/frontend-models/resource-definition.js +237 -291
  649. package/build/src/frontend-models/transport-serialization.js +203 -266
  650. package/build/src/frontend-models/use-created-event.js +5 -7
  651. package/build/src/frontend-models/use-destroyed-event.js +80 -93
  652. package/build/src/frontend-models/use-model-class-event.js +79 -91
  653. package/build/src/frontend-models/use-updated-event.js +84 -97
  654. package/build/src/frontend-models/websocket-channel.js +381 -441
  655. package/build/src/frontend-models/websocket-publishers.js +142 -175
  656. package/build/src/http-client/header.js +13 -14
  657. package/build/src/http-client/index.js +116 -132
  658. package/build/src/http-client/request.js +71 -87
  659. package/build/src/http-client/response.js +122 -140
  660. package/build/src/http-client/websocket-client.js +15 -17
  661. package/build/src/http-server/client/index.js +409 -465
  662. package/build/src/http-server/client/params-to-object.js +124 -135
  663. package/build/src/http-server/client/request-buffer/form-data-part.js +111 -132
  664. package/build/src/http-server/client/request-buffer/header.js +15 -16
  665. package/build/src/http-server/client/request-buffer/index.js +446 -506
  666. package/build/src/http-server/client/request-parser.js +163 -186
  667. package/build/src/http-server/client/request-runner.js +226 -259
  668. package/build/src/http-server/client/request-timing.js +132 -151
  669. package/build/src/http-server/client/request.js +96 -108
  670. package/build/src/http-server/client/response.js +213 -235
  671. package/build/src/http-server/client/uploaded-file/memory-uploaded-file.js +25 -29
  672. package/build/src/http-server/client/uploaded-file/temporary-uploaded-file.js +25 -29
  673. package/build/src/http-server/client/uploaded-file/uploaded-file.js +33 -33
  674. package/build/src/http-server/client/websocket-request.js +114 -137
  675. package/build/src/http-server/client/websocket-session.js +1452 -1657
  676. package/build/src/http-server/cookie.js +216 -236
  677. package/build/src/http-server/development-reloader.js +190 -221
  678. package/build/src/http-server/index.js +451 -525
  679. package/build/src/http-server/remote-address.js +38 -50
  680. package/build/src/http-server/server-client.js +181 -208
  681. package/build/src/http-server/server-lock.js +153 -167
  682. package/build/src/http-server/websocket-channel-subscribers.js +81 -93
  683. package/build/src/http-server/websocket-channel.js +104 -117
  684. package/build/src/http-server/websocket-connection.js +96 -104
  685. package/build/src/http-server/websocket-event-log-store.js +350 -404
  686. package/build/src/http-server/websocket-events-host.js +145 -164
  687. package/build/src/http-server/websocket-events.js +47 -47
  688. package/build/src/http-server/worker-handler/channel-subscriber-dispatch.js +13 -14
  689. package/build/src/http-server/worker-handler/in-process.js +123 -141
  690. package/build/src/http-server/worker-handler/index.js +313 -349
  691. package/build/src/http-server/worker-handler/worker-script.js +4 -5
  692. package/build/src/http-server/worker-handler/worker-thread.js +240 -269
  693. package/build/src/initializer.js +31 -36
  694. package/build/src/jobs/mail-delivery.js +13 -15
  695. package/build/src/logger/base-logger.js +24 -26
  696. package/build/src/logger/console-logger.js +21 -23
  697. package/build/src/logger/file-logger.js +29 -31
  698. package/build/src/logger/outputs/array-output.js +37 -42
  699. package/build/src/logger/outputs/console-output.js +20 -24
  700. package/build/src/logger/outputs/file-output.js +43 -48
  701. package/build/src/logger/outputs/stdout-output.js +39 -48
  702. package/build/src/logger.js +338 -394
  703. package/build/src/mailer/backends/smtp.js +134 -163
  704. package/build/src/mailer/base.js +211 -251
  705. package/build/src/mailer/delivery.js +56 -64
  706. package/build/src/mailer/index.js +4 -22
  707. package/build/src/mailer.js +4 -13
  708. package/build/src/plugins/sqljs-wasm-route-controller.js +42 -52
  709. package/build/src/plugins/sqljs-wasm-route.js +28 -38
  710. package/build/src/record-payload-values.js +25 -28
  711. package/build/src/routes/app-routes.js +12 -14
  712. package/build/src/routes/base-route.js +112 -130
  713. package/build/src/routes/basic-route.js +83 -102
  714. package/build/src/routes/built-in/debug/controller.js +10 -10
  715. package/build/src/routes/built-in/errors/controller.js +5 -5
  716. package/build/src/routes/get-route.js +50 -63
  717. package/build/src/routes/hooks/frontend-model-command-route-hook.js +66 -80
  718. package/build/src/routes/index.js +36 -43
  719. package/build/src/routes/namespace-route.js +38 -47
  720. package/build/src/routes/plugin-routes.js +107 -124
  721. package/build/src/routes/post-route.js +51 -62
  722. package/build/src/routes/resolver.js +422 -494
  723. package/build/src/routes/resource-route.js +124 -143
  724. package/build/src/routes/root-route.js +7 -8
  725. package/build/src/testing/base-expect.js +13 -14
  726. package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +329 -405
  727. package/build/src/testing/browser-test-app.js +23 -29
  728. package/build/src/testing/expect-to-change.js +41 -50
  729. package/build/src/testing/expect-utils.js +139 -184
  730. package/build/src/testing/expect.js +638 -731
  731. package/build/src/testing/request-client.js +70 -85
  732. package/build/src/testing/test-files-finder.js +285 -339
  733. package/build/src/testing/test-filter-parser.js +124 -155
  734. package/build/src/testing/test-runner.js +883 -1020
  735. package/build/src/testing/test-suite-splitter.js +114 -142
  736. package/build/src/testing/test.js +216 -256
  737. package/build/src/utils/backtrace-cleaner-node.js +62 -69
  738. package/build/src/utils/backtrace-cleaner.js +188 -216
  739. package/build/src/utils/ensure-error.js +7 -7
  740. package/build/src/utils/event-emitter.js +4 -6
  741. package/build/src/utils/file-exists.js +9 -10
  742. package/build/src/utils/format-value.js +67 -76
  743. package/build/src/utils/model-scope.js +27 -31
  744. package/build/src/utils/nest-callbacks.js +10 -13
  745. package/build/src/utils/plain-object.js +5 -6
  746. package/build/src/utils/ransack.js +448 -563
  747. package/build/src/utils/rest-args-error.js +5 -6
  748. package/build/src/utils/singularize-model-name.js +9 -11
  749. package/build/src/utils/split-sql-statements.js +68 -79
  750. package/build/src/utils/to-import-specifier.js +24 -30
  751. package/build/src/utils/with-tracked-stack-async-hooks.js +60 -74
  752. package/build/src/utils/with-tracked-stack.js +14 -18
  753. package/build/src/velocious-error.js +27 -30
  754. package/build/templates/configuration.js +61 -0
  755. package/build/templates/generate-migration.js +11 -0
  756. package/build/templates/generate-model.js +6 -0
  757. package/build/templates/routes.js +11 -0
  758. package/build/testing/base-expect.js +17 -0
  759. package/build/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
  760. package/build/testing/browser-test-app.js +32 -0
  761. package/build/testing/expect-to-change.js +55 -0
  762. package/build/testing/expect-utils.js +269 -0
  763. package/build/testing/expect.js +763 -0
  764. package/build/testing/request-client.js +90 -0
  765. package/build/testing/test-files-finder.js +364 -0
  766. package/build/testing/test-filter-parser.js +198 -0
  767. package/build/testing/test-runner.js +1168 -0
  768. package/build/testing/test-suite-splitter.js +177 -0
  769. package/build/testing/test.js +370 -0
  770. package/build/utils/backtrace-cleaner-node.js +87 -0
  771. package/build/utils/backtrace-cleaner.js +266 -0
  772. package/build/utils/ensure-error.js +15 -0
  773. package/build/utils/event-emitter.js +8 -0
  774. package/build/utils/file-exists.js +18 -0
  775. package/build/utils/format-value.js +101 -0
  776. package/build/utils/model-scope.js +56 -0
  777. package/build/utils/nest-callbacks.js +22 -0
  778. package/build/utils/plain-object.js +14 -0
  779. package/build/utils/ransack.js +859 -0
  780. package/build/utils/rest-args-error.js +14 -0
  781. package/build/utils/singularize-model-name.js +18 -0
  782. package/build/utils/split-sql-statements.js +88 -0
  783. package/build/utils/to-import-specifier.js +53 -0
  784. package/build/utils/with-tracked-stack-async-hooks.js +103 -0
  785. package/build/utils/with-tracked-stack.js +38 -0
  786. package/build/velocious-error.js +34 -0
  787. package/package.json +3 -3
  788. package/src/configuration-types.js +1 -1
  789. package/src/database/record/index.js +174 -25
  790. package/src/environment-handlers/node/cli/commands/generate/base-models.js +50 -21
  791. package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +5 -5
  792. package/src/frontend-model-resource/base-resource.js +6 -2
  793. package/src/frontend-models/resource-definition.js +3 -3
  794. package/src/frontend-models/websocket-publishers.js +6 -6
@@ -1,591 +1,519 @@
1
1
  // @ts-check
2
-
3
- import UUID from "pure-uuid"
4
- import TableData from "../../table-data/index.js"
5
- import normalizeRecordAttachmentInput from "./normalize-input.js"
6
-
7
- const ATTACHMENTS_TABLE = "velocious_attachments"
8
-
2
+ import UUID from "pure-uuid";
3
+ import TableData from "../../table-data/index.js";
4
+ import normalizeRecordAttachmentInput from "./normalize-input.js";
5
+ const ATTACHMENTS_TABLE = "velocious_attachments";
9
6
  /**
10
7
  * AttachmentDriverConstructor type.
11
8
  @typedef {import("../../../configuration-types.js").AttachmentDriverConstructor} AttachmentDriverConstructor */
12
9
  /**
13
10
  * Stores by configuration.
14
11
  @type {WeakMap<import("../../../configuration.js").default, Map<string, RecordAttachmentsStore>>} */
15
- const storesByConfiguration = new WeakMap()
16
-
12
+ const storesByConfiguration = new WeakMap();
17
13
  /**
18
14
  * Runs generate uuid.
19
15
  * @returns {string} - Generated UUID v4 value.
20
16
  */
21
17
  function generateUUID() {
22
- return new UUID(4).format()
18
+ return new UUID(4).format();
23
19
  }
24
-
25
20
  /**
26
21
  * Runs store key for model.
27
22
  * @param {import("../index.js").default} model - Model instance.
28
23
  * @returns {string} - Store key.
29
24
  */
30
25
  function storeKeyForModel(model) {
31
- return `${model.getModelClass().getDatabaseIdentifier()}`
26
+ return `${model.getModelClass().getDatabaseIdentifier()}`;
32
27
  }
33
-
34
28
  /**
35
29
  * Runs the recordAttachmentsStoreForModel helper.
36
30
  * @param {import("../index.js").default} model - Model instance.
37
31
  * @returns {RecordAttachmentsStore} - Store instance.
38
32
  */
39
33
  export function recordAttachmentsStoreForModel(model) {
40
- const configuration = model._getConfiguration()
41
- let storesByDatabaseIdentifier = storesByConfiguration.get(configuration)
42
-
43
- if (!storesByDatabaseIdentifier) {
44
- storesByDatabaseIdentifier = new Map()
45
- storesByConfiguration.set(configuration, storesByDatabaseIdentifier)
46
- }
47
-
48
- const key = storeKeyForModel(model)
49
- let store = storesByDatabaseIdentifier.get(key)
50
-
51
- if (store) return store
52
-
53
- store = new RecordAttachmentsStore({
54
- configuration,
55
- databaseIdentifier: model.getModelClass().getDatabaseIdentifier()
56
- })
57
-
58
- storesByDatabaseIdentifier.set(key, store)
59
-
60
- return store
34
+ const configuration = model._getConfiguration();
35
+ let storesByDatabaseIdentifier = storesByConfiguration.get(configuration);
36
+ if (!storesByDatabaseIdentifier) {
37
+ storesByDatabaseIdentifier = new Map();
38
+ storesByConfiguration.set(configuration, storesByDatabaseIdentifier);
39
+ }
40
+ const key = storeKeyForModel(model);
41
+ let store = storesByDatabaseIdentifier.get(key);
42
+ if (store)
43
+ return store;
44
+ store = new RecordAttachmentsStore({
45
+ configuration,
46
+ databaseIdentifier: model.getModelClass().getDatabaseIdentifier()
47
+ });
48
+ storesByDatabaseIdentifier.set(key, store);
49
+ return store;
61
50
  }
62
-
63
51
  /**
64
52
  * Attachment persistence store.
65
53
  */
66
54
  export default class RecordAttachmentsStore {
67
- /**
68
- * Runs constructor.
69
- * @param {object} args - Options.
70
- * @param {import("../../../configuration.js").default} args.configuration - Configuration instance.
71
- * @param {string} args.databaseIdentifier - Database identifier.
72
- */
73
- constructor({configuration, databaseIdentifier}) {
74
- this.configuration = configuration
75
- this.databaseIdentifier = databaseIdentifier
76
- this._readyPromise = null
77
- this._driverColumnsAvailable = false
78
- this._contentBase64Nullable = true
79
- /**
80
- * Narrows the runtime value to the documented type.
81
- @type {Map<string, Record<string, ?>>} */
82
- this._attachmentDriversByName = new Map()
83
55
  /**
84
- * Narrows the runtime value to the documented type.
85
- @type {Map<AttachmentDriverConstructor | Record<string, ?>, Record<string, ?>>} */
86
- this._attachmentDriversByReference = new Map()
87
- }
88
-
89
- /**
90
- * Runs ensure ready.
91
- * @returns {Promise<void>} - Resolves when schema is ready.
92
- */
93
- async ensureReady() {
94
- if (this._readyPromise) {
95
- await this._readyPromise
96
- return
56
+ * Runs constructor.
57
+ * @param {object} args - Options.
58
+ * @param {import("../../../configuration.js").default} args.configuration - Configuration instance.
59
+ * @param {string} args.databaseIdentifier - Database identifier.
60
+ */
61
+ constructor({ configuration, databaseIdentifier }) {
62
+ this.configuration = configuration;
63
+ this.databaseIdentifier = databaseIdentifier;
64
+ this._readyPromise = null;
65
+ this._driverColumnsAvailable = false;
66
+ this._contentBase64Nullable = true;
67
+ /**
68
+ * Narrows the runtime value to the documented type.
69
+ @type {Map<string, Record<string, ?>>} */
70
+ this._attachmentDriversByName = new Map();
71
+ /**
72
+ * Narrows the runtime value to the documented type.
73
+ @type {Map<AttachmentDriverConstructor | Record<string, ?>, Record<string, ?>>} */
74
+ this._attachmentDriversByReference = new Map();
97
75
  }
98
-
99
- this._readyPromise = (async () => {
100
- await this._withDb(async (db) => {
101
- if (await db.tableExists(ATTACHMENTS_TABLE)) {
102
- await this.ensureAttachmentStoreSchema({db})
103
- return
76
+ /**
77
+ * Runs ensure ready.
78
+ * @returns {Promise<void>} - Resolves when schema is ready.
79
+ */
80
+ async ensureReady() {
81
+ if (this._readyPromise) {
82
+ await this._readyPromise;
83
+ return;
104
84
  }
105
-
106
- const table = new TableData(ATTACHMENTS_TABLE, {ifNotExists: true})
107
-
108
- table.string("id", {null: false, primaryKey: true})
109
- table.string("record_type", {null: false, index: true})
110
- table.string("record_id", {null: false, index: true})
111
- table.string("name", {null: false, index: true})
112
- table.integer("position", {null: false})
113
- table.string("filename", {null: false})
114
- table.string("content_type", {null: true})
115
- table.bigint("byte_size", {null: false})
116
- table.string("driver", {null: true})
117
- table.string("storage_key", {null: true})
118
- table.text("content_base64", {null: true})
119
- table.bigint("created_at_ms", {null: false})
120
- table.bigint("updated_at_ms", {null: false})
121
-
122
- await db.createTable(table)
123
- this._driverColumnsAvailable = true
124
- this._contentBase64Nullable = true
125
- })
126
- })()
127
-
128
- try {
129
- await this._readyPromise
130
- } finally {
131
- this._readyPromise = null
132
- }
133
- }
134
-
135
- /**
136
- * Runs attach.
137
- * @param {object} args - Options.
138
- * @param {import("../index.js").default} args.model - Model instance.
139
- * @param {string} args.name - Attachment name.
140
- * @param {?} args.input - Attachment input.
141
- * @param {boolean} args.replace - Whether to replace existing attachments.
142
- * @returns {Promise<void>} - Resolves when complete.
143
- */
144
- async attach({input, model, name, replace}) {
145
- await this.ensureReady()
146
- const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {}
147
- const allowPathInput = attachmentsConfiguration.allowPathInput === true
148
- const allowedPathPrefixes = Array.isArray(attachmentsConfiguration.allowedPathPrefixes)
149
- ? attachmentsConfiguration.allowedPathPrefixes
150
- : undefined
151
-
152
- const normalizedInput = await normalizeRecordAttachmentInput(input, {
153
- allowPathInput,
154
- allowedPathPrefixes,
155
- environmentHandler: this.configuration.getEnvironmentHandler()
156
- })
157
- const attachmentDriver = await this.resolveAttachmentDriver({model, name})
158
- const attachmentDriverName = this._attachmentDriverNameFor({model, name})
159
- const now = Date.now()
160
- const recordType = model.getModelClass().getModelName()
161
- const recordId = String(model.id())
162
- const attachmentId = generateUUID()
163
- const {storageKey} = await attachmentDriver.write({
164
- attachmentId,
165
- input: normalizedInput,
166
- model,
167
- name
168
- })
169
-
170
- await this._withDb(async (db) => {
171
- if (replace) {
172
- const existingRows = await db
173
- .newQuery()
174
- .from(ATTACHMENTS_TABLE)
175
- .where({name, record_id: recordId, record_type: recordType})
176
- .results()
177
-
178
- for (const existingRow of existingRows) {
179
- await this.deleteAttachmentRowStorage({model, name, row: existingRow})
85
+ this._readyPromise = (async () => {
86
+ await this._withDb(async (db) => {
87
+ if (await db.tableExists(ATTACHMENTS_TABLE)) {
88
+ await this.ensureAttachmentStoreSchema({ db });
89
+ return;
90
+ }
91
+ const table = new TableData(ATTACHMENTS_TABLE, { ifNotExists: true });
92
+ table.string("id", { null: false, primaryKey: true });
93
+ table.string("record_type", { null: false, index: true });
94
+ table.string("record_id", { null: false, index: true });
95
+ table.string("name", { null: false, index: true });
96
+ table.integer("position", { null: false });
97
+ table.string("filename", { null: false });
98
+ table.string("content_type", { null: true });
99
+ table.bigint("byte_size", { null: false });
100
+ table.string("driver", { null: true });
101
+ table.string("storage_key", { null: true });
102
+ table.text("content_base64", { null: true });
103
+ table.bigint("created_at_ms", { null: false });
104
+ table.bigint("updated_at_ms", { null: false });
105
+ await db.createTable(table);
106
+ this._driverColumnsAvailable = true;
107
+ this._contentBase64Nullable = true;
108
+ });
109
+ })();
110
+ try {
111
+ await this._readyPromise;
112
+ }
113
+ finally {
114
+ this._readyPromise = null;
180
115
  }
181
-
182
- await db.delete({
183
- conditions: {name, record_id: recordId, record_type: recordType},
184
- tableName: ATTACHMENTS_TABLE
185
- })
186
- }
187
-
188
- const position = replace ? 0 : await this._nextPosition({db, name, recordId, recordType})
189
- /**
190
- * Insert data.
191
- @type {Record<string, ?>} */
192
- const insertData = {
193
- byte_size: normalizedInput.byteSize,
194
- content_base64: this._contentBase64Nullable ? null : normalizedInput.contentBase64,
195
- content_type: normalizedInput.contentType,
196
- created_at_ms: now,
197
- filename: normalizedInput.filename,
198
- id: attachmentId,
199
- name,
200
- position,
201
- record_id: recordId,
202
- record_type: recordType,
203
- updated_at_ms: now
204
- }
205
-
206
- if (this._driverColumnsAvailable) {
207
- insertData.driver = attachmentDriverName
208
- insertData.storage_key = storageKey
209
- }
210
-
211
- await db.insert({
212
- data: insertData,
213
- tableName: ATTACHMENTS_TABLE
214
- })
215
- })
216
- }
217
-
218
- /**
219
- * Runs ensure attachment store schema.
220
- * @param {object} args - Options.
221
- * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
222
- * @returns {Promise<void>} - Resolves when schema columns are ensured.
223
- */
224
- async ensureAttachmentStoreSchema({db}) {
225
- const table = await db.getTableByNameOrFail(ATTACHMENTS_TABLE)
226
- const columns = await table.getColumns()
227
- const hasDriverColumn = columns.some((column) => column.getName() === "driver")
228
- const hasStorageKeyColumn = columns.some((column) => column.getName() === "storage_key")
229
- const contentBase64Column = columns.find((column) => column.getName() === "content_base64")
230
- const alterTable = new TableData(ATTACHMENTS_TABLE)
231
- let shouldAlter = false
232
-
233
- if (!hasDriverColumn) {
234
- alterTable.string("driver", {null: true})
235
- shouldAlter = true
236
- }
237
-
238
- if (!hasStorageKeyColumn) {
239
- alterTable.string("storage_key", {null: true})
240
- shouldAlter = true
241
- }
242
-
243
- if (shouldAlter) {
244
- const alterTableSQLs = await db.alterTableSQLs(alterTable)
245
-
246
- for (const sql of alterTableSQLs) {
247
- await db.query(sql)
248
- }
249
- }
250
-
251
- this._driverColumnsAvailable = true
252
- this._contentBase64Nullable = contentBase64Column ? contentBase64Column.getNull() : true
253
- }
254
-
255
- /**
256
- * Runs read attachment row.
257
- * @param {object} args - Options.
258
- * @param {import("../index.js").default} args.model - Model instance.
259
- * @param {string} args.name - Attachment name.
260
- * @param {Record<string, ?>} args.row - Attachment row.
261
- * @returns {Promise<Buffer>} - Attachment bytes.
262
- */
263
- async readAttachmentRow({model, name, row}) {
264
- if (typeof row.content_base64 === "string" && row.content_base64.length > 0) {
265
- return Buffer.from(row.content_base64, "base64")
266
116
  }
267
-
268
- const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null
269
-
270
- if (!storageKey) {
271
- throw new Error(`Attachment row ${String(row.id)} is missing storage key`)
117
+ /**
118
+ * Runs attach.
119
+ * @param {object} args - Options.
120
+ * @param {import("../index.js").default} args.model - Model instance.
121
+ * @param {string} args.name - Attachment name.
122
+ * @param {?} args.input - Attachment input.
123
+ * @param {boolean} args.replace - Whether to replace existing attachments.
124
+ * @returns {Promise<void>} - Resolves when complete.
125
+ */
126
+ async attach({ input, model, name, replace }) {
127
+ await this.ensureReady();
128
+ const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {};
129
+ const allowPathInput = attachmentsConfiguration.allowPathInput === true;
130
+ const allowedPathPrefixes = Array.isArray(attachmentsConfiguration.allowedPathPrefixes)
131
+ ? attachmentsConfiguration.allowedPathPrefixes
132
+ : undefined;
133
+ const normalizedInput = await normalizeRecordAttachmentInput(input, {
134
+ allowPathInput,
135
+ allowedPathPrefixes,
136
+ environmentHandler: this.configuration.getEnvironmentHandler()
137
+ });
138
+ const attachmentDriver = await this.resolveAttachmentDriver({ model, name });
139
+ const attachmentDriverName = this._attachmentDriverNameFor({ model, name });
140
+ const now = Date.now();
141
+ const recordType = model.getModelClass().getModelName();
142
+ const recordId = String(model.id());
143
+ const attachmentId = generateUUID();
144
+ const { storageKey } = await attachmentDriver.write({
145
+ attachmentId,
146
+ input: normalizedInput,
147
+ model,
148
+ name
149
+ });
150
+ await this._withDb(async (db) => {
151
+ if (replace) {
152
+ const existingRows = await db
153
+ .newQuery()
154
+ .from(ATTACHMENTS_TABLE)
155
+ .where({ name, record_id: recordId, record_type: recordType })
156
+ .results();
157
+ for (const existingRow of existingRows) {
158
+ await this.deleteAttachmentRowStorage({ model, name, row: existingRow });
159
+ }
160
+ await db.delete({
161
+ conditions: { name, record_id: recordId, record_type: recordType },
162
+ tableName: ATTACHMENTS_TABLE
163
+ });
164
+ }
165
+ const position = replace ? 0 : await this._nextPosition({ db, name, recordId, recordType });
166
+ /**
167
+ * Insert data.
168
+ @type {Record<string, ?>} */
169
+ const insertData = {
170
+ byte_size: normalizedInput.byteSize,
171
+ content_base64: this._contentBase64Nullable ? null : normalizedInput.contentBase64,
172
+ content_type: normalizedInput.contentType,
173
+ created_at_ms: now,
174
+ filename: normalizedInput.filename,
175
+ id: attachmentId,
176
+ name,
177
+ position,
178
+ record_id: recordId,
179
+ record_type: recordType,
180
+ updated_at_ms: now
181
+ };
182
+ if (this._driverColumnsAvailable) {
183
+ insertData.driver = attachmentDriverName;
184
+ insertData.storage_key = storageKey;
185
+ }
186
+ await db.insert({
187
+ data: insertData,
188
+ tableName: ATTACHMENTS_TABLE
189
+ });
190
+ });
272
191
  }
273
-
274
- const attachmentDriver = await this.resolveAttachmentDriver({model, name, row})
275
-
276
- return await attachmentDriver.read({
277
- model,
278
- name,
279
- row,
280
- storageKey
281
- })
282
- }
283
-
284
- /**
285
- * Runs attachment row url.
286
- * @param {object} args - Options.
287
- * @param {import("../index.js").default} args.model - Model instance.
288
- * @param {string} args.name - Attachment name.
289
- * @param {Record<string, ?>} args.row - Attachment row.
290
- * @returns {Promise<string | null>} - Attachment URL.
291
- */
292
- async attachmentRowUrl({model, name, row}) {
293
- const attachmentDriver = await this.resolveAttachmentDriver({model, name, row})
294
-
295
- if (typeof attachmentDriver.url !== "function") return null
296
-
297
- const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0
298
- ? row.storage_key
299
- : (typeof row.id === "string" ? row.id : "")
300
-
301
- if (!storageKey) return null
302
-
303
- return await attachmentDriver.url({
304
- model,
305
- name,
306
- row,
307
- storageKey
308
- })
309
- }
310
-
311
- /**
312
- * Runs find one.
313
- * @param {object} args - Options.
314
- * @param {import("../index.js").default} args.model - Model instance.
315
- * @param {string} args.name - Attachment name.
316
- * @param {string} [args.id] - Optional attachment id.
317
- * @returns {Promise<Record<string, ?> | null>} - Attachment row.
318
- */
319
- async findOne({id, model, name}) {
320
- await this.ensureReady()
321
-
322
- return await this._withDb(async (db) => {
323
- const recordType = model.getModelClass().getModelName()
324
- const recordId = String(model.id())
325
- let query = db
326
- .newQuery()
327
- .from(ATTACHMENTS_TABLE)
328
- .where({name, record_id: recordId, record_type: recordType})
329
- .order("position ASC")
330
- .order("created_at_ms DESC")
331
- .limit(1)
332
-
333
- if (id) {
334
- query = query.where({id})
335
- }
336
-
337
- const rows = await query.results()
338
-
339
- return rows[0] || null
340
- })
341
- }
342
-
343
- /**
344
- * Runs find many.
345
- * @param {object} args - Options.
346
- * @param {import("../index.js").default} args.model - Model instance.
347
- * @param {string} args.name - Attachment name.
348
- * @returns {Promise<Array<Record<string, ?>>>} - Attachment rows.
349
- */
350
- async findMany({model, name}) {
351
- await this.ensureReady()
352
-
353
- return await this._withDb(async (db) => {
354
- const recordType = model.getModelClass().getModelName()
355
- const recordId = String(model.id())
356
- const query = db
357
- .newQuery()
358
- .from(ATTACHMENTS_TABLE)
359
- .where({name, record_id: recordId, record_type: recordType})
360
- .order("position ASC")
361
- .order("created_at_ms ASC")
362
-
363
- return await query.results()
364
- })
365
- }
366
-
367
- /**
368
- * Runs delete attachment row storage.
369
- * @param {object} args - Options.
370
- * @param {import("../index.js").default} args.model - Model instance.
371
- * @param {string} args.name - Attachment name.
372
- * @param {Record<string, ?>} args.row - Attachment row.
373
- * @returns {Promise<void>} - Resolves when row storage has been deleted.
374
- */
375
- async deleteAttachmentRowStorage({model, name, row}) {
376
- const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null
377
-
378
- if (!storageKey) return
379
-
380
- const attachmentDriver = await this.resolveAttachmentDriver({model, name, row})
381
-
382
- if (typeof attachmentDriver.delete !== "function") return
383
-
384
- await attachmentDriver.delete({
385
- model,
386
- name,
387
- row,
388
- storageKey
389
- })
390
- }
391
-
392
- /**
393
- * Runs attachment driver by name.
394
- * @param {string} driverName - Driver name.
395
- * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
396
- */
397
- async attachmentDriverByName(driverName) {
398
- if (this._attachmentDriversByName.has(driverName)) {
399
- return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByName.get(driverName))
192
+ /**
193
+ * Runs ensure attachment store schema.
194
+ * @param {object} args - Options.
195
+ * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
196
+ * @returns {Promise<void>} - Resolves when schema columns are ensured.
197
+ */
198
+ async ensureAttachmentStoreSchema({ db }) {
199
+ const table = await db.getTableByNameOrFail(ATTACHMENTS_TABLE);
200
+ const columns = await table.getColumns();
201
+ const hasDriverColumn = columns.some((column) => column.getName() === "driver");
202
+ const hasStorageKeyColumn = columns.some((column) => column.getName() === "storage_key");
203
+ const contentBase64Column = columns.find((column) => column.getName() === "content_base64");
204
+ const alterTable = new TableData(ATTACHMENTS_TABLE);
205
+ let shouldAlter = false;
206
+ if (!hasDriverColumn) {
207
+ alterTable.string("driver", { null: true });
208
+ shouldAlter = true;
209
+ }
210
+ if (!hasStorageKeyColumn) {
211
+ alterTable.string("storage_key", { null: true });
212
+ shouldAlter = true;
213
+ }
214
+ if (shouldAlter) {
215
+ const alterTableSQLs = await db.alterTableSQLs(alterTable);
216
+ for (const sql of alterTableSQLs) {
217
+ await db.query(sql);
218
+ }
219
+ }
220
+ this._driverColumnsAvailable = true;
221
+ this._contentBase64Nullable = contentBase64Column ? contentBase64Column.getNull() : true;
400
222
  }
401
-
402
- const attachmentConfiguration = this.configuration.getAttachmentsConfiguration?.() || {}
403
- const configuredDriver = attachmentConfiguration.drivers?.[driverName]
404
223
  /**
405
- * Defines attachmentDriver.
406
- @type {Record<string, ?>} */
407
- let attachmentDriver
408
-
409
- if (!configuredDriver) {
410
- throw new Error(`No configured attachment storage driver named "${driverName}"`)
411
- } else if (configuredDriver.instance && typeof configuredDriver.instance === "object") {
412
- attachmentDriver = configuredDriver.instance
413
- } else if (typeof configuredDriver.driverClass === "function") {
414
- attachmentDriver = new configuredDriver.driverClass({
415
- configuration: this.configuration,
416
- name: driverName,
417
- options: configuredDriver
418
- })
419
- } else if (typeof configuredDriver.create === "function") {
420
- attachmentDriver = configuredDriver.create({
421
- configuration: this.configuration,
422
- name: driverName,
423
- options: configuredDriver
424
- })
425
- } else {
426
- throw new Error(`Attachment storage driver "${driverName}" must define instance, driverClass, or create`)
224
+ * Runs read attachment row.
225
+ * @param {object} args - Options.
226
+ * @param {import("../index.js").default} args.model - Model instance.
227
+ * @param {string} args.name - Attachment name.
228
+ * @param {Record<string, ?>} args.row - Attachment row.
229
+ * @returns {Promise<Buffer>} - Attachment bytes.
230
+ */
231
+ async readAttachmentRow({ model, name, row }) {
232
+ if (typeof row.content_base64 === "string" && row.content_base64.length > 0) {
233
+ return Buffer.from(row.content_base64, "base64");
234
+ }
235
+ const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null;
236
+ if (!storageKey) {
237
+ throw new Error(`Attachment row ${String(row.id)} is missing storage key`);
238
+ }
239
+ const attachmentDriver = await this.resolveAttachmentDriver({ model, name, row });
240
+ return await attachmentDriver.read({
241
+ model,
242
+ name,
243
+ row,
244
+ storageKey
245
+ });
427
246
  }
428
-
429
- if (!attachmentDriver || typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
430
- throw new Error(`Attachment storage driver "${driverName}" must implement write/read`)
247
+ /**
248
+ * Runs attachment row url.
249
+ * @param {object} args - Options.
250
+ * @param {import("../index.js").default} args.model - Model instance.
251
+ * @param {string} args.name - Attachment name.
252
+ * @param {Record<string, ?>} args.row - Attachment row.
253
+ * @returns {Promise<string | null>} - Attachment URL.
254
+ */
255
+ async attachmentRowUrl({ model, name, row }) {
256
+ const attachmentDriver = await this.resolveAttachmentDriver({ model, name, row });
257
+ if (typeof attachmentDriver.url !== "function")
258
+ return null;
259
+ const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0
260
+ ? row.storage_key
261
+ : (typeof row.id === "string" ? row.id : "");
262
+ if (!storageKey)
263
+ return null;
264
+ return await attachmentDriver.url({
265
+ model,
266
+ name,
267
+ row,
268
+ storageKey
269
+ });
431
270
  }
432
-
433
- this._attachmentDriversByName.set(driverName, attachmentDriver)
434
-
435
- return attachmentDriver
436
- }
437
-
438
- /**
439
- * Runs attachment driver by reference.
440
- * @param {object} args - Options.
441
- * @param {AttachmentDriverConstructor | Record<string, ?>} args.driverReference - Driver class or instance.
442
- * @param {string} args.attachmentName - Attachment name.
443
- * @param {typeof import("../index.js").default} args.modelClass - Model class.
444
- * @returns {Record<string, ?>} - Attachment driver instance.
445
- */
446
- attachmentDriverByReference({attachmentName, driverReference, modelClass}) {
447
- if (this._attachmentDriversByReference.has(driverReference)) {
448
- return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByReference.get(driverReference))
271
+ /**
272
+ * Runs find one.
273
+ * @param {object} args - Options.
274
+ * @param {import("../index.js").default} args.model - Model instance.
275
+ * @param {string} args.name - Attachment name.
276
+ * @param {string} [args.id] - Optional attachment id.
277
+ * @returns {Promise<Record<string, ?> | null>} - Attachment row.
278
+ */
279
+ async findOne({ id, model, name }) {
280
+ await this.ensureReady();
281
+ return await this._withDb(async (db) => {
282
+ const recordType = model.getModelClass().getModelName();
283
+ const recordId = String(model.id());
284
+ let query = db
285
+ .newQuery()
286
+ .from(ATTACHMENTS_TABLE)
287
+ .where({ name, record_id: recordId, record_type: recordType })
288
+ .order("position ASC")
289
+ .order("created_at_ms DESC")
290
+ .limit(1);
291
+ if (id) {
292
+ query = query.where({ id });
293
+ }
294
+ const rows = await query.results();
295
+ return rows[0] || null;
296
+ });
449
297
  }
450
-
451
298
  /**
452
- * Defines attachmentDriver.
453
- @type {Record<string, ?>} */
454
- let attachmentDriver
455
-
456
- if (typeof driverReference === "function") {
457
- const DriverClass = /**
458
- * Narrows the runtime value to the documented type.
459
- @type {AttachmentDriverConstructor} */ (driverReference)
460
-
461
- attachmentDriver = new DriverClass({
462
- attachmentName,
463
- configuration: this.configuration,
464
- modelClass
465
- })
466
- } else if (driverReference && typeof driverReference === "object") {
467
- attachmentDriver = driverReference
468
- } else {
469
- throw new Error(`Invalid attachment driver reference for ${modelClass.name}#${attachmentName}`)
299
+ * Runs find many.
300
+ * @param {object} args - Options.
301
+ * @param {import("../index.js").default} args.model - Model instance.
302
+ * @param {string} args.name - Attachment name.
303
+ * @returns {Promise<Array<Record<string, ?>>>} - Attachment rows.
304
+ */
305
+ async findMany({ model, name }) {
306
+ await this.ensureReady();
307
+ return await this._withDb(async (db) => {
308
+ const recordType = model.getModelClass().getModelName();
309
+ const recordId = String(model.id());
310
+ const query = db
311
+ .newQuery()
312
+ .from(ATTACHMENTS_TABLE)
313
+ .where({ name, record_id: recordId, record_type: recordType })
314
+ .order("position ASC")
315
+ .order("created_at_ms ASC");
316
+ return await query.results();
317
+ });
470
318
  }
471
-
472
- if (typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
473
- throw new Error(`Attachment driver for ${modelClass.name}#${attachmentName} must implement write/read`)
319
+ /**
320
+ * Runs delete attachment row storage.
321
+ * @param {object} args - Options.
322
+ * @param {import("../index.js").default} args.model - Model instance.
323
+ * @param {string} args.name - Attachment name.
324
+ * @param {Record<string, ?>} args.row - Attachment row.
325
+ * @returns {Promise<void>} - Resolves when row storage has been deleted.
326
+ */
327
+ async deleteAttachmentRowStorage({ model, name, row }) {
328
+ const storageKey = typeof row.storage_key === "string" && row.storage_key.length > 0 ? row.storage_key : null;
329
+ if (!storageKey)
330
+ return;
331
+ const attachmentDriver = await this.resolveAttachmentDriver({ model, name, row });
332
+ if (typeof attachmentDriver.delete !== "function")
333
+ return;
334
+ await attachmentDriver.delete({
335
+ model,
336
+ name,
337
+ row,
338
+ storageKey
339
+ });
474
340
  }
475
-
476
- this._attachmentDriversByReference.set(driverReference, attachmentDriver)
477
-
478
- return attachmentDriver
479
- }
480
-
481
- /**
482
- * Runs attachment driver name for.
483
- * @param {object} args - Options.
484
- * @param {import("../index.js").default} args.model - Model instance.
485
- * @param {string} args.name - Attachment name.
486
- * @returns {string} - Attachment driver name.
487
- */
488
- _attachmentDriverNameFor({model, name}) {
489
- const attachmentDefinition = model.getModelClass().getAttachmentByName(name)
490
- const configuredDriver = attachmentDefinition.driver
491
- const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {}
492
- const defaultDriver = attachmentsConfiguration.defaultDriver
493
-
494
- if (typeof configuredDriver === "string" && configuredDriver.length > 0) {
495
- return configuredDriver
341
+ /**
342
+ * Runs attachment driver by name.
343
+ * @param {string} driverName - Driver name.
344
+ * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
345
+ */
346
+ async attachmentDriverByName(driverName) {
347
+ if (this._attachmentDriversByName.has(driverName)) {
348
+ return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByName.get(driverName));
349
+ }
350
+ const attachmentConfiguration = this.configuration.getAttachmentsConfiguration?.() || {};
351
+ const configuredDriver = attachmentConfiguration.drivers?.[driverName];
352
+ /**
353
+ * Defines attachmentDriver.
354
+ @type {Record<string, ?>} */
355
+ let attachmentDriver;
356
+ if (!configuredDriver) {
357
+ throw new Error(`No configured attachment storage driver named "${driverName}"`);
358
+ }
359
+ else if (configuredDriver.instance && typeof configuredDriver.instance === "object") {
360
+ attachmentDriver = configuredDriver.instance;
361
+ }
362
+ else if (typeof configuredDriver.driverClass === "function") {
363
+ attachmentDriver = new configuredDriver.driverClass({
364
+ configuration: this.configuration,
365
+ name: driverName,
366
+ options: configuredDriver
367
+ });
368
+ }
369
+ else if (typeof configuredDriver.create === "function") {
370
+ attachmentDriver = configuredDriver.create({
371
+ configuration: this.configuration,
372
+ name: driverName,
373
+ options: configuredDriver
374
+ });
375
+ }
376
+ else {
377
+ throw new Error(`Attachment storage driver "${driverName}" must define instance, driverClass, or create`);
378
+ }
379
+ if (!attachmentDriver || typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
380
+ throw new Error(`Attachment storage driver "${driverName}" must implement write/read`);
381
+ }
382
+ this._attachmentDriversByName.set(driverName, attachmentDriver);
383
+ return attachmentDriver;
496
384
  }
497
-
498
- if (typeof configuredDriver === "function") {
499
- return configuredDriver.name || "custom"
385
+ /**
386
+ * Runs attachment driver by reference.
387
+ * @param {object} args - Options.
388
+ * @param {AttachmentDriverConstructor | Record<string, ?>} args.driverReference - Driver class or instance.
389
+ * @param {string} args.attachmentName - Attachment name.
390
+ * @param {typeof import("../index.js").default} args.modelClass - Model class.
391
+ * @returns {Record<string, ?>} - Attachment driver instance.
392
+ */
393
+ attachmentDriverByReference({ attachmentName, driverReference, modelClass }) {
394
+ if (this._attachmentDriversByReference.has(driverReference)) {
395
+ return /** Narrows the runtime value to the documented type. @type {Record<string, ?>} */ (this._attachmentDriversByReference.get(driverReference));
396
+ }
397
+ /**
398
+ * Defines attachmentDriver.
399
+ @type {Record<string, ?>} */
400
+ let attachmentDriver;
401
+ if (typeof driverReference === "function") {
402
+ const DriverClass = /**
403
+ * Narrows the runtime value to the documented type.
404
+ @type {AttachmentDriverConstructor} */ (driverReference);
405
+ attachmentDriver = new DriverClass({
406
+ attachmentName,
407
+ configuration: this.configuration,
408
+ modelClass
409
+ });
410
+ }
411
+ else if (driverReference && typeof driverReference === "object") {
412
+ attachmentDriver = driverReference;
413
+ }
414
+ else {
415
+ throw new Error(`Invalid attachment driver reference for ${modelClass.name}#${attachmentName}`);
416
+ }
417
+ if (typeof attachmentDriver.write !== "function" || typeof attachmentDriver.read !== "function") {
418
+ throw new Error(`Attachment driver for ${modelClass.name}#${attachmentName} must implement write/read`);
419
+ }
420
+ this._attachmentDriversByReference.set(driverReference, attachmentDriver);
421
+ return attachmentDriver;
500
422
  }
501
-
502
- if (configuredDriver && typeof configuredDriver === "object") {
503
- const constructorName = configuredDriver.constructor?.name
504
-
505
- if (typeof constructorName === "string" && constructorName.length > 0 && constructorName !== "Object") {
506
- return constructorName
507
- }
508
-
509
- return "custom"
423
+ /**
424
+ * Runs attachment driver name for.
425
+ * @param {object} args - Options.
426
+ * @param {import("../index.js").default} args.model - Model instance.
427
+ * @param {string} args.name - Attachment name.
428
+ * @returns {string} - Attachment driver name.
429
+ */
430
+ _attachmentDriverNameFor({ model, name }) {
431
+ const attachmentDefinition = model.getModelClass().getAttachmentByName(name);
432
+ const configuredDriver = attachmentDefinition.driver;
433
+ const attachmentsConfiguration = this.configuration.getAttachmentsConfiguration?.() || {};
434
+ const defaultDriver = attachmentsConfiguration.defaultDriver;
435
+ if (typeof configuredDriver === "string" && configuredDriver.length > 0) {
436
+ return configuredDriver;
437
+ }
438
+ if (typeof configuredDriver === "function") {
439
+ return configuredDriver.name || "custom";
440
+ }
441
+ if (configuredDriver && typeof configuredDriver === "object") {
442
+ const constructorName = configuredDriver.constructor?.name;
443
+ if (typeof constructorName === "string" && constructorName.length > 0 && constructorName !== "Object") {
444
+ return constructorName;
445
+ }
446
+ return "custom";
447
+ }
448
+ if (typeof defaultDriver === "string" && defaultDriver.length > 0) {
449
+ return defaultDriver;
450
+ }
451
+ throw new Error(`No attachment driver configured for ${model.getModelClass().name}#${name}`);
510
452
  }
511
-
512
- if (typeof defaultDriver === "string" && defaultDriver.length > 0) {
513
- return defaultDriver
453
+ /**
454
+ * Runs resolve attachment driver.
455
+ * @param {object} args - Options.
456
+ * @param {import("../index.js").default} args.model - Model instance.
457
+ * @param {string} args.name - Attachment name.
458
+ * @param {Record<string, ?>} [args.row] - Attachment row.
459
+ * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
460
+ */
461
+ async resolveAttachmentDriver({ model, name, row }) {
462
+ const attachmentDefinition = model.getModelClass().getAttachmentByName(name);
463
+ const configuredDriver = attachmentDefinition.driver;
464
+ if (typeof configuredDriver === "function" || (configuredDriver && typeof configuredDriver === "object")) {
465
+ return this.attachmentDriverByReference({
466
+ attachmentName: name,
467
+ driverReference: configuredDriver,
468
+ modelClass: model.getModelClass()
469
+ });
470
+ }
471
+ const fallbackDriverName = typeof row?.driver === "string" && row.driver.length > 0
472
+ ? row.driver
473
+ : this._attachmentDriverNameFor({ model, name });
474
+ return await this.attachmentDriverByName(fallbackDriverName);
514
475
  }
515
-
516
- throw new Error(`No attachment driver configured for ${model.getModelClass().name}#${name}`)
517
- }
518
-
519
- /**
520
- * Runs resolve attachment driver.
521
- * @param {object} args - Options.
522
- * @param {import("../index.js").default} args.model - Model instance.
523
- * @param {string} args.name - Attachment name.
524
- * @param {Record<string, ?>} [args.row] - Attachment row.
525
- * @returns {Promise<Record<string, ?>>} - Attachment storage driver instance.
526
- */
527
- async resolveAttachmentDriver({model, name, row}) {
528
- const attachmentDefinition = model.getModelClass().getAttachmentByName(name)
529
- const configuredDriver = attachmentDefinition.driver
530
- if (typeof configuredDriver === "function" || (configuredDriver && typeof configuredDriver === "object")) {
531
- return this.attachmentDriverByReference({
532
- attachmentName: name,
533
- driverReference: configuredDriver,
534
- modelClass: model.getModelClass()
535
- })
476
+ /**
477
+ * Runs next position.
478
+ * @param {object} args - Options.
479
+ * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
480
+ * @param {string} args.name - Attachment name.
481
+ * @param {string} args.recordId - Record id.
482
+ * @param {string} args.recordType - Record type.
483
+ * @returns {Promise<number>} - Next position.
484
+ */
485
+ async _nextPosition({ db, name, recordId, recordType }) {
486
+ const query = db
487
+ .newQuery()
488
+ .from(ATTACHMENTS_TABLE)
489
+ .where({ name, record_id: recordId, record_type: recordType })
490
+ .order("position DESC")
491
+ .limit(1);
492
+ const rows = await query.results();
493
+ const currentRow = /**
494
+ * Narrows the runtime value to the documented type.
495
+ @type {{position?: string | number | null} | undefined} */ (rows[0]);
496
+ const current = Number(currentRow?.position);
497
+ if (!Number.isFinite(current))
498
+ return 0;
499
+ return current + 1;
536
500
  }
537
-
538
- const fallbackDriverName = typeof row?.driver === "string" && row.driver.length > 0
539
- ? row.driver
540
- : this._attachmentDriverNameFor({model, name})
541
-
542
- return await this.attachmentDriverByName(fallbackDriverName)
543
- }
544
-
545
- /**
546
- * Runs next position.
547
- * @param {object} args - Options.
548
- * @param {import("../../../database/drivers/base.js").default} args.db - DB connection.
549
- * @param {string} args.name - Attachment name.
550
- * @param {string} args.recordId - Record id.
551
- * @param {string} args.recordType - Record type.
552
- * @returns {Promise<number>} - Next position.
553
- */
554
- async _nextPosition({db, name, recordId, recordType}) {
555
- const query = db
556
- .newQuery()
557
- .from(ATTACHMENTS_TABLE)
558
- .where({name, record_id: recordId, record_type: recordType})
559
- .order("position DESC")
560
- .limit(1)
561
- const rows = await query.results()
562
- const currentRow = /**
563
- * Narrows the runtime value to the documented type.
564
- @type {{position?: string | number | null} | undefined} */ (rows[0])
565
- const current = Number(currentRow?.position)
566
-
567
- if (!Number.isFinite(current)) return 0
568
-
569
- return current + 1
570
- }
571
-
572
- /**
573
- * Runs with db.
574
- * @template T
575
- * @param {(db: import("../../../database/drivers/base.js").default) => Promise<T>} callback - Callback.
576
- * @returns {Promise<T>} - Callback result.
577
- */
578
- async _withDb(callback) {
579
- const pool = this.configuration.getDatabasePool(this.databaseIdentifier)
580
501
  /**
581
- * Defines result.
582
- @type {T | undefined} */
583
- let result
584
-
585
- await pool.withConnection({name: "Record attachment store"}, async (db) => {
586
- result = await callback(db)
587
- })
588
-
589
- return /** Narrows the runtime value to the documented type. @type {T} */ (result)
590
- }
502
+ * Runs with db.
503
+ * @template T
504
+ * @param {(db: import("../../../database/drivers/base.js").default) => Promise<T>} callback - Callback.
505
+ * @returns {Promise<T>} - Callback result.
506
+ */
507
+ async _withDb(callback) {
508
+ const pool = this.configuration.getDatabasePool(this.databaseIdentifier);
509
+ /**
510
+ * Defines result.
511
+ @type {T | undefined} */
512
+ let result;
513
+ await pool.withConnection({ name: "Record attachment store" }, async (db) => {
514
+ result = await callback(db);
515
+ });
516
+ return /** Narrows the runtime value to the documented type. @type {T} */ (result);
517
+ }
591
518
  }
519
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvZGF0YWJhc2UvcmVjb3JkL2F0dGFjaG1lbnRzL3N0b3JlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLElBQUksTUFBTSxXQUFXLENBQUE7QUFDNUIsT0FBTyxTQUFTLE1BQU0sMkJBQTJCLENBQUE7QUFDakQsT0FBTyw4QkFBOEIsTUFBTSxzQkFBc0IsQ0FBQTtBQUVqRSxNQUFNLGlCQUFpQixHQUFHLHVCQUF1QixDQUFBO0FBRWpEOztpSEFFaUg7QUFDakg7O3NHQUVzRztBQUN0RyxNQUFNLHFCQUFxQixHQUFHLElBQUksT0FBTyxFQUFFLENBQUE7QUFFM0M7OztHQUdHO0FBQ0gsU0FBUyxZQUFZO0lBQ25CLE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUE7QUFDN0IsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLGdCQUFnQixDQUFDLEtBQUs7SUFDN0IsT0FBTyxHQUFHLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLENBQUE7QUFDM0QsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsOEJBQThCLENBQUMsS0FBSztJQUNsRCxNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtJQUMvQyxJQUFJLDBCQUEwQixHQUFHLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQTtJQUV6RSxJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQztRQUNoQywwQkFBMEIsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFBO1FBQ3RDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsMEJBQTBCLENBQUMsQ0FBQTtJQUN0RSxDQUFDO0lBRUQsTUFBTSxHQUFHLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUE7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Q0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztZQUFFLE9BQU8sQ0FBQyxDQUFBO1FBRXZDLE9BQU8sT0FBTyxHQUFHLENBQUMsQ0FBQTtJQUNwQixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVE7UUFDcEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUE7UUFDeEU7O2tDQUUwQjtRQUMxQixJQUFJLE1BQU0sQ0FBQTtRQUVWLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FBQyxFQUFDLElBQUksRUFBRSx5QkFBeUIsRUFBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRTtZQUN4RSxNQUFNLEdBQUcsTUFBTSxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDN0IsQ0FBQyxDQUFDLENBQUE7UUFFRixPQUFPLGtFQUFrRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUE7SUFDcEYsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBVVUlEIGZyb20gXCJwdXJlLXV1aWRcIlxuaW1wb3J0IFRhYmxlRGF0YSBmcm9tIFwiLi4vLi4vdGFibGUtZGF0YS9pbmRleC5qc1wiXG5pbXBvcnQgbm9ybWFsaXplUmVjb3JkQXR0YWNobWVudElucHV0IGZyb20gXCIuL25vcm1hbGl6ZS1pbnB1dC5qc1wiXG5cbmNvbnN0IEFUVEFDSE1FTlRTX1RBQkxFID0gXCJ2ZWxvY2lvdXNfYXR0YWNobWVudHNcIlxuXG4vKipcbiAqIEF0dGFjaG1lbnREcml2ZXJDb25zdHJ1Y3RvciB0eXBlLlxuICBAdHlwZWRlZiB7aW1wb3J0KFwiLi4vLi4vLi4vY29uZmlndXJhdGlvbi10eXBlcy5qc1wiKS5BdHRhY2htZW50RHJpdmVyQ29uc3RydWN0b3J9IEF0dGFjaG1lbnREcml2ZXJDb25zdHJ1Y3RvciAqL1xuLyoqXG4gKiBTdG9yZXMgYnkgY29uZmlndXJhdGlvbi5cbiAgQHR5cGUge1dlYWtNYXA8aW1wb3J0KFwiLi4vLi4vLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0LCBNYXA8c3RyaW5nLCBSZWNvcmRBdHRhY2htZW50c1N0b3JlPj59ICovXG5jb25zdCBzdG9yZXNCeUNvbmZpZ3VyYXRpb24gPSBuZXcgV2Vha01hcCgpXG5cbi8qKlxuICogUnVucyBnZW5lcmF0ZSB1dWlkLlxuICogQHJldHVybnMge3N0cmluZ30gLSBHZW5lcmF0ZWQgVVVJRCB2NCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gZ2VuZXJhdGVVVUlEKCkge1xuICByZXR1cm4gbmV3IFVVSUQoNCkuZm9ybWF0KClcbn1cblxuLyoqXG4gKiBSdW5zIHN0b3JlIGtleSBmb3IgbW9kZWwuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2luZGV4LmpzXCIpLmRlZmF1bHR9IG1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSAtIFN0b3JlIGtleS5cbiAqL1xuZnVuY3Rpb24gc3RvcmVLZXlGb3JNb2RlbChtb2RlbCkge1xuICByZXR1cm4gYCR7bW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldERhdGFiYXNlSWRlbnRpZmllcigpfWBcbn1cblxuLyoqXG4gKiBSdW5zIHRoZSByZWNvcmRBdHRhY2htZW50c1N0b3JlRm9yTW9kZWwgaGVscGVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBtb2RlbCAtIE1vZGVsIGluc3RhbmNlLlxuICogQHJldHVybnMge1JlY29yZEF0dGFjaG1lbnRzU3RvcmV9IC0gU3RvcmUgaW5zdGFuY2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWNvcmRBdHRhY2htZW50c1N0b3JlRm9yTW9kZWwobW9kZWwpIHtcbiAgY29uc3QgY29uZmlndXJhdGlvbiA9IG1vZGVsLl9nZXRDb25maWd1cmF0aW9uKClcbiAgbGV0IHN0b3Jlc0J5RGF0YWJhc2VJZGVudGlmaWVyID0gc3RvcmVzQnlDb25maWd1cmF0aW9uLmdldChjb25maWd1cmF0aW9uKVxuXG4gIGlmICghc3RvcmVzQnlEYXRhYmFzZUlkZW50aWZpZXIpIHtcbiAgICBzdG9yZXNCeURhdGFiYXNlSWRlbnRpZmllciA9IG5ldyBNYXAoKVxuICAgIHN0b3Jlc0J5Q29uZmlndXJhdGlvbi5zZXQoY29uZmlndXJhdGlvbiwgc3RvcmVzQnlEYXRhYmFzZUlkZW50aWZpZXIpXG4gIH1cblxuICBjb25zdCBrZXkgPSBzdG9yZUtleUZvck1vZGVsKG1vZGVsKVxuICBsZXQgc3RvcmUgPSBzdG9yZXNCeURhdGFiYXNlSWRlbnRpZmllci5nZXQoa2V5KVxuXG4gIGlmIChzdG9yZSkgcmV0dXJuIHN0b3JlXG5cbiAgc3RvcmUgPSBuZXcgUmVjb3JkQXR0YWNobWVudHNTdG9yZSh7XG4gICAgY29uZmlndXJhdGlvbixcbiAgICBkYXRhYmFzZUlkZW50aWZpZXI6IG1vZGVsLmdldE1vZGVsQ2xhc3MoKS5nZXREYXRhYmFzZUlkZW50aWZpZXIoKVxuICB9KVxuXG4gIHN0b3Jlc0J5RGF0YWJhc2VJZGVudGlmaWVyLnNldChrZXksIHN0b3JlKVxuXG4gIHJldHVybiBzdG9yZVxufVxuXG4vKipcbiAqIEF0dGFjaG1lbnQgcGVyc2lzdGVuY2Ugc3RvcmUuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlY29yZEF0dGFjaG1lbnRzU3RvcmUge1xuICAvKipcbiAgICogUnVucyBjb25zdHJ1Y3Rvci5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uLy4uL2NvbmZpZ3VyYXRpb24uanNcIikuZGVmYXVsdH0gYXJncy5jb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MuZGF0YWJhc2VJZGVudGlmaWVyIC0gRGF0YWJhc2UgaWRlbnRpZmllci5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb25maWd1cmF0aW9uLCBkYXRhYmFzZUlkZW50aWZpZXJ9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIHRoaXMuZGF0YWJhc2VJZGVudGlmaWVyID0gZGF0YWJhc2VJZGVudGlmaWVyXG4gICAgdGhpcy5fcmVhZHlQcm9taXNlID0gbnVsbFxuICAgIHRoaXMuX2RyaXZlckNvbHVtbnNBdmFpbGFibGUgPSBmYWxzZVxuICAgIHRoaXMuX2NvbnRlbnRCYXNlNjROdWxsYWJsZSA9IHRydWVcbiAgICAvKipcbiAgICAgKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuXG4gICAgICBAdHlwZSB7TWFwPHN0cmluZywgUmVjb3JkPHN0cmluZywgPz4+fSAqL1xuICAgIHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlOYW1lID0gbmV3IE1hcCgpXG4gICAgLyoqXG4gICAgICogTmFycm93cyB0aGUgcnVudGltZSB2YWx1ZSB0byB0aGUgZG9jdW1lbnRlZCB0eXBlLlxuICAgICAgQHR5cGUge01hcDxBdHRhY2htZW50RHJpdmVyQ29uc3RydWN0b3IgfCBSZWNvcmQ8c3RyaW5nLCA/PiwgUmVjb3JkPHN0cmluZywgPz4+fSAqL1xuICAgIHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlSZWZlcmVuY2UgPSBuZXcgTWFwKClcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGVuc3VyZSByZWFkeS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBzY2hlbWEgaXMgcmVhZHkuXG4gICAqL1xuICBhc3luYyBlbnN1cmVSZWFkeSgpIHtcbiAgICBpZiAodGhpcy5fcmVhZHlQcm9taXNlKSB7XG4gICAgICBhd2FpdCB0aGlzLl9yZWFkeVByb21pc2VcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHRoaXMuX3JlYWR5UHJvbWlzZSA9IChhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiB7XG4gICAgICAgIGlmIChhd2FpdCBkYi50YWJsZUV4aXN0cyhBVFRBQ0hNRU5UU19UQUJMRSkpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmVuc3VyZUF0dGFjaG1lbnRTdG9yZVNjaGVtYSh7ZGJ9KVxuICAgICAgICAgIHJldHVyblxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGFibGUgPSBuZXcgVGFibGVEYXRhKEFUVEFDSE1FTlRTX1RBQkxFLCB7aWZOb3RFeGlzdHM6IHRydWV9KVxuXG4gICAgICAgIHRhYmxlLnN0cmluZyhcImlkXCIsIHtudWxsOiBmYWxzZSwgcHJpbWFyeUtleTogdHJ1ZX0pXG4gICAgICAgIHRhYmxlLnN0cmluZyhcInJlY29yZF90eXBlXCIsIHtudWxsOiBmYWxzZSwgaW5kZXg6IHRydWV9KVxuICAgICAgICB0YWJsZS5zdHJpbmcoXCJyZWNvcmRfaWRcIiwge251bGw6IGZhbHNlLCBpbmRleDogdHJ1ZX0pXG4gICAgICAgIHRhYmxlLnN0cmluZyhcIm5hbWVcIiwge251bGw6IGZhbHNlLCBpbmRleDogdHJ1ZX0pXG4gICAgICAgIHRhYmxlLmludGVnZXIoXCJwb3NpdGlvblwiLCB7bnVsbDogZmFsc2V9KVxuICAgICAgICB0YWJsZS5zdHJpbmcoXCJmaWxlbmFtZVwiLCB7bnVsbDogZmFsc2V9KVxuICAgICAgICB0YWJsZS5zdHJpbmcoXCJjb250ZW50X3R5cGVcIiwge251bGw6IHRydWV9KVxuICAgICAgICB0YWJsZS5iaWdpbnQoXCJieXRlX3NpemVcIiwge251bGw6IGZhbHNlfSlcbiAgICAgICAgdGFibGUuc3RyaW5nKFwiZHJpdmVyXCIsIHtudWxsOiB0cnVlfSlcbiAgICAgICAgdGFibGUuc3RyaW5nKFwic3RvcmFnZV9rZXlcIiwge251bGw6IHRydWV9KVxuICAgICAgICB0YWJsZS50ZXh0KFwiY29udGVudF9iYXNlNjRcIiwge251bGw6IHRydWV9KVxuICAgICAgICB0YWJsZS5iaWdpbnQoXCJjcmVhdGVkX2F0X21zXCIsIHtudWxsOiBmYWxzZX0pXG4gICAgICAgIHRhYmxlLmJpZ2ludChcInVwZGF0ZWRfYXRfbXNcIiwge251bGw6IGZhbHNlfSlcblxuICAgICAgICBhd2FpdCBkYi5jcmVhdGVUYWJsZSh0YWJsZSlcbiAgICAgICAgdGhpcy5fZHJpdmVyQ29sdW1uc0F2YWlsYWJsZSA9IHRydWVcbiAgICAgICAgdGhpcy5fY29udGVudEJhc2U2NE51bGxhYmxlID0gdHJ1ZVxuICAgICAgfSlcbiAgICB9KSgpXG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5fcmVhZHlQcm9taXNlXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuX3JlYWR5UHJvbWlzZSA9IG51bGxcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBhdHRhY2guXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7P30gYXJncy5pbnB1dCAtIEF0dGFjaG1lbnQgaW5wdXQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXJncy5yZXBsYWNlIC0gV2hldGhlciB0byByZXBsYWNlIGV4aXN0aW5nIGF0dGFjaG1lbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgYXR0YWNoKHtpbnB1dCwgbW9kZWwsIG5hbWUsIHJlcGxhY2V9KSB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpXG4gICAgY29uc3QgYXR0YWNobWVudHNDb25maWd1cmF0aW9uID0gdGhpcy5jb25maWd1cmF0aW9uLmdldEF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbj8uKCkgfHwge31cbiAgICBjb25zdCBhbGxvd1BhdGhJbnB1dCA9IGF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbi5hbGxvd1BhdGhJbnB1dCA9PT0gdHJ1ZVxuICAgIGNvbnN0IGFsbG93ZWRQYXRoUHJlZml4ZXMgPSBBcnJheS5pc0FycmF5KGF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbi5hbGxvd2VkUGF0aFByZWZpeGVzKVxuICAgICAgPyBhdHRhY2htZW50c0NvbmZpZ3VyYXRpb24uYWxsb3dlZFBhdGhQcmVmaXhlc1xuICAgICAgOiB1bmRlZmluZWRcblxuICAgIGNvbnN0IG5vcm1hbGl6ZWRJbnB1dCA9IGF3YWl0IG5vcm1hbGl6ZVJlY29yZEF0dGFjaG1lbnRJbnB1dChpbnB1dCwge1xuICAgICAgYWxsb3dQYXRoSW5wdXQsXG4gICAgICBhbGxvd2VkUGF0aFByZWZpeGVzLFxuICAgICAgZW52aXJvbm1lbnRIYW5kbGVyOiB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RW52aXJvbm1lbnRIYW5kbGVyKClcbiAgICB9KVxuICAgIGNvbnN0IGF0dGFjaG1lbnREcml2ZXIgPSBhd2FpdCB0aGlzLnJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZX0pXG4gICAgY29uc3QgYXR0YWNobWVudERyaXZlck5hbWUgPSB0aGlzLl9hdHRhY2htZW50RHJpdmVyTmFtZUZvcih7bW9kZWwsIG5hbWV9KVxuICAgIGNvbnN0IG5vdyA9IERhdGUubm93KClcbiAgICBjb25zdCByZWNvcmRUeXBlID0gbW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldE1vZGVsTmFtZSgpXG4gICAgY29uc3QgcmVjb3JkSWQgPSBTdHJpbmcobW9kZWwuaWQoKSlcbiAgICBjb25zdCBhdHRhY2htZW50SWQgPSBnZW5lcmF0ZVVVSUQoKVxuICAgIGNvbnN0IHtzdG9yYWdlS2V5fSA9IGF3YWl0IGF0dGFjaG1lbnREcml2ZXIud3JpdGUoe1xuICAgICAgYXR0YWNobWVudElkLFxuICAgICAgaW5wdXQ6IG5vcm1hbGl6ZWRJbnB1dCxcbiAgICAgIG1vZGVsLFxuICAgICAgbmFtZVxuICAgIH0pXG5cbiAgICBhd2FpdCB0aGlzLl93aXRoRGIoYXN5bmMgKGRiKSA9PiB7XG4gICAgICBpZiAocmVwbGFjZSkge1xuICAgICAgICBjb25zdCBleGlzdGluZ1Jvd3MgPSBhd2FpdCBkYlxuICAgICAgICAgIC5uZXdRdWVyeSgpXG4gICAgICAgICAgLmZyb20oQVRUQUNITUVOVFNfVEFCTEUpXG4gICAgICAgICAgLndoZXJlKHtuYW1lLCByZWNvcmRfaWQ6IHJlY29yZElkLCByZWNvcmRfdHlwZTogcmVjb3JkVHlwZX0pXG4gICAgICAgICAgLnJlc3VsdHMoKVxuXG4gICAgICAgIGZvciAoY29uc3QgZXhpc3RpbmdSb3cgb2YgZXhpc3RpbmdSb3dzKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5kZWxldGVBdHRhY2htZW50Um93U3RvcmFnZSh7bW9kZWwsIG5hbWUsIHJvdzogZXhpc3RpbmdSb3d9KVxuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgZGIuZGVsZXRlKHtcbiAgICAgICAgICBjb25kaXRpb25zOiB7bmFtZSwgcmVjb3JkX2lkOiByZWNvcmRJZCwgcmVjb3JkX3R5cGU6IHJlY29yZFR5cGV9LFxuICAgICAgICAgIHRhYmxlTmFtZTogQVRUQUNITUVOVFNfVEFCTEVcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgY29uc3QgcG9zaXRpb24gPSByZXBsYWNlID8gMCA6IGF3YWl0IHRoaXMuX25leHRQb3NpdGlvbih7ZGIsIG5hbWUsIHJlY29yZElkLCByZWNvcmRUeXBlfSlcbiAgICAgIC8qKlxuICAgICAgICogSW5zZXJ0IGRhdGEuXG4gICAgICAgIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICAgIGNvbnN0IGluc2VydERhdGEgPSB7XG4gICAgICAgIGJ5dGVfc2l6ZTogbm9ybWFsaXplZElucHV0LmJ5dGVTaXplLFxuICAgICAgICBjb250ZW50X2Jhc2U2NDogdGhpcy5fY29udGVudEJhc2U2NE51bGxhYmxlID8gbnVsbCA6IG5vcm1hbGl6ZWRJbnB1dC5jb250ZW50QmFzZTY0LFxuICAgICAgICBjb250ZW50X3R5cGU6IG5vcm1hbGl6ZWRJbnB1dC5jb250ZW50VHlwZSxcbiAgICAgICAgY3JlYXRlZF9hdF9tczogbm93LFxuICAgICAgICBmaWxlbmFtZTogbm9ybWFsaXplZElucHV0LmZpbGVuYW1lLFxuICAgICAgICBpZDogYXR0YWNobWVudElkLFxuICAgICAgICBuYW1lLFxuICAgICAgICBwb3NpdGlvbixcbiAgICAgICAgcmVjb3JkX2lkOiByZWNvcmRJZCxcbiAgICAgICAgcmVjb3JkX3R5cGU6IHJlY29yZFR5cGUsXG4gICAgICAgIHVwZGF0ZWRfYXRfbXM6IG5vd1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fZHJpdmVyQ29sdW1uc0F2YWlsYWJsZSkge1xuICAgICAgICBpbnNlcnREYXRhLmRyaXZlciA9IGF0dGFjaG1lbnREcml2ZXJOYW1lXG4gICAgICAgIGluc2VydERhdGEuc3RvcmFnZV9rZXkgPSBzdG9yYWdlS2V5XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGRiLmluc2VydCh7XG4gICAgICAgIGRhdGE6IGluc2VydERhdGEsXG4gICAgICAgIHRhYmxlTmFtZTogQVRUQUNITUVOVFNfVEFCTEVcbiAgICAgIH0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGVuc3VyZSBhdHRhY2htZW50IHN0b3JlIHNjaGVtYS5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uLy4uLy4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0fSBhcmdzLmRiIC0gREIgY29ubmVjdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiBzY2hlbWEgY29sdW1ucyBhcmUgZW5zdXJlZC5cbiAgICovXG4gIGFzeW5jIGVuc3VyZUF0dGFjaG1lbnRTdG9yZVNjaGVtYSh7ZGJ9KSB7XG4gICAgY29uc3QgdGFibGUgPSBhd2FpdCBkYi5nZXRUYWJsZUJ5TmFtZU9yRmFpbChBVFRBQ0hNRU5UU19UQUJMRSlcbiAgICBjb25zdCBjb2x1bW5zID0gYXdhaXQgdGFibGUuZ2V0Q29sdW1ucygpXG4gICAgY29uc3QgaGFzRHJpdmVyQ29sdW1uID0gY29sdW1ucy5zb21lKChjb2x1bW4pID0+IGNvbHVtbi5nZXROYW1lKCkgPT09IFwiZHJpdmVyXCIpXG4gICAgY29uc3QgaGFzU3RvcmFnZUtleUNvbHVtbiA9IGNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiBjb2x1bW4uZ2V0TmFtZSgpID09PSBcInN0b3JhZ2Vfa2V5XCIpXG4gICAgY29uc3QgY29udGVudEJhc2U2NENvbHVtbiA9IGNvbHVtbnMuZmluZCgoY29sdW1uKSA9PiBjb2x1bW4uZ2V0TmFtZSgpID09PSBcImNvbnRlbnRfYmFzZTY0XCIpXG4gICAgY29uc3QgYWx0ZXJUYWJsZSA9IG5ldyBUYWJsZURhdGEoQVRUQUNITUVOVFNfVEFCTEUpXG4gICAgbGV0IHNob3VsZEFsdGVyID0gZmFsc2VcblxuICAgIGlmICghaGFzRHJpdmVyQ29sdW1uKSB7XG4gICAgICBhbHRlclRhYmxlLnN0cmluZyhcImRyaXZlclwiLCB7bnVsbDogdHJ1ZX0pXG4gICAgICBzaG91bGRBbHRlciA9IHRydWVcbiAgICB9XG5cbiAgICBpZiAoIWhhc1N0b3JhZ2VLZXlDb2x1bW4pIHtcbiAgICAgIGFsdGVyVGFibGUuc3RyaW5nKFwic3RvcmFnZV9rZXlcIiwge251bGw6IHRydWV9KVxuICAgICAgc2hvdWxkQWx0ZXIgPSB0cnVlXG4gICAgfVxuXG4gICAgaWYgKHNob3VsZEFsdGVyKSB7XG4gICAgICBjb25zdCBhbHRlclRhYmxlU1FMcyA9IGF3YWl0IGRiLmFsdGVyVGFibGVTUUxzKGFsdGVyVGFibGUpXG5cbiAgICAgIGZvciAoY29uc3Qgc3FsIG9mIGFsdGVyVGFibGVTUUxzKSB7XG4gICAgICAgIGF3YWl0IGRiLnF1ZXJ5KHNxbClcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl9kcml2ZXJDb2x1bW5zQXZhaWxhYmxlID0gdHJ1ZVxuICAgIHRoaXMuX2NvbnRlbnRCYXNlNjROdWxsYWJsZSA9IGNvbnRlbnRCYXNlNjRDb2x1bW4gPyBjb250ZW50QmFzZTY0Q29sdW1uLmdldE51bGwoKSA6IHRydWVcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHJlYWQgYXR0YWNobWVudCByb3cuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgPz59IGFyZ3Mucm93IC0gQXR0YWNobWVudCByb3cuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEJ1ZmZlcj59IC0gQXR0YWNobWVudCBieXRlcy5cbiAgICovXG4gIGFzeW5jIHJlYWRBdHRhY2htZW50Um93KHttb2RlbCwgbmFtZSwgcm93fSkge1xuICAgIGlmICh0eXBlb2Ygcm93LmNvbnRlbnRfYmFzZTY0ID09PSBcInN0cmluZ1wiICYmIHJvdy5jb250ZW50X2Jhc2U2NC5sZW5ndGggPiAwKSB7XG4gICAgICByZXR1cm4gQnVmZmVyLmZyb20ocm93LmNvbnRlbnRfYmFzZTY0LCBcImJhc2U2NFwiKVxuICAgIH1cblxuICAgIGNvbnN0IHN0b3JhZ2VLZXkgPSB0eXBlb2Ygcm93LnN0b3JhZ2Vfa2V5ID09PSBcInN0cmluZ1wiICYmIHJvdy5zdG9yYWdlX2tleS5sZW5ndGggPiAwID8gcm93LnN0b3JhZ2Vfa2V5IDogbnVsbFxuXG4gICAgaWYgKCFzdG9yYWdlS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEF0dGFjaG1lbnQgcm93ICR7U3RyaW5nKHJvdy5pZCl9IGlzIG1pc3Npbmcgc3RvcmFnZSBrZXlgKVxuICAgIH1cblxuICAgIGNvbnN0IGF0dGFjaG1lbnREcml2ZXIgPSBhd2FpdCB0aGlzLnJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZSwgcm93fSlcblxuICAgIHJldHVybiBhd2FpdCBhdHRhY2htZW50RHJpdmVyLnJlYWQoe1xuICAgICAgbW9kZWwsXG4gICAgICBuYW1lLFxuICAgICAgcm93LFxuICAgICAgc3RvcmFnZUtleVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBhdHRhY2htZW50IHJvdyB1cmwuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgPz59IGFyZ3Mucm93IC0gQXR0YWNobWVudCByb3cuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZyB8IG51bGw+fSAtIEF0dGFjaG1lbnQgVVJMLlxuICAgKi9cbiAgYXN5bmMgYXR0YWNobWVudFJvd1VybCh7bW9kZWwsIG5hbWUsIHJvd30pIHtcbiAgICBjb25zdCBhdHRhY2htZW50RHJpdmVyID0gYXdhaXQgdGhpcy5yZXNvbHZlQXR0YWNobWVudERyaXZlcih7bW9kZWwsIG5hbWUsIHJvd30pXG5cbiAgICBpZiAodHlwZW9mIGF0dGFjaG1lbnREcml2ZXIudXJsICE9PSBcImZ1bmN0aW9uXCIpIHJldHVybiBudWxsXG5cbiAgICBjb25zdCBzdG9yYWdlS2V5ID0gdHlwZW9mIHJvdy5zdG9yYWdlX2tleSA9PT0gXCJzdHJpbmdcIiAmJiByb3cuc3RvcmFnZV9rZXkubGVuZ3RoID4gMFxuICAgICAgPyByb3cuc3RvcmFnZV9rZXlcbiAgICAgIDogKHR5cGVvZiByb3cuaWQgPT09IFwic3RyaW5nXCIgPyByb3cuaWQgOiBcIlwiKVxuXG4gICAgaWYgKCFzdG9yYWdlS2V5KSByZXR1cm4gbnVsbFxuXG4gICAgcmV0dXJuIGF3YWl0IGF0dGFjaG1lbnREcml2ZXIudXJsKHtcbiAgICAgIG1vZGVsLFxuICAgICAgbmFtZSxcbiAgICAgIHJvdyxcbiAgICAgIHN0b3JhZ2VLZXlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgZmluZCBvbmUuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbYXJncy5pZF0gLSBPcHRpb25hbCBhdHRhY2htZW50IGlkLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCA/PiB8IG51bGw+fSAtIEF0dGFjaG1lbnQgcm93LlxuICAgKi9cbiAgYXN5bmMgZmluZE9uZSh7aWQsIG1vZGVsLCBuYW1lfSkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZFR5cGUgPSBtb2RlbC5nZXRNb2RlbENsYXNzKCkuZ2V0TW9kZWxOYW1lKClcbiAgICAgIGNvbnN0IHJlY29yZElkID0gU3RyaW5nKG1vZGVsLmlkKCkpXG4gICAgICBsZXQgcXVlcnkgPSBkYlxuICAgICAgICAubmV3UXVlcnkoKVxuICAgICAgICAuZnJvbShBVFRBQ0hNRU5UU19UQUJMRSlcbiAgICAgICAgLndoZXJlKHtuYW1lLCByZWNvcmRfaWQ6IHJlY29yZElkLCByZWNvcmRfdHlwZTogcmVjb3JkVHlwZX0pXG4gICAgICAgIC5vcmRlcihcInBvc2l0aW9uIEFTQ1wiKVxuICAgICAgICAub3JkZXIoXCJjcmVhdGVkX2F0X21zIERFU0NcIilcbiAgICAgICAgLmxpbWl0KDEpXG5cbiAgICAgIGlmIChpZCkge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LndoZXJlKHtpZH0pXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJvd3MgPSBhd2FpdCBxdWVyeS5yZXN1bHRzKClcblxuICAgICAgcmV0dXJuIHJvd3NbMF0gfHwgbnVsbFxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyBmaW5kIG1hbnkuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPEFycmF5PFJlY29yZDxzdHJpbmcsID8+Pj59IC0gQXR0YWNobWVudCByb3dzLlxuICAgKi9cbiAgYXN5bmMgZmluZE1hbnkoe21vZGVsLCBuYW1lfSkge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuX3dpdGhEYihhc3luYyAoZGIpID0+IHtcbiAgICAgIGNvbnN0IHJlY29yZFR5cGUgPSBtb2RlbC5nZXRNb2RlbENsYXNzKCkuZ2V0TW9kZWxOYW1lKClcbiAgICAgIGNvbnN0IHJlY29yZElkID0gU3RyaW5nKG1vZGVsLmlkKCkpXG4gICAgICBjb25zdCBxdWVyeSA9IGRiXG4gICAgICAgIC5uZXdRdWVyeSgpXG4gICAgICAgIC5mcm9tKEFUVEFDSE1FTlRTX1RBQkxFKVxuICAgICAgICAud2hlcmUoe25hbWUsIHJlY29yZF9pZDogcmVjb3JkSWQsIHJlY29yZF90eXBlOiByZWNvcmRUeXBlfSlcbiAgICAgICAgLm9yZGVyKFwicG9zaXRpb24gQVNDXCIpXG4gICAgICAgIC5vcmRlcihcImNyZWF0ZWRfYXRfbXMgQVNDXCIpXG5cbiAgICAgIHJldHVybiBhd2FpdCBxdWVyeS5yZXN1bHRzKClcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgZGVsZXRlIGF0dGFjaG1lbnQgcm93IHN0b3JhZ2UuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsIC0gTW9kZWwgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7UmVjb3JkPHN0cmluZywgPz59IGFyZ3Mucm93IC0gQXR0YWNobWVudCByb3cuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIHdoZW4gcm93IHN0b3JhZ2UgaGFzIGJlZW4gZGVsZXRlZC5cbiAgICovXG4gIGFzeW5jIGRlbGV0ZUF0dGFjaG1lbnRSb3dTdG9yYWdlKHttb2RlbCwgbmFtZSwgcm93fSkge1xuICAgIGNvbnN0IHN0b3JhZ2VLZXkgPSB0eXBlb2Ygcm93LnN0b3JhZ2Vfa2V5ID09PSBcInN0cmluZ1wiICYmIHJvdy5zdG9yYWdlX2tleS5sZW5ndGggPiAwID8gcm93LnN0b3JhZ2Vfa2V5IDogbnVsbFxuXG4gICAgaWYgKCFzdG9yYWdlS2V5KSByZXR1cm5cblxuICAgIGNvbnN0IGF0dGFjaG1lbnREcml2ZXIgPSBhd2FpdCB0aGlzLnJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZSwgcm93fSlcblxuICAgIGlmICh0eXBlb2YgYXR0YWNobWVudERyaXZlci5kZWxldGUgIT09IFwiZnVuY3Rpb25cIikgcmV0dXJuXG5cbiAgICBhd2FpdCBhdHRhY2htZW50RHJpdmVyLmRlbGV0ZSh7XG4gICAgICBtb2RlbCxcbiAgICAgIG5hbWUsXG4gICAgICByb3csXG4gICAgICBzdG9yYWdlS2V5XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGF0dGFjaG1lbnQgZHJpdmVyIGJ5IG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkcml2ZXJOYW1lIC0gRHJpdmVyIG5hbWUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsID8+Pn0gLSBBdHRhY2htZW50IHN0b3JhZ2UgZHJpdmVyIGluc3RhbmNlLlxuICAgKi9cbiAgYXN5bmMgYXR0YWNobWVudERyaXZlckJ5TmFtZShkcml2ZXJOYW1lKSB7XG4gICAgaWYgKHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlOYW1lLmhhcyhkcml2ZXJOYW1lKSkge1xuICAgICAgcmV0dXJuIC8qKiBOYXJyb3dzIHRoZSBydW50aW1lIHZhbHVlIHRvIHRoZSBkb2N1bWVudGVkIHR5cGUuIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi8gKHRoaXMuX2F0dGFjaG1lbnREcml2ZXJzQnlOYW1lLmdldChkcml2ZXJOYW1lKSlcbiAgICB9XG5cbiAgICBjb25zdCBhdHRhY2htZW50Q29uZmlndXJhdGlvbiA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXRBdHRhY2htZW50c0NvbmZpZ3VyYXRpb24/LigpIHx8IHt9XG4gICAgY29uc3QgY29uZmlndXJlZERyaXZlciA9IGF0dGFjaG1lbnRDb25maWd1cmF0aW9uLmRyaXZlcnM/Lltkcml2ZXJOYW1lXVxuICAgIC8qKlxuICAgICAqIERlZmluZXMgYXR0YWNobWVudERyaXZlci5cbiAgICAgIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICBsZXQgYXR0YWNobWVudERyaXZlclxuXG4gICAgaWYgKCFjb25maWd1cmVkRHJpdmVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGNvbmZpZ3VyZWQgYXR0YWNobWVudCBzdG9yYWdlIGRyaXZlciBuYW1lZCBcIiR7ZHJpdmVyTmFtZX1cImApXG4gICAgfSBlbHNlIGlmIChjb25maWd1cmVkRHJpdmVyLmluc3RhbmNlICYmIHR5cGVvZiBjb25maWd1cmVkRHJpdmVyLmluc3RhbmNlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBhdHRhY2htZW50RHJpdmVyID0gY29uZmlndXJlZERyaXZlci5pbnN0YW5jZVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbmZpZ3VyZWREcml2ZXIuZHJpdmVyQ2xhc3MgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgYXR0YWNobWVudERyaXZlciA9IG5ldyBjb25maWd1cmVkRHJpdmVyLmRyaXZlckNsYXNzKHtcbiAgICAgICAgY29uZmlndXJhdGlvbjogdGhpcy5jb25maWd1cmF0aW9uLFxuICAgICAgICBuYW1lOiBkcml2ZXJOYW1lLFxuICAgICAgICBvcHRpb25zOiBjb25maWd1cmVkRHJpdmVyXG4gICAgICB9KVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbmZpZ3VyZWREcml2ZXIuY3JlYXRlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGF0dGFjaG1lbnREcml2ZXIgPSBjb25maWd1cmVkRHJpdmVyLmNyZWF0ZSh7XG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgbmFtZTogZHJpdmVyTmFtZSxcbiAgICAgICAgb3B0aW9uczogY29uZmlndXJlZERyaXZlclxuICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBBdHRhY2htZW50IHN0b3JhZ2UgZHJpdmVyIFwiJHtkcml2ZXJOYW1lfVwiIG11c3QgZGVmaW5lIGluc3RhbmNlLCBkcml2ZXJDbGFzcywgb3IgY3JlYXRlYClcbiAgICB9XG5cbiAgICBpZiAoIWF0dGFjaG1lbnREcml2ZXIgfHwgdHlwZW9mIGF0dGFjaG1lbnREcml2ZXIud3JpdGUgIT09IFwiZnVuY3Rpb25cIiB8fCB0eXBlb2YgYXR0YWNobWVudERyaXZlci5yZWFkICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQXR0YWNobWVudCBzdG9yYWdlIGRyaXZlciBcIiR7ZHJpdmVyTmFtZX1cIiBtdXN0IGltcGxlbWVudCB3cml0ZS9yZWFkYClcbiAgICB9XG5cbiAgICB0aGlzLl9hdHRhY2htZW50RHJpdmVyc0J5TmFtZS5zZXQoZHJpdmVyTmFtZSwgYXR0YWNobWVudERyaXZlcilcblxuICAgIHJldHVybiBhdHRhY2htZW50RHJpdmVyXG4gIH1cblxuICAvKipcbiAgICogUnVucyBhdHRhY2htZW50IGRyaXZlciBieSByZWZlcmVuY2UuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtBdHRhY2htZW50RHJpdmVyQ29uc3RydWN0b3IgfCBSZWNvcmQ8c3RyaW5nLCA/Pn0gYXJncy5kcml2ZXJSZWZlcmVuY2UgLSBEcml2ZXIgY2xhc3Mgb3IgaW5zdGFuY2UuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmF0dGFjaG1lbnROYW1lIC0gQXR0YWNobWVudCBuYW1lLlxuICAgKiBAcGFyYW0ge3R5cGVvZiBpbXBvcnQoXCIuLi9pbmRleC5qc1wiKS5kZWZhdWx0fSBhcmdzLm1vZGVsQ2xhc3MgLSBNb2RlbCBjbGFzcy5cbiAgICogQHJldHVybnMge1JlY29yZDxzdHJpbmcsID8+fSAtIEF0dGFjaG1lbnQgZHJpdmVyIGluc3RhbmNlLlxuICAgKi9cbiAgYXR0YWNobWVudERyaXZlckJ5UmVmZXJlbmNlKHthdHRhY2htZW50TmFtZSwgZHJpdmVyUmVmZXJlbmNlLCBtb2RlbENsYXNzfSkge1xuICAgIGlmICh0aGlzLl9hdHRhY2htZW50RHJpdmVyc0J5UmVmZXJlbmNlLmhhcyhkcml2ZXJSZWZlcmVuY2UpKSB7XG4gICAgICByZXR1cm4gLyoqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS4gQHR5cGUge1JlY29yZDxzdHJpbmcsID8+fSAqLyAodGhpcy5fYXR0YWNobWVudERyaXZlcnNCeVJlZmVyZW5jZS5nZXQoZHJpdmVyUmVmZXJlbmNlKSlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWZpbmVzIGF0dGFjaG1lbnREcml2ZXIuXG4gICAgICBAdHlwZSB7UmVjb3JkPHN0cmluZywgPz59ICovXG4gICAgbGV0IGF0dGFjaG1lbnREcml2ZXJcblxuICAgIGlmICh0eXBlb2YgZHJpdmVyUmVmZXJlbmNlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGNvbnN0IERyaXZlckNsYXNzID0gLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAdHlwZSB7QXR0YWNobWVudERyaXZlckNvbnN0cnVjdG9yfSAqLyAoZHJpdmVyUmVmZXJlbmNlKVxuXG4gICAgICBhdHRhY2htZW50RHJpdmVyID0gbmV3IERyaXZlckNsYXNzKHtcbiAgICAgICAgYXR0YWNobWVudE5hbWUsXG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgbW9kZWxDbGFzc1xuICAgICAgfSlcbiAgICB9IGVsc2UgaWYgKGRyaXZlclJlZmVyZW5jZSAmJiB0eXBlb2YgZHJpdmVyUmVmZXJlbmNlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBhdHRhY2htZW50RHJpdmVyID0gZHJpdmVyUmVmZXJlbmNlXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBhdHRhY2htZW50IGRyaXZlciByZWZlcmVuY2UgZm9yICR7bW9kZWxDbGFzcy5uYW1lfSMke2F0dGFjaG1lbnROYW1lfWApXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBhdHRhY2htZW50RHJpdmVyLndyaXRlICE9PSBcImZ1bmN0aW9uXCIgfHwgdHlwZW9mIGF0dGFjaG1lbnREcml2ZXIucmVhZCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEF0dGFjaG1lbnQgZHJpdmVyIGZvciAke21vZGVsQ2xhc3MubmFtZX0jJHthdHRhY2htZW50TmFtZX0gbXVzdCBpbXBsZW1lbnQgd3JpdGUvcmVhZGApXG4gICAgfVxuXG4gICAgdGhpcy5fYXR0YWNobWVudERyaXZlcnNCeVJlZmVyZW5jZS5zZXQoZHJpdmVyUmVmZXJlbmNlLCBhdHRhY2htZW50RHJpdmVyKVxuXG4gICAgcmV0dXJuIGF0dGFjaG1lbnREcml2ZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGF0dGFjaG1lbnQgZHJpdmVyIG5hbWUgZm9yLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vaW5kZXguanNcIikuZGVmYXVsdH0gYXJncy5tb2RlbCAtIE1vZGVsIGluc3RhbmNlLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5uYW1lIC0gQXR0YWNobWVudCBuYW1lLlxuICAgKiBAcmV0dXJucyB7c3RyaW5nfSAtIEF0dGFjaG1lbnQgZHJpdmVyIG5hbWUuXG4gICAqL1xuICBfYXR0YWNobWVudERyaXZlck5hbWVGb3Ioe21vZGVsLCBuYW1lfSkge1xuICAgIGNvbnN0IGF0dGFjaG1lbnREZWZpbml0aW9uID0gbW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldEF0dGFjaG1lbnRCeU5hbWUobmFtZSlcbiAgICBjb25zdCBjb25maWd1cmVkRHJpdmVyID0gYXR0YWNobWVudERlZmluaXRpb24uZHJpdmVyXG4gICAgY29uc3QgYXR0YWNobWVudHNDb25maWd1cmF0aW9uID0gdGhpcy5jb25maWd1cmF0aW9uLmdldEF0dGFjaG1lbnRzQ29uZmlndXJhdGlvbj8uKCkgfHwge31cbiAgICBjb25zdCBkZWZhdWx0RHJpdmVyID0gYXR0YWNobWVudHNDb25maWd1cmF0aW9uLmRlZmF1bHREcml2ZXJcblxuICAgIGlmICh0eXBlb2YgY29uZmlndXJlZERyaXZlciA9PT0gXCJzdHJpbmdcIiAmJiBjb25maWd1cmVkRHJpdmVyLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBjb25maWd1cmVkRHJpdmVyXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBjb25maWd1cmVkRHJpdmVyID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHJldHVybiBjb25maWd1cmVkRHJpdmVyLm5hbWUgfHwgXCJjdXN0b21cIlxuICAgIH1cblxuICAgIGlmIChjb25maWd1cmVkRHJpdmVyICYmIHR5cGVvZiBjb25maWd1cmVkRHJpdmVyID09PSBcIm9iamVjdFwiKSB7XG4gICAgICBjb25zdCBjb25zdHJ1Y3Rvck5hbWUgPSBjb25maWd1cmVkRHJpdmVyLmNvbnN0cnVjdG9yPy5uYW1lXG5cbiAgICAgIGlmICh0eXBlb2YgY29uc3RydWN0b3JOYW1lID09PSBcInN0cmluZ1wiICYmIGNvbnN0cnVjdG9yTmFtZS5sZW5ndGggPiAwICYmIGNvbnN0cnVjdG9yTmFtZSAhPT0gXCJPYmplY3RcIikge1xuICAgICAgICByZXR1cm4gY29uc3RydWN0b3JOYW1lXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBcImN1c3RvbVwiXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBkZWZhdWx0RHJpdmVyID09PSBcInN0cmluZ1wiICYmIGRlZmF1bHREcml2ZXIubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIGRlZmF1bHREcml2ZXJcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGF0dGFjaG1lbnQgZHJpdmVyIGNvbmZpZ3VyZWQgZm9yICR7bW9kZWwuZ2V0TW9kZWxDbGFzcygpLm5hbWV9IyR7bmFtZX1gKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgcmVzb2x2ZSBhdHRhY2htZW50IGRyaXZlci5cbiAgICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2luZGV4LmpzXCIpLmRlZmF1bHR9IGFyZ3MubW9kZWwgLSBNb2RlbCBpbnN0YW5jZS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MubmFtZSAtIEF0dGFjaG1lbnQgbmFtZS5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gW2FyZ3Mucm93XSAtIEF0dGFjaG1lbnQgcm93LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCA/Pj59IC0gQXR0YWNobWVudCBzdG9yYWdlIGRyaXZlciBpbnN0YW5jZS5cbiAgICovXG4gIGFzeW5jIHJlc29sdmVBdHRhY2htZW50RHJpdmVyKHttb2RlbCwgbmFtZSwgcm93fSkge1xuICAgIGNvbnN0IGF0dGFjaG1lbnREZWZpbml0aW9uID0gbW9kZWwuZ2V0TW9kZWxDbGFzcygpLmdldEF0dGFjaG1lbnRCeU5hbWUobmFtZSlcbiAgICBjb25zdCBjb25maWd1cmVkRHJpdmVyID0gYXR0YWNobWVudERlZmluaXRpb24uZHJpdmVyXG4gICAgaWYgKHR5cGVvZiBjb25maWd1cmVkRHJpdmVyID09PSBcImZ1bmN0aW9uXCIgfHwgKGNvbmZpZ3VyZWREcml2ZXIgJiYgdHlwZW9mIGNvbmZpZ3VyZWREcml2ZXIgPT09IFwib2JqZWN0XCIpKSB7XG4gICAgICByZXR1cm4gdGhpcy5hdHRhY2htZW50RHJpdmVyQnlSZWZlcmVuY2Uoe1xuICAgICAgICBhdHRhY2htZW50TmFtZTogbmFtZSxcbiAgICAgICAgZHJpdmVyUmVmZXJlbmNlOiBjb25maWd1cmVkRHJpdmVyLFxuICAgICAgICBtb2RlbENsYXNzOiBtb2RlbC5nZXRNb2RlbENsYXNzKClcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgY29uc3QgZmFsbGJhY2tEcml2ZXJOYW1lID0gdHlwZW9mIHJvdz8uZHJpdmVyID09PSBcInN0cmluZ1wiICYmIHJvdy5kcml2ZXIubGVuZ3RoID4gMFxuICAgICAgPyByb3cuZHJpdmVyXG4gICAgICA6IHRoaXMuX2F0dGFjaG1lbnREcml2ZXJOYW1lRm9yKHttb2RlbCwgbmFtZX0pXG5cbiAgICByZXR1cm4gYXdhaXQgdGhpcy5hdHRhY2htZW50RHJpdmVyQnlOYW1lKGZhbGxiYWNrRHJpdmVyTmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIG5leHQgcG9zaXRpb24uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi8uLi8uLi9kYXRhYmFzZS9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdH0gYXJncy5kYiAtIERCIGNvbm5lY3Rpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBBdHRhY2htZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLnJlY29yZElkIC0gUmVjb3JkIGlkLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gYXJncy5yZWNvcmRUeXBlIC0gUmVjb3JkIHR5cGUuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPG51bWJlcj59IC0gTmV4dCBwb3NpdGlvbi5cbiAgICovXG4gIGFzeW5jIF9uZXh0UG9zaXRpb24oe2RiLCBuYW1lLCByZWNvcmRJZCwgcmVjb3JkVHlwZX0pIHtcbiAgICBjb25zdCBxdWVyeSA9IGRiXG4gICAgICAubmV3UXVlcnkoKVxuICAgICAgLmZyb20oQVRUQUNITUVOVFNfVEFCTEUpXG4gICAgICAud2hlcmUoe25hbWUsIHJlY29yZF9pZDogcmVjb3JkSWQsIHJlY29yZF90eXBlOiByZWNvcmRUeXBlfSlcbiAgICAgIC5vcmRlcihcInBvc2l0aW9uIERFU0NcIilcbiAgICAgIC5saW1pdCgxKVxuICAgIGNvbnN0IHJvd3MgPSBhd2FpdCBxdWVyeS5yZXN1bHRzKClcbiAgICBjb25zdCBjdXJyZW50Um93ID0gLyoqXG4gICAgICAgICAgICAgICAgICAgICAgICAqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICBAdHlwZSB7e3Bvc2l0aW9uPzogc3RyaW5nIHwgbnVtYmVyIHwgbnVsbH0gfCB1bmRlZmluZWR9ICovIChyb3dzWzBdKVxuICAgIGNvbnN0IGN1cnJlbnQgPSBOdW1iZXIoY3VycmVudFJvdz8ucG9zaXRpb24pXG5cbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShjdXJyZW50KSkgcmV0dXJuIDBcblxuICAgIHJldHVybiBjdXJyZW50ICsgMVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgd2l0aCBkYi5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHsoZGI6IGltcG9ydChcIi4uLy4uLy4uL2RhdGFiYXNlL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0KSA9PiBQcm9taXNlPFQ+fSBjYWxsYmFjayAtIENhbGxiYWNrLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUPn0gLSBDYWxsYmFjayByZXN1bHQuXG4gICAqL1xuICBhc3luYyBfd2l0aERiKGNhbGxiYWNrKSB7XG4gICAgY29uc3QgcG9vbCA9IHRoaXMuY29uZmlndXJhdGlvbi5nZXREYXRhYmFzZVBvb2wodGhpcy5kYXRhYmFzZUlkZW50aWZpZXIpXG4gICAgLyoqXG4gICAgICogRGVmaW5lcyByZXN1bHQuXG4gICAgICBAdHlwZSB7VCB8IHVuZGVmaW5lZH0gKi9cbiAgICBsZXQgcmVzdWx0XG5cbiAgICBhd2FpdCBwb29sLndpdGhDb25uZWN0aW9uKHtuYW1lOiBcIlJlY29yZCBhdHRhY2htZW50IHN0b3JlXCJ9LCBhc3luYyAoZGIpID0+IHtcbiAgICAgIHJlc3VsdCA9IGF3YWl0IGNhbGxiYWNrKGRiKVxuICAgIH0pXG5cbiAgICByZXR1cm4gLyoqIE5hcnJvd3MgdGhlIHJ1bnRpbWUgdmFsdWUgdG8gdGhlIGRvY3VtZW50ZWQgdHlwZS4gQHR5cGUge1R9ICovIChyZXN1bHQpXG4gIH1cbn1cbiJdfQ==