velocious 1.0.430 → 1.0.432

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 (831) hide show
  1. package/bin/velocious.js +48 -0
  2. package/build/application.js +229 -0
  3. package/build/authorization/ability.js +329 -0
  4. package/build/authorization/base-resource.js +143 -0
  5. package/build/background-jobs/client.js +50 -0
  6. package/build/background-jobs/cron-expression.js +277 -0
  7. package/build/background-jobs/forked-runner-child.js +86 -0
  8. package/build/background-jobs/job-record.js +13 -0
  9. package/build/background-jobs/job-registry.js +92 -0
  10. package/build/background-jobs/job-runner.js +107 -0
  11. package/build/background-jobs/job.js +77 -0
  12. package/build/background-jobs/json-socket.js +78 -0
  13. package/build/background-jobs/main.js +926 -0
  14. package/build/background-jobs/normalize-error.js +26 -0
  15. package/build/background-jobs/scheduler.js +274 -0
  16. package/build/background-jobs/socket-request.js +68 -0
  17. package/build/background-jobs/status-reporter.js +101 -0
  18. package/build/background-jobs/store.js +994 -0
  19. package/build/background-jobs/types.js +70 -0
  20. package/build/background-jobs/web/authorization.js +89 -0
  21. package/build/background-jobs/web/controller.js +280 -0
  22. package/build/background-jobs/web/index.js +57 -0
  23. package/build/background-jobs/web/path-matcher.js +74 -0
  24. package/build/background-jobs/web/registry.js +49 -0
  25. package/build/background-jobs/worker.js +683 -0
  26. package/build/beacon/client.js +330 -0
  27. package/build/beacon/in-process-broker.js +71 -0
  28. package/build/beacon/in-process-client.js +139 -0
  29. package/build/beacon/server.js +148 -0
  30. package/build/beacon/types.js +55 -0
  31. package/build/bin/velocious.js +39 -34
  32. package/build/cli/base-command.js +67 -0
  33. package/build/cli/browser-cli.js +45 -0
  34. package/build/cli/commands/background-jobs-main.js +7 -0
  35. package/build/cli/commands/background-jobs-runner.js +7 -0
  36. package/build/cli/commands/background-jobs-worker.js +7 -0
  37. package/build/cli/commands/beacon.js +7 -0
  38. package/build/cli/commands/console.js +12 -0
  39. package/build/cli/commands/db/base-command.js +82 -0
  40. package/build/cli/commands/db/create.js +64 -0
  41. package/build/cli/commands/db/drop.js +75 -0
  42. package/build/cli/commands/db/migrate.js +17 -0
  43. package/build/cli/commands/db/reset.js +22 -0
  44. package/build/cli/commands/db/rollback.js +15 -0
  45. package/build/cli/commands/db/schema/dump.js +12 -0
  46. package/build/cli/commands/db/schema/load.js +12 -0
  47. package/build/cli/commands/db/seed.js +12 -0
  48. package/build/cli/commands/db/tenants/check.js +38 -0
  49. package/build/cli/commands/db/tenants/create.js +33 -0
  50. package/build/cli/commands/db/tenants/migrate.js +49 -0
  51. package/build/cli/commands/destroy/migration.js +7 -0
  52. package/build/cli/commands/generate/base-models.js +7 -0
  53. package/build/cli/commands/generate/frontend-models.js +12 -0
  54. package/build/cli/commands/generate/migration.js +7 -0
  55. package/build/cli/commands/generate/model.js +7 -0
  56. package/build/cli/commands/init.js +11 -0
  57. package/build/cli/commands/routes.js +7 -0
  58. package/build/cli/commands/run-script.js +12 -0
  59. package/build/cli/commands/runner.js +12 -0
  60. package/build/cli/commands/server.js +7 -0
  61. package/build/cli/commands/test.js +9 -0
  62. package/build/cli/index.js +152 -0
  63. package/build/cli/tenant-database-command-helper.js +198 -0
  64. package/build/cli/use-browser-cli.js +30 -0
  65. package/build/configuration-resolver.js +65 -0
  66. package/build/configuration-types.js +429 -0
  67. package/build/configuration.js +2590 -0
  68. package/build/controller.js +421 -0
  69. package/build/current-configuration.js +31 -0
  70. package/build/current.js +80 -0
  71. package/build/database/annotations-async-hooks.js +47 -0
  72. package/build/database/annotations.js +40 -0
  73. package/build/database/drivers/base-column.js +182 -0
  74. package/build/database/drivers/base-columns-index.js +81 -0
  75. package/build/database/drivers/base-foreign-key.js +104 -0
  76. package/build/database/drivers/base-table.js +156 -0
  77. package/build/database/drivers/base.js +1609 -0
  78. package/build/database/drivers/mssql/column.js +74 -0
  79. package/build/database/drivers/mssql/columns-index.js +6 -0
  80. package/build/database/drivers/mssql/connect-connection.js +16 -0
  81. package/build/database/drivers/mssql/foreign-key.js +12 -0
  82. package/build/database/drivers/mssql/index.js +590 -0
  83. package/build/database/drivers/mssql/options.js +79 -0
  84. package/build/database/drivers/mssql/query-parser.js +6 -0
  85. package/build/database/drivers/mssql/sql/alter-table.js +4 -0
  86. package/build/database/drivers/mssql/sql/create-database.js +36 -0
  87. package/build/database/drivers/mssql/sql/create-index.js +4 -0
  88. package/build/database/drivers/mssql/sql/create-table.js +4 -0
  89. package/build/database/drivers/mssql/sql/delete.js +19 -0
  90. package/build/database/drivers/mssql/sql/drop-database.js +36 -0
  91. package/build/database/drivers/mssql/sql/drop-table.js +4 -0
  92. package/build/database/drivers/mssql/sql/insert.js +4 -0
  93. package/build/database/drivers/mssql/sql/update.js +31 -0
  94. package/build/database/drivers/mssql/sql/upsert.js +23 -0
  95. package/build/database/drivers/mssql/structure-sql.js +120 -0
  96. package/build/database/drivers/mssql/table.js +145 -0
  97. package/build/database/drivers/mysql/column.js +112 -0
  98. package/build/database/drivers/mysql/columns-index.js +22 -0
  99. package/build/database/drivers/mysql/foreign-key.js +12 -0
  100. package/build/database/drivers/mysql/index.js +473 -0
  101. package/build/database/drivers/mysql/options.js +34 -0
  102. package/build/database/drivers/mysql/query-parser.js +6 -0
  103. package/build/database/drivers/mysql/query.js +37 -0
  104. package/build/database/drivers/mysql/sql/alter-table.js +6 -0
  105. package/build/database/drivers/mysql/sql/create-database.js +39 -0
  106. package/build/database/drivers/mysql/sql/create-index.js +6 -0
  107. package/build/database/drivers/mysql/sql/create-table.js +6 -0
  108. package/build/database/drivers/mysql/sql/delete.js +21 -0
  109. package/build/database/drivers/mysql/sql/drop-database.js +6 -0
  110. package/build/database/drivers/mysql/sql/drop-table.js +6 -0
  111. package/build/database/drivers/mysql/sql/insert.js +6 -0
  112. package/build/database/drivers/mysql/sql/update.js +33 -0
  113. package/build/database/drivers/mysql/sql/upsert.js +13 -0
  114. package/build/database/drivers/mysql/structure-sql.js +93 -0
  115. package/build/database/drivers/mysql/table.js +121 -0
  116. package/build/database/drivers/pgsql/column.js +90 -0
  117. package/build/database/drivers/pgsql/columns-index.js +6 -0
  118. package/build/database/drivers/pgsql/foreign-key.js +12 -0
  119. package/build/database/drivers/pgsql/index.js +441 -0
  120. package/build/database/drivers/pgsql/options.js +32 -0
  121. package/build/database/drivers/pgsql/query-parser.js +6 -0
  122. package/build/database/drivers/pgsql/sql/alter-table.js +6 -0
  123. package/build/database/drivers/pgsql/sql/create-database.js +38 -0
  124. package/build/database/drivers/pgsql/sql/create-index.js +6 -0
  125. package/build/database/drivers/pgsql/sql/create-table.js +6 -0
  126. package/build/database/drivers/pgsql/sql/delete.js +21 -0
  127. package/build/database/drivers/pgsql/sql/drop-database.js +6 -0
  128. package/build/database/drivers/pgsql/sql/drop-table.js +6 -0
  129. package/build/database/drivers/pgsql/sql/insert.js +6 -0
  130. package/build/database/drivers/pgsql/sql/update.js +33 -0
  131. package/build/database/drivers/pgsql/sql/upsert.js +14 -0
  132. package/build/database/drivers/pgsql/structure-sql.js +126 -0
  133. package/build/database/drivers/pgsql/table.js +135 -0
  134. package/build/database/drivers/sqlite/base.js +509 -0
  135. package/build/database/drivers/sqlite/column.js +75 -0
  136. package/build/database/drivers/sqlite/columns-index.js +30 -0
  137. package/build/database/drivers/sqlite/connection-sql-js.js +46 -0
  138. package/build/database/drivers/sqlite/foreign-key.js +24 -0
  139. package/build/database/drivers/sqlite/index.js +394 -0
  140. package/build/database/drivers/sqlite/index.native.js +72 -0
  141. package/build/database/drivers/sqlite/index.web.js +99 -0
  142. package/build/database/drivers/sqlite/options.js +32 -0
  143. package/build/database/drivers/sqlite/query-parser.js +6 -0
  144. package/build/database/drivers/sqlite/query.js +35 -0
  145. package/build/database/drivers/sqlite/query.native.js +35 -0
  146. package/build/database/drivers/sqlite/query.web.js +49 -0
  147. package/build/database/drivers/sqlite/sql/alter-table.js +187 -0
  148. package/build/database/drivers/sqlite/sql/create-index.js +6 -0
  149. package/build/database/drivers/sqlite/sql/create-table.js +6 -0
  150. package/build/database/drivers/sqlite/sql/delete.js +26 -0
  151. package/build/database/drivers/sqlite/sql/drop-table.js +6 -0
  152. package/build/database/drivers/sqlite/sql/insert.js +6 -0
  153. package/build/database/drivers/sqlite/sql/update.js +33 -0
  154. package/build/database/drivers/sqlite/sql/upsert.js +14 -0
  155. package/build/database/drivers/sqlite/structure-sql.js +56 -0
  156. package/build/database/drivers/sqlite/table-rebuilder.js +96 -0
  157. package/build/database/drivers/sqlite/table.js +131 -0
  158. package/build/database/drivers/structure-sql/utils.js +35 -0
  159. package/build/database/handler.js +13 -0
  160. package/build/database/initializer-from-require-context.js +101 -0
  161. package/build/database/migration/index.js +438 -0
  162. package/build/database/migrator/files-finder.js +55 -0
  163. package/build/database/migrator/types.js +31 -0
  164. package/build/database/migrator.js +557 -0
  165. package/build/database/pool/async-tracked-multi-connection.js +1164 -0
  166. package/build/database/pool/base-methods-forward.js +52 -0
  167. package/build/database/pool/base.js +380 -0
  168. package/build/database/pool/single-multi-use.js +118 -0
  169. package/build/database/query/alter-table-base.js +104 -0
  170. package/build/database/query/base.js +49 -0
  171. package/build/database/query/create-database-base.js +42 -0
  172. package/build/database/query/create-index-base.js +117 -0
  173. package/build/database/query/create-table-base.js +205 -0
  174. package/build/database/query/delete-base.js +19 -0
  175. package/build/database/query/drop-database-base.js +38 -0
  176. package/build/database/query/drop-table-base.js +58 -0
  177. package/build/database/query/from-base.js +36 -0
  178. package/build/database/query/from-plain.js +16 -0
  179. package/build/database/query/from-table.js +18 -0
  180. package/build/database/query/index.js +533 -0
  181. package/build/database/query/insert-base.js +172 -0
  182. package/build/database/query/join-base.js +43 -0
  183. package/build/database/query/join-object.js +167 -0
  184. package/build/database/query/join-plain.js +18 -0
  185. package/build/database/query/join-tracker.js +93 -0
  186. package/build/database/query/model-class-query.js +1577 -0
  187. package/build/database/query/order-base.js +33 -0
  188. package/build/database/query/order-column.js +77 -0
  189. package/build/database/query/order-plain.js +28 -0
  190. package/build/database/query/preloader/belongs-to.js +267 -0
  191. package/build/database/query/preloader/ensure-model-class-initialized.js +18 -0
  192. package/build/database/query/preloader/has-many.js +316 -0
  193. package/build/database/query/preloader/has-one.js +123 -0
  194. package/build/database/query/preloader/selection.js +152 -0
  195. package/build/database/query/preloader.js +201 -0
  196. package/build/database/query/query-data.js +305 -0
  197. package/build/database/query/select-base.js +30 -0
  198. package/build/database/query/select-plain.js +18 -0
  199. package/build/database/query/select-table-and-column.js +28 -0
  200. package/build/database/query/update-base.js +41 -0
  201. package/build/database/query/upsert-base.js +103 -0
  202. package/build/database/query/where-base.js +38 -0
  203. package/build/database/query/where-combinator.js +31 -0
  204. package/build/database/query/where-hash.js +77 -0
  205. package/build/database/query/where-model-class-hash.js +505 -0
  206. package/build/database/query/where-not.js +23 -0
  207. package/build/database/query/where-plain.js +20 -0
  208. package/build/database/query/with-count.js +219 -0
  209. package/build/database/query-parser/base-query-parser.js +40 -0
  210. package/build/database/query-parser/from-parser.js +49 -0
  211. package/build/database/query-parser/group-parser.js +55 -0
  212. package/build/database/query-parser/joins-parser.js +37 -0
  213. package/build/database/query-parser/limit-parser.js +77 -0
  214. package/build/database/query-parser/options.js +94 -0
  215. package/build/database/query-parser/order-parser.js +45 -0
  216. package/build/database/query-parser/select-parser.js +67 -0
  217. package/build/database/query-parser/where-parser.js +46 -0
  218. package/build/database/record/acts-as-list.js +374 -0
  219. package/build/database/record/attachments/download.js +49 -0
  220. package/build/database/record/attachments/handle.js +188 -0
  221. package/build/database/record/attachments/normalize-input.js +213 -0
  222. package/build/database/record/attachments/storage-drivers/filesystem.js +114 -0
  223. package/build/database/record/attachments/storage-drivers/native.js +146 -0
  224. package/build/database/record/attachments/storage-drivers/s3.js +245 -0
  225. package/build/database/record/attachments/store.js +591 -0
  226. package/build/database/record/index.js +4094 -0
  227. package/build/database/record/instance-relationships/base.js +289 -0
  228. package/build/database/record/instance-relationships/belongs-to.js +84 -0
  229. package/build/database/record/instance-relationships/has-many.js +284 -0
  230. package/build/database/record/instance-relationships/has-one.js +117 -0
  231. package/build/database/record/record-not-found-error.js +3 -0
  232. package/build/database/record/relationships/base.js +195 -0
  233. package/build/database/record/relationships/belongs-to.js +57 -0
  234. package/build/database/record/relationships/has-many.js +46 -0
  235. package/build/database/record/relationships/has-one.js +46 -0
  236. package/build/database/record/state-machine.js +278 -0
  237. package/build/database/record/user-module.js +43 -0
  238. package/build/database/record/validators/base.js +27 -0
  239. package/build/database/record/validators/format.js +50 -0
  240. package/build/database/record/validators/presence.js +24 -0
  241. package/build/database/record/validators/uniqueness.js +124 -0
  242. package/build/database/table-data/index.js +241 -0
  243. package/build/database/table-data/table-column.js +416 -0
  244. package/build/database/table-data/table-foreign-key.js +69 -0
  245. package/build/database/table-data/table-index.js +46 -0
  246. package/build/database/table-data/table-reference.js +13 -0
  247. package/build/database/use-database.js +48 -0
  248. package/build/environment-handlers/base.js +561 -0
  249. package/build/environment-handlers/browser.js +338 -0
  250. package/build/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
  251. package/build/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
  252. package/build/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
  253. package/build/environment-handlers/node/cli/commands/beacon.js +21 -0
  254. package/build/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
  255. package/build/environment-handlers/node/cli/commands/console.js +149 -0
  256. package/build/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
  257. package/build/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
  258. package/build/environment-handlers/node/cli/commands/db/seed.js +79 -0
  259. package/build/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
  260. package/build/environment-handlers/node/cli/commands/generate/base-models.js +396 -0
  261. package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
  262. package/build/environment-handlers/node/cli/commands/generate/migration.js +45 -0
  263. package/build/environment-handlers/node/cli/commands/generate/model.js +45 -0
  264. package/build/environment-handlers/node/cli/commands/init.js +68 -0
  265. package/build/environment-handlers/node/cli/commands/routes.js +63 -0
  266. package/build/environment-handlers/node/cli/commands/run-script.js +85 -0
  267. package/build/environment-handlers/node/cli/commands/runner.js +84 -0
  268. package/build/environment-handlers/node/cli/commands/server.js +151 -0
  269. package/build/environment-handlers/node/cli/commands/test.js +118 -0
  270. package/build/environment-handlers/node.js +887 -0
  271. package/build/error-logger.js +30 -0
  272. package/build/frontend-model-controller.js +3491 -0
  273. package/build/frontend-model-resource/base-resource.js +935 -0
  274. package/build/frontend-models/base.js +4004 -0
  275. package/build/frontend-models/clear-pending-debounced-callback.js +16 -0
  276. package/build/frontend-models/event-hook-models.js +49 -0
  277. package/build/frontend-models/model-registry.js +28 -0
  278. package/build/frontend-models/outgoing-event-buffer.js +51 -0
  279. package/build/frontend-models/preloader.js +169 -0
  280. package/build/frontend-models/query.js +2245 -0
  281. package/build/frontend-models/resource-config-validation.js +56 -0
  282. package/build/frontend-models/resource-definition.js +399 -0
  283. package/build/frontend-models/transport-serialization.js +369 -0
  284. package/build/frontend-models/use-created-event.js +21 -0
  285. package/build/frontend-models/use-destroyed-event.js +148 -0
  286. package/build/frontend-models/use-model-class-event.js +164 -0
  287. package/build/frontend-models/use-updated-event.js +152 -0
  288. package/build/frontend-models/websocket-channel.js +494 -0
  289. package/build/frontend-models/websocket-publishers.js +224 -0
  290. package/build/http-client/header.js +17 -0
  291. package/build/http-client/index.js +139 -0
  292. package/build/http-client/request.js +94 -0
  293. package/build/http-client/response.js +151 -0
  294. package/build/http-client/websocket-client.js +27 -0
  295. package/build/http-server/client/index.js +507 -0
  296. package/build/http-server/client/params-to-object.js +152 -0
  297. package/build/http-server/client/request-buffer/form-data-part.js +139 -0
  298. package/build/http-server/client/request-buffer/header.js +19 -0
  299. package/build/http-server/client/request-buffer/index.js +535 -0
  300. package/build/http-server/client/request-parser.js +195 -0
  301. package/build/http-server/client/request-runner.js +321 -0
  302. package/build/http-server/client/request-timing.js +171 -0
  303. package/build/http-server/client/request.js +114 -0
  304. package/build/http-server/client/response.js +251 -0
  305. package/build/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
  306. package/build/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
  307. package/build/http-server/client/uploaded-file/uploaded-file.js +36 -0
  308. package/build/http-server/client/websocket-request.js +147 -0
  309. package/build/http-server/client/websocket-session.js +1755 -0
  310. package/build/http-server/cookie.js +245 -0
  311. package/build/http-server/development-reloader.js +240 -0
  312. package/build/http-server/index.js +561 -0
  313. package/build/http-server/remote-address.js +77 -0
  314. package/build/http-server/server-client.js +222 -0
  315. package/build/http-server/server-lock.js +178 -0
  316. package/build/http-server/websocket-channel-subscribers.js +110 -0
  317. package/build/http-server/websocket-channel.js +137 -0
  318. package/build/http-server/websocket-connection.js +118 -0
  319. package/build/http-server/websocket-event-log-store.js +433 -0
  320. package/build/http-server/websocket-events-host.js +170 -0
  321. package/build/http-server/websocket-events.js +50 -0
  322. package/build/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
  323. package/build/http-server/worker-handler/in-process.js +155 -0
  324. package/build/http-server/worker-handler/index.js +370 -0
  325. package/build/http-server/worker-handler/worker-script.js +6 -0
  326. package/build/http-server/worker-handler/worker-thread.js +286 -0
  327. package/build/index.js +1 -2
  328. package/build/initializer.js +39 -0
  329. package/build/jobs/mail-delivery.js +22 -0
  330. package/build/logger/base-logger.js +34 -0
  331. package/build/logger/console-logger.js +28 -0
  332. package/build/logger/file-logger.js +36 -0
  333. package/build/logger/outputs/array-output.js +50 -0
  334. package/build/logger/outputs/console-output.js +32 -0
  335. package/build/logger/outputs/file-output.js +55 -0
  336. package/build/logger/outputs/stdout-output.js +64 -0
  337. package/build/logger.js +507 -0
  338. package/build/mailer/backends/smtp.js +197 -0
  339. package/build/mailer/base.js +337 -0
  340. package/build/mailer/delivery.js +70 -0
  341. package/build/mailer/index.js +24 -0
  342. package/build/mailer.js +15 -0
  343. package/build/plugins/sqljs-wasm-route-controller.js +70 -0
  344. package/build/plugins/sqljs-wasm-route.js +71 -0
  345. package/build/record-payload-values.js +83 -0
  346. package/build/routes/app-routes.js +17 -0
  347. package/build/routes/base-route.js +133 -0
  348. package/build/routes/basic-route.js +109 -0
  349. package/build/routes/built-in/debug/controller.js +12 -0
  350. package/build/routes/built-in/errors/controller.js +7 -0
  351. package/build/routes/get-route.js +75 -0
  352. package/build/routes/hooks/frontend-model-command-route-hook.js +100 -0
  353. package/build/routes/index.js +50 -0
  354. package/build/routes/namespace-route.js +51 -0
  355. package/build/routes/plugin-routes.js +141 -0
  356. package/build/routes/post-route.js +74 -0
  357. package/build/routes/resolver.js +535 -0
  358. package/build/routes/resource-route.js +154 -0
  359. package/build/routes/root-route.js +11 -0
  360. package/build/src/authorization/ability.d.ts +24 -23
  361. package/build/src/authorization/ability.d.ts.map +1 -1
  362. package/build/src/authorization/ability.js +14 -13
  363. package/build/src/authorization/base-resource.d.ts +20 -26
  364. package/build/src/authorization/base-resource.d.ts.map +1 -1
  365. package/build/src/authorization/base-resource.js +13 -11
  366. package/build/src/configuration-types.d.ts +21 -2
  367. package/build/src/configuration-types.d.ts.map +1 -1
  368. package/build/src/configuration-types.js +8 -2
  369. package/build/src/database/query/where-combinator.d.ts.map +1 -1
  370. package/build/src/database/query/where-combinator.js +1 -2
  371. package/build/src/database/record/acts-as-list.js +2 -2
  372. package/build/src/database/record/attachments/store.d.ts +1 -1
  373. package/build/src/database/record/attachments/store.d.ts.map +1 -1
  374. package/build/src/database/record/attachments/store.js +2 -2
  375. package/build/src/database/record/index.d.ts +82 -20
  376. package/build/src/database/record/index.d.ts.map +1 -1
  377. package/build/src/database/record/index.js +126 -13
  378. package/build/src/database/record/relationships/base.d.ts +2 -2
  379. package/build/src/database/record/relationships/base.d.ts.map +1 -1
  380. package/build/src/database/record/relationships/base.js +3 -3
  381. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts +4 -2
  382. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
  383. package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +59 -36
  384. package/build/src/frontend-model-controller.d.ts +6 -6
  385. package/build/src/frontend-model-controller.d.ts.map +1 -1
  386. package/build/src/frontend-model-controller.js +4 -4
  387. package/build/src/frontend-model-resource/base-resource.d.ts +18 -17
  388. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  389. package/build/src/frontend-model-resource/base-resource.js +22 -10
  390. package/build/src/frontend-models/base.d.ts +19 -12
  391. package/build/src/frontend-models/base.d.ts.map +1 -1
  392. package/build/src/frontend-models/base.js +79 -48
  393. package/build/src/frontend-models/preloader.d.ts +6 -6
  394. package/build/src/frontend-models/preloader.d.ts.map +1 -1
  395. package/build/src/frontend-models/preloader.js +5 -5
  396. package/build/src/frontend-models/query.d.ts.map +1 -1
  397. package/build/src/frontend-models/query.js +1 -4
  398. package/build/src/utils/ransack.d.ts.map +1 -1
  399. package/build/src/utils/ransack.js +1 -2
  400. package/build/templates/configuration.js +61 -0
  401. package/build/templates/generate-migration.js +11 -0
  402. package/build/templates/generate-model.js +6 -0
  403. package/build/templates/routes.js +11 -0
  404. package/build/testing/base-expect.js +17 -0
  405. package/build/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
  406. package/build/testing/browser-test-app.js +32 -0
  407. package/build/testing/expect-to-change.js +55 -0
  408. package/build/testing/expect-utils.js +269 -0
  409. package/build/testing/expect.js +763 -0
  410. package/build/testing/request-client.js +90 -0
  411. package/build/testing/test-files-finder.js +364 -0
  412. package/build/testing/test-filter-parser.js +198 -0
  413. package/build/testing/test-runner.js +1168 -0
  414. package/build/testing/test-suite-splitter.js +177 -0
  415. package/build/testing/test.js +370 -0
  416. package/build/utils/backtrace-cleaner-node.js +87 -0
  417. package/build/utils/backtrace-cleaner.js +266 -0
  418. package/build/utils/ensure-error.js +15 -0
  419. package/build/utils/event-emitter.js +8 -0
  420. package/build/utils/file-exists.js +18 -0
  421. package/build/utils/format-value.js +101 -0
  422. package/build/utils/model-scope.js +56 -0
  423. package/build/utils/nest-callbacks.js +22 -0
  424. package/build/utils/plain-object.js +14 -0
  425. package/build/utils/ransack.js +859 -0
  426. package/build/utils/rest-args-error.js +14 -0
  427. package/build/utils/singularize-model-name.js +18 -0
  428. package/build/utils/split-sql-statements.js +88 -0
  429. package/build/utils/to-import-specifier.js +53 -0
  430. package/build/utils/with-tracked-stack-async-hooks.js +103 -0
  431. package/build/utils/with-tracked-stack.js +38 -0
  432. package/build/velocious-error.js +34 -0
  433. package/index.js +1 -0
  434. package/package.json +10 -4
  435. package/scripts/clean-build.js +8 -0
  436. package/scripts/ensure-bin-executable.js +13 -0
  437. package/scripts/run-tests.js +37 -0
  438. package/scripts/test-browser.js +486 -0
  439. package/src/application.js +229 -0
  440. package/src/authorization/ability.js +329 -0
  441. package/src/authorization/base-resource.js +143 -0
  442. package/src/background-jobs/client.js +50 -0
  443. package/src/background-jobs/cron-expression.js +277 -0
  444. package/src/background-jobs/forked-runner-child.js +86 -0
  445. package/src/background-jobs/job-record.js +13 -0
  446. package/src/background-jobs/job-registry.js +92 -0
  447. package/src/background-jobs/job-runner.js +107 -0
  448. package/src/background-jobs/job.js +77 -0
  449. package/src/background-jobs/json-socket.js +78 -0
  450. package/src/background-jobs/main.js +926 -0
  451. package/src/background-jobs/normalize-error.js +26 -0
  452. package/src/background-jobs/scheduler.js +274 -0
  453. package/src/background-jobs/socket-request.js +68 -0
  454. package/src/background-jobs/status-reporter.js +101 -0
  455. package/src/background-jobs/store.js +994 -0
  456. package/src/background-jobs/types.js +70 -0
  457. package/src/background-jobs/web/authorization.js +89 -0
  458. package/src/background-jobs/web/controller.js +280 -0
  459. package/src/background-jobs/web/index.js +57 -0
  460. package/src/background-jobs/web/path-matcher.js +74 -0
  461. package/src/background-jobs/web/registry.js +49 -0
  462. package/src/background-jobs/worker.js +683 -0
  463. package/src/beacon/client.js +330 -0
  464. package/src/beacon/in-process-broker.js +71 -0
  465. package/src/beacon/in-process-client.js +139 -0
  466. package/src/beacon/server.js +148 -0
  467. package/src/beacon/types.js +55 -0
  468. package/src/cli/base-command.js +67 -0
  469. package/src/cli/browser-cli.js +45 -0
  470. package/src/cli/commands/background-jobs-main.js +7 -0
  471. package/src/cli/commands/background-jobs-runner.js +7 -0
  472. package/src/cli/commands/background-jobs-worker.js +7 -0
  473. package/src/cli/commands/beacon.js +7 -0
  474. package/src/cli/commands/console.js +12 -0
  475. package/src/cli/commands/db/base-command.js +82 -0
  476. package/src/cli/commands/db/create.js +64 -0
  477. package/src/cli/commands/db/drop.js +75 -0
  478. package/src/cli/commands/db/migrate.js +17 -0
  479. package/src/cli/commands/db/reset.js +22 -0
  480. package/src/cli/commands/db/rollback.js +15 -0
  481. package/src/cli/commands/db/schema/dump.js +12 -0
  482. package/src/cli/commands/db/schema/load.js +12 -0
  483. package/src/cli/commands/db/seed.js +12 -0
  484. package/src/cli/commands/db/tenants/check.js +38 -0
  485. package/src/cli/commands/db/tenants/create.js +33 -0
  486. package/src/cli/commands/db/tenants/migrate.js +49 -0
  487. package/src/cli/commands/destroy/migration.js +7 -0
  488. package/src/cli/commands/generate/base-models.js +7 -0
  489. package/src/cli/commands/generate/frontend-models.js +12 -0
  490. package/src/cli/commands/generate/migration.js +7 -0
  491. package/src/cli/commands/generate/model.js +7 -0
  492. package/src/cli/commands/init.js +11 -0
  493. package/src/cli/commands/routes.js +7 -0
  494. package/src/cli/commands/run-script.js +12 -0
  495. package/src/cli/commands/runner.js +12 -0
  496. package/src/cli/commands/server.js +7 -0
  497. package/src/cli/commands/test.js +9 -0
  498. package/src/cli/index.js +152 -0
  499. package/src/cli/tenant-database-command-helper.js +198 -0
  500. package/src/cli/use-browser-cli.js +30 -0
  501. package/src/configuration-resolver.js +65 -0
  502. package/src/configuration-types.js +429 -0
  503. package/src/configuration.js +2590 -0
  504. package/src/controller.js +421 -0
  505. package/src/current-configuration.js +31 -0
  506. package/src/current.js +80 -0
  507. package/src/database/annotations-async-hooks.js +47 -0
  508. package/src/database/annotations.js +40 -0
  509. package/src/database/drivers/base-column.js +182 -0
  510. package/src/database/drivers/base-columns-index.js +81 -0
  511. package/src/database/drivers/base-foreign-key.js +104 -0
  512. package/src/database/drivers/base-table.js +156 -0
  513. package/src/database/drivers/base.js +1609 -0
  514. package/src/database/drivers/mssql/column.js +74 -0
  515. package/src/database/drivers/mssql/columns-index.js +6 -0
  516. package/src/database/drivers/mssql/connect-connection.js +16 -0
  517. package/src/database/drivers/mssql/foreign-key.js +12 -0
  518. package/src/database/drivers/mssql/index.js +590 -0
  519. package/src/database/drivers/mssql/options.js +79 -0
  520. package/src/database/drivers/mssql/query-parser.js +6 -0
  521. package/src/database/drivers/mssql/sql/alter-table.js +4 -0
  522. package/src/database/drivers/mssql/sql/create-database.js +36 -0
  523. package/src/database/drivers/mssql/sql/create-index.js +4 -0
  524. package/src/database/drivers/mssql/sql/create-table.js +4 -0
  525. package/src/database/drivers/mssql/sql/delete.js +19 -0
  526. package/src/database/drivers/mssql/sql/drop-database.js +36 -0
  527. package/src/database/drivers/mssql/sql/drop-table.js +4 -0
  528. package/src/database/drivers/mssql/sql/insert.js +4 -0
  529. package/src/database/drivers/mssql/sql/update.js +31 -0
  530. package/src/database/drivers/mssql/sql/upsert.js +23 -0
  531. package/src/database/drivers/mssql/structure-sql.js +120 -0
  532. package/src/database/drivers/mssql/table.js +145 -0
  533. package/src/database/drivers/mysql/column.js +112 -0
  534. package/src/database/drivers/mysql/columns-index.js +22 -0
  535. package/src/database/drivers/mysql/foreign-key.js +12 -0
  536. package/src/database/drivers/mysql/index.js +473 -0
  537. package/src/database/drivers/mysql/options.js +34 -0
  538. package/src/database/drivers/mysql/query-parser.js +6 -0
  539. package/src/database/drivers/mysql/query.js +37 -0
  540. package/src/database/drivers/mysql/sql/alter-table.js +6 -0
  541. package/src/database/drivers/mysql/sql/create-database.js +39 -0
  542. package/src/database/drivers/mysql/sql/create-index.js +6 -0
  543. package/src/database/drivers/mysql/sql/create-table.js +6 -0
  544. package/src/database/drivers/mysql/sql/delete.js +21 -0
  545. package/src/database/drivers/mysql/sql/drop-database.js +6 -0
  546. package/src/database/drivers/mysql/sql/drop-table.js +6 -0
  547. package/src/database/drivers/mysql/sql/insert.js +6 -0
  548. package/src/database/drivers/mysql/sql/update.js +33 -0
  549. package/src/database/drivers/mysql/sql/upsert.js +13 -0
  550. package/src/database/drivers/mysql/structure-sql.js +93 -0
  551. package/src/database/drivers/mysql/table.js +121 -0
  552. package/src/database/drivers/pgsql/column.js +90 -0
  553. package/src/database/drivers/pgsql/columns-index.js +6 -0
  554. package/src/database/drivers/pgsql/foreign-key.js +12 -0
  555. package/src/database/drivers/pgsql/index.js +441 -0
  556. package/src/database/drivers/pgsql/options.js +32 -0
  557. package/src/database/drivers/pgsql/query-parser.js +6 -0
  558. package/src/database/drivers/pgsql/sql/alter-table.js +6 -0
  559. package/src/database/drivers/pgsql/sql/create-database.js +38 -0
  560. package/src/database/drivers/pgsql/sql/create-index.js +6 -0
  561. package/src/database/drivers/pgsql/sql/create-table.js +6 -0
  562. package/src/database/drivers/pgsql/sql/delete.js +21 -0
  563. package/src/database/drivers/pgsql/sql/drop-database.js +6 -0
  564. package/src/database/drivers/pgsql/sql/drop-table.js +6 -0
  565. package/src/database/drivers/pgsql/sql/insert.js +6 -0
  566. package/src/database/drivers/pgsql/sql/update.js +33 -0
  567. package/src/database/drivers/pgsql/sql/upsert.js +14 -0
  568. package/src/database/drivers/pgsql/structure-sql.js +126 -0
  569. package/src/database/drivers/pgsql/table.js +135 -0
  570. package/src/database/drivers/sqlite/base.js +509 -0
  571. package/src/database/drivers/sqlite/column.js +75 -0
  572. package/src/database/drivers/sqlite/columns-index.js +30 -0
  573. package/src/database/drivers/sqlite/connection-sql-js.js +46 -0
  574. package/src/database/drivers/sqlite/foreign-key.js +24 -0
  575. package/src/database/drivers/sqlite/index.js +394 -0
  576. package/src/database/drivers/sqlite/index.native.js +72 -0
  577. package/src/database/drivers/sqlite/index.web.js +99 -0
  578. package/src/database/drivers/sqlite/options.js +32 -0
  579. package/src/database/drivers/sqlite/query-parser.js +6 -0
  580. package/src/database/drivers/sqlite/query.js +35 -0
  581. package/src/database/drivers/sqlite/query.native.js +35 -0
  582. package/src/database/drivers/sqlite/query.web.js +49 -0
  583. package/src/database/drivers/sqlite/sql/alter-table.js +187 -0
  584. package/src/database/drivers/sqlite/sql/create-index.js +6 -0
  585. package/src/database/drivers/sqlite/sql/create-table.js +6 -0
  586. package/src/database/drivers/sqlite/sql/delete.js +26 -0
  587. package/src/database/drivers/sqlite/sql/drop-table.js +6 -0
  588. package/src/database/drivers/sqlite/sql/insert.js +6 -0
  589. package/src/database/drivers/sqlite/sql/update.js +33 -0
  590. package/src/database/drivers/sqlite/sql/upsert.js +14 -0
  591. package/src/database/drivers/sqlite/structure-sql.js +56 -0
  592. package/src/database/drivers/sqlite/table-rebuilder.js +96 -0
  593. package/src/database/drivers/sqlite/table.js +131 -0
  594. package/src/database/drivers/structure-sql/utils.js +35 -0
  595. package/src/database/handler.js +13 -0
  596. package/src/database/initializer-from-require-context.js +101 -0
  597. package/src/database/migration/index.js +438 -0
  598. package/src/database/migrator/files-finder.js +55 -0
  599. package/src/database/migrator/types.js +31 -0
  600. package/src/database/migrator.js +557 -0
  601. package/src/database/pool/async-tracked-multi-connection.js +1164 -0
  602. package/src/database/pool/base-methods-forward.js +52 -0
  603. package/src/database/pool/base.js +380 -0
  604. package/src/database/pool/single-multi-use.js +118 -0
  605. package/src/database/query/alter-table-base.js +104 -0
  606. package/src/database/query/base.js +49 -0
  607. package/src/database/query/create-database-base.js +42 -0
  608. package/src/database/query/create-index-base.js +117 -0
  609. package/src/database/query/create-table-base.js +205 -0
  610. package/src/database/query/delete-base.js +19 -0
  611. package/src/database/query/drop-database-base.js +38 -0
  612. package/src/database/query/drop-table-base.js +58 -0
  613. package/src/database/query/from-base.js +36 -0
  614. package/src/database/query/from-plain.js +16 -0
  615. package/src/database/query/from-table.js +18 -0
  616. package/src/database/query/index.js +533 -0
  617. package/src/database/query/insert-base.js +172 -0
  618. package/src/database/query/join-base.js +43 -0
  619. package/src/database/query/join-object.js +167 -0
  620. package/src/database/query/join-plain.js +18 -0
  621. package/src/database/query/join-tracker.js +93 -0
  622. package/src/database/query/model-class-query.js +1577 -0
  623. package/src/database/query/order-base.js +33 -0
  624. package/src/database/query/order-column.js +77 -0
  625. package/src/database/query/order-plain.js +28 -0
  626. package/src/database/query/preloader/belongs-to.js +267 -0
  627. package/src/database/query/preloader/ensure-model-class-initialized.js +18 -0
  628. package/src/database/query/preloader/has-many.js +316 -0
  629. package/src/database/query/preloader/has-one.js +123 -0
  630. package/src/database/query/preloader/selection.js +152 -0
  631. package/src/database/query/preloader.js +201 -0
  632. package/src/database/query/query-data.js +305 -0
  633. package/src/database/query/select-base.js +30 -0
  634. package/src/database/query/select-plain.js +18 -0
  635. package/src/database/query/select-table-and-column.js +28 -0
  636. package/src/database/query/update-base.js +41 -0
  637. package/src/database/query/upsert-base.js +103 -0
  638. package/src/database/query/where-base.js +38 -0
  639. package/src/database/query/where-combinator.js +31 -0
  640. package/src/database/query/where-hash.js +77 -0
  641. package/src/database/query/where-model-class-hash.js +505 -0
  642. package/src/database/query/where-not.js +23 -0
  643. package/src/database/query/where-plain.js +20 -0
  644. package/src/database/query/with-count.js +219 -0
  645. package/src/database/query-parser/base-query-parser.js +40 -0
  646. package/src/database/query-parser/from-parser.js +49 -0
  647. package/src/database/query-parser/group-parser.js +55 -0
  648. package/src/database/query-parser/joins-parser.js +37 -0
  649. package/src/database/query-parser/limit-parser.js +77 -0
  650. package/src/database/query-parser/options.js +94 -0
  651. package/src/database/query-parser/order-parser.js +45 -0
  652. package/src/database/query-parser/select-parser.js +67 -0
  653. package/src/database/query-parser/where-parser.js +46 -0
  654. package/src/database/record/acts-as-list.js +374 -0
  655. package/src/database/record/attachments/download.js +49 -0
  656. package/src/database/record/attachments/handle.js +188 -0
  657. package/src/database/record/attachments/normalize-input.js +213 -0
  658. package/src/database/record/attachments/storage-drivers/filesystem.js +114 -0
  659. package/src/database/record/attachments/storage-drivers/native.js +146 -0
  660. package/src/database/record/attachments/storage-drivers/s3.js +245 -0
  661. package/src/database/record/attachments/store.js +591 -0
  662. package/src/database/record/index.js +4094 -0
  663. package/src/database/record/instance-relationships/base.js +289 -0
  664. package/src/database/record/instance-relationships/belongs-to.js +84 -0
  665. package/src/database/record/instance-relationships/has-many.js +284 -0
  666. package/src/database/record/instance-relationships/has-one.js +117 -0
  667. package/src/database/record/record-not-found-error.js +3 -0
  668. package/src/database/record/relationships/base.js +195 -0
  669. package/src/database/record/relationships/belongs-to.js +57 -0
  670. package/src/database/record/relationships/has-many.js +46 -0
  671. package/src/database/record/relationships/has-one.js +46 -0
  672. package/src/database/record/state-machine.js +278 -0
  673. package/src/database/record/user-module.js +43 -0
  674. package/src/database/record/validators/base.js +27 -0
  675. package/src/database/record/validators/format.js +50 -0
  676. package/src/database/record/validators/presence.js +24 -0
  677. package/src/database/record/validators/uniqueness.js +124 -0
  678. package/src/database/table-data/index.js +241 -0
  679. package/src/database/table-data/table-column.js +416 -0
  680. package/src/database/table-data/table-foreign-key.js +69 -0
  681. package/src/database/table-data/table-index.js +46 -0
  682. package/src/database/table-data/table-reference.js +13 -0
  683. package/src/database/use-database.js +48 -0
  684. package/src/environment-handlers/base.js +561 -0
  685. package/src/environment-handlers/browser.js +338 -0
  686. package/src/environment-handlers/node/cli/commands/background-jobs-main.js +21 -0
  687. package/src/environment-handlers/node/cli/commands/background-jobs-runner.js +24 -0
  688. package/src/environment-handlers/node/cli/commands/background-jobs-worker.js +47 -0
  689. package/src/environment-handlers/node/cli/commands/beacon.js +21 -0
  690. package/src/environment-handlers/node/cli/commands/cli-command-context.js +31 -0
  691. package/src/environment-handlers/node/cli/commands/console.js +149 -0
  692. package/src/environment-handlers/node/cli/commands/db/schema/dump.js +43 -0
  693. package/src/environment-handlers/node/cli/commands/db/schema/load.js +69 -0
  694. package/src/environment-handlers/node/cli/commands/db/seed.js +79 -0
  695. package/src/environment-handlers/node/cli/commands/destroy/migration.js +47 -0
  696. package/src/environment-handlers/node/cli/commands/generate/base-models.js +396 -0
  697. package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +872 -0
  698. package/src/environment-handlers/node/cli/commands/generate/migration.js +45 -0
  699. package/src/environment-handlers/node/cli/commands/generate/model.js +45 -0
  700. package/src/environment-handlers/node/cli/commands/init.js +68 -0
  701. package/src/environment-handlers/node/cli/commands/routes.js +63 -0
  702. package/src/environment-handlers/node/cli/commands/run-script.js +85 -0
  703. package/src/environment-handlers/node/cli/commands/runner.js +84 -0
  704. package/src/environment-handlers/node/cli/commands/server.js +151 -0
  705. package/src/environment-handlers/node/cli/commands/test.js +118 -0
  706. package/src/environment-handlers/node.js +887 -0
  707. package/src/error-logger.js +30 -0
  708. package/src/frontend-model-controller.js +3491 -0
  709. package/src/frontend-model-resource/base-resource.js +935 -0
  710. package/src/frontend-models/base.js +4004 -0
  711. package/src/frontend-models/clear-pending-debounced-callback.js +16 -0
  712. package/src/frontend-models/event-hook-models.js +49 -0
  713. package/src/frontend-models/model-registry.js +28 -0
  714. package/src/frontend-models/outgoing-event-buffer.js +51 -0
  715. package/src/frontend-models/preloader.js +169 -0
  716. package/src/frontend-models/query.js +2245 -0
  717. package/src/frontend-models/resource-config-validation.js +56 -0
  718. package/src/frontend-models/resource-definition.js +399 -0
  719. package/src/frontend-models/transport-serialization.js +369 -0
  720. package/src/frontend-models/use-created-event.js +21 -0
  721. package/src/frontend-models/use-destroyed-event.js +148 -0
  722. package/src/frontend-models/use-model-class-event.js +164 -0
  723. package/src/frontend-models/use-updated-event.js +152 -0
  724. package/src/frontend-models/websocket-channel.js +494 -0
  725. package/src/frontend-models/websocket-publishers.js +224 -0
  726. package/src/http-client/header.js +17 -0
  727. package/src/http-client/index.js +139 -0
  728. package/src/http-client/request.js +94 -0
  729. package/src/http-client/response.js +151 -0
  730. package/src/http-client/websocket-client.js +27 -0
  731. package/src/http-server/client/index.js +507 -0
  732. package/src/http-server/client/params-to-object.js +152 -0
  733. package/src/http-server/client/request-buffer/form-data-part.js +139 -0
  734. package/src/http-server/client/request-buffer/header.js +19 -0
  735. package/src/http-server/client/request-buffer/index.js +535 -0
  736. package/src/http-server/client/request-parser.js +195 -0
  737. package/src/http-server/client/request-runner.js +321 -0
  738. package/src/http-server/client/request-timing.js +171 -0
  739. package/src/http-server/client/request.js +114 -0
  740. package/src/http-server/client/response.js +251 -0
  741. package/src/http-server/client/uploaded-file/memory-uploaded-file.js +32 -0
  742. package/src/http-server/client/uploaded-file/temporary-uploaded-file.js +32 -0
  743. package/src/http-server/client/uploaded-file/uploaded-file.js +36 -0
  744. package/src/http-server/client/websocket-request.js +147 -0
  745. package/src/http-server/client/websocket-session.js +1755 -0
  746. package/src/http-server/cookie.js +245 -0
  747. package/src/http-server/development-reloader.js +240 -0
  748. package/src/http-server/index.js +561 -0
  749. package/src/http-server/remote-address.js +77 -0
  750. package/src/http-server/server-client.js +222 -0
  751. package/src/http-server/server-lock.js +178 -0
  752. package/src/http-server/websocket-channel-subscribers.js +110 -0
  753. package/src/http-server/websocket-channel.js +137 -0
  754. package/src/http-server/websocket-connection.js +118 -0
  755. package/src/http-server/websocket-event-log-store.js +433 -0
  756. package/src/http-server/websocket-events-host.js +170 -0
  757. package/src/http-server/websocket-events.js +50 -0
  758. package/src/http-server/worker-handler/channel-subscriber-dispatch.js +28 -0
  759. package/src/http-server/worker-handler/in-process.js +155 -0
  760. package/src/http-server/worker-handler/index.js +370 -0
  761. package/src/http-server/worker-handler/worker-script.js +6 -0
  762. package/src/http-server/worker-handler/worker-thread.js +286 -0
  763. package/src/initializer.js +39 -0
  764. package/src/jobs/.gitkeep +1 -0
  765. package/src/jobs/mail-delivery.js +22 -0
  766. package/src/logger/base-logger.js +34 -0
  767. package/src/logger/console-logger.js +28 -0
  768. package/src/logger/file-logger.js +36 -0
  769. package/src/logger/outputs/array-output.js +50 -0
  770. package/src/logger/outputs/console-output.js +32 -0
  771. package/src/logger/outputs/file-output.js +55 -0
  772. package/src/logger/outputs/stdout-output.js +64 -0
  773. package/src/logger.js +507 -0
  774. package/src/mailer/backends/smtp.js +197 -0
  775. package/src/mailer/base.js +337 -0
  776. package/src/mailer/delivery.js +70 -0
  777. package/src/mailer/index.js +24 -0
  778. package/src/mailer.js +15 -0
  779. package/src/plugins/sqljs-wasm-route-controller.js +70 -0
  780. package/src/plugins/sqljs-wasm-route.js +71 -0
  781. package/src/record-payload-values.js +83 -0
  782. package/src/routes/app-routes.js +17 -0
  783. package/src/routes/base-route.js +133 -0
  784. package/src/routes/basic-route.js +109 -0
  785. package/src/routes/built-in/debug/controller.js +12 -0
  786. package/src/routes/built-in/errors/controller.js +7 -0
  787. package/src/routes/built-in/errors/not-found.ejs +1 -0
  788. package/src/routes/get-route.js +75 -0
  789. package/src/routes/hooks/frontend-model-command-route-hook.js +100 -0
  790. package/src/routes/index.js +50 -0
  791. package/src/routes/namespace-route.js +51 -0
  792. package/src/routes/plugin-routes.js +141 -0
  793. package/src/routes/post-route.js +74 -0
  794. package/src/routes/resolver.js +535 -0
  795. package/src/routes/resource-route.js +154 -0
  796. package/src/routes/root-route.js +11 -0
  797. package/src/templates/configuration.js +61 -0
  798. package/src/templates/generate-migration.js +11 -0
  799. package/src/templates/generate-model.js +6 -0
  800. package/src/templates/routes.js +11 -0
  801. package/src/testing/base-expect.js +17 -0
  802. package/src/testing/browser-frontend-model-event-hook-scenarios.js +520 -0
  803. package/src/testing/browser-test-app.js +32 -0
  804. package/src/testing/expect-to-change.js +55 -0
  805. package/src/testing/expect-utils.js +269 -0
  806. package/src/testing/expect.js +763 -0
  807. package/src/testing/request-client.js +90 -0
  808. package/src/testing/test-files-finder.js +364 -0
  809. package/src/testing/test-filter-parser.js +198 -0
  810. package/src/testing/test-runner.js +1168 -0
  811. package/src/testing/test-suite-splitter.js +177 -0
  812. package/src/testing/test.js +370 -0
  813. package/src/types/external-modules.d.ts +57 -0
  814. package/src/utils/backtrace-cleaner-node.js +87 -0
  815. package/src/utils/backtrace-cleaner.js +266 -0
  816. package/src/utils/ensure-error.js +15 -0
  817. package/src/utils/event-emitter.js +8 -0
  818. package/src/utils/file-exists.js +18 -0
  819. package/src/utils/format-value.js +101 -0
  820. package/src/utils/model-scope.js +56 -0
  821. package/src/utils/nest-callbacks.js +22 -0
  822. package/src/utils/plain-object.js +14 -0
  823. package/src/utils/ransack.js +859 -0
  824. package/src/utils/rest-args-error.js +14 -0
  825. package/src/utils/singularize-model-name.js +18 -0
  826. package/src/utils/split-sql-statements.js +88 -0
  827. package/src/utils/to-import-specifier.js +53 -0
  828. package/src/utils/with-tracked-stack-async-hooks.js +103 -0
  829. package/src/utils/with-tracked-stack.js +38 -0
  830. package/src/velocious-error.js +34 -0
  831. package/tsconfig.json +16 -0
@@ -0,0 +1,935 @@
1
+ // @ts-check
2
+
3
+ import AuthorizationBaseResource from "../authorization/base-resource.js"
4
+ import * as inflection from "inflection"
5
+
6
+ /**
7
+ * FrontendModelResourceControllerArgs type.
8
+ * @typedef {object} FrontendModelResourceControllerArgs
9
+ * @property {import("../controller.js").default} controller - Frontend-model controller instance.
10
+ * @property {typeof import("../database/record/index.js").default} modelClass - Backing model class.
11
+ * @property {string} modelName - Model name.
12
+ * @property {import("../configuration-types.js").VelociousLooseObject} params - Request params.
13
+ * @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration | import("../configuration-types.js").FrontendModelResourceConfiguration} resourceConfiguration - Normalized resource configuration (or raw input shape during early bootstrap).
14
+ */
15
+
16
+ /**
17
+ * FrontendModelResourceAbilityArgs type.
18
+ * @typedef {object} FrontendModelResourceAbilityArgs
19
+ * @property {import("../authorization/ability.js").default} [ability] - Ability instance when the resource is used directly for authorization.
20
+ * @property {import("../configuration-types.js").VelociousLooseObject} [context] - Ability context.
21
+ * @property {import("../configuration-types.js").VelociousLooseObject} [locals] - Ability locals.
22
+ * @property {typeof import("../database/record/index.js").default} [modelClass] - Optional backing model class override.
23
+ * @property {string} [modelName] - Optional model name override.
24
+ * @property {import("../configuration-types.js").VelociousLooseObject} [params] - Optional params override.
25
+ * @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration | import("../configuration-types.js").FrontendModelResourceConfiguration} [resourceConfiguration] - Optional normalized resource configuration.
26
+ */
27
+
28
+ /**
29
+ * Base class for backend frontend-model resources.
30
+ */
31
+ export default class FrontendModelBaseResource extends AuthorizationBaseResource {
32
+ /**
33
+ * Backing model class.
34
+ @type {typeof import("../database/record/index.js").default | undefined} */
35
+ static ModelClass = undefined
36
+
37
+ /**
38
+ * Attributes.
39
+ @type {Record<string, ?> | string[] | undefined} */
40
+ static attributes = undefined
41
+ /**
42
+ * Abilities.
43
+ @type {string[] | undefined} */
44
+ static abilities = undefined
45
+ /**
46
+ * Attachments.
47
+ @type {Record<string, ?> | undefined} */
48
+ static attachments = undefined
49
+ /**
50
+ * Collection commands.
51
+ @type {string[] | undefined} */
52
+ static collectionCommands = undefined
53
+ /**
54
+ * Built in collection commands.
55
+ @type {string[] | undefined} */
56
+ static builtInCollectionCommands = undefined
57
+ /**
58
+ * Member commands.
59
+ @type {string[] | undefined} */
60
+ static memberCommands = undefined
61
+ /**
62
+ * Built in member commands.
63
+ @type {string[] | undefined} */
64
+ static builtInMemberCommands = undefined
65
+ /**
66
+ * Relationships.
67
+ @type {string[] | undefined} */
68
+ static relationships = undefined
69
+ /**
70
+ * Translated attributes.
71
+ @type {string[] | undefined} */
72
+ static translatedAttributes = undefined
73
+
74
+ /**
75
+ * Runs constructor.
76
+ * @param {FrontendModelResourceAbilityArgs | FrontendModelResourceControllerArgs} args - Resource args.
77
+ */
78
+ constructor(args) {
79
+ super({
80
+ ability: "ability" in args ? args.ability : undefined,
81
+ context: "context" in args ? args.context || {} : {},
82
+ locals: "locals" in args ? args.locals || {} : {}
83
+ })
84
+
85
+ this.controller = "controller" in args ? args.controller : undefined
86
+ this.modelClassValue = "modelClass" in args ? args.modelClass : /**
87
+ * Narrows the runtime value to the documented type.
88
+ @type {typeof import("../database/record/index.js").default | undefined} */ (/**
89
+ * Narrows the runtime value to the documented type.
90
+ @type {typeof FrontendModelBaseResource} */ (this.constructor).modelClass())
91
+ this.modelNameValue = "modelName" in args ? args.modelName : (this.modelClassValue?.getModelName ? this.modelClassValue.getModelName() : this.modelClassValue?.name || "")
92
+ this.paramsValue = "params" in args ? args.params : undefined
93
+ this.resourceConfigurationValue = "resourceConfiguration" in args ? args.resourceConfiguration : /**
94
+ * Narrows the runtime value to the documented type.
95
+ @type {import("../configuration-types.js").FrontendModelResourceConfiguration} */ ({attributes: []})
96
+ }
97
+
98
+ /**
99
+ * Runs typed controller instance.
100
+ * @returns {import("../controller.js").default & {
101
+ * frontendModelAuthorizedQuery: (action: "index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url") => import("../database/query/model-class-query.js").default<typeof import("../database/record/index.js").default>,
102
+ * frontendModelIndexQuery: () => import("../database/query/model-class-query.js").default<typeof import("../database/record/index.js").default>,
103
+ * frontendModelPreload: () => import("../database/query/index.js").NestedPreloadRecord | null,
104
+ * serializeFrontendModel: (model: import("../database/record/index.js").default) => Promise<Record<string, unknown>>
105
+ * }} - Controller instance with frontend-model helpers.
106
+ */
107
+ typedControllerInstance() {
108
+ return /** Narrows the runtime value to the documented type. @type {?} */ (this.controller)
109
+ }
110
+
111
+ /**
112
+ * Runs resource config.
113
+ * @returns {import("../configuration-types.js").FrontendModelResourceConfiguration} - Static resource config (raw user input shape; consumers normalize).
114
+ */
115
+ static resourceConfig() {
116
+ /**
117
+ * Config.
118
+ @type {import("../configuration-types.js").FrontendModelResourceConfiguration} */
119
+ const config = {
120
+ attributes: this.attributes || []
121
+ }
122
+
123
+ if (this.abilities) config.abilities = this.abilities
124
+ if (this.attachments) config.attachments = this.attachments
125
+ if (this.builtInCollectionCommands) config.builtInCollectionCommands = this.builtInCollectionCommands
126
+ if (this.builtInMemberCommands) config.builtInMemberCommands = this.builtInMemberCommands
127
+ if (this.collectionCommands) config.collectionCommands = this.collectionCommands
128
+ if (this.memberCommands) config.memberCommands = this.memberCommands
129
+ if (this.relationships) config.relationships = this.relationships
130
+
131
+ return config
132
+ }
133
+
134
+ /**
135
+ * Runs static model class.
136
+ * @returns {typeof import("../database/record/index.js").default | undefined} - Backing model class.
137
+ */
138
+ static modelClass() {
139
+ return this.ModelClass
140
+ }
141
+
142
+ /**
143
+ * Runs controller instance.
144
+ * @returns {import("../controller.js").default} - Controller instance.
145
+ */
146
+ controllerInstance() {
147
+ if (!this.controller) throw new Error(`${this.constructor.name} requires a controller instance.`)
148
+
149
+ return this.controller
150
+ }
151
+
152
+ /**
153
+ * Runs model class.
154
+ * @returns {typeof import("../database/record/index.js").default} - Model class.
155
+ */
156
+ modelClass() {
157
+ if (!this.modelClassValue) {
158
+ throw new Error(`${this.constructor.name} requires a model class.`)
159
+ }
160
+
161
+ return this.modelClassValue
162
+ }
163
+
164
+ /**
165
+ * Runs model name.
166
+ * @returns {string} - Model name.
167
+ */
168
+ modelName() {
169
+ if (!this.modelNameValue) throw new Error(`${this.constructor.name} requires a model name.`)
170
+
171
+ return this.modelNameValue
172
+ }
173
+
174
+ /**
175
+ * Runs params.
176
+ * @returns {import("../configuration-types.js").VelociousLooseObject} - Params.
177
+ */
178
+ params() { return this.paramsValue || super.params() || {} }
179
+
180
+ /**
181
+ * Runs resource configuration.
182
+ * @returns {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration | import("../configuration-types.js").FrontendModelResourceConfiguration} - Resource config (normalized at runtime; raw during early bootstrap).
183
+ */
184
+ resourceConfiguration() {
185
+ if (!this.resourceConfigurationValue) throw new Error(`${this.constructor.name} requires a resource configuration.`)
186
+
187
+ return this.resourceConfigurationValue
188
+ }
189
+
190
+ /**
191
+ * Returns a Rails-strong-params / api_maker-style permit spec declaring
192
+ * which attributes and nested attributes are writable for the current
193
+ * request. Submitting an attribute or nested-relationship key that is
194
+ * not permitted raises an error and fails the write.
195
+ *
196
+ * The returned value is a flat array that mixes:
197
+ * - `"attributeName"` strings for plain attribute writes
198
+ * - `{<relationshipName>Attributes: [...]}` objects where the value
199
+ * is itself a permit spec for the nested relationship
200
+ *
201
+ * This matches Rails strong_params (`permit(:first_name, :last_name,
202
+ * contact_attributes: [:email, details_attributes: [:detail]])`) and
203
+ * the api_maker sister project. Include `"_destroy"` inside a nested
204
+ * permit to allow `_destroy: true` entries for that relationship —
205
+ * the model must also declare `acceptsNestedAttributesFor(name,
206
+ * {allowDestroy: true})` for the destroy to be applied.
207
+ *
208
+ * Example:
209
+ *
210
+ * class ProjectResource extends FrontendModelBaseResource {
211
+ * permittedParams(arg) {
212
+ * return [
213
+ * "name",
214
+ * "description",
215
+ * {tasksAttributes: ["id", "_destroy", "name",
216
+ * {subtasksAttributes: ["id", "_destroy", "name"]}
217
+ * ]}
218
+ * ]
219
+ * }
220
+ * }
221
+ *
222
+ * Default implementation returns `[]` — nothing permitted. Subclasses
223
+ * must override to enable writes. A resource that does not declare
224
+ * `permittedParams` cannot accept any write.
225
+ * @param {{action?: "create" | "update", params?: Record<string, ?>, ability?: import("../authorization/ability.js").default, locals?: Record<string, ?>}} [arg] - Request context.
226
+ * @returns {Array<string | Record<string, ?>>} - Permit spec.
227
+ */
228
+ permittedParams(arg) {
229
+ void arg
230
+
231
+ return []
232
+ }
233
+
234
+ /**
235
+ * Runs primary key.
236
+ * @returns {string} - Primary key.
237
+ */
238
+ primaryKey() { return this.modelClass().primaryKey() }
239
+
240
+ /**
241
+ * Runs authorized query.
242
+ * @param {"index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url"} action - Ability action.
243
+ * @template {typeof import("../database/record/index.js").default} [MC=typeof import("../database/record/index.js").default]
244
+ * @returns {import("../database/query/model-class-query.js").default<MC>} - Authorized query.
245
+ */
246
+ authorizedQuery(action) {
247
+ return /** Narrows the authorized query to the resource's model class. @type {import("../database/query/model-class-query.js").default<MC>} */ (this.typedControllerInstance().frontendModelAuthorizedQuery(action))
248
+ }
249
+
250
+ /**
251
+ * Runs supports pluck.
252
+ * @param {"index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url"} action - Action.
253
+ * @returns {boolean | Promise<boolean>} - Whether pluck is supported.
254
+ */
255
+ supportsPluck(action) {
256
+ void action
257
+
258
+ return Object.getPrototypeOf(this).records === FrontendModelBaseResource.prototype.records
259
+ }
260
+
261
+ /**
262
+ * Runs supports count.
263
+ * @param {"index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url"} action - Action.
264
+ * @returns {boolean | Promise<boolean>} - Whether count is supported.
265
+ */
266
+ supportsCount(action) {
267
+ void action
268
+
269
+ return Object.getPrototypeOf(this).records === FrontendModelBaseResource.prototype.records ||
270
+ Object.getPrototypeOf(this).count !== FrontendModelBaseResource.prototype.count
271
+ }
272
+
273
+ /**
274
+ * Runs before action.
275
+ * @param {"index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url"} action - Action.
276
+ * @returns {boolean | void | Promise<boolean | void>} - Continue processing unless false.
277
+ */
278
+ beforeAction(action) {
279
+ void action
280
+
281
+ // No-op by default.
282
+ }
283
+
284
+ /**
285
+ * Runs records.
286
+ * @returns {Promise<import("../database/record/index.js").default[]>} - Records for index action.
287
+ */
288
+ async records() {
289
+ return await this.typedControllerInstance().frontendModelIndexQuery().toArray()
290
+ }
291
+
292
+ /**
293
+ * Runs count.
294
+ * @returns {Promise<number>} - Records count for index action.
295
+ */
296
+ async count() {
297
+ return await this.typedControllerInstance().frontendModelIndexQuery().count()
298
+ }
299
+
300
+ /**
301
+ * Runs find.
302
+ * @param {"find" | "update" | "destroy" | "attach" | "download" | "url"} action - Action.
303
+ * @param {string | number} id - Record id.
304
+ * @returns {Promise<import("../database/record/index.js").default | null>} - Located model.
305
+ */
306
+ async find(action, id) {
307
+ let query = this.authorizedQuery(action)
308
+ const preload = action === "find" ? this.typedControllerInstance().frontendModelPreload() : null
309
+
310
+ if (preload) {
311
+ query = query.preload(preload)
312
+ }
313
+
314
+ return await query.findBy({[this.primaryKey()]: id})
315
+ }
316
+
317
+ /**
318
+ * Runs create.
319
+ * @param {Record<string, ?>} attributes - Create attributes.
320
+ * @param {{controller?: ?, nestedAttributes?: Record<string, ?> | null}} [options] - Save options.
321
+ * @returns {Promise<import("../database/record/index.js").default>} - Created model.
322
+ */
323
+ async create(attributes, options = {}) {
324
+ const permit = parsePermittedParams(this.permittedParams({action: "create", ability: this.ability, locals: this.locals, params: attributes}))
325
+ const filtered = filterWritableFrontendModelAttributes(this.modelClass().prototype, attributes, this, permit.attributes)
326
+ const ModelClass = this.modelClass()
327
+ const model = new ModelClass()
328
+
329
+ await ModelClass.transaction(async () => {
330
+ await this._assignWithVirtualSetters(model, filtered)
331
+ await model.save()
332
+
333
+ if (options.nestedAttributes) {
334
+ await this._applyNestedAttributes(model, options.nestedAttributes, options.controller || null, permit)
335
+ }
336
+ })
337
+
338
+ await this._preloadNestedWritableRelationships(model, permit)
339
+
340
+ return model
341
+ }
342
+
343
+ /**
344
+ * Runs handle unauthorized created model.
345
+ * @param {import("../database/record/index.js").default} model - Created model.
346
+ * @returns {Promise<void>} - Cleanup after failed authorization.
347
+ */
348
+ async handleUnauthorizedCreatedModel(model) {
349
+ await model.destroy()
350
+ }
351
+
352
+ /**
353
+ * Runs update.
354
+ * @param {import("../database/record/index.js").default} model - Existing model.
355
+ * @param {Record<string, ?>} attributes - Update attributes.
356
+ * @param {{controller?: ?, nestedAttributes?: Record<string, ?> | null}} [options] - Save options.
357
+ * @returns {Promise<import("../database/record/index.js").default>} - Updated model.
358
+ */
359
+ async update(model, attributes, options = {}) {
360
+ const permit = parsePermittedParams(this.permittedParams({action: "update", ability: this.ability, locals: this.locals, params: attributes}))
361
+ const filtered = filterWritableFrontendModelAttributes(model, attributes, this, permit.attributes)
362
+ const ModelClass = this.modelClass()
363
+
364
+ await ModelClass.transaction(async () => {
365
+ await this._assignWithVirtualSetters(model, filtered)
366
+ await model.save()
367
+
368
+ if (options.nestedAttributes) {
369
+ await this._applyNestedAttributes(model, options.nestedAttributes, options.controller || null, permit)
370
+ }
371
+ })
372
+
373
+ await this._preloadNestedWritableRelationships(model, permit)
374
+
375
+ return model
376
+ }
377
+
378
+ /**
379
+ * Assigns attributes to a model, using virtual setters on the resource when available.
380
+ * @param {import("../database/record/index.js").default} model - Model instance.
381
+ * @param {Record<string, ?>} attributes - Attributes to assign.
382
+ * @returns {Promise<void>}
383
+ */
384
+ async _assignWithVirtualSetters(model, attributes) {
385
+ /**
386
+ * Direct attributes.
387
+ @type {Record<string, ?>} */
388
+ const directAttributes = {}
389
+ const translatedSet = new Set(/**
390
+ * Narrows the runtime value to the documented type.
391
+ @type {typeof FrontendModelBaseResource} */ (this.constructor).translatedAttributes || [])
392
+
393
+ for (const [name, value] of Object.entries(attributes)) {
394
+ const resourceSetterName = `set${inflection.camelize(name)}Attribute`
395
+
396
+ if (typeof /**
397
+ * Narrows the runtime value to the documented type.
398
+ @type {Record<string, ?>} */ (/**
399
+ * Narrows the runtime value to the documented type.
400
+ @type {?} */ (this))[resourceSetterName] === "function") {
401
+ await /**
402
+ * Narrows the runtime value to the documented type.
403
+ @type {Record<string, ?>} */ (/**
404
+ * Narrows the runtime value to the documented type.
405
+ @type {?} */ (this))[resourceSetterName](model, value)
406
+ } else if (translatedSet.has(name)) {
407
+ await this._setTranslatedAttributeOnModel(model, name, value)
408
+ } else {
409
+ directAttributes[name] = value
410
+ }
411
+ }
412
+
413
+ if (Object.keys(directAttributes).length > 0) {
414
+ model.assign(directAttributes)
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Sets a translated attribute on a model via the translations relationship.
420
+ * @param {import("../database/record/index.js").default} model - Model instance.
421
+ * @param {string} name - Attribute name.
422
+ * @param {?} value - Attribute value.
423
+ * @returns {Promise<void>}
424
+ */
425
+ async _setTranslatedAttributeOnModel(model, name, value) {
426
+ const locale = this.context?.configuration?.getLocale?.() || "en"
427
+ const instanceRelationship = model.getRelationshipByName("translations")
428
+
429
+ /**
430
+ * Defines translation.
431
+ @type {import("../database/record/index.js").default | undefined} */
432
+ let translation
433
+
434
+ if (model.isNewRecord()) {
435
+ const loaded = instanceRelationship.loaded()
436
+
437
+ if (Array.isArray(loaded)) {
438
+ translation = loaded.find((/**
439
+ * Narrows the runtime value to the documented type.
440
+ @type {Record<string, ?>} */ t) => t.locale() === locale)
441
+ }
442
+ } else {
443
+ if (!instanceRelationship.getPreloaded()) {
444
+ await model.loadRelationship("translations")
445
+ }
446
+
447
+ const loaded = instanceRelationship.loaded()
448
+
449
+ if (Array.isArray(loaded)) {
450
+ translation = loaded.find((/**
451
+ * Narrows the runtime value to the documented type.
452
+ @type {Record<string, ?>} */ t) => t.locale() === locale)
453
+ }
454
+ }
455
+
456
+ if (!translation) {
457
+ translation = instanceRelationship.build({locale})
458
+ }
459
+
460
+ /**
461
+ * Assignments.
462
+ @type {Record<string, ?>} */
463
+ const assignments = {}
464
+
465
+ assignments[name] = value
466
+ translation.assign(assignments)
467
+ }
468
+
469
+ /**
470
+ * Runs destroy.
471
+ * @param {import("../database/record/index.js").default} model - Existing model.
472
+ * @returns {Promise<void>} - No return value.
473
+ */
474
+ async destroy(model) {
475
+ await model.destroy()
476
+ }
477
+
478
+ /**
479
+ * Runs serialize.
480
+ * @param {import("../database/record/index.js").default} model - Model to serialize.
481
+ * @param {"index" | "find" | "create" | "update"} [action] - Action.
482
+ * @returns {Promise<Record<string, ?>>} - Serialized model payload.
483
+ */
484
+ async serialize(model, action) {
485
+ void action
486
+
487
+ return await this.typedControllerInstance().serializeFrontendModel(model)
488
+ }
489
+
490
+ /**
491
+ * Applies a `nestedAttributes` payload to a freshly-saved parent model,
492
+ * cascading create/update/destroy writes across the declared relationships.
493
+ *
494
+ * Each child is authorized against its own resource's abilities (never the
495
+ * parent's). Destroys run before updates, updates before creates, to avoid
496
+ * unique-constraint conflicts when replacing a child at the same natural key.
497
+ *
498
+ * Attribute filtering for nested children uses the parent resource's
499
+ * permit spec for that relationship — api_maker-style. Policy options
500
+ * (allowDestroy, limit, rejectIf) come from the MODEL's
501
+ * `acceptedNestedAttributesFor(name)` declaration.
502
+ * @param {import("../database/record/index.js").default} parent - Parent model instance.
503
+ * @param {Record<string, ?>} nestedAttributes - Nested-attribute payload keyed by relationship name.
504
+ * @param {?} controller - Controller instance for resource resolution and authorization.
505
+ * @param {{attributes: string[], nested: Record<string, ?>} | null} [parentPermit] - Parsed parent permit spec.
506
+ * @returns {Promise<void>}
507
+ */
508
+ async _applyNestedAttributes(parent, nestedAttributes, controller, parentPermit = null) {
509
+ const resolvedParent = parentPermit
510
+ || parsePermittedParams(this.permittedParams({action: "update", ability: this.ability, locals: this.locals, params: {}}))
511
+
512
+ for (const relationshipName of Object.keys(nestedAttributes)) {
513
+ const childPermit = resolvedParent.nested[relationshipName]
514
+
515
+ if (!childPermit) {
516
+ throw new Error(`Nested attributes for '${relationshipName}' are not permitted by ${this.constructor.name}.permittedParams(). Include {${relationshipName}Attributes: [...]} in the returned permit.`)
517
+ }
518
+
519
+ const entries = nestedAttributes[relationshipName]
520
+
521
+ if (!Array.isArray(entries)) {
522
+ throw new Error(`Expected array for nestedAttributes['${relationshipName}'] but got: ${typeof entries}`)
523
+ }
524
+
525
+ const parentModelClass = /**
526
+ * Narrows the runtime value to the documented type.
527
+ @type {?} */ (parent.getModelClass())
528
+ const modelAcceptance = parentModelClass.acceptedNestedAttributesFor?.(relationshipName)
529
+
530
+ if (!modelAcceptance) {
531
+ throw new Error(`Model ${parentModelClass.name} does not accept nested attributes for '${relationshipName}'. Declare it via ${parentModelClass.name}.acceptsNestedAttributesFor('${relationshipName}').`)
532
+ }
533
+
534
+ const destroyPermitted = childPermit.attributes.includes("_destroy")
535
+
536
+ if (destroyPermitted && !modelAcceptance.allowDestroy) {
537
+ throw new Error(`Resource permits _destroy on nestedAttributes['${relationshipName}'] but the model ${parentModelClass.name} does not allow destroy for that relationship. Set {allowDestroy: true} on ${parentModelClass.name}.acceptsNestedAttributesFor('${relationshipName}', ...).`)
538
+ }
539
+
540
+ if (typeof modelAcceptance.limit === "number" && entries.length > modelAcceptance.limit) {
541
+ throw new Error(`nestedAttributes['${relationshipName}'] exceeds model-declared limit of ${modelAcceptance.limit}.`)
542
+ }
543
+
544
+ const parentRelationship = parent.getRelationshipByName(relationshipName)
545
+ const relationshipDefinitions = parentModelClass.relationships?.() || {}
546
+ const definition = relationshipDefinitions[relationshipName]
547
+
548
+ if (!definition || definition.type !== "hasMany") {
549
+ throw new Error(`Nested attributes for '${relationshipName}' require a hasMany relationship. v1 does not support '${definition?.type}'.`)
550
+ }
551
+
552
+ const targetModelClass = /**
553
+ * Narrows the runtime value to the documented type.
554
+ @type {?} */ (parent.getModelClass()).relationshipModelClass?.(relationshipName)
555
+
556
+ if (!targetModelClass) {
557
+ throw new Error(`No target model class resolved for relationship '${relationshipName}' on ${parent.getModelClass().name}.`)
558
+ }
559
+
560
+ const childResourceConfig = controller?.frontendModelResourceConfigurationForModelClass?.(targetModelClass)
561
+
562
+ if (!childResourceConfig) {
563
+ throw new Error(`No frontend-model resource registered for child model '${targetModelClass.getModelName?.() || targetModelClass.name}' under relationship '${relationshipName}'.`)
564
+ }
565
+
566
+ const childResource = new childResourceConfig.resourceClass({
567
+ ability: this.ability,
568
+ controller,
569
+ context: this.context || {},
570
+ locals: this.locals || {},
571
+ modelClass: targetModelClass,
572
+ modelName: childResourceConfig.modelName,
573
+ params: controller?.frontendModelParams?.() || {},
574
+ resourceConfiguration: childResourceConfig.resourceConfiguration
575
+ })
576
+
577
+ const foreignKey = definition.foreignKey || this._inferForeignKey(parent, definition)
578
+ const ability = controller?.currentAbility?.()
579
+
580
+ const destroyEntries = []
581
+ const updateEntries = []
582
+ const createEntries = []
583
+
584
+ for (const entry of entries) {
585
+ if (typeof modelAcceptance.rejectIf === "function" && modelAcceptance.rejectIf(entry?.attributes || {})) continue
586
+
587
+ if (entry?._destroy) {
588
+ if (!destroyPermitted) {
589
+ throw new Error(`nestedAttributes['${relationshipName}'] entry requested _destroy but "_destroy" is not in the permit for this relationship.`)
590
+ }
591
+ if (!entry.id) {
592
+ throw new Error(`nestedAttributes['${relationshipName}'] _destroy entry is missing an id.`)
593
+ }
594
+ destroyEntries.push(entry)
595
+ } else if (entry?.id) {
596
+ updateEntries.push(entry)
597
+ } else {
598
+ createEntries.push(entry)
599
+ }
600
+ }
601
+
602
+ // The permit's attribute list governs what child fields can be written.
603
+ // Exclude `_destroy` from the writable set since it's a control flag,
604
+ // not an attribute on the record.
605
+ const childWritableAttributes = /**
606
+ * Narrows the runtime value to the documented type.
607
+ @type {string[]} */ (childPermit.attributes).filter((name) => name !== "_destroy")
608
+
609
+ for (const entry of destroyEntries) {
610
+ const existing = await this._findScopedChild({
611
+ ability,
612
+ action: "destroy",
613
+ childResourceConfiguration: childResourceConfig.resourceConfiguration,
614
+ foreignKey,
615
+ id: entry.id,
616
+ parent,
617
+ relationshipName,
618
+ targetModelClass
619
+ })
620
+
621
+ await childResource.destroy(existing)
622
+ }
623
+
624
+ for (const entry of updateEntries) {
625
+ const existing = await this._findScopedChild({
626
+ ability,
627
+ action: "update",
628
+ childResourceConfiguration: childResourceConfig.resourceConfiguration,
629
+ foreignKey,
630
+ id: entry.id,
631
+ parent,
632
+ relationshipName,
633
+ targetModelClass
634
+ })
635
+
636
+ if (entry.attributes && typeof entry.attributes === "object") {
637
+ const filtered = filterWritableFrontendModelAttributes(existing, entry.attributes, childResource, childWritableAttributes)
638
+ await /**
639
+ * Narrows the runtime value to the documented type.
640
+ @type {?} */ (childResource)._assignWithVirtualSetters(existing, filtered)
641
+ await existing.save()
642
+ }
643
+
644
+ if (entry.nestedAttributes) {
645
+ await /**
646
+ * Narrows the runtime value to the documented type.
647
+ @type {?} */ (childResource)._applyNestedAttributes(existing, entry.nestedAttributes, controller, childPermit)
648
+ }
649
+ }
650
+
651
+ for (const entry of createEntries) {
652
+ const childAttributes = entry?.attributes && typeof entry.attributes === "object" ? entry.attributes : {}
653
+
654
+ const child = parentRelationship.build({...childAttributes, [foreignKey]: parent.id()})
655
+
656
+ const filtered = filterWritableFrontendModelAttributes(child, childAttributes, childResource, childWritableAttributes)
657
+
658
+ await /**
659
+ * Narrows the runtime value to the documented type.
660
+ @type {?} */ (childResource)._assignWithVirtualSetters(child, filtered)
661
+ await child.save()
662
+
663
+ await this._authorizeCreatedChild({
664
+ ability,
665
+ child,
666
+ childResourceConfiguration: childResourceConfig.resourceConfiguration,
667
+ relationshipName,
668
+ targetModelClass
669
+ })
670
+
671
+ if (entry.nestedAttributes) {
672
+ await /**
673
+ * Narrows the runtime value to the documented type.
674
+ @type {?} */ (childResource)._applyNestedAttributes(child, entry.nestedAttributes, controller, childPermit)
675
+ }
676
+ }
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Resolves the ability action for a child resource using the child's own
682
+ * `abilities` mapping — never the parent controller's. This preserves
683
+ * custom mappings like `{update: "manage"}` and catches unmapped actions
684
+ * instead of silently defaulting to the raw action name.
685
+ * @param {import("../configuration-types.js").FrontendModelResourceConfiguration} childResourceConfiguration - Child resource configuration.
686
+ * @param {"create" | "update" | "destroy"} action - Frontend action.
687
+ * @returns {string} - Ability action for the child resource.
688
+ */
689
+ _resolveChildAbilityAction(childResourceConfiguration, action) {
690
+ const abilities = childResourceConfiguration?.abilities
691
+
692
+ if (!abilities || typeof abilities !== "object" || Array.isArray(abilities)) {
693
+ throw new Error(`Nested child resource must define an 'abilities' object to authorize nested ${action}.`)
694
+ }
695
+
696
+ const abilityAction = /**
697
+ * Narrows the runtime value to the documented type.
698
+ @type {Record<string, string>} */ (abilities)[action]
699
+
700
+ if (typeof abilityAction !== "string" || abilityAction.length < 1) {
701
+ throw new Error(`Nested child resource must define abilities.${action}.`)
702
+ }
703
+
704
+ return abilityAction
705
+ }
706
+
707
+ /**
708
+ * Finds an existing child for a nested update/destroy, scoped to the
709
+ * child's own model class, the parent's foreign key, AND the child
710
+ * resource's ability mapping for the requested action. Throws when the
711
+ * child does not exist, does not belong to the current parent, or is
712
+ * not authorized — all of which must roll the transaction back.
713
+ * @param {object} args - Arguments.
714
+ * @param {import("../authorization/ability.js").default | undefined} args.ability - Current ability.
715
+ * @param {"update" | "destroy"} args.action - Frontend action.
716
+ * @param {import("../configuration-types.js").FrontendModelResourceConfiguration} args.childResourceConfiguration - Child resource configuration.
717
+ * @param {string} args.foreignKey - Foreign-key attribute on the child pointing to the parent.
718
+ * @param {string | number} args.id - Child id from the payload.
719
+ * @param {import("../database/record/index.js").default} args.parent - Parent model instance.
720
+ * @param {string} args.relationshipName - Parent's relationship name (for error messages).
721
+ * @param {typeof import("../database/record/index.js").default} args.targetModelClass - Child model class.
722
+ * @returns {Promise<import("../database/record/index.js").default>} - Authorized, parent-linked child model.
723
+ */
724
+ async _findScopedChild({ability, action, childResourceConfiguration, foreignKey, id, parent, relationshipName, targetModelClass}) {
725
+ const primaryKey = targetModelClass.primaryKey()
726
+ const lookup = {[primaryKey]: id, [foreignKey]: parent.id()}
727
+ const query = ability
728
+ ? /**
729
+ * Narrows the runtime value to the documented type.
730
+ @type {?} */ (targetModelClass).accessibleFor(this._resolveChildAbilityAction(childResourceConfiguration, action), ability)
731
+ : /**
732
+ * Narrows the runtime value to the documented type.
733
+ @type {?} */ (targetModelClass).where({})
734
+
735
+ const existing = await query.findBy(lookup)
736
+
737
+ if (!existing) {
738
+ throw new Error(`Cannot ${action} nested ${relationshipName}[id=${id}]: record not found, does not belong to parent ${parent.getModelClass().name}[id=${parent.id()}], or is not authorized.`)
739
+ }
740
+
741
+ return existing
742
+ }
743
+
744
+ /**
745
+ * Verifies an already-saved nested child is authorized under the child
746
+ * resource's own `create` ability. Rolls back via thrown error when not
747
+ * authorized so the outer transaction destroys the insert.
748
+ * @param {object} args - Arguments.
749
+ * @param {import("../authorization/ability.js").default | undefined} args.ability - Current ability.
750
+ * @param {import("../database/record/index.js").default} args.child - Child model instance just created.
751
+ * @param {import("../configuration-types.js").FrontendModelResourceConfiguration} args.childResourceConfiguration - Child resource configuration.
752
+ * @param {string} args.relationshipName - Parent's relationship name (for error messages).
753
+ * @param {typeof import("../database/record/index.js").default} args.targetModelClass - Child model class.
754
+ * @returns {Promise<void>}
755
+ */
756
+ async _authorizeCreatedChild({ability, child, childResourceConfiguration, relationshipName, targetModelClass}) {
757
+ if (!ability) return
758
+
759
+ const abilityAction = this._resolveChildAbilityAction(childResourceConfiguration, "create")
760
+ const primaryKey = targetModelClass.primaryKey()
761
+ const authorizedIds = await /**
762
+ * Narrows the runtime value to the documented type.
763
+ @type {?} */ (targetModelClass)
764
+ .accessibleFor(abilityAction, ability)
765
+ .where({[primaryKey]: child.readAttribute(primaryKey)})
766
+ .pluck(primaryKey)
767
+
768
+ if (authorizedIds.length === 0) {
769
+ throw new Error(`Nested create on ${relationshipName}[${targetModelClass.name}] not authorized.`)
770
+ }
771
+ }
772
+
773
+ /**
774
+ * Best-effort foreign-key inference for relationships that don't declare it.
775
+ * @param {import("../database/record/index.js").default} parent - Parent model.
776
+ * @param {{foreignKey?: string}} definition - Relationship definition.
777
+ * @returns {string} - Foreign-key attribute name.
778
+ */
779
+ _inferForeignKey(parent, definition) {
780
+ if (definition.foreignKey) return definition.foreignKey
781
+
782
+ const parentModelName = parent.getModelClass().name || ""
783
+ const underscored = parentModelName.replace(/([A-Z])/g, (match, letter, index) => (index === 0 ? letter.toLowerCase() : `_${letter.toLowerCase()}`))
784
+
785
+ return `${inflection.camelize(underscored, true)}Id`
786
+ }
787
+
788
+ /**
789
+ * After nested writes, preload every relationship declared in the
790
+ * parent's permit so the post-save serialize step emits them and the
791
+ * client can reconcile ids.
792
+ * @param {import("../database/record/index.js").default} model - Saved parent model.
793
+ * @param {{attributes: string[], nested: Record<string, ?>}} permit - Parsed parent permit.
794
+ * @returns {Promise<void>}
795
+ */
796
+ async _preloadNestedWritableRelationships(model, permit) {
797
+ const relationshipNames = Object.keys(permit.nested)
798
+
799
+ if (relationshipNames.length === 0) return
800
+
801
+ for (const relationshipName of relationshipNames) {
802
+ if (typeof /**
803
+ * Narrows the runtime value to the documented type.
804
+ @type {?} */ (model).loadRelationship === "function") {
805
+ await /**
806
+ * Narrows the runtime value to the documented type.
807
+ @type {?} */ (model).loadRelationship(relationshipName)
808
+ }
809
+ }
810
+ }
811
+ }
812
+
813
+ /**
814
+ * Parses the Rails/api_maker-style flat permit spec returned from
815
+ * `permittedParams(arg)` into a structured shape used internally by the
816
+ * write pipeline. Strings become attribute permits; objects whose keys
817
+ * end in `Attributes` become nested permits (the key prefix names the
818
+ * relationship).
819
+ *
820
+ * parsePermittedParams(["firstName", "lastName",
821
+ * {tasksAttributes: ["id", "_destroy", "name"]}
822
+ * ])
823
+ * // → {
824
+ * // attributes: ["firstName", "lastName"],
825
+ * // nested: {
826
+ * // tasks: {attributes: ["id", "_destroy", "name"], nested: {}}
827
+ * // }
828
+ * // }
829
+ * @param {Array<string | Record<string, ?>> | undefined} permitSpec - Flat permit spec.
830
+ * @returns {{attributes: string[], nested: Record<string, {attributes: string[], nested: Record<string, ?>}>}} - Parsed structure.
831
+ */
832
+ function parsePermittedParams(permitSpec) {
833
+ /**
834
+ * Attributes.
835
+ @type {string[]} */
836
+ const attributes = []
837
+ /**
838
+ * Nested.
839
+ @type {Record<string, {attributes: string[], nested: Record<string, ?>}>} */
840
+ const nested = {}
841
+
842
+ if (!Array.isArray(permitSpec)) return {attributes, nested}
843
+
844
+ for (const entry of permitSpec) {
845
+ if (typeof entry === "string") {
846
+ attributes.push(entry)
847
+ } else if (entry && typeof entry === "object" && !Array.isArray(entry)) {
848
+ for (const [key, value] of Object.entries(entry)) {
849
+ if (!key.endsWith("Attributes")) {
850
+ throw new Error(`Invalid permittedParams entry: nested relationship keys must end in "Attributes" (got "${key}"). Use "${key}Attributes" instead.`)
851
+ }
852
+ const relationshipName = key.slice(0, -"Attributes".length)
853
+
854
+ if (!relationshipName) {
855
+ throw new Error(`Invalid permittedParams entry: empty relationship name in key "${key}".`)
856
+ }
857
+ if (!Array.isArray(value)) {
858
+ throw new Error(`Invalid permittedParams entry for "${key}": expected array permit spec, got ${typeof value}.`)
859
+ }
860
+
861
+ nested[relationshipName] = parsePermittedParams(value)
862
+ }
863
+ } else {
864
+ throw new Error(`Invalid permittedParams entry: expected string or nested-attributes object, got ${typeof entry}.`)
865
+ }
866
+ }
867
+
868
+ return {attributes, nested}
869
+ }
870
+
871
+ /**
872
+ * Runs filter writable frontend model attributes.
873
+ * @param {Record<string, ?>} receiver - Model instance or prototype.
874
+ * @param {Record<string, ?>} attributes - Incoming frontend-model attributes.
875
+ * @param {FrontendModelBaseResource | null} [resource] - Resource instance for virtual-setter detection.
876
+ * @param {string[] | null} [permittedAttributeNames] - Optional explicit permit list. `null` falls back to setter-existence checks only.
877
+ * @returns {Record<string, ?>} - Writable attributes only.
878
+ */
879
+ function filterWritableFrontendModelAttributes(receiver, attributes, resource = /**
880
+ * Narrows the runtime value to the documented type.
881
+ @type {FrontendModelBaseResource | null} */ (null), permittedAttributeNames = null) {
882
+ // Frontend-model writes should fail fast when callers submit read-only or unknown attrs.
883
+ // Silent drops hide contract mistakes in generated models and app-side wrapper code.
884
+ /**
885
+ * Writable attributes.
886
+ @type {Record<string, ?>} */
887
+ const writableAttributes = {}
888
+ /**
889
+ * Invalid attributes.
890
+ @type {string[]} */
891
+ const invalidAttributes = []
892
+ /**
893
+ * Not permitted attributes.
894
+ @type {string[]} */
895
+ const notPermittedAttributes = []
896
+
897
+ const permitSet = Array.isArray(permittedAttributeNames) ? new Set(permittedAttributeNames) : null
898
+ const translatedSet = resource ? new Set(/**
899
+ * Narrows the runtime value to the documented type.
900
+ @type {typeof FrontendModelBaseResource} */ (resource.constructor).translatedAttributes || []) : new Set()
901
+
902
+ for (const [attributeName, value] of Object.entries(attributes)) {
903
+ if (permitSet && !permitSet.has(attributeName)) {
904
+ notPermittedAttributes.push(attributeName)
905
+ continue
906
+ }
907
+
908
+ const setterName = `set${inflection.camelize(attributeName)}`
909
+ const resourceSetterName = `${setterName}Attribute`
910
+
911
+ if (setterName in receiver) {
912
+ writableAttributes[attributeName] = value
913
+ } else if (resource && typeof /**
914
+ * Narrows the runtime value to the documented type.
915
+ @type {Record<string, ?>} */ (/**
916
+ * Narrows the runtime value to the documented type.
917
+ @type {?} */ (resource))[resourceSetterName] === "function") {
918
+ writableAttributes[attributeName] = value
919
+ } else if (translatedSet.has(attributeName)) {
920
+ writableAttributes[attributeName] = value
921
+ } else {
922
+ invalidAttributes.push(attributeName)
923
+ }
924
+ }
925
+
926
+ if (notPermittedAttributes.length > 0) {
927
+ throw new Error(`Frontend model write attributes not permitted by permittedParams(): ${notPermittedAttributes.join(", ")}`)
928
+ }
929
+
930
+ if (invalidAttributes.length > 0) {
931
+ throw new Error(`Invalid frontend model write attributes: ${invalidAttributes.join(", ")}`)
932
+ }
933
+
934
+ return writableAttributes
935
+ }