velocious 1.0.448 → 1.0.450

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 (645) hide show
  1. package/build/application.js +4 -4
  2. package/build/authorization/ability.js +8 -8
  3. package/build/authorization/base-resource.js +4 -4
  4. package/build/background-jobs/cron-expression.js +1 -1
  5. package/build/background-jobs/forked-runner-child.js +1 -1
  6. package/build/background-jobs/job-registry.js +1 -1
  7. package/build/background-jobs/job-runner.js +1 -1
  8. package/build/background-jobs/job.js +1 -1
  9. package/build/background-jobs/json-socket.js +4 -4
  10. package/build/background-jobs/main.js +21 -21
  11. package/build/background-jobs/scheduler.js +7 -7
  12. package/build/background-jobs/store.js +7 -7
  13. package/build/background-jobs/web/controller.js +2 -2
  14. package/build/background-jobs/worker.js +12 -12
  15. package/build/beacon/client.js +11 -8
  16. package/build/beacon/in-process-broker.js +2 -2
  17. package/build/beacon/in-process-client.js +2 -2
  18. package/build/beacon/server.js +3 -3
  19. package/build/cli/browser-cli.js +1 -1
  20. package/build/cli/commands/db/base-command.js +2 -2
  21. package/build/cli/index.js +2 -2
  22. package/build/cli/tenant-database-command-helper.js +3 -3
  23. package/build/cli/use-browser-cli.js +1 -1
  24. package/build/configuration.js +38 -38
  25. package/build/controller.js +8 -8
  26. package/build/current-configuration.js +1 -1
  27. package/build/database/annotations-async-hooks.js +2 -2
  28. package/build/database/annotations.js +3 -3
  29. package/build/database/drivers/base-column.js +1 -1
  30. package/build/database/drivers/base-foreign-key.js +1 -1
  31. package/build/database/drivers/base-table.js +1 -1
  32. package/build/database/drivers/base.js +10 -10
  33. package/build/database/drivers/mssql/index.js +1 -1
  34. package/build/database/drivers/mssql/table.js +1 -1
  35. package/build/database/drivers/mysql/index.js +3 -3
  36. package/build/database/drivers/mysql/query.js +1 -1
  37. package/build/database/drivers/mysql/table.js +1 -1
  38. package/build/database/drivers/pgsql/index.js +2 -2
  39. package/build/database/drivers/sqlite/base.js +16 -16
  40. package/build/database/drivers/sqlite/index.js +11 -11
  41. package/build/database/drivers/sqlite/index.native.js +1 -1
  42. package/build/database/drivers/sqlite/index.web.js +3 -3
  43. package/build/database/drivers/sqlite/query.js +1 -1
  44. package/build/database/drivers/sqlite/query.web.js +1 -1
  45. package/build/database/drivers/sqlite/sql/alter-table.js +2 -2
  46. package/build/database/drivers/sqlite/table.js +1 -1
  47. package/build/database/migrator/files-finder.js +1 -1
  48. package/build/database/migrator.js +6 -6
  49. package/build/database/pool/async-tracked-multi-connection.js +27 -27
  50. package/build/database/pool/base-methods-forward.js +4 -4
  51. package/build/database/pool/base.js +8 -8
  52. package/build/database/query/from-base.js +1 -1
  53. package/build/database/query/index.js +10 -10
  54. package/build/database/query/join-object.js +3 -3
  55. package/build/database/query/model-class-query.js +39 -39
  56. package/build/database/query/preloader/belongs-to.js +22 -22
  57. package/build/database/query/preloader/has-many.js +20 -20
  58. package/build/database/query/preloader/has-one.js +8 -8
  59. package/build/database/query/preloader/selection.js +3 -3
  60. package/build/database/query/preloader.js +8 -8
  61. package/build/database/query/query-data.js +9 -9
  62. package/build/database/query/where-model-class-hash.js +7 -7
  63. package/build/database/query/with-count.js +9 -9
  64. package/build/database/record/acts-as-list.js +15 -15
  65. package/build/database/record/attachments/handle.js +2 -2
  66. package/build/database/record/attachments/normalize-input.js +12 -12
  67. package/build/database/record/attachments/storage-drivers/s3.js +6 -6
  68. package/build/database/record/attachments/store.js +13 -13
  69. package/build/database/record/index.js +127 -128
  70. package/build/database/record/instance-relationships/base.js +11 -11
  71. package/build/database/record/instance-relationships/belongs-to.js +3 -3
  72. package/build/database/record/instance-relationships/has-many.js +8 -8
  73. package/build/database/record/instance-relationships/has-one.js +7 -7
  74. package/build/database/record/relationships/base.js +2 -2
  75. package/build/database/record/state-machine.js +7 -7
  76. package/build/database/record/validators/presence.js +1 -1
  77. package/build/database/record/validators/uniqueness.js +5 -5
  78. package/build/database/table-data/index.js +4 -4
  79. package/build/environment-handlers/base.js +2 -2
  80. package/build/environment-handlers/browser.js +7 -7
  81. package/build/environment-handlers/node/cli/commands/cli-command-context.js +1 -1
  82. package/build/environment-handlers/node/cli/commands/console.js +4 -4
  83. package/build/environment-handlers/node/cli/commands/db/schema/dump.js +1 -1
  84. package/build/environment-handlers/node/cli/commands/db/schema/load.js +3 -3
  85. package/build/environment-handlers/node/cli/commands/generate/base-models.js +1 -16
  86. package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +179 -89
  87. package/build/environment-handlers/node.js +6 -6
  88. package/build/frontend-model-controller.js +90 -82
  89. package/build/frontend-model-resource/base-resource.js +343 -167
  90. package/build/frontend-models/base.js +362 -205
  91. package/build/frontend-models/clear-pending-debounced-callback.js +1 -1
  92. package/build/frontend-models/event-hook-models.js +2 -2
  93. package/build/frontend-models/outgoing-event-buffer.js +2 -2
  94. package/build/frontend-models/preloader.js +8 -7
  95. package/build/frontend-models/query.js +43 -38
  96. package/build/frontend-models/resource-definition.js +6 -6
  97. package/build/frontend-models/transport-serialization.js +11 -11
  98. package/build/frontend-models/use-destroyed-event.js +10 -10
  99. package/build/frontend-models/use-model-class-event.js +11 -11
  100. package/build/frontend-models/use-updated-event.js +11 -11
  101. package/build/frontend-models/websocket-channel.js +26 -17
  102. package/build/frontend-models/websocket-publishers.js +9 -9
  103. package/build/http-client/response.js +2 -2
  104. package/build/http-server/client/index.js +8 -8
  105. package/build/http-server/client/params-to-object.js +10 -10
  106. package/build/http-server/client/request-buffer/form-data-part.js +2 -2
  107. package/build/http-server/client/request-buffer/index.js +8 -8
  108. package/build/http-server/client/request-parser.js +3 -3
  109. package/build/http-server/client/request-runner.js +6 -6
  110. package/build/http-server/client/request-timing.js +5 -5
  111. package/build/http-server/client/request.js +1 -1
  112. package/build/http-server/client/response.js +5 -5
  113. package/build/http-server/client/websocket-request.js +4 -4
  114. package/build/http-server/client/websocket-session.js +18 -18
  115. package/build/http-server/development-reloader.js +5 -5
  116. package/build/http-server/index.js +12 -12
  117. package/build/http-server/remote-address.js +4 -4
  118. package/build/http-server/server-client.js +3 -3
  119. package/build/http-server/server-lock.js +4 -4
  120. package/build/http-server/websocket-channel-subscribers.js +3 -3
  121. package/build/http-server/websocket-channel.js +1 -1
  122. package/build/http-server/websocket-connection.js +1 -1
  123. package/build/http-server/websocket-event-log-store.js +6 -6
  124. package/build/http-server/websocket-events-host.js +2 -2
  125. package/build/http-server/worker-handler/in-process.js +7 -7
  126. package/build/http-server/worker-handler/index.js +4 -4
  127. package/build/http-server/worker-handler/worker-thread.js +3 -3
  128. package/build/logger/outputs/array-output.js +3 -3
  129. package/build/logger/outputs/console-output.js +1 -1
  130. package/build/logger/outputs/file-output.js +4 -4
  131. package/build/logger/outputs/stdout-output.js +1 -1
  132. package/build/logger.js +10 -10
  133. package/build/mailer/backends/smtp.js +3 -3
  134. package/build/mailer/base.js +8 -8
  135. package/build/mailer/delivery.js +4 -4
  136. package/build/plugins/sqljs-wasm-route-controller.js +1 -1
  137. package/build/routes/base-route.js +6 -6
  138. package/build/routes/basic-route.js +1 -1
  139. package/build/routes/hooks/frontend-model-command-route-hook.js +1 -1
  140. package/build/routes/index.js +1 -1
  141. package/build/routes/plugin-routes.js +1 -1
  142. package/build/routes/resolver.js +11 -11
  143. package/build/routes/resource-route.js +1 -1
  144. package/build/src/application.d.ts +3 -3
  145. package/build/src/application.d.ts.map +1 -1
  146. package/build/src/application.js +5 -5
  147. package/build/src/authorization/ability.d.ts +7 -7
  148. package/build/src/authorization/ability.d.ts.map +1 -1
  149. package/build/src/authorization/ability.js +9 -9
  150. package/build/src/authorization/base-resource.d.ts +1 -1
  151. package/build/src/authorization/base-resource.d.ts.map +1 -1
  152. package/build/src/authorization/base-resource.js +5 -5
  153. package/build/src/background-jobs/cron-expression.js +2 -2
  154. package/build/src/background-jobs/forked-runner-child.js +2 -2
  155. package/build/src/background-jobs/job-record.d.ts +2 -1
  156. package/build/src/background-jobs/job-record.d.ts.map +1 -1
  157. package/build/src/background-jobs/job-registry.d.ts +1 -1
  158. package/build/src/background-jobs/job-registry.d.ts.map +1 -1
  159. package/build/src/background-jobs/job-registry.js +2 -2
  160. package/build/src/background-jobs/job-runner.js +2 -2
  161. package/build/src/background-jobs/job.js +2 -2
  162. package/build/src/background-jobs/json-socket.d.ts +4 -4
  163. package/build/src/background-jobs/json-socket.d.ts.map +1 -1
  164. package/build/src/background-jobs/json-socket.js +5 -5
  165. package/build/src/background-jobs/main.d.ts +18 -18
  166. package/build/src/background-jobs/main.d.ts.map +1 -1
  167. package/build/src/background-jobs/main.js +22 -22
  168. package/build/src/background-jobs/scheduler.d.ts +5 -5
  169. package/build/src/background-jobs/scheduler.d.ts.map +1 -1
  170. package/build/src/background-jobs/scheduler.js +8 -8
  171. package/build/src/background-jobs/store.js +8 -8
  172. package/build/src/background-jobs/web/controller.js +3 -3
  173. package/build/src/background-jobs/worker.d.ts +6 -6
  174. package/build/src/background-jobs/worker.d.ts.map +1 -1
  175. package/build/src/background-jobs/worker.js +13 -13
  176. package/build/src/beacon/client.d.ts +4 -4
  177. package/build/src/beacon/client.d.ts.map +1 -1
  178. package/build/src/beacon/client.js +12 -9
  179. package/build/src/beacon/in-process-broker.d.ts.map +1 -1
  180. package/build/src/beacon/in-process-broker.js +3 -3
  181. package/build/src/beacon/in-process-client.d.ts +1 -1
  182. package/build/src/beacon/in-process-client.d.ts.map +1 -1
  183. package/build/src/beacon/in-process-client.js +3 -3
  184. package/build/src/beacon/server.d.ts +2 -2
  185. package/build/src/beacon/server.d.ts.map +1 -1
  186. package/build/src/beacon/server.js +4 -4
  187. package/build/src/cli/browser-cli.js +2 -2
  188. package/build/src/cli/commands/db/base-command.d.ts +2 -2
  189. package/build/src/cli/commands/db/base-command.d.ts.map +1 -1
  190. package/build/src/cli/commands/db/base-command.js +3 -3
  191. package/build/src/cli/index.js +3 -3
  192. package/build/src/cli/tenant-database-command-helper.d.ts +1 -1
  193. package/build/src/cli/tenant-database-command-helper.d.ts.map +1 -1
  194. package/build/src/cli/tenant-database-command-helper.js +4 -4
  195. package/build/src/cli/use-browser-cli.js +2 -2
  196. package/build/src/configuration.d.ts +14 -14
  197. package/build/src/configuration.d.ts.map +1 -1
  198. package/build/src/configuration.js +39 -39
  199. package/build/src/controller.js +10 -10
  200. package/build/src/current-configuration.js +2 -2
  201. package/build/src/database/annotations-async-hooks.js +3 -3
  202. package/build/src/database/annotations.d.ts.map +1 -1
  203. package/build/src/database/annotations.js +4 -4
  204. package/build/src/database/drivers/base-column.d.ts +1 -1
  205. package/build/src/database/drivers/base-column.d.ts.map +1 -1
  206. package/build/src/database/drivers/base-column.js +2 -2
  207. package/build/src/database/drivers/base-foreign-key.d.ts +1 -1
  208. package/build/src/database/drivers/base-foreign-key.d.ts.map +1 -1
  209. package/build/src/database/drivers/base-foreign-key.js +2 -2
  210. package/build/src/database/drivers/base-table.d.ts +1 -1
  211. package/build/src/database/drivers/base-table.d.ts.map +1 -1
  212. package/build/src/database/drivers/base-table.js +2 -2
  213. package/build/src/database/drivers/base.d.ts +6 -6
  214. package/build/src/database/drivers/base.d.ts.map +1 -1
  215. package/build/src/database/drivers/base.js +11 -11
  216. package/build/src/database/drivers/mssql/index.js +2 -2
  217. package/build/src/database/drivers/mssql/table.js +2 -2
  218. package/build/src/database/drivers/mysql/index.js +4 -4
  219. package/build/src/database/drivers/mysql/query.js +2 -2
  220. package/build/src/database/drivers/mysql/table.js +2 -2
  221. package/build/src/database/drivers/pgsql/index.js +3 -3
  222. package/build/src/database/drivers/sqlite/base.d.ts +3 -3
  223. package/build/src/database/drivers/sqlite/base.d.ts.map +1 -1
  224. package/build/src/database/drivers/sqlite/base.js +17 -17
  225. package/build/src/database/drivers/sqlite/index.d.ts +4 -4
  226. package/build/src/database/drivers/sqlite/index.d.ts.map +1 -1
  227. package/build/src/database/drivers/sqlite/index.js +12 -12
  228. package/build/src/database/drivers/sqlite/index.native.js +2 -2
  229. package/build/src/database/drivers/sqlite/index.web.d.ts +2 -2
  230. package/build/src/database/drivers/sqlite/index.web.d.ts.map +1 -1
  231. package/build/src/database/drivers/sqlite/index.web.js +4 -4
  232. package/build/src/database/drivers/sqlite/query.js +2 -2
  233. package/build/src/database/drivers/sqlite/query.web.js +2 -2
  234. package/build/src/database/drivers/sqlite/sql/alter-table.js +3 -3
  235. package/build/src/database/drivers/sqlite/table.js +2 -2
  236. package/build/src/database/migrator/files-finder.js +2 -2
  237. package/build/src/database/migrator.d.ts +1 -1
  238. package/build/src/database/migrator.d.ts.map +1 -1
  239. package/build/src/database/migrator.js +7 -7
  240. package/build/src/database/pool/async-tracked-multi-connection.d.ts +9 -9
  241. package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
  242. package/build/src/database/pool/async-tracked-multi-connection.js +28 -28
  243. package/build/src/database/pool/base-methods-forward.js +7 -7
  244. package/build/src/database/pool/base.d.ts +1 -1
  245. package/build/src/database/pool/base.d.ts.map +1 -1
  246. package/build/src/database/pool/base.js +9 -9
  247. package/build/src/database/query/from-base.d.ts +1 -1
  248. package/build/src/database/query/from-base.d.ts.map +1 -1
  249. package/build/src/database/query/from-base.js +2 -2
  250. package/build/src/database/query/index.d.ts +4 -4
  251. package/build/src/database/query/index.d.ts.map +1 -1
  252. package/build/src/database/query/index.js +11 -11
  253. package/build/src/database/query/join-object.js +4 -4
  254. package/build/src/database/query/model-class-query.d.ts +4 -4
  255. package/build/src/database/query/model-class-query.d.ts.map +1 -1
  256. package/build/src/database/query/model-class-query.js +40 -40
  257. package/build/src/database/query/preloader/belongs-to.d.ts +2 -2
  258. package/build/src/database/query/preloader/belongs-to.d.ts.map +1 -1
  259. package/build/src/database/query/preloader/belongs-to.js +23 -23
  260. package/build/src/database/query/preloader/has-many.d.ts +1 -1
  261. package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
  262. package/build/src/database/query/preloader/has-many.js +21 -21
  263. package/build/src/database/query/preloader/has-one.d.ts +2 -2
  264. package/build/src/database/query/preloader/has-one.d.ts.map +1 -1
  265. package/build/src/database/query/preloader/has-one.js +9 -9
  266. package/build/src/database/query/preloader/selection.js +4 -4
  267. package/build/src/database/query/preloader.d.ts +1 -1
  268. package/build/src/database/query/preloader.d.ts.map +1 -1
  269. package/build/src/database/query/preloader.js +9 -9
  270. package/build/src/database/query/query-data.js +10 -10
  271. package/build/src/database/query/where-model-class-hash.js +8 -8
  272. package/build/src/database/query/with-count.js +10 -10
  273. package/build/src/database/record/acts-as-list.js +20 -20
  274. package/build/src/database/record/attachments/handle.d.ts +2 -2
  275. package/build/src/database/record/attachments/handle.d.ts.map +1 -1
  276. package/build/src/database/record/attachments/handle.js +3 -3
  277. package/build/src/database/record/attachments/normalize-input.js +15 -15
  278. package/build/src/database/record/attachments/storage-drivers/s3.js +7 -7
  279. package/build/src/database/record/attachments/store.d.ts +2 -2
  280. package/build/src/database/record/attachments/store.d.ts.map +1 -1
  281. package/build/src/database/record/attachments/store.js +14 -14
  282. package/build/src/database/record/index.d.ts +35 -32
  283. package/build/src/database/record/index.d.ts.map +1 -1
  284. package/build/src/database/record/index.js +147 -148
  285. package/build/src/database/record/instance-relationships/base.d.ts +3 -3
  286. package/build/src/database/record/instance-relationships/base.d.ts.map +1 -1
  287. package/build/src/database/record/instance-relationships/base.js +13 -13
  288. package/build/src/database/record/instance-relationships/belongs-to.js +4 -4
  289. package/build/src/database/record/instance-relationships/has-many.js +9 -9
  290. package/build/src/database/record/instance-relationships/has-one.d.ts +1 -1
  291. package/build/src/database/record/instance-relationships/has-one.d.ts.map +1 -1
  292. package/build/src/database/record/instance-relationships/has-one.js +8 -8
  293. package/build/src/database/record/relationships/base.js +4 -4
  294. package/build/src/database/record/state-machine.js +8 -8
  295. package/build/src/database/record/validators/presence.js +2 -2
  296. package/build/src/database/record/validators/uniqueness.js +6 -6
  297. package/build/src/database/table-data/index.d.ts +4 -4
  298. package/build/src/database/table-data/index.d.ts.map +1 -1
  299. package/build/src/database/table-data/index.js +5 -5
  300. package/build/src/environment-handlers/base.js +3 -3
  301. package/build/src/environment-handlers/browser.d.ts +3 -3
  302. package/build/src/environment-handlers/browser.d.ts.map +1 -1
  303. package/build/src/environment-handlers/browser.js +8 -8
  304. package/build/src/environment-handlers/node/cli/commands/cli-command-context.js +2 -2
  305. package/build/src/environment-handlers/node/cli/commands/console.d.ts.map +1 -1
  306. package/build/src/environment-handlers/node/cli/commands/console.js +5 -5
  307. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.d.ts +1 -1
  308. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.d.ts.map +1 -1
  309. package/build/src/environment-handlers/node/cli/commands/db/schema/dump.js +2 -2
  310. package/build/src/environment-handlers/node/cli/commands/db/schema/load.d.ts +1 -1
  311. package/build/src/environment-handlers/node/cli/commands/db/schema/load.d.ts.map +1 -1
  312. package/build/src/environment-handlers/node/cli/commands/db/schema/load.js +4 -4
  313. package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
  314. package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +2 -15
  315. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +105 -33
  316. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
  317. package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +172 -87
  318. package/build/src/environment-handlers/node.d.ts +2 -2
  319. package/build/src/environment-handlers/node.d.ts.map +1 -1
  320. package/build/src/environment-handlers/node.js +7 -7
  321. package/build/src/frontend-model-controller.d.ts +5 -6
  322. package/build/src/frontend-model-controller.d.ts.map +1 -1
  323. package/build/src/frontend-model-controller.js +95 -89
  324. package/build/src/frontend-model-resource/base-resource.d.ts +239 -91
  325. package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
  326. package/build/src/frontend-model-resource/base-resource.js +302 -172
  327. package/build/src/frontend-models/base.d.ts +186 -115
  328. package/build/src/frontend-models/base.d.ts.map +1 -1
  329. package/build/src/frontend-models/base.js +347 -218
  330. package/build/src/frontend-models/clear-pending-debounced-callback.js +2 -2
  331. package/build/src/frontend-models/event-hook-models.d.ts.map +1 -1
  332. package/build/src/frontend-models/event-hook-models.js +3 -3
  333. package/build/src/frontend-models/outgoing-event-buffer.d.ts +1 -1
  334. package/build/src/frontend-models/outgoing-event-buffer.d.ts.map +1 -1
  335. package/build/src/frontend-models/outgoing-event-buffer.js +3 -3
  336. package/build/src/frontend-models/preloader.d.ts.map +1 -1
  337. package/build/src/frontend-models/preloader.js +9 -8
  338. package/build/src/frontend-models/query.d.ts +16 -8
  339. package/build/src/frontend-models/query.d.ts.map +1 -1
  340. package/build/src/frontend-models/query.js +43 -39
  341. package/build/src/frontend-models/resource-definition.js +7 -7
  342. package/build/src/frontend-models/transport-serialization.js +12 -12
  343. package/build/src/frontend-models/use-destroyed-event.d.ts.map +1 -1
  344. package/build/src/frontend-models/use-destroyed-event.js +11 -11
  345. package/build/src/frontend-models/use-model-class-event.d.ts.map +1 -1
  346. package/build/src/frontend-models/use-model-class-event.js +12 -12
  347. package/build/src/frontend-models/use-updated-event.d.ts.map +1 -1
  348. package/build/src/frontend-models/use-updated-event.js +12 -12
  349. package/build/src/frontend-models/websocket-channel.d.ts +6 -1
  350. package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
  351. package/build/src/frontend-models/websocket-channel.js +26 -18
  352. package/build/src/frontend-models/websocket-publishers.js +11 -11
  353. package/build/src/http-client/response.d.ts +2 -2
  354. package/build/src/http-client/response.d.ts.map +1 -1
  355. package/build/src/http-client/response.js +3 -3
  356. package/build/src/http-server/client/index.d.ts +1 -1
  357. package/build/src/http-server/client/index.d.ts.map +1 -1
  358. package/build/src/http-server/client/index.js +9 -9
  359. package/build/src/http-server/client/params-to-object.js +11 -11
  360. package/build/src/http-server/client/request-buffer/form-data-part.d.ts +2 -2
  361. package/build/src/http-server/client/request-buffer/form-data-part.d.ts.map +1 -1
  362. package/build/src/http-server/client/request-buffer/form-data-part.js +3 -3
  363. package/build/src/http-server/client/request-buffer/index.d.ts +4 -4
  364. package/build/src/http-server/client/request-buffer/index.d.ts.map +1 -1
  365. package/build/src/http-server/client/request-buffer/index.js +9 -9
  366. package/build/src/http-server/client/request-parser.d.ts +1 -1
  367. package/build/src/http-server/client/request-parser.d.ts.map +1 -1
  368. package/build/src/http-server/client/request-parser.js +4 -4
  369. package/build/src/http-server/client/request-runner.js +7 -7
  370. package/build/src/http-server/client/request-timing.d.ts +5 -5
  371. package/build/src/http-server/client/request-timing.d.ts.map +1 -1
  372. package/build/src/http-server/client/request-timing.js +6 -6
  373. package/build/src/http-server/client/request.js +2 -2
  374. package/build/src/http-server/client/response.d.ts +3 -3
  375. package/build/src/http-server/client/response.d.ts.map +1 -1
  376. package/build/src/http-server/client/response.js +6 -6
  377. package/build/src/http-server/client/websocket-request.d.ts +3 -3
  378. package/build/src/http-server/client/websocket-request.d.ts.map +1 -1
  379. package/build/src/http-server/client/websocket-request.js +5 -5
  380. package/build/src/http-server/client/websocket-session.d.ts +6 -6
  381. package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
  382. package/build/src/http-server/client/websocket-session.js +19 -19
  383. package/build/src/http-server/development-reloader.d.ts +3 -3
  384. package/build/src/http-server/development-reloader.d.ts.map +1 -1
  385. package/build/src/http-server/development-reloader.js +6 -6
  386. package/build/src/http-server/index.d.ts +7 -7
  387. package/build/src/http-server/index.d.ts.map +1 -1
  388. package/build/src/http-server/index.js +13 -13
  389. package/build/src/http-server/remote-address.js +6 -6
  390. package/build/src/http-server/server-client.js +4 -4
  391. package/build/src/http-server/server-lock.js +5 -5
  392. package/build/src/http-server/websocket-channel-subscribers.d.ts +1 -1
  393. package/build/src/http-server/websocket-channel-subscribers.d.ts.map +1 -1
  394. package/build/src/http-server/websocket-channel-subscribers.js +4 -4
  395. package/build/src/http-server/websocket-channel.d.ts +1 -1
  396. package/build/src/http-server/websocket-channel.d.ts.map +1 -1
  397. package/build/src/http-server/websocket-channel.js +2 -2
  398. package/build/src/http-server/websocket-connection.d.ts +1 -1
  399. package/build/src/http-server/websocket-connection.d.ts.map +1 -1
  400. package/build/src/http-server/websocket-connection.js +2 -2
  401. package/build/src/http-server/websocket-event-log-store.d.ts +1 -1
  402. package/build/src/http-server/websocket-event-log-store.d.ts.map +1 -1
  403. package/build/src/http-server/websocket-event-log-store.js +7 -7
  404. package/build/src/http-server/websocket-events-host.d.ts +1 -1
  405. package/build/src/http-server/websocket-events-host.d.ts.map +1 -1
  406. package/build/src/http-server/websocket-events-host.js +3 -3
  407. package/build/src/http-server/worker-handler/in-process.d.ts +3 -3
  408. package/build/src/http-server/worker-handler/in-process.d.ts.map +1 -1
  409. package/build/src/http-server/worker-handler/in-process.js +9 -9
  410. package/build/src/http-server/worker-handler/index.d.ts +4 -4
  411. package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
  412. package/build/src/http-server/worker-handler/index.js +5 -5
  413. package/build/src/http-server/worker-handler/worker-thread.d.ts +2 -2
  414. package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
  415. package/build/src/http-server/worker-handler/worker-thread.js +4 -4
  416. package/build/src/logger/outputs/array-output.d.ts +3 -3
  417. package/build/src/logger/outputs/array-output.d.ts.map +1 -1
  418. package/build/src/logger/outputs/array-output.js +4 -4
  419. package/build/src/logger/outputs/console-output.d.ts +1 -1
  420. package/build/src/logger/outputs/console-output.d.ts.map +1 -1
  421. package/build/src/logger/outputs/console-output.js +2 -2
  422. package/build/src/logger/outputs/file-output.d.ts +4 -4
  423. package/build/src/logger/outputs/file-output.d.ts.map +1 -1
  424. package/build/src/logger/outputs/file-output.js +5 -5
  425. package/build/src/logger/outputs/stdout-output.d.ts.map +1 -1
  426. package/build/src/logger/outputs/stdout-output.js +2 -2
  427. package/build/src/logger.d.ts.map +1 -1
  428. package/build/src/logger.js +11 -11
  429. package/build/src/mailer/backends/smtp.d.ts.map +1 -1
  430. package/build/src/mailer/backends/smtp.js +5 -5
  431. package/build/src/mailer/base.js +11 -11
  432. package/build/src/mailer/delivery.d.ts +3 -3
  433. package/build/src/mailer/delivery.d.ts.map +1 -1
  434. package/build/src/mailer/delivery.js +5 -5
  435. package/build/src/plugins/sqljs-wasm-route-controller.js +2 -2
  436. package/build/src/routes/base-route.d.ts +6 -6
  437. package/build/src/routes/base-route.d.ts.map +1 -1
  438. package/build/src/routes/base-route.js +7 -7
  439. package/build/src/routes/basic-route.js +2 -2
  440. package/build/src/routes/hooks/frontend-model-command-route-hook.js +2 -2
  441. package/build/src/routes/index.js +2 -2
  442. package/build/src/routes/plugin-routes.js +2 -2
  443. package/build/src/routes/resolver.d.ts +1 -1
  444. package/build/src/routes/resolver.d.ts.map +1 -1
  445. package/build/src/routes/resolver.js +13 -13
  446. package/build/src/routes/resource-route.d.ts +1 -1
  447. package/build/src/routes/resource-route.d.ts.map +1 -1
  448. package/build/src/routes/resource-route.js +2 -2
  449. package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts.map +1 -1
  450. package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +9 -9
  451. package/build/src/testing/expect-utils.js +13 -13
  452. package/build/src/testing/expect.d.ts +7 -1
  453. package/build/src/testing/expect.d.ts.map +1 -1
  454. package/build/src/testing/expect.js +17 -9
  455. package/build/src/testing/test-files-finder.d.ts +8 -8
  456. package/build/src/testing/test-files-finder.d.ts.map +1 -1
  457. package/build/src/testing/test-files-finder.js +9 -9
  458. package/build/src/testing/test-filter-parser.js +3 -3
  459. package/build/src/testing/test-runner.d.ts +2 -2
  460. package/build/src/testing/test-runner.d.ts.map +1 -1
  461. package/build/src/testing/test-runner.js +17 -17
  462. package/build/src/testing/test-suite-splitter.js +2 -2
  463. package/build/src/testing/test.d.ts +2 -2
  464. package/build/src/testing/test.d.ts.map +1 -1
  465. package/build/src/testing/test.js +16 -16
  466. package/build/src/utils/backtrace-cleaner.d.ts +1 -1
  467. package/build/src/utils/backtrace-cleaner.d.ts.map +1 -1
  468. package/build/src/utils/backtrace-cleaner.js +2 -2
  469. package/build/src/utils/format-value.js +2 -2
  470. package/build/src/utils/model-scope.js +2 -2
  471. package/build/src/utils/ransack.js +27 -27
  472. package/build/src/utils/with-tracked-stack-async-hooks.js +8 -8
  473. package/build/src/utils/with-tracked-stack.js +4 -4
  474. package/build/testing/browser-frontend-model-event-hook-scenarios.js +8 -8
  475. package/build/testing/expect-utils.js +11 -11
  476. package/build/testing/expect.js +16 -7
  477. package/build/testing/test-files-finder.js +8 -8
  478. package/build/testing/test-filter-parser.js +2 -2
  479. package/build/testing/test-runner.js +16 -16
  480. package/build/testing/test-suite-splitter.js +1 -1
  481. package/build/testing/test.js +15 -15
  482. package/build/utils/backtrace-cleaner.js +1 -1
  483. package/build/utils/format-value.js +1 -1
  484. package/build/utils/model-scope.js +1 -1
  485. package/build/utils/ransack.js +26 -26
  486. package/build/utils/with-tracked-stack-async-hooks.js +7 -7
  487. package/build/utils/with-tracked-stack.js +3 -3
  488. package/package.json +2 -1
  489. package/src/application.js +4 -4
  490. package/src/authorization/ability.js +8 -8
  491. package/src/authorization/base-resource.js +4 -4
  492. package/src/background-jobs/cron-expression.js +1 -1
  493. package/src/background-jobs/forked-runner-child.js +1 -1
  494. package/src/background-jobs/job-registry.js +1 -1
  495. package/src/background-jobs/job-runner.js +1 -1
  496. package/src/background-jobs/job.js +1 -1
  497. package/src/background-jobs/json-socket.js +4 -4
  498. package/src/background-jobs/main.js +21 -21
  499. package/src/background-jobs/scheduler.js +7 -7
  500. package/src/background-jobs/store.js +7 -7
  501. package/src/background-jobs/web/controller.js +2 -2
  502. package/src/background-jobs/worker.js +12 -12
  503. package/src/beacon/client.js +11 -8
  504. package/src/beacon/in-process-broker.js +2 -2
  505. package/src/beacon/in-process-client.js +2 -2
  506. package/src/beacon/server.js +3 -3
  507. package/src/cli/browser-cli.js +1 -1
  508. package/src/cli/commands/db/base-command.js +2 -2
  509. package/src/cli/index.js +2 -2
  510. package/src/cli/tenant-database-command-helper.js +3 -3
  511. package/src/cli/use-browser-cli.js +1 -1
  512. package/src/configuration.js +38 -38
  513. package/src/controller.js +8 -8
  514. package/src/current-configuration.js +1 -1
  515. package/src/database/annotations-async-hooks.js +2 -2
  516. package/src/database/annotations.js +3 -3
  517. package/src/database/drivers/base-column.js +1 -1
  518. package/src/database/drivers/base-foreign-key.js +1 -1
  519. package/src/database/drivers/base-table.js +1 -1
  520. package/src/database/drivers/base.js +10 -10
  521. package/src/database/drivers/mssql/index.js +1 -1
  522. package/src/database/drivers/mssql/table.js +1 -1
  523. package/src/database/drivers/mysql/index.js +3 -3
  524. package/src/database/drivers/mysql/query.js +1 -1
  525. package/src/database/drivers/mysql/table.js +1 -1
  526. package/src/database/drivers/pgsql/index.js +2 -2
  527. package/src/database/drivers/sqlite/base.js +16 -16
  528. package/src/database/drivers/sqlite/index.js +11 -11
  529. package/src/database/drivers/sqlite/index.native.js +1 -1
  530. package/src/database/drivers/sqlite/index.web.js +3 -3
  531. package/src/database/drivers/sqlite/query.js +1 -1
  532. package/src/database/drivers/sqlite/query.web.js +1 -1
  533. package/src/database/drivers/sqlite/sql/alter-table.js +2 -2
  534. package/src/database/drivers/sqlite/table.js +1 -1
  535. package/src/database/migrator/files-finder.js +1 -1
  536. package/src/database/migrator.js +6 -6
  537. package/src/database/pool/async-tracked-multi-connection.js +27 -27
  538. package/src/database/pool/base-methods-forward.js +4 -4
  539. package/src/database/pool/base.js +8 -8
  540. package/src/database/query/from-base.js +1 -1
  541. package/src/database/query/index.js +10 -10
  542. package/src/database/query/join-object.js +3 -3
  543. package/src/database/query/model-class-query.js +39 -39
  544. package/src/database/query/preloader/belongs-to.js +22 -22
  545. package/src/database/query/preloader/has-many.js +20 -20
  546. package/src/database/query/preloader/has-one.js +8 -8
  547. package/src/database/query/preloader/selection.js +3 -3
  548. package/src/database/query/preloader.js +8 -8
  549. package/src/database/query/query-data.js +9 -9
  550. package/src/database/query/where-model-class-hash.js +7 -7
  551. package/src/database/query/with-count.js +9 -9
  552. package/src/database/record/acts-as-list.js +15 -15
  553. package/src/database/record/attachments/handle.js +2 -2
  554. package/src/database/record/attachments/normalize-input.js +12 -12
  555. package/src/database/record/attachments/storage-drivers/s3.js +6 -6
  556. package/src/database/record/attachments/store.js +13 -13
  557. package/src/database/record/index.js +127 -128
  558. package/src/database/record/instance-relationships/base.js +11 -11
  559. package/src/database/record/instance-relationships/belongs-to.js +3 -3
  560. package/src/database/record/instance-relationships/has-many.js +8 -8
  561. package/src/database/record/instance-relationships/has-one.js +7 -7
  562. package/src/database/record/relationships/base.js +2 -2
  563. package/src/database/record/state-machine.js +7 -7
  564. package/src/database/record/validators/presence.js +1 -1
  565. package/src/database/record/validators/uniqueness.js +5 -5
  566. package/src/database/table-data/index.js +4 -4
  567. package/src/environment-handlers/base.js +2 -2
  568. package/src/environment-handlers/browser.js +7 -7
  569. package/src/environment-handlers/node/cli/commands/cli-command-context.js +1 -1
  570. package/src/environment-handlers/node/cli/commands/console.js +4 -4
  571. package/src/environment-handlers/node/cli/commands/db/schema/dump.js +1 -1
  572. package/src/environment-handlers/node/cli/commands/db/schema/load.js +3 -3
  573. package/src/environment-handlers/node/cli/commands/generate/base-models.js +1 -16
  574. package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +179 -89
  575. package/src/environment-handlers/node.js +6 -6
  576. package/src/frontend-model-controller.js +90 -82
  577. package/src/frontend-model-resource/base-resource.js +343 -167
  578. package/src/frontend-models/base.js +362 -205
  579. package/src/frontend-models/clear-pending-debounced-callback.js +1 -1
  580. package/src/frontend-models/event-hook-models.js +2 -2
  581. package/src/frontend-models/outgoing-event-buffer.js +2 -2
  582. package/src/frontend-models/preloader.js +8 -7
  583. package/src/frontend-models/query.js +43 -38
  584. package/src/frontend-models/resource-definition.js +6 -6
  585. package/src/frontend-models/transport-serialization.js +11 -11
  586. package/src/frontend-models/use-destroyed-event.js +10 -10
  587. package/src/frontend-models/use-model-class-event.js +11 -11
  588. package/src/frontend-models/use-updated-event.js +11 -11
  589. package/src/frontend-models/websocket-channel.js +26 -17
  590. package/src/frontend-models/websocket-publishers.js +9 -9
  591. package/src/http-client/response.js +2 -2
  592. package/src/http-server/client/index.js +8 -8
  593. package/src/http-server/client/params-to-object.js +10 -10
  594. package/src/http-server/client/request-buffer/form-data-part.js +2 -2
  595. package/src/http-server/client/request-buffer/index.js +8 -8
  596. package/src/http-server/client/request-parser.js +3 -3
  597. package/src/http-server/client/request-runner.js +6 -6
  598. package/src/http-server/client/request-timing.js +5 -5
  599. package/src/http-server/client/request.js +1 -1
  600. package/src/http-server/client/response.js +5 -5
  601. package/src/http-server/client/websocket-request.js +4 -4
  602. package/src/http-server/client/websocket-session.js +18 -18
  603. package/src/http-server/development-reloader.js +5 -5
  604. package/src/http-server/index.js +12 -12
  605. package/src/http-server/remote-address.js +4 -4
  606. package/src/http-server/server-client.js +3 -3
  607. package/src/http-server/server-lock.js +4 -4
  608. package/src/http-server/websocket-channel-subscribers.js +3 -3
  609. package/src/http-server/websocket-channel.js +1 -1
  610. package/src/http-server/websocket-connection.js +1 -1
  611. package/src/http-server/websocket-event-log-store.js +6 -6
  612. package/src/http-server/websocket-events-host.js +2 -2
  613. package/src/http-server/worker-handler/in-process.js +7 -7
  614. package/src/http-server/worker-handler/index.js +4 -4
  615. package/src/http-server/worker-handler/worker-thread.js +3 -3
  616. package/src/logger/outputs/array-output.js +3 -3
  617. package/src/logger/outputs/console-output.js +1 -1
  618. package/src/logger/outputs/file-output.js +4 -4
  619. package/src/logger/outputs/stdout-output.js +1 -1
  620. package/src/logger.js +10 -10
  621. package/src/mailer/backends/smtp.js +3 -3
  622. package/src/mailer/base.js +8 -8
  623. package/src/mailer/delivery.js +4 -4
  624. package/src/plugins/sqljs-wasm-route-controller.js +1 -1
  625. package/src/routes/base-route.js +6 -6
  626. package/src/routes/basic-route.js +1 -1
  627. package/src/routes/hooks/frontend-model-command-route-hook.js +1 -1
  628. package/src/routes/index.js +1 -1
  629. package/src/routes/plugin-routes.js +1 -1
  630. package/src/routes/resolver.js +11 -11
  631. package/src/routes/resource-route.js +1 -1
  632. package/src/testing/browser-frontend-model-event-hook-scenarios.js +8 -8
  633. package/src/testing/expect-utils.js +11 -11
  634. package/src/testing/expect.js +16 -7
  635. package/src/testing/test-files-finder.js +8 -8
  636. package/src/testing/test-filter-parser.js +2 -2
  637. package/src/testing/test-runner.js +16 -16
  638. package/src/testing/test-suite-splitter.js +1 -1
  639. package/src/testing/test.js +15 -15
  640. package/src/utils/backtrace-cleaner.js +1 -1
  641. package/src/utils/format-value.js +1 -1
  642. package/src/utils/model-scope.js +1 -1
  643. package/src/utils/ransack.js +26 -26
  644. package/src/utils/with-tracked-stack-async-hooks.js +7 -7
  645. package/src/utils/with-tracked-stack.js +3 -3
@@ -4,6 +4,22 @@ import path from "node:path"
4
4
  import * as inflection from "inflection"
5
5
  import {frontendModelResourceClassFromDefinition, frontendModelResourceConfigurationFromDefinition, frontendModelResourcesForBackendProject} from "../../../../../frontend-models/resource-definition.js"
6
6
 
7
+ /**
8
+ * Attribute metadata used for generated frontend-model JSDoc.
9
+ * @typedef {object} FrontendAttributeConfig
10
+ * @property {string} [type] - Column type.
11
+ * @property {string} [columnType] - Column type.
12
+ * @property {string} [sqlType] - SQL type.
13
+ * @property {string} [dataType] - Data type.
14
+ * @property {string} [name] - Attribute name when configured as an array entry.
15
+ * @property {boolean} [null] - Whether null is allowed.
16
+ * @property {() => string} [getType] - Returns column type.
17
+ * @property {() => boolean} [getNull] - Returns whether null is allowed.
18
+ */
19
+ /**
20
+ * Permit spec returned by frontend-model resources during generation.
21
+ * @typedef {Array<string | Record<string, object>>} FrontendModelGeneratorPermitSpec
22
+ */
7
23
 
8
24
  /** Node CLI command that generates frontend model classes from backend project resource config. */
9
25
  export default class DbGenerateFrontendModels extends BaseCommand {
@@ -29,15 +45,15 @@ export default class DbGenerateFrontendModels extends BaseCommand {
29
45
 
30
46
  /**
31
47
  * Ensured directories.
32
- @type {Set<string>} */
48
+ * @type {Set<string>} */
33
49
  const ensuredDirectories = new Set()
34
50
  /**
35
51
  * Generated model names by directory.
36
- @type {Map<string, Set<string>>} */
52
+ * @type {Map<string, Set<string>>} */
37
53
  const generatedModelNamesByDirectory = new Map()
38
54
  /**
39
55
  * Generated files by directory.
40
- @type {Map<string, Array<{className: string, fileName: string}>>} */
56
+ * @type {Map<string, Array<{className: string, fileName: string}>>} */
41
57
  const generatedFilesByDirectory = new Map()
42
58
 
43
59
  for (const backendProject of backendProjects) {
@@ -124,8 +140,8 @@ export default class DbGenerateFrontendModels extends BaseCommand {
124
140
  * @param {object} args - Arguments.
125
141
  * @param {Set<string>} args.availableFrontendModelClassNames - Available frontend model class names in backend project.
126
142
  * @param {string} args.className - Model class name.
127
- * @param {Record<string, ?>} args.modelConfig - Model configuration.
128
- * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass]
143
+ * @param {import("../../../../../configuration-types.js").NormalizedFrontendModelResourceConfiguration} args.modelConfig - Model configuration.
144
+ * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass] - Resource class.
129
145
  * @returns {void} - No return value.
130
146
  */
131
147
  validateModelConfig({availableFrontendModelClassNames, className, modelConfig, resourceClass}) {
@@ -135,11 +151,12 @@ export default class DbGenerateFrontendModels extends BaseCommand {
135
151
  throw new Error(`Model '${className}' is missing required 'abilities' config`)
136
152
  }
137
153
 
138
- const readActions = ["index", "find"]
139
-
140
- for (const action of readActions) {
141
- const abilityAction = abilities[action]
154
+ const readActions = [
155
+ {action: "index", abilityAction: abilities.index},
156
+ {action: "find", abilityAction: abilities.find}
157
+ ]
142
158
 
159
+ for (const {action, abilityAction} of readActions) {
143
160
  if (typeof abilityAction !== "string" || abilityAction.length < 1) {
144
161
  throw new Error(`Model '${className}' is missing required abilities.${action} config`)
145
162
  }
@@ -169,13 +186,13 @@ export default class DbGenerateFrontendModels extends BaseCommand {
169
186
 
170
187
  /**
171
188
  * Runs available frontend model class names.
172
- * @param {Record<string, ?>} resources - Resource configuration keyed by model name.
189
+ * @param {Record<string, import("../../../../../configuration-types.js").FrontendModelResourceDefinition>} resources - Resource configuration keyed by model name.
173
190
  * @returns {Set<string>} - Available frontend model class names.
174
191
  */
175
192
  availableFrontendModelClassNames(resources) {
176
193
  /**
177
194
  * Class names.
178
- @type {Set<string>} */
195
+ * @type {Set<string>} */
179
196
  const classNames = new Set()
180
197
 
181
198
  for (const resourceModelName in resources) {
@@ -217,8 +234,8 @@ export default class DbGenerateFrontendModels extends BaseCommand {
217
234
  * @param {string} args.className - Model class name.
218
235
  * @param {string} args.importPath - Base class import path.
219
236
  * @param {typeof import("../../../../../database/record/index.js").default | undefined} args.modelClass - Backend model class.
220
- * @param {Record<string, ?>} args.modelConfig - Model configuration.
221
- * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass]
237
+ * @param {import("../../../../../configuration-types.js").NormalizedFrontendModelResourceConfiguration} args.modelConfig - Model configuration.
238
+ * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass] - Resource class.
222
239
  * @returns {string} - Generated file content.
223
240
  */
224
241
  buildModelFileContent({className, importPath, modelClass, modelConfig, resourceClass}) {
@@ -234,6 +251,8 @@ export default class DbGenerateFrontendModels extends BaseCommand {
234
251
  const permittedCreateParams = this.permittedParamsForGenerator(resourceClass || null, "create")
235
252
  const permittedUpdateParams = this.permittedParamsForGenerator(resourceClass || null, "update")
236
253
  const nestedWriteTypes = this.nestedWriteTypesForModel({className, permittedParams: permittedCreateParams.concat(permittedUpdateParams), relationships})
254
+ const usesTransportValue = attributes.some((attribute) => attribute.jsDocType.includes("FrontendModelTransportValue"))
255
+ || nestedWriteTypes.some((nestedWriteType) => nestedWriteType.attributes.some((attribute) => attribute.type.includes("FrontendModelTransportValue")))
237
256
  const builtInCollectionCommands = {
238
257
  create: modelConfig.builtInCollectionCommands.create || "create",
239
258
  index: modelConfig.builtInCollectionCommands.index || "index"
@@ -265,6 +284,16 @@ export default class DbGenerateFrontendModels extends BaseCommand {
265
284
  fileContent += ` * Frontend model resource config.\n`
266
285
  fileContent += ` * @typedef {import("${importPath}").FrontendModelResourceConfig} FrontendModelResourceConfig\n`
267
286
  fileContent += " */\n"
287
+ fileContent += "/**\n"
288
+ fileContent += " * Fallback attribute value type for generated fields without narrower metadata.\n"
289
+ fileContent += ` * @typedef {import("${importPath}").FrontendModelAttributeValue} FrontendModelAttributeValue\n`
290
+ fileContent += " */\n"
291
+ if (usesTransportValue) {
292
+ fileContent += "/**\n"
293
+ fileContent += " * Value supported by frontend-model transport serialization and deserialization.\n"
294
+ fileContent += ` * @typedef {import("${importPath}").FrontendModelTransportValue} FrontendModelTransportValue\n`
295
+ fileContent += " */\n"
296
+ }
268
297
  fileContent += "\n"
269
298
  fileContent += "/**\n"
270
299
  fileContent += ` * ${attributesTypeName} type.\n`
@@ -282,23 +311,13 @@ export default class DbGenerateFrontendModels extends BaseCommand {
282
311
  }
283
312
  fileContent += " */\n"
284
313
  }
285
- fileContent += this.writeAttributesTypedef({attributes, attributesTypeName, nestedWriteTypes, permittedParams: permittedCreateParams, typeName: createAttributesTypeName})
286
- fileContent += this.writeAttributesTypedef({attributes, attributesTypeName, nestedWriteTypes, permittedParams: permittedUpdateParams, typeName: updateAttributesTypeName})
287
- fileContent += `/** Frontend model for ${className}. */\n`
288
- fileContent += `export default class ${className} extends FrontendModelBase {\n`
289
- fileContent += " /**\n"
290
- fileContent += ` * Creates a ${className}.\n`
291
- fileContent += ` * @param {${createAttributesTypeName}} [attributes] - Attributes for the new model.\n`
292
- fileContent += ` * @returns {Promise<${className}>} - Persisted model.\n`
293
- fileContent += " */\n"
294
- fileContent += ` static async create(attributes = {}) { return /** @type {Promise<${className}>} */ (super.create(attributes)) }\n\n`
295
-
296
- fileContent += " /**\n"
297
- fileContent += ` * Updates this ${className}.\n`
298
- fileContent += ` * @param {${updateAttributesTypeName}} [newAttributes] - Attributes to assign before saving.\n`
299
- fileContent += ` * @returns {Promise<${className}>} - Updated model.\n`
300
- fileContent += " */\n"
301
- fileContent += ` async update(newAttributes = {}) { return /** @type {Promise<${className}>} */ (super.update(newAttributes)) }\n\n`
314
+ fileContent += this.writeAttributesTypedef({attributes, attributesTypeName, modelClass, nestedWriteTypes, permittedParams: permittedCreateParams, typeName: createAttributesTypeName})
315
+ fileContent += this.writeAttributesTypedef({attributes, attributesTypeName, modelClass, nestedWriteTypes, permittedParams: permittedUpdateParams, typeName: updateAttributesTypeName})
316
+ fileContent += "/**\n"
317
+ fileContent += ` * Frontend model for ${className}.\n`
318
+ fileContent += ` * @augments {FrontendModelBase<${attributesTypeName}, ${createAttributesTypeName}, ${updateAttributesTypeName}>}\n`
319
+ fileContent += " */\n"
320
+ fileContent += `class ${className} extends FrontendModelBase {\n`
302
321
  fileContent += " /** @returns {FrontendModelResourceConfig} - Resource config. */\n"
303
322
  fileContent += " static resourceConfig() {\n"
304
323
  fileContent += " return {\n"
@@ -416,8 +435,8 @@ export default class DbGenerateFrontendModels extends BaseCommand {
416
435
  fileContent += "\n"
417
436
  fileContent += " /**\n"
418
437
  fileContent += ` * Runs ${methodName}.\n`
419
- fileContent += " * @param {...?} commandArguments - Custom command arguments.\n"
420
- fileContent += " * @returns {Promise<Record<string, ?>>} - Command response.\n"
438
+ fileContent += " * @param {...FrontendModelAttributeValue} commandArguments - Custom command arguments.\n"
439
+ fileContent += " * @returns {Promise<Record<string, FrontendModelAttributeValue>>} - Command response.\n"
421
440
  fileContent += " */\n"
422
441
  fileContent += ` static async ${methodName}(...commandArguments) {\n`
423
442
  fileContent += " return await this.executeCustomCommand({\n"
@@ -433,8 +452,8 @@ export default class DbGenerateFrontendModels extends BaseCommand {
433
452
  fileContent += "\n"
434
453
  fileContent += " /**\n"
435
454
  fileContent += ` * Runs ${methodName}.\n`
436
- fileContent += " * @param {...?} commandArguments - Custom command arguments.\n"
437
- fileContent += " * @returns {Promise<Record<string, ?>>} - Command response.\n"
455
+ fileContent += " * @param {...FrontendModelAttributeValue} commandArguments - Custom command arguments.\n"
456
+ fileContent += " * @returns {Promise<Record<string, FrontendModelAttributeValue>>} - Command response.\n"
438
457
  fileContent += " */\n"
439
458
  fileContent += ` async ${methodName}(...commandArguments) {\n`
440
459
  fileContent += ` return await ${className}.executeCustomCommand({\n`
@@ -450,71 +469,91 @@ export default class DbGenerateFrontendModels extends BaseCommand {
450
469
  for (const relationship of relationships) {
451
470
  const relationshipNameCamelized = inflection.camelize(relationship.relationshipName)
452
471
  const targetImportPath = `./${relationship.targetFileName}.js`
472
+ const targetInstanceType = `import(${JSON.stringify(targetImportPath)}).${relationship.targetClassName}`
473
+ const targetCreateAttributesType = `import(${JSON.stringify(targetImportPath)}).${relationship.targetClassName}CreateAttributes`
453
474
 
454
475
  if (relationship.type == "hasMany") {
476
+ fileContent += "\n"
477
+ fileContent += " /**\n"
478
+ fileContent += ` * Returns ${relationship.relationshipName} relationship helper.\n`
479
+ fileContent += ` * @returns {import(${JSON.stringify(importPath)}).FrontendModelHasManyRelationship<${className}, ${targetInstanceType}, ${targetCreateAttributesType}>} - Relationship helper.\n`
480
+ fileContent += " */\n"
481
+ fileContent += ` ${relationship.relationshipName}Relationship() { return /** @type {import(${JSON.stringify(importPath)}).FrontendModelHasManyRelationship<${className}, ${targetInstanceType}, ${targetCreateAttributesType}>} */ (this.getRelationshipByName(${JSON.stringify(relationship.relationshipName)})) }\n`
482
+
455
483
  fileContent += "\n"
456
484
  fileContent += " /**\n"
457
485
  fileContent += ` * Returns ${relationship.relationshipName}.\n`
458
- fileContent += ` * @returns {import(${JSON.stringify(importPath)}).FrontendModelHasManyRelationship<typeof import(${JSON.stringify(`./${inflection.dasherize(inflection.underscore(className))}.js`)}).default, typeof import(${JSON.stringify(targetImportPath)}).default>} - Relationship helper.\n`
486
+ fileContent += ` * @returns {import(${JSON.stringify(importPath)}).FrontendModelHasManyRelationship<${className}, ${targetInstanceType}, ${targetCreateAttributesType}>} - Relationship helper.\n`
459
487
  fileContent += " */\n"
460
- fileContent += ` ${relationship.relationshipName}() { return /** @type {import(${JSON.stringify(importPath)}).FrontendModelHasManyRelationship<typeof import(${JSON.stringify(`./${inflection.dasherize(inflection.underscore(className))}.js`)}).default, typeof import(${JSON.stringify(targetImportPath)}).default>} */ (this.getRelationshipByName(${JSON.stringify(relationship.relationshipName)})) }\n`
488
+ fileContent += ` ${relationship.relationshipName}() { return this.${relationship.relationshipName}Relationship() }\n`
461
489
 
462
490
  fileContent += "\n"
463
491
  fileContent += " /**\n"
464
492
  fileContent += ` * Returns loaded ${relationship.relationshipName}.\n`
465
- fileContent += ` * @returns {Array<import(${JSON.stringify(targetImportPath)}).default>} - Loaded related models.\n`
493
+ fileContent += ` * @returns {Array<${targetInstanceType}>} - Loaded related models.\n`
466
494
  fileContent += " */\n"
467
- fileContent += ` ${relationship.relationshipName}Loaded() { return /** @type {Array<import(${JSON.stringify(targetImportPath)}).default>} */ (this.getRelationshipByName(${JSON.stringify(relationship.relationshipName)}).loaded()) }\n`
495
+ fileContent += ` ${relationship.relationshipName}Loaded() { return this.${relationship.relationshipName}Relationship().loaded() }\n`
468
496
 
469
497
  fileContent += "\n"
470
498
  fileContent += " /**\n"
471
499
  fileContent += ` * Loads ${relationship.relationshipName}.\n`
472
- fileContent += ` * @returns {Promise<Array<import(${JSON.stringify(targetImportPath)}).default>>} - Loaded related models.\n`
500
+ fileContent += ` * @returns {Promise<Array<${targetInstanceType}>>} - Loaded related models.\n`
473
501
  fileContent += " */\n"
474
- fileContent += ` async load${relationshipNameCamelized}() { return /** @type {Promise<Array<import(${JSON.stringify(targetImportPath)}).default>>} */ (this.loadRelationship(${JSON.stringify(relationship.relationshipName)})) }\n`
502
+ fileContent += ` async load${relationshipNameCamelized}() { return await this.${relationship.relationshipName}Relationship().load() }\n`
475
503
  } else {
504
+ fileContent += "\n"
505
+ fileContent += " /**\n"
506
+ fileContent += ` * Returns ${relationship.relationshipName} relationship helper.\n`
507
+ fileContent += ` * @returns {import(${JSON.stringify(importPath)}).FrontendModelSingularRelationship<${className}, ${targetInstanceType}, ${targetCreateAttributesType}>} - Relationship helper.\n`
508
+ fileContent += " */\n"
509
+ fileContent += ` ${relationship.relationshipName}Relationship() { return /** @type {import(${JSON.stringify(importPath)}).FrontendModelSingularRelationship<${className}, ${targetInstanceType}, ${targetCreateAttributesType}>} */ (this.getRelationshipByName(${JSON.stringify(relationship.relationshipName)})) }\n`
510
+
476
511
  fileContent += "\n"
477
512
  fileContent += " /**\n"
478
513
  fileContent += ` * Returns ${relationship.relationshipName}.\n`
479
- fileContent += ` * @returns {import(${JSON.stringify(targetImportPath)}).default | null} - Loaded related model.\n`
514
+ fileContent += ` * @returns {${targetInstanceType} | null} - Loaded related model.\n`
480
515
  fileContent += " */\n"
481
- fileContent += ` ${relationship.relationshipName}() { return /** @type {import(${JSON.stringify(targetImportPath)}).default | null} */ (this.getRelationshipByName(${JSON.stringify(relationship.relationshipName)}).loaded()) }\n`
516
+ fileContent += ` ${relationship.relationshipName}() { return this.${relationship.relationshipName}Relationship().loaded() }\n`
482
517
 
483
518
  fileContent += "\n"
484
519
  fileContent += " /**\n"
485
520
  fileContent += ` * Builds ${relationship.relationshipName}.\n`
486
- fileContent += ` * @param {Record<string, ?>} [attributes] - Attributes for the new related model.\n`
487
- fileContent += ` * @returns {import(${JSON.stringify(targetImportPath)}).default} - Built related model.\n`
521
+ fileContent += ` * @param {${targetCreateAttributesType}} [attributes] - Attributes for the new related model.\n`
522
+ fileContent += ` * @returns {${targetInstanceType}} - Built related model.\n`
488
523
  fileContent += " */\n"
489
- fileContent += ` build${relationshipNameCamelized}(attributes = {}) { return /** @type {import(${JSON.stringify(targetImportPath)}).default} */ (this.getRelationshipByName(${JSON.stringify(relationship.relationshipName)}).build(attributes)) }\n`
524
+ fileContent += ` build${relationshipNameCamelized}(attributes = {}) { return this.${relationship.relationshipName}Relationship().build(attributes) }\n`
490
525
 
491
526
  fileContent += "\n"
492
527
  fileContent += " /**\n"
493
528
  fileContent += ` * Loads ${relationship.relationshipName}.\n`
494
- fileContent += ` * @returns {Promise<import(${JSON.stringify(targetImportPath)}).default | null>} - Loaded related model.\n`
529
+ fileContent += ` * @returns {Promise<${targetInstanceType} | null>} - Loaded related model.\n`
495
530
  fileContent += " */\n"
496
- fileContent += ` async load${relationshipNameCamelized}() { return /** @type {Promise<import(${JSON.stringify(targetImportPath)}).default | null>} */ (this.loadRelationship(${JSON.stringify(relationship.relationshipName)})) }\n`
531
+ fileContent += ` async load${relationshipNameCamelized}() { return await this.${relationship.relationshipName}Relationship().load() }\n`
497
532
 
498
533
  fileContent += "\n"
499
534
  fileContent += " /**\n"
500
535
  fileContent += ` * Returns or loads ${relationship.relationshipName}.\n`
501
- fileContent += ` * @returns {Promise<import(${JSON.stringify(targetImportPath)}).default | null>} - Loaded related model.\n`
536
+ fileContent += ` * @returns {Promise<${targetInstanceType} | null>} - Loaded related model.\n`
502
537
  fileContent += " */\n"
503
- fileContent += ` async ${relationship.relationshipName}OrLoad() { return /** @type {Promise<import(${JSON.stringify(targetImportPath)}).default | null>} */ (this.relationshipOrLoad(${JSON.stringify(relationship.relationshipName)})) }\n`
538
+ fileContent += ` async ${relationship.relationshipName}OrLoad() { return await this.${relationship.relationshipName}Relationship().orLoad() }\n`
504
539
 
505
540
  fileContent += "\n"
506
541
  fileContent += " /**\n"
507
542
  fileContent += ` * Sets ${relationship.relationshipName}.\n`
508
- fileContent += ` * @param {import(${JSON.stringify(targetImportPath)}).default | null} model - Related model.\n`
509
- fileContent += ` * @returns {import(${JSON.stringify(targetImportPath)}).default | null} - Assigned related model.\n`
543
+ fileContent += ` * @param {${targetInstanceType} | null} model - Related model.\n`
544
+ fileContent += " * @returns {void}\n"
510
545
  fileContent += " */\n"
511
- fileContent += ` set${relationshipNameCamelized}(model) { return /** @type {import(${JSON.stringify(targetImportPath)}).default | null} */ (this.setRelationship(${JSON.stringify(relationship.relationshipName)}, model)) }\n`
546
+ fileContent += ` set${relationshipNameCamelized}(model) { this.${relationship.relationshipName}Relationship().setLoaded(model) }\n`
512
547
  }
513
548
  }
514
549
 
515
550
  fileContent += "}\n"
516
551
  fileContent += "\n"
517
552
  fileContent += `FrontendModelBase.registerModel(${className})\n`
553
+ fileContent += "\n"
554
+ fileContent += `export {${className}}\n`
555
+ fileContent += "\n"
556
+ fileContent += `export default ${className}\n`
518
557
 
519
558
  return fileContent
520
559
  }
@@ -556,46 +595,83 @@ export default class DbGenerateFrontendModels extends BaseCommand {
556
595
  * @param {object} args - Arguments.
557
596
  * @param {Array<{jsDocType: string, name: string}>} args.attributes - Generated read attributes.
558
597
  * @param {string} args.attributesTypeName - Generated read attributes typedef name.
598
+ * @param {typeof import("../../../../../database/record/index.js").default | undefined} args.modelClass - Backend model class.
559
599
  * @param {Array<{attributes: Array<{name: string, type: string}>, relationshipName: string, typeName: string}>} args.nestedWriteTypes - Nested write typedefs.
560
- * @param {Array<string | Record<string, ?>>} args.permittedParams - Resource permitted params spec.
600
+ * @param {Array<string | Record<string, object>>} args.permittedParams - Resource permitted params spec.
561
601
  * @param {string} args.typeName - Typedef name.
562
602
  * @returns {string} - Generated typedef source.
563
603
  */
564
- writeAttributesTypedef({attributes, attributesTypeName, nestedWriteTypes, permittedParams, typeName}) {
565
- let output = "/**\n"
604
+ writeAttributesTypedef({attributes, attributesTypeName, modelClass, nestedWriteTypes, permittedParams, typeName}) {
605
+ const attributeLines = []
566
606
 
567
- output += ` * Attributes accepted by ${typeName}.\n`
568
- output += ` * @typedef {object} ${typeName}\n`
607
+ let output = "/**\n"
569
608
 
570
609
  const attributesByName = new Map(attributes.map((attribute) => [attribute.name, attribute]))
571
610
  const nestedWriteTypesByKey = new Map(nestedWriteTypes.map((nestedWriteType) => [`${nestedWriteType.relationshipName}Attributes`, nestedWriteType]))
611
+ const emittedAttributeNames = new Set()
572
612
 
573
613
  for (const entry of permittedParams) {
574
614
  if (typeof entry == "string") {
575
- const attribute = attributesByName.get(entry)
576
- const type = attribute ? `${attributesTypeName}[${JSON.stringify(attribute.name)}]` : "?"
615
+ const attributeName = this.frontendWriteAttributeName({attributeName: entry, attributesByName, modelClass})
616
+
617
+ if (emittedAttributeNames.has(attributeName)) continue
618
+
619
+ emittedAttributeNames.add(attributeName)
577
620
 
578
- output += ` * @property {${type}} [${entry}] - Permitted ${entry} value.\n`
621
+ const attribute = attributesByName.get(attributeName)
622
+ const type = attribute ? `${attributesTypeName}[${JSON.stringify(attribute.name)}]` : "FrontendModelAttributeValue"
623
+
624
+ attributeLines.push(` * @property {${type}} [${attributeName}] - Permitted ${attributeName} value.\n`)
579
625
  } else if (entry && typeof entry == "object" && !Array.isArray(entry)) {
580
626
  for (const key of Object.keys(entry)) {
581
627
  const nestedWriteType = nestedWriteTypesByKey.get(key)
582
- const type = nestedWriteType ? `Array<${nestedWriteType.typeName}>` : "Array<Record<string, ?>>"
628
+ const type = nestedWriteType ? `Array<${nestedWriteType.typeName}>` : "Array<object>"
583
629
 
584
- output += ` * @property {${type}} [${key}] - Permitted nested ${key} values.\n`
630
+ attributeLines.push(` * @property {${type}} [${key}] - Permitted nested ${key} values.\n`)
585
631
  }
586
632
  }
587
633
  }
588
634
 
635
+ output += ` * Attributes accepted by ${typeName}.\n`
636
+ if (attributeLines.length === 0) {
637
+ output += ` * @typedef {Record<string, never>} ${typeName}\n`
638
+ } else {
639
+ output += ` * @typedef {object} ${typeName}\n`
640
+ output += attributeLines.join("")
641
+ }
589
642
  output += " */\n"
590
643
 
591
644
  return output
592
645
  }
593
646
 
647
+ /**
648
+ * Resolves a permitted write attribute to the generated frontend attribute name.
649
+ * @param {{attributeName: string, attributesByName: Map<string, {jsDocType: string, name: string}>, modelClass: typeof import("../../../../../database/record/index.js").default | undefined}} args - Arguments.
650
+ * @returns {string} - Frontend attribute name used by generated accessors.
651
+ */
652
+ frontendWriteAttributeName({attributeName, attributesByName, modelClass}) {
653
+ if (attributesByName.has(attributeName)) return attributeName
654
+
655
+ if (modelClass) {
656
+ const resolvedAttributeName = modelClass.resolveAttributeName(attributeName)
657
+
658
+ if (resolvedAttributeName && attributesByName.has(resolvedAttributeName)) return resolvedAttributeName
659
+ }
660
+
661
+ const normalizedAttributeName = inflection.camelize(attributeName, true).toLowerCase()
662
+ const matchingAttributeName = Array.from(attributesByName.keys()).find((candidateName) => candidateName.toLowerCase() === normalizedAttributeName)
663
+
664
+ if (matchingAttributeName) return matchingAttributeName
665
+
666
+ // Write-only virtual params are valid permitted params even when they have no read attribute.
667
+ return attributeName
668
+ }
669
+
594
670
  /**
595
671
  * Runs nested write types for model.
596
672
  * @param {object} args - Arguments.
597
673
  * @param {string} args.className - Frontend model class name.
598
- * @param {Array<string | Record<string, ?>>} args.permittedParams - Combined permitted params specs.
674
+ * @param {FrontendModelGeneratorPermitSpec} args.permittedParams - Combined permitted params specs.
599
675
  * @param {Array<{autoload: boolean, relationshipName: string, targetClassName: string, targetFileName: string, type: "belongsTo" | "hasOne" | "hasMany"}>} args.relationships - Generated relationships.
600
676
  * @returns {Array<{attributes: Array<{name: string, type: string}>, relationshipName: string, typeName: string}>} - Nested write typedefs.
601
677
  */
@@ -637,7 +713,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
637
713
  /**
638
714
  * Runs nested write attributes for spec.
639
715
  * @param {object} args - Arguments.
640
- * @param {?} args.nestedSpec - Nested permit spec.
716
+ * @param {Array<string | Record<string, object>> | object | string | null | undefined} args.nestedSpec - Nested permit spec.
641
717
  * @param {typeof import("../../../../../database/record/index.js").default | undefined} args.targetModelClass - Target backend model class.
642
718
  * @returns {Array<{name: string, type: string}>} - Nested write attributes.
643
719
  */
@@ -645,11 +721,12 @@ export default class DbGenerateFrontendModels extends BaseCommand {
645
721
  if (!Array.isArray(nestedSpec)) return []
646
722
 
647
723
  return nestedSpec.filter((entry) => typeof entry == "string").map((attributeName) => {
648
- const attributeConfig = this.frontendAttributeConfigForModelAttribute({attributeName, modelClass: targetModelClass})
724
+ const resolvedAttributeName = targetModelClass?.resolveAttributeName(attributeName) || attributeName
725
+ const attributeConfig = this.frontendAttributeConfigForModelAttribute({attributeName: resolvedAttributeName, modelClass: targetModelClass})
649
726
 
650
727
  return {
651
- name: attributeName,
652
- type: attributeConfig ? this.jsDocTypeForFrontendAttribute({attributeConfig}) : "?"
728
+ name: resolvedAttributeName,
729
+ type: attributeConfig ? this.jsDocTypeForFrontendAttribute({attributeConfig}) : "FrontendModelAttributeValue"
653
730
  }
654
731
  })
655
732
  }
@@ -658,14 +735,14 @@ export default class DbGenerateFrontendModels extends BaseCommand {
658
735
  * Runs permitted params for generator.
659
736
  * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} resourceClass - Resource class.
660
737
  * @param {"create" | "update"} action - Write action.
661
- * @returns {Array<string | Record<string, ?>>} - Permitted params spec.
738
+ * @returns {FrontendModelGeneratorPermitSpec} - Permitted params spec.
662
739
  */
663
740
  permittedParamsForGenerator(resourceClass, action) {
664
741
  if (!resourceClass || typeof resourceClass !== "function") return []
665
742
 
666
743
  const prototypeWithMethod = /**
667
744
  * Resource prototype.
668
- * @type {{permittedParams?: (arg?: object) => Array<string | Record<string, ?>>}}
745
+ * @type {{permittedParams?: (arg?: object) => FrontendModelGeneratorPermitSpec}}
669
746
  */ (resourceClass.prototype)
670
747
 
671
748
  if (typeof prototypeWithMethod?.permittedParams !== "function") return []
@@ -708,7 +785,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
708
785
 
709
786
  const prototypeWithMethod = /**
710
787
  * Resource prototype.
711
- * @type {{permittedParams?: (arg?: object) => Array<string | Record<string, ?>>}}
788
+ * @type {{permittedParams?: (arg?: object) => FrontendModelGeneratorPermitSpec}}
712
789
  */ (resourceClass.prototype)
713
790
 
714
791
  if (typeof prototypeWithMethod?.permittedParams !== "function") return []
@@ -737,7 +814,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
737
814
 
738
815
  /**
739
816
  * Relationship names.
740
- @type {string[]} */
817
+ * @type {string[]} */
741
818
  const relationshipNames = []
742
819
 
743
820
  for (const entry of spec) {
@@ -818,7 +895,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
818
895
  * Runs attribute definitions for model.
819
896
  * @param {object} args - Arguments.
820
897
  * @param {typeof import("../../../../../database/record/index.js").default | undefined} args.modelClass - Backend model class.
821
- * @param {Record<string, ?>} args.modelConfig - Model configuration.
898
+ * @param {import("../../../../../configuration-types.js").NormalizedFrontendModelResourceConfiguration} args.modelConfig - Model configuration.
822
899
  * @returns {Array<{jsDocType: string, name: string}>} - Attribute definitions.
823
900
  */
824
901
  attributeDefinitionsForModel({modelClass, modelConfig}) {
@@ -838,13 +915,25 @@ export default class DbGenerateFrontendModels extends BaseCommand {
838
915
  }
839
916
 
840
917
  if (Array.isArray(attributes)) {
841
- return attributes.map((entry) => {
842
- const attributeName = typeof entry === "string" ? entry : entry.name
918
+ return attributes.map((attributeDefinition) => {
919
+ /** @type {FrontendAttributeConfig | null} */
920
+ let attributeConfig = null
921
+ let attributeName
922
+
923
+ if (typeof attributeDefinition == "string") {
924
+ attributeName = attributeDefinition
925
+ attributeConfig = this.frontendAttributeConfigForModelAttribute({attributeName, modelClass})
926
+ } else if (attributeDefinition && typeof attributeDefinition == "object" && !Array.isArray(attributeDefinition)) {
927
+ attributeConfig = /** @type {FrontendAttributeConfig} */ (attributeDefinition)
928
+ attributeName = attributeConfig.name
929
+ }
930
+
931
+ if (typeof attributeName != "string" || attributeName.length < 1) {
932
+ throw new Error(`Expected frontend model attribute array entries to be strings or objects with a name, got: ${JSON.stringify(attributeDefinition)}`)
933
+ }
843
934
 
844
935
  return {
845
- jsDocType: this.jsDocTypeForFrontendAttribute({
846
- attributeConfig: this.frontendAttributeConfigForModelAttribute({attributeName, modelClass})
847
- }),
936
+ jsDocType: this.jsDocTypeForFrontendAttribute({attributeConfig}),
848
937
  name: attributeName
849
938
  }
850
939
  })
@@ -856,9 +945,10 @@ export default class DbGenerateFrontendModels extends BaseCommand {
856
945
 
857
946
  return Object.keys(attributes).map((attributeName) => {
858
947
  const attributeConfig = attributes[attributeName]
948
+ const normalizedAttributeConfig = attributeConfig && typeof attributeConfig === "object" ? attributeConfig : null
859
949
 
860
950
  return {
861
- jsDocType: this.jsDocTypeForFrontendAttribute({attributeConfig}),
951
+ jsDocType: this.jsDocTypeForFrontendAttribute({attributeConfig: normalizedAttributeConfig}),
862
952
  name: attributeName
863
953
  }
864
954
  })
@@ -867,7 +957,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
867
957
  /**
868
958
  * Runs js doc type for frontend attribute.
869
959
  * @param {object} args - Arguments.
870
- * @param {?} args.attributeConfig - Attribute configuration value.
960
+ * @param {FrontendAttributeConfig | null | undefined} args.attributeConfig - Attribute configuration value.
871
961
  * @returns {string} - JSDoc type.
872
962
  */
873
963
  jsDocTypeForFrontendAttribute({attributeConfig}) {
@@ -882,12 +972,12 @@ export default class DbGenerateFrontendModels extends BaseCommand {
882
972
 
883
973
  /**
884
974
  * Runs js doc type for frontend attribute base type.
885
- * @param {?} attributeConfig - Attribute configuration value.
975
+ * @param {FrontendAttributeConfig | null | undefined} attributeConfig - Attribute configuration value.
886
976
  * @returns {string} - Non-nullable JSDoc type.
887
977
  */
888
978
  jsDocTypeForFrontendAttributeBaseType(attributeConfig) {
889
979
  if (!attributeConfig || typeof attributeConfig !== "object") {
890
- return "any"
980
+ return "FrontendModelAttributeValue"
891
981
  }
892
982
 
893
983
  const type = this.frontendAttributeTypeValue(attributeConfig)
@@ -895,7 +985,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
895
985
  if (type == "boolean") {
896
986
  return "boolean"
897
987
  } else if (type == "json" || type == "jsonb") {
898
- return "Record<string, any>"
988
+ return "FrontendModelTransportValue"
899
989
  } else if (type && ["blob", "char", "nvarchar", "varchar", "text", "longtext", "uuid", "character varying"].includes(type)) {
900
990
  return "string"
901
991
  } else if (type && ["bit", "bigint", "decimal", "double", "double precision", "float", "int", "integer", "numeric", "real", "smallint", "tinyint"].includes(type)) {
@@ -903,13 +993,13 @@ export default class DbGenerateFrontendModels extends BaseCommand {
903
993
  } else if (type && ["date", "datetime", "timestamp", "timestamp without time zone", "timestamptz"].includes(type)) {
904
994
  return "Date"
905
995
  } else {
906
- return "any"
996
+ return "FrontendModelAttributeValue"
907
997
  }
908
998
  }
909
999
 
910
1000
  /**
911
1001
  * Runs frontend attribute can be null.
912
- * @param {?} attributeConfig - Attribute configuration value.
1002
+ * @param {FrontendAttributeConfig | null | undefined} attributeConfig - Attribute configuration value.
913
1003
  * @returns {boolean} - Whether the attribute allows null values.
914
1004
  */
915
1005
  frontendAttributeCanBeNull(attributeConfig) {
@@ -926,7 +1016,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
926
1016
 
927
1017
  /**
928
1018
  * Runs frontend attribute type value.
929
- * @param {?} attributeConfig - Attribute configuration value.
1019
+ * @param {FrontendAttributeConfig | null | undefined} attributeConfig - Attribute configuration value.
930
1020
  * @returns {string | null} - Normalized column type.
931
1021
  */
932
1022
  frontendAttributeTypeValue(attributeConfig) {
@@ -952,7 +1042,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
952
1042
  * @param {object} args - Arguments.
953
1043
  * @param {string} args.attributeName - Frontend model attribute name.
954
1044
  * @param {typeof import("../../../../../database/record/index.js").default | undefined} args.modelClass - Backend model class.
955
- * @returns {?} - Attribute config inferred from the backend model when available.
1045
+ * @returns {FrontendAttributeConfig | null} - Attribute config inferred from the backend model when available.
956
1046
  */
957
1047
  frontendAttributeConfigForModelAttribute({attributeName, modelClass}) {
958
1048
  if (!modelClass) {
@@ -972,8 +1062,8 @@ export default class DbGenerateFrontendModels extends BaseCommand {
972
1062
  * Runs relationships for model.
973
1063
  * @param {object} args - Arguments.
974
1064
  * @param {string} args.className - Model class name.
975
- * @param {Record<string, ?>} args.modelConfig - Model configuration.
976
- * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass]
1065
+ * @param {import("../../../../../configuration-types.js").NormalizedFrontendModelResourceConfiguration} args.modelConfig - Model configuration.
1066
+ * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass] - Resource class.
977
1067
  * @returns {Array<{autoload: boolean, relationshipName: string, targetClassName: string, targetFileName: string, type: "belongsTo" | "hasOne" | "hasMany"}>} - Relationships.
978
1068
  */
979
1069
  relationshipsForModel({className, modelConfig, resourceClass}) {
@@ -995,7 +1085,7 @@ export default class DbGenerateFrontendModels extends BaseCommand {
995
1085
  * @param {object} args - Arguments.
996
1086
  * @param {string} args.className - Model class name.
997
1087
  * @param {string} args.relationshipName - Relationship name.
998
- * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass]
1088
+ * @param {import("../../../../../configuration-types.js").FrontendModelResourceClassType | null} [args.resourceClass] - Resource class.
999
1089
  * @returns {{autoload: boolean, relationshipName: string, targetClassName: string, targetFileName: string, type: "belongsTo" | "hasOne" | "hasMany"}} Inferred relationship definition.
1000
1090
  */
1001
1091
  inferredRelationshipDefinition({className, relationshipName, resourceClass}) {
@@ -35,7 +35,7 @@ import toImportSpecifier from "../utils/to-import-specifier.js"
35
35
 
36
36
  /**
37
37
  * Defines this typedef.
38
- @typedef {{ability?: import("../authorization/ability.js").default, offsetMinutes: number, requestTiming?: import("../http-server/client/request-timing.js").default, tenant?: ?}} TimezoneStore */
38
+ * @typedef {{ability?: import("../authorization/ability.js").default, offsetMinutes: number, requestTiming?: import("../http-server/client/request-timing.js").default, tenant?: ?}} TimezoneStore */
39
39
 
40
40
  /**
41
41
  * Runs path within allowed prefixes.
@@ -61,12 +61,12 @@ function pathWithinAllowedPrefixes(filePath, allowedPathPrefixes) {
61
61
  export default class VelociousEnvironmentHandlerNode extends Base{
62
62
  /**
63
63
  * Timezone async local storage.
64
- @type {import("node:async_hooks").AsyncLocalStorage<TimezoneStore> | undefined} */
64
+ * @type {import("node:async_hooks").AsyncLocalStorage<TimezoneStore> | undefined} */
65
65
  _timezoneAsyncLocalStorage = NodeAsyncLocalStorage ? new NodeAsyncLocalStorage() : undefined
66
66
 
67
67
  /**
68
68
  * Find commands result.
69
- @type {import("./base.js").CommandFileObjectType[] | undefined} */
69
+ * @type {import("./base.js").CommandFileObjectType[] | undefined} */
70
70
  _findCommandsResult = undefined
71
71
 
72
72
  /**
@@ -113,7 +113,7 @@ export default class VelociousEnvironmentHandlerNode extends Base{
113
113
 
114
114
  /**
115
115
  * Discovered.
116
- @type {Record<string, ?>} */
116
+ * @type {Record<string, ?>} */
117
117
  const discovered = {}
118
118
 
119
119
  for (const file of files) {
@@ -131,7 +131,7 @@ export default class VelociousEnvironmentHandlerNode extends Base{
131
131
  .split("-")
132
132
  .map((/**
133
133
  * Narrows the runtime value to the documented type.
134
- @type {string} */ part) => part.charAt(0).toUpperCase() + part.slice(1))
134
+ * @type {string} */ part) => part.charAt(0).toUpperCase() + part.slice(1))
135
135
  .join("")
136
136
 
137
137
  discovered[modelName] = ResourceClass
@@ -863,7 +863,7 @@ export default class VelociousEnvironmentHandlerNode extends Base{
863
863
  async _structureSqlByIdentifier({dbs}) {
864
864
  const sqlByIdentifier = /**
865
865
  * Narrows the runtime value to the documented type.
866
- @type {Record<string, string>} */ ({})
866
+ * @type {Record<string, string>} */ ({})
867
867
 
868
868
  for (const identifier of Object.keys(dbs)) {
869
869
  const db = dbs[identifier]