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.
- package/build/application.js +4 -4
- package/build/authorization/ability.js +8 -8
- package/build/authorization/base-resource.js +4 -4
- package/build/background-jobs/cron-expression.js +1 -1
- package/build/background-jobs/forked-runner-child.js +1 -1
- package/build/background-jobs/job-registry.js +1 -1
- package/build/background-jobs/job-runner.js +1 -1
- package/build/background-jobs/job.js +1 -1
- package/build/background-jobs/json-socket.js +4 -4
- package/build/background-jobs/main.js +21 -21
- package/build/background-jobs/scheduler.js +7 -7
- package/build/background-jobs/store.js +7 -7
- package/build/background-jobs/web/controller.js +2 -2
- package/build/background-jobs/worker.js +12 -12
- package/build/beacon/client.js +11 -8
- package/build/beacon/in-process-broker.js +2 -2
- package/build/beacon/in-process-client.js +2 -2
- package/build/beacon/server.js +3 -3
- package/build/cli/browser-cli.js +1 -1
- package/build/cli/commands/db/base-command.js +2 -2
- package/build/cli/index.js +2 -2
- package/build/cli/tenant-database-command-helper.js +3 -3
- package/build/cli/use-browser-cli.js +1 -1
- package/build/configuration.js +38 -38
- package/build/controller.js +8 -8
- package/build/current-configuration.js +1 -1
- package/build/database/annotations-async-hooks.js +2 -2
- package/build/database/annotations.js +3 -3
- package/build/database/drivers/base-column.js +1 -1
- package/build/database/drivers/base-foreign-key.js +1 -1
- package/build/database/drivers/base-table.js +1 -1
- package/build/database/drivers/base.js +10 -10
- package/build/database/drivers/mssql/index.js +1 -1
- package/build/database/drivers/mssql/table.js +1 -1
- package/build/database/drivers/mysql/index.js +3 -3
- package/build/database/drivers/mysql/query.js +1 -1
- package/build/database/drivers/mysql/table.js +1 -1
- package/build/database/drivers/pgsql/index.js +2 -2
- package/build/database/drivers/sqlite/base.js +16 -16
- package/build/database/drivers/sqlite/index.js +11 -11
- package/build/database/drivers/sqlite/index.native.js +1 -1
- package/build/database/drivers/sqlite/index.web.js +3 -3
- package/build/database/drivers/sqlite/query.js +1 -1
- package/build/database/drivers/sqlite/query.web.js +1 -1
- package/build/database/drivers/sqlite/sql/alter-table.js +2 -2
- package/build/database/drivers/sqlite/table.js +1 -1
- package/build/database/migrator/files-finder.js +1 -1
- package/build/database/migrator.js +6 -6
- package/build/database/pool/async-tracked-multi-connection.js +27 -27
- package/build/database/pool/base-methods-forward.js +4 -4
- package/build/database/pool/base.js +8 -8
- package/build/database/query/from-base.js +1 -1
- package/build/database/query/index.js +10 -10
- package/build/database/query/join-object.js +3 -3
- package/build/database/query/model-class-query.js +39 -39
- package/build/database/query/preloader/belongs-to.js +22 -22
- package/build/database/query/preloader/has-many.js +20 -20
- package/build/database/query/preloader/has-one.js +8 -8
- package/build/database/query/preloader/selection.js +3 -3
- package/build/database/query/preloader.js +8 -8
- package/build/database/query/query-data.js +9 -9
- package/build/database/query/where-model-class-hash.js +7 -7
- package/build/database/query/with-count.js +9 -9
- package/build/database/record/acts-as-list.js +15 -15
- package/build/database/record/attachments/handle.js +2 -2
- package/build/database/record/attachments/normalize-input.js +12 -12
- package/build/database/record/attachments/storage-drivers/s3.js +6 -6
- package/build/database/record/attachments/store.js +13 -13
- package/build/database/record/index.js +127 -128
- package/build/database/record/instance-relationships/base.js +11 -11
- package/build/database/record/instance-relationships/belongs-to.js +3 -3
- package/build/database/record/instance-relationships/has-many.js +8 -8
- package/build/database/record/instance-relationships/has-one.js +7 -7
- package/build/database/record/relationships/base.js +2 -2
- package/build/database/record/state-machine.js +7 -7
- package/build/database/record/validators/presence.js +1 -1
- package/build/database/record/validators/uniqueness.js +5 -5
- package/build/database/table-data/index.js +4 -4
- package/build/environment-handlers/base.js +2 -2
- package/build/environment-handlers/browser.js +7 -7
- package/build/environment-handlers/node/cli/commands/cli-command-context.js +1 -1
- package/build/environment-handlers/node/cli/commands/console.js +4 -4
- package/build/environment-handlers/node/cli/commands/db/schema/dump.js +1 -1
- package/build/environment-handlers/node/cli/commands/db/schema/load.js +3 -3
- package/build/environment-handlers/node/cli/commands/generate/base-models.js +1 -16
- package/build/environment-handlers/node/cli/commands/generate/frontend-models.js +179 -89
- package/build/environment-handlers/node.js +6 -6
- package/build/frontend-model-controller.js +90 -82
- package/build/frontend-model-resource/base-resource.js +343 -167
- package/build/frontend-models/base.js +362 -205
- package/build/frontend-models/clear-pending-debounced-callback.js +1 -1
- package/build/frontend-models/event-hook-models.js +2 -2
- package/build/frontend-models/outgoing-event-buffer.js +2 -2
- package/build/frontend-models/preloader.js +8 -7
- package/build/frontend-models/query.js +43 -38
- package/build/frontend-models/resource-definition.js +6 -6
- package/build/frontend-models/transport-serialization.js +11 -11
- package/build/frontend-models/use-destroyed-event.js +10 -10
- package/build/frontend-models/use-model-class-event.js +11 -11
- package/build/frontend-models/use-updated-event.js +11 -11
- package/build/frontend-models/websocket-channel.js +26 -17
- package/build/frontend-models/websocket-publishers.js +9 -9
- package/build/http-client/response.js +2 -2
- package/build/http-server/client/index.js +8 -8
- package/build/http-server/client/params-to-object.js +10 -10
- package/build/http-server/client/request-buffer/form-data-part.js +2 -2
- package/build/http-server/client/request-buffer/index.js +8 -8
- package/build/http-server/client/request-parser.js +3 -3
- package/build/http-server/client/request-runner.js +6 -6
- package/build/http-server/client/request-timing.js +5 -5
- package/build/http-server/client/request.js +1 -1
- package/build/http-server/client/response.js +5 -5
- package/build/http-server/client/websocket-request.js +4 -4
- package/build/http-server/client/websocket-session.js +18 -18
- package/build/http-server/development-reloader.js +5 -5
- package/build/http-server/index.js +12 -12
- package/build/http-server/remote-address.js +4 -4
- package/build/http-server/server-client.js +3 -3
- package/build/http-server/server-lock.js +4 -4
- package/build/http-server/websocket-channel-subscribers.js +3 -3
- package/build/http-server/websocket-channel.js +1 -1
- package/build/http-server/websocket-connection.js +1 -1
- package/build/http-server/websocket-event-log-store.js +6 -6
- package/build/http-server/websocket-events-host.js +2 -2
- package/build/http-server/worker-handler/in-process.js +7 -7
- package/build/http-server/worker-handler/index.js +4 -4
- package/build/http-server/worker-handler/worker-thread.js +3 -3
- package/build/logger/outputs/array-output.js +3 -3
- package/build/logger/outputs/console-output.js +1 -1
- package/build/logger/outputs/file-output.js +4 -4
- package/build/logger/outputs/stdout-output.js +1 -1
- package/build/logger.js +10 -10
- package/build/mailer/backends/smtp.js +3 -3
- package/build/mailer/base.js +8 -8
- package/build/mailer/delivery.js +4 -4
- package/build/plugins/sqljs-wasm-route-controller.js +1 -1
- package/build/routes/base-route.js +6 -6
- package/build/routes/basic-route.js +1 -1
- package/build/routes/hooks/frontend-model-command-route-hook.js +1 -1
- package/build/routes/index.js +1 -1
- package/build/routes/plugin-routes.js +1 -1
- package/build/routes/resolver.js +11 -11
- package/build/routes/resource-route.js +1 -1
- package/build/src/application.d.ts +3 -3
- package/build/src/application.d.ts.map +1 -1
- package/build/src/application.js +5 -5
- package/build/src/authorization/ability.d.ts +7 -7
- package/build/src/authorization/ability.d.ts.map +1 -1
- package/build/src/authorization/ability.js +9 -9
- package/build/src/authorization/base-resource.d.ts +1 -1
- package/build/src/authorization/base-resource.d.ts.map +1 -1
- package/build/src/authorization/base-resource.js +5 -5
- package/build/src/background-jobs/cron-expression.js +2 -2
- package/build/src/background-jobs/forked-runner-child.js +2 -2
- package/build/src/background-jobs/job-record.d.ts +2 -1
- package/build/src/background-jobs/job-record.d.ts.map +1 -1
- package/build/src/background-jobs/job-registry.d.ts +1 -1
- package/build/src/background-jobs/job-registry.d.ts.map +1 -1
- package/build/src/background-jobs/job-registry.js +2 -2
- package/build/src/background-jobs/job-runner.js +2 -2
- package/build/src/background-jobs/job.js +2 -2
- package/build/src/background-jobs/json-socket.d.ts +4 -4
- package/build/src/background-jobs/json-socket.d.ts.map +1 -1
- package/build/src/background-jobs/json-socket.js +5 -5
- package/build/src/background-jobs/main.d.ts +18 -18
- package/build/src/background-jobs/main.d.ts.map +1 -1
- package/build/src/background-jobs/main.js +22 -22
- package/build/src/background-jobs/scheduler.d.ts +5 -5
- package/build/src/background-jobs/scheduler.d.ts.map +1 -1
- package/build/src/background-jobs/scheduler.js +8 -8
- package/build/src/background-jobs/store.js +8 -8
- package/build/src/background-jobs/web/controller.js +3 -3
- package/build/src/background-jobs/worker.d.ts +6 -6
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +13 -13
- package/build/src/beacon/client.d.ts +4 -4
- package/build/src/beacon/client.d.ts.map +1 -1
- package/build/src/beacon/client.js +12 -9
- package/build/src/beacon/in-process-broker.d.ts.map +1 -1
- package/build/src/beacon/in-process-broker.js +3 -3
- package/build/src/beacon/in-process-client.d.ts +1 -1
- package/build/src/beacon/in-process-client.d.ts.map +1 -1
- package/build/src/beacon/in-process-client.js +3 -3
- package/build/src/beacon/server.d.ts +2 -2
- package/build/src/beacon/server.d.ts.map +1 -1
- package/build/src/beacon/server.js +4 -4
- package/build/src/cli/browser-cli.js +2 -2
- package/build/src/cli/commands/db/base-command.d.ts +2 -2
- package/build/src/cli/commands/db/base-command.d.ts.map +1 -1
- package/build/src/cli/commands/db/base-command.js +3 -3
- package/build/src/cli/index.js +3 -3
- package/build/src/cli/tenant-database-command-helper.d.ts +1 -1
- package/build/src/cli/tenant-database-command-helper.d.ts.map +1 -1
- package/build/src/cli/tenant-database-command-helper.js +4 -4
- package/build/src/cli/use-browser-cli.js +2 -2
- package/build/src/configuration.d.ts +14 -14
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +39 -39
- package/build/src/controller.js +10 -10
- package/build/src/current-configuration.js +2 -2
- package/build/src/database/annotations-async-hooks.js +3 -3
- package/build/src/database/annotations.d.ts.map +1 -1
- package/build/src/database/annotations.js +4 -4
- package/build/src/database/drivers/base-column.d.ts +1 -1
- package/build/src/database/drivers/base-column.d.ts.map +1 -1
- package/build/src/database/drivers/base-column.js +2 -2
- package/build/src/database/drivers/base-foreign-key.d.ts +1 -1
- package/build/src/database/drivers/base-foreign-key.d.ts.map +1 -1
- package/build/src/database/drivers/base-foreign-key.js +2 -2
- package/build/src/database/drivers/base-table.d.ts +1 -1
- package/build/src/database/drivers/base-table.d.ts.map +1 -1
- package/build/src/database/drivers/base-table.js +2 -2
- package/build/src/database/drivers/base.d.ts +6 -6
- package/build/src/database/drivers/base.d.ts.map +1 -1
- package/build/src/database/drivers/base.js +11 -11
- package/build/src/database/drivers/mssql/index.js +2 -2
- package/build/src/database/drivers/mssql/table.js +2 -2
- package/build/src/database/drivers/mysql/index.js +4 -4
- package/build/src/database/drivers/mysql/query.js +2 -2
- package/build/src/database/drivers/mysql/table.js +2 -2
- package/build/src/database/drivers/pgsql/index.js +3 -3
- package/build/src/database/drivers/sqlite/base.d.ts +3 -3
- package/build/src/database/drivers/sqlite/base.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/base.js +17 -17
- package/build/src/database/drivers/sqlite/index.d.ts +4 -4
- package/build/src/database/drivers/sqlite/index.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/index.js +12 -12
- package/build/src/database/drivers/sqlite/index.native.js +2 -2
- package/build/src/database/drivers/sqlite/index.web.d.ts +2 -2
- package/build/src/database/drivers/sqlite/index.web.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/index.web.js +4 -4
- package/build/src/database/drivers/sqlite/query.js +2 -2
- package/build/src/database/drivers/sqlite/query.web.js +2 -2
- package/build/src/database/drivers/sqlite/sql/alter-table.js +3 -3
- package/build/src/database/drivers/sqlite/table.js +2 -2
- package/build/src/database/migrator/files-finder.js +2 -2
- package/build/src/database/migrator.d.ts +1 -1
- package/build/src/database/migrator.d.ts.map +1 -1
- package/build/src/database/migrator.js +7 -7
- package/build/src/database/pool/async-tracked-multi-connection.d.ts +9 -9
- package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
- package/build/src/database/pool/async-tracked-multi-connection.js +28 -28
- package/build/src/database/pool/base-methods-forward.js +7 -7
- package/build/src/database/pool/base.d.ts +1 -1
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +9 -9
- package/build/src/database/query/from-base.d.ts +1 -1
- package/build/src/database/query/from-base.d.ts.map +1 -1
- package/build/src/database/query/from-base.js +2 -2
- package/build/src/database/query/index.d.ts +4 -4
- package/build/src/database/query/index.d.ts.map +1 -1
- package/build/src/database/query/index.js +11 -11
- package/build/src/database/query/join-object.js +4 -4
- package/build/src/database/query/model-class-query.d.ts +4 -4
- package/build/src/database/query/model-class-query.d.ts.map +1 -1
- package/build/src/database/query/model-class-query.js +40 -40
- package/build/src/database/query/preloader/belongs-to.d.ts +2 -2
- package/build/src/database/query/preloader/belongs-to.d.ts.map +1 -1
- package/build/src/database/query/preloader/belongs-to.js +23 -23
- package/build/src/database/query/preloader/has-many.d.ts +1 -1
- package/build/src/database/query/preloader/has-many.d.ts.map +1 -1
- package/build/src/database/query/preloader/has-many.js +21 -21
- package/build/src/database/query/preloader/has-one.d.ts +2 -2
- package/build/src/database/query/preloader/has-one.d.ts.map +1 -1
- package/build/src/database/query/preloader/has-one.js +9 -9
- package/build/src/database/query/preloader/selection.js +4 -4
- package/build/src/database/query/preloader.d.ts +1 -1
- package/build/src/database/query/preloader.d.ts.map +1 -1
- package/build/src/database/query/preloader.js +9 -9
- package/build/src/database/query/query-data.js +10 -10
- package/build/src/database/query/where-model-class-hash.js +8 -8
- package/build/src/database/query/with-count.js +10 -10
- package/build/src/database/record/acts-as-list.js +20 -20
- package/build/src/database/record/attachments/handle.d.ts +2 -2
- package/build/src/database/record/attachments/handle.d.ts.map +1 -1
- package/build/src/database/record/attachments/handle.js +3 -3
- package/build/src/database/record/attachments/normalize-input.js +15 -15
- package/build/src/database/record/attachments/storage-drivers/s3.js +7 -7
- package/build/src/database/record/attachments/store.d.ts +2 -2
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +14 -14
- package/build/src/database/record/index.d.ts +35 -32
- package/build/src/database/record/index.d.ts.map +1 -1
- package/build/src/database/record/index.js +147 -148
- package/build/src/database/record/instance-relationships/base.d.ts +3 -3
- package/build/src/database/record/instance-relationships/base.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/base.js +13 -13
- package/build/src/database/record/instance-relationships/belongs-to.js +4 -4
- package/build/src/database/record/instance-relationships/has-many.js +9 -9
- package/build/src/database/record/instance-relationships/has-one.d.ts +1 -1
- package/build/src/database/record/instance-relationships/has-one.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/has-one.js +8 -8
- package/build/src/database/record/relationships/base.js +4 -4
- package/build/src/database/record/state-machine.js +8 -8
- package/build/src/database/record/validators/presence.js +2 -2
- package/build/src/database/record/validators/uniqueness.js +6 -6
- package/build/src/database/table-data/index.d.ts +4 -4
- package/build/src/database/table-data/index.d.ts.map +1 -1
- package/build/src/database/table-data/index.js +5 -5
- package/build/src/environment-handlers/base.js +3 -3
- package/build/src/environment-handlers/browser.d.ts +3 -3
- package/build/src/environment-handlers/browser.d.ts.map +1 -1
- package/build/src/environment-handlers/browser.js +8 -8
- package/build/src/environment-handlers/node/cli/commands/cli-command-context.js +2 -2
- package/build/src/environment-handlers/node/cli/commands/console.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/console.js +5 -5
- package/build/src/environment-handlers/node/cli/commands/db/schema/dump.d.ts +1 -1
- package/build/src/environment-handlers/node/cli/commands/db/schema/dump.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/db/schema/dump.js +2 -2
- package/build/src/environment-handlers/node/cli/commands/db/schema/load.d.ts +1 -1
- package/build/src/environment-handlers/node/cli/commands/db/schema/load.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/db/schema/load.js +4 -4
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/base-models.js +2 -15
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts +105 -33
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.d.ts.map +1 -1
- package/build/src/environment-handlers/node/cli/commands/generate/frontend-models.js +172 -87
- package/build/src/environment-handlers/node.d.ts +2 -2
- package/build/src/environment-handlers/node.d.ts.map +1 -1
- package/build/src/environment-handlers/node.js +7 -7
- package/build/src/frontend-model-controller.d.ts +5 -6
- package/build/src/frontend-model-controller.d.ts.map +1 -1
- package/build/src/frontend-model-controller.js +95 -89
- package/build/src/frontend-model-resource/base-resource.d.ts +239 -91
- package/build/src/frontend-model-resource/base-resource.d.ts.map +1 -1
- package/build/src/frontend-model-resource/base-resource.js +302 -172
- package/build/src/frontend-models/base.d.ts +186 -115
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +347 -218
- package/build/src/frontend-models/clear-pending-debounced-callback.js +2 -2
- package/build/src/frontend-models/event-hook-models.d.ts.map +1 -1
- package/build/src/frontend-models/event-hook-models.js +3 -3
- package/build/src/frontend-models/outgoing-event-buffer.d.ts +1 -1
- package/build/src/frontend-models/outgoing-event-buffer.d.ts.map +1 -1
- package/build/src/frontend-models/outgoing-event-buffer.js +3 -3
- package/build/src/frontend-models/preloader.d.ts.map +1 -1
- package/build/src/frontend-models/preloader.js +9 -8
- package/build/src/frontend-models/query.d.ts +16 -8
- package/build/src/frontend-models/query.d.ts.map +1 -1
- package/build/src/frontend-models/query.js +43 -39
- package/build/src/frontend-models/resource-definition.js +7 -7
- package/build/src/frontend-models/transport-serialization.js +12 -12
- package/build/src/frontend-models/use-destroyed-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-destroyed-event.js +11 -11
- package/build/src/frontend-models/use-model-class-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-model-class-event.js +12 -12
- package/build/src/frontend-models/use-updated-event.d.ts.map +1 -1
- package/build/src/frontend-models/use-updated-event.js +12 -12
- package/build/src/frontend-models/websocket-channel.d.ts +6 -1
- package/build/src/frontend-models/websocket-channel.d.ts.map +1 -1
- package/build/src/frontend-models/websocket-channel.js +26 -18
- package/build/src/frontend-models/websocket-publishers.js +11 -11
- package/build/src/http-client/response.d.ts +2 -2
- package/build/src/http-client/response.d.ts.map +1 -1
- package/build/src/http-client/response.js +3 -3
- package/build/src/http-server/client/index.d.ts +1 -1
- package/build/src/http-server/client/index.d.ts.map +1 -1
- package/build/src/http-server/client/index.js +9 -9
- package/build/src/http-server/client/params-to-object.js +11 -11
- package/build/src/http-server/client/request-buffer/form-data-part.d.ts +2 -2
- package/build/src/http-server/client/request-buffer/form-data-part.d.ts.map +1 -1
- package/build/src/http-server/client/request-buffer/form-data-part.js +3 -3
- package/build/src/http-server/client/request-buffer/index.d.ts +4 -4
- package/build/src/http-server/client/request-buffer/index.d.ts.map +1 -1
- package/build/src/http-server/client/request-buffer/index.js +9 -9
- package/build/src/http-server/client/request-parser.d.ts +1 -1
- package/build/src/http-server/client/request-parser.d.ts.map +1 -1
- package/build/src/http-server/client/request-parser.js +4 -4
- package/build/src/http-server/client/request-runner.js +7 -7
- package/build/src/http-server/client/request-timing.d.ts +5 -5
- package/build/src/http-server/client/request-timing.d.ts.map +1 -1
- package/build/src/http-server/client/request-timing.js +6 -6
- package/build/src/http-server/client/request.js +2 -2
- package/build/src/http-server/client/response.d.ts +3 -3
- package/build/src/http-server/client/response.d.ts.map +1 -1
- package/build/src/http-server/client/response.js +6 -6
- package/build/src/http-server/client/websocket-request.d.ts +3 -3
- package/build/src/http-server/client/websocket-request.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-request.js +5 -5
- package/build/src/http-server/client/websocket-session.d.ts +6 -6
- package/build/src/http-server/client/websocket-session.d.ts.map +1 -1
- package/build/src/http-server/client/websocket-session.js +19 -19
- package/build/src/http-server/development-reloader.d.ts +3 -3
- package/build/src/http-server/development-reloader.d.ts.map +1 -1
- package/build/src/http-server/development-reloader.js +6 -6
- package/build/src/http-server/index.d.ts +7 -7
- package/build/src/http-server/index.d.ts.map +1 -1
- package/build/src/http-server/index.js +13 -13
- package/build/src/http-server/remote-address.js +6 -6
- package/build/src/http-server/server-client.js +4 -4
- package/build/src/http-server/server-lock.js +5 -5
- package/build/src/http-server/websocket-channel-subscribers.d.ts +1 -1
- package/build/src/http-server/websocket-channel-subscribers.d.ts.map +1 -1
- package/build/src/http-server/websocket-channel-subscribers.js +4 -4
- package/build/src/http-server/websocket-channel.d.ts +1 -1
- package/build/src/http-server/websocket-channel.d.ts.map +1 -1
- package/build/src/http-server/websocket-channel.js +2 -2
- package/build/src/http-server/websocket-connection.d.ts +1 -1
- package/build/src/http-server/websocket-connection.d.ts.map +1 -1
- package/build/src/http-server/websocket-connection.js +2 -2
- package/build/src/http-server/websocket-event-log-store.d.ts +1 -1
- package/build/src/http-server/websocket-event-log-store.d.ts.map +1 -1
- package/build/src/http-server/websocket-event-log-store.js +7 -7
- package/build/src/http-server/websocket-events-host.d.ts +1 -1
- package/build/src/http-server/websocket-events-host.d.ts.map +1 -1
- package/build/src/http-server/websocket-events-host.js +3 -3
- package/build/src/http-server/worker-handler/in-process.d.ts +3 -3
- package/build/src/http-server/worker-handler/in-process.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/in-process.js +9 -9
- package/build/src/http-server/worker-handler/index.d.ts +4 -4
- package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/index.js +5 -5
- package/build/src/http-server/worker-handler/worker-thread.d.ts +2 -2
- package/build/src/http-server/worker-handler/worker-thread.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/worker-thread.js +4 -4
- package/build/src/logger/outputs/array-output.d.ts +3 -3
- package/build/src/logger/outputs/array-output.d.ts.map +1 -1
- package/build/src/logger/outputs/array-output.js +4 -4
- package/build/src/logger/outputs/console-output.d.ts +1 -1
- package/build/src/logger/outputs/console-output.d.ts.map +1 -1
- package/build/src/logger/outputs/console-output.js +2 -2
- package/build/src/logger/outputs/file-output.d.ts +4 -4
- package/build/src/logger/outputs/file-output.d.ts.map +1 -1
- package/build/src/logger/outputs/file-output.js +5 -5
- package/build/src/logger/outputs/stdout-output.d.ts.map +1 -1
- package/build/src/logger/outputs/stdout-output.js +2 -2
- package/build/src/logger.d.ts.map +1 -1
- package/build/src/logger.js +11 -11
- package/build/src/mailer/backends/smtp.d.ts.map +1 -1
- package/build/src/mailer/backends/smtp.js +5 -5
- package/build/src/mailer/base.js +11 -11
- package/build/src/mailer/delivery.d.ts +3 -3
- package/build/src/mailer/delivery.d.ts.map +1 -1
- package/build/src/mailer/delivery.js +5 -5
- package/build/src/plugins/sqljs-wasm-route-controller.js +2 -2
- package/build/src/routes/base-route.d.ts +6 -6
- package/build/src/routes/base-route.d.ts.map +1 -1
- package/build/src/routes/base-route.js +7 -7
- package/build/src/routes/basic-route.js +2 -2
- package/build/src/routes/hooks/frontend-model-command-route-hook.js +2 -2
- package/build/src/routes/index.js +2 -2
- package/build/src/routes/plugin-routes.js +2 -2
- package/build/src/routes/resolver.d.ts +1 -1
- package/build/src/routes/resolver.d.ts.map +1 -1
- package/build/src/routes/resolver.js +13 -13
- package/build/src/routes/resource-route.d.ts +1 -1
- package/build/src/routes/resource-route.d.ts.map +1 -1
- package/build/src/routes/resource-route.js +2 -2
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts.map +1 -1
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +9 -9
- package/build/src/testing/expect-utils.js +13 -13
- package/build/src/testing/expect.d.ts +7 -1
- package/build/src/testing/expect.d.ts.map +1 -1
- package/build/src/testing/expect.js +17 -9
- package/build/src/testing/test-files-finder.d.ts +8 -8
- package/build/src/testing/test-files-finder.d.ts.map +1 -1
- package/build/src/testing/test-files-finder.js +9 -9
- package/build/src/testing/test-filter-parser.js +3 -3
- package/build/src/testing/test-runner.d.ts +2 -2
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +17 -17
- package/build/src/testing/test-suite-splitter.js +2 -2
- package/build/src/testing/test.d.ts +2 -2
- package/build/src/testing/test.d.ts.map +1 -1
- package/build/src/testing/test.js +16 -16
- package/build/src/utils/backtrace-cleaner.d.ts +1 -1
- package/build/src/utils/backtrace-cleaner.d.ts.map +1 -1
- package/build/src/utils/backtrace-cleaner.js +2 -2
- package/build/src/utils/format-value.js +2 -2
- package/build/src/utils/model-scope.js +2 -2
- package/build/src/utils/ransack.js +27 -27
- package/build/src/utils/with-tracked-stack-async-hooks.js +8 -8
- package/build/src/utils/with-tracked-stack.js +4 -4
- package/build/testing/browser-frontend-model-event-hook-scenarios.js +8 -8
- package/build/testing/expect-utils.js +11 -11
- package/build/testing/expect.js +16 -7
- package/build/testing/test-files-finder.js +8 -8
- package/build/testing/test-filter-parser.js +2 -2
- package/build/testing/test-runner.js +16 -16
- package/build/testing/test-suite-splitter.js +1 -1
- package/build/testing/test.js +15 -15
- package/build/utils/backtrace-cleaner.js +1 -1
- package/build/utils/format-value.js +1 -1
- package/build/utils/model-scope.js +1 -1
- package/build/utils/ransack.js +26 -26
- package/build/utils/with-tracked-stack-async-hooks.js +7 -7
- package/build/utils/with-tracked-stack.js +3 -3
- package/package.json +2 -1
- package/src/application.js +4 -4
- package/src/authorization/ability.js +8 -8
- package/src/authorization/base-resource.js +4 -4
- package/src/background-jobs/cron-expression.js +1 -1
- package/src/background-jobs/forked-runner-child.js +1 -1
- package/src/background-jobs/job-registry.js +1 -1
- package/src/background-jobs/job-runner.js +1 -1
- package/src/background-jobs/job.js +1 -1
- package/src/background-jobs/json-socket.js +4 -4
- package/src/background-jobs/main.js +21 -21
- package/src/background-jobs/scheduler.js +7 -7
- package/src/background-jobs/store.js +7 -7
- package/src/background-jobs/web/controller.js +2 -2
- package/src/background-jobs/worker.js +12 -12
- package/src/beacon/client.js +11 -8
- package/src/beacon/in-process-broker.js +2 -2
- package/src/beacon/in-process-client.js +2 -2
- package/src/beacon/server.js +3 -3
- package/src/cli/browser-cli.js +1 -1
- package/src/cli/commands/db/base-command.js +2 -2
- package/src/cli/index.js +2 -2
- package/src/cli/tenant-database-command-helper.js +3 -3
- package/src/cli/use-browser-cli.js +1 -1
- package/src/configuration.js +38 -38
- package/src/controller.js +8 -8
- package/src/current-configuration.js +1 -1
- package/src/database/annotations-async-hooks.js +2 -2
- package/src/database/annotations.js +3 -3
- package/src/database/drivers/base-column.js +1 -1
- package/src/database/drivers/base-foreign-key.js +1 -1
- package/src/database/drivers/base-table.js +1 -1
- package/src/database/drivers/base.js +10 -10
- package/src/database/drivers/mssql/index.js +1 -1
- package/src/database/drivers/mssql/table.js +1 -1
- package/src/database/drivers/mysql/index.js +3 -3
- package/src/database/drivers/mysql/query.js +1 -1
- package/src/database/drivers/mysql/table.js +1 -1
- package/src/database/drivers/pgsql/index.js +2 -2
- package/src/database/drivers/sqlite/base.js +16 -16
- package/src/database/drivers/sqlite/index.js +11 -11
- package/src/database/drivers/sqlite/index.native.js +1 -1
- package/src/database/drivers/sqlite/index.web.js +3 -3
- package/src/database/drivers/sqlite/query.js +1 -1
- package/src/database/drivers/sqlite/query.web.js +1 -1
- package/src/database/drivers/sqlite/sql/alter-table.js +2 -2
- package/src/database/drivers/sqlite/table.js +1 -1
- package/src/database/migrator/files-finder.js +1 -1
- package/src/database/migrator.js +6 -6
- package/src/database/pool/async-tracked-multi-connection.js +27 -27
- package/src/database/pool/base-methods-forward.js +4 -4
- package/src/database/pool/base.js +8 -8
- package/src/database/query/from-base.js +1 -1
- package/src/database/query/index.js +10 -10
- package/src/database/query/join-object.js +3 -3
- package/src/database/query/model-class-query.js +39 -39
- package/src/database/query/preloader/belongs-to.js +22 -22
- package/src/database/query/preloader/has-many.js +20 -20
- package/src/database/query/preloader/has-one.js +8 -8
- package/src/database/query/preloader/selection.js +3 -3
- package/src/database/query/preloader.js +8 -8
- package/src/database/query/query-data.js +9 -9
- package/src/database/query/where-model-class-hash.js +7 -7
- package/src/database/query/with-count.js +9 -9
- package/src/database/record/acts-as-list.js +15 -15
- package/src/database/record/attachments/handle.js +2 -2
- package/src/database/record/attachments/normalize-input.js +12 -12
- package/src/database/record/attachments/storage-drivers/s3.js +6 -6
- package/src/database/record/attachments/store.js +13 -13
- package/src/database/record/index.js +127 -128
- package/src/database/record/instance-relationships/base.js +11 -11
- package/src/database/record/instance-relationships/belongs-to.js +3 -3
- package/src/database/record/instance-relationships/has-many.js +8 -8
- package/src/database/record/instance-relationships/has-one.js +7 -7
- package/src/database/record/relationships/base.js +2 -2
- package/src/database/record/state-machine.js +7 -7
- package/src/database/record/validators/presence.js +1 -1
- package/src/database/record/validators/uniqueness.js +5 -5
- package/src/database/table-data/index.js +4 -4
- package/src/environment-handlers/base.js +2 -2
- package/src/environment-handlers/browser.js +7 -7
- package/src/environment-handlers/node/cli/commands/cli-command-context.js +1 -1
- package/src/environment-handlers/node/cli/commands/console.js +4 -4
- package/src/environment-handlers/node/cli/commands/db/schema/dump.js +1 -1
- package/src/environment-handlers/node/cli/commands/db/schema/load.js +3 -3
- package/src/environment-handlers/node/cli/commands/generate/base-models.js +1 -16
- package/src/environment-handlers/node/cli/commands/generate/frontend-models.js +179 -89
- package/src/environment-handlers/node.js +6 -6
- package/src/frontend-model-controller.js +90 -82
- package/src/frontend-model-resource/base-resource.js +343 -167
- package/src/frontend-models/base.js +362 -205
- package/src/frontend-models/clear-pending-debounced-callback.js +1 -1
- package/src/frontend-models/event-hook-models.js +2 -2
- package/src/frontend-models/outgoing-event-buffer.js +2 -2
- package/src/frontend-models/preloader.js +8 -7
- package/src/frontend-models/query.js +43 -38
- package/src/frontend-models/resource-definition.js +6 -6
- package/src/frontend-models/transport-serialization.js +11 -11
- package/src/frontend-models/use-destroyed-event.js +10 -10
- package/src/frontend-models/use-model-class-event.js +11 -11
- package/src/frontend-models/use-updated-event.js +11 -11
- package/src/frontend-models/websocket-channel.js +26 -17
- package/src/frontend-models/websocket-publishers.js +9 -9
- package/src/http-client/response.js +2 -2
- package/src/http-server/client/index.js +8 -8
- package/src/http-server/client/params-to-object.js +10 -10
- package/src/http-server/client/request-buffer/form-data-part.js +2 -2
- package/src/http-server/client/request-buffer/index.js +8 -8
- package/src/http-server/client/request-parser.js +3 -3
- package/src/http-server/client/request-runner.js +6 -6
- package/src/http-server/client/request-timing.js +5 -5
- package/src/http-server/client/request.js +1 -1
- package/src/http-server/client/response.js +5 -5
- package/src/http-server/client/websocket-request.js +4 -4
- package/src/http-server/client/websocket-session.js +18 -18
- package/src/http-server/development-reloader.js +5 -5
- package/src/http-server/index.js +12 -12
- package/src/http-server/remote-address.js +4 -4
- package/src/http-server/server-client.js +3 -3
- package/src/http-server/server-lock.js +4 -4
- package/src/http-server/websocket-channel-subscribers.js +3 -3
- package/src/http-server/websocket-channel.js +1 -1
- package/src/http-server/websocket-connection.js +1 -1
- package/src/http-server/websocket-event-log-store.js +6 -6
- package/src/http-server/websocket-events-host.js +2 -2
- package/src/http-server/worker-handler/in-process.js +7 -7
- package/src/http-server/worker-handler/index.js +4 -4
- package/src/http-server/worker-handler/worker-thread.js +3 -3
- package/src/logger/outputs/array-output.js +3 -3
- package/src/logger/outputs/console-output.js +1 -1
- package/src/logger/outputs/file-output.js +4 -4
- package/src/logger/outputs/stdout-output.js +1 -1
- package/src/logger.js +10 -10
- package/src/mailer/backends/smtp.js +3 -3
- package/src/mailer/base.js +8 -8
- package/src/mailer/delivery.js +4 -4
- package/src/plugins/sqljs-wasm-route-controller.js +1 -1
- package/src/routes/base-route.js +6 -6
- package/src/routes/basic-route.js +1 -1
- package/src/routes/hooks/frontend-model-command-route-hook.js +1 -1
- package/src/routes/index.js +1 -1
- package/src/routes/plugin-routes.js +1 -1
- package/src/routes/resolver.js +11 -11
- package/src/routes/resource-route.js +1 -1
- package/src/testing/browser-frontend-model-event-hook-scenarios.js +8 -8
- package/src/testing/expect-utils.js +11 -11
- package/src/testing/expect.js +16 -7
- package/src/testing/test-files-finder.js +8 -8
- package/src/testing/test-filter-parser.js +2 -2
- package/src/testing/test-runner.js +16 -16
- package/src/testing/test-suite-splitter.js +1 -1
- package/src/testing/test.js +15 -15
- package/src/utils/backtrace-cleaner.js +1 -1
- package/src/utils/format-value.js +1 -1
- package/src/utils/model-scope.js +1 -1
- package/src/utils/ransack.js +26 -26
- package/src/utils/with-tracked-stack-async-hooks.js +7 -7
- package/src/utils/with-tracked-stack.js +3 -3
|
@@ -4,10 +4,29 @@ import AuthorizationBaseResource from "../authorization/base-resource.js"
|
|
|
4
4
|
import * as inflection from "inflection"
|
|
5
5
|
import isPlainObject from "../utils/plain-object.js"
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Built-in frontend-model resource action.
|
|
9
|
+
* @typedef {"index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url"} FrontendModelResourceAction
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Frontend-model controller methods used by resources.
|
|
14
|
+
* @typedef {import("../controller.js").default & {
|
|
15
|
+
* currentAbility: () => import("../authorization/ability.js").default | undefined,
|
|
16
|
+
* frontendModelAbilityAction: (action: FrontendModelResourceAction) => string,
|
|
17
|
+
* frontendModelAuthorizedQuery: (action: FrontendModelResourceAction) => import("../database/query/model-class-query.js").default<typeof import("../database/record/index.js").default>,
|
|
18
|
+
* frontendModelIndexQuery: () => import("../database/query/model-class-query.js").default<typeof import("../database/record/index.js").default>,
|
|
19
|
+
* frontendModelParams: () => import("../configuration-types.js").VelociousParams,
|
|
20
|
+
* frontendModelPreload: () => import("../database/query/index.js").NestedPreloadRecord | null,
|
|
21
|
+
* frontendModelResourceConfigurationForModelClass: (modelClass: typeof import("../database/record/index.js").default) => FrontendModelResolvedResourceConfiguration | null,
|
|
22
|
+
* serializeFrontendModel: (model: import("../database/record/index.js").default) => Promise<Record<string, object | string | number | boolean | null>>
|
|
23
|
+
* }} FrontendModelResourceController
|
|
24
|
+
*/
|
|
25
|
+
|
|
7
26
|
/**
|
|
8
27
|
* FrontendModelResourceControllerArgs type.
|
|
9
28
|
* @typedef {object} FrontendModelResourceControllerArgs
|
|
10
|
-
* @property {
|
|
29
|
+
* @property {FrontendModelResourceController} controller - Frontend-model controller instance.
|
|
11
30
|
* @property {typeof import("../database/record/index.js").default} modelClass - Backing model class.
|
|
12
31
|
* @property {string} modelName - Model name.
|
|
13
32
|
* @property {import("../configuration-types.js").VelociousParams} params - Request params.
|
|
@@ -35,51 +54,68 @@ import isPlainObject from "../utils/plain-object.js"
|
|
|
35
54
|
* @property {import("../configuration-types.js").NormalizedFrontendModelResourceConfiguration} resourceConfiguration - Normalized resource configuration.
|
|
36
55
|
*/
|
|
37
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Transport-safe value accepted in frontend-model resource mutation payloads.
|
|
59
|
+
* Nested object/array values are intentionally opaque because TypeScript rejects
|
|
60
|
+
* recursive JSDoc typedefs for this transport payload contract.
|
|
61
|
+
* @typedef {import("../frontend-models/base.js").FrontendModelTransportValue | import("../database/record/index.js").default | Record<string, unknown> | Array<unknown>} FrontendModelResourcePayloadValue
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Attribute payload accepted by frontend-model resource mutations.
|
|
66
|
+
* @typedef {Record<string, FrontendModelResourcePayloadValue>} FrontendModelResourceAttributePayload
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Virtual setter method on a frontend-model resource.
|
|
71
|
+
* @typedef {function(import("../database/record/index.js").default, FrontendModelResourcePayloadValue): (void | Promise<void>)} FrontendModelResourceVirtualSetter
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Static helpers used when checking whether a model-like receiver accepts an attribute.
|
|
76
|
+
* @typedef {object} WritableAttributeReceiverClass
|
|
77
|
+
* @property {function(string): string} [resolveAttributeName] - Resolves aliases to canonical attribute names.
|
|
78
|
+
* @property {function(Record<string, ?>, string): string} [findMemberNameInsensitive] - Locates a setter method on the receiver.
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Options passed while saving frontend-model resource mutations.
|
|
83
|
+
* @typedef {object} FrontendModelResourceSaveOptions
|
|
84
|
+
* @property {FrontendModelResourceAttributePayload | null} [attachments] - Uploaded attachment attributes.
|
|
85
|
+
* @property {FrontendModelResourceController | null} [controller] - Controller handling the mutation.
|
|
86
|
+
* @property {FrontendModelResourceAttributePayload | null} [nestedAttributes] - Nested attributes payload.
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Normalized nested attributes entry.
|
|
91
|
+
* @typedef {FrontendModelResourceAttributePayload & {id?: string | number, _destroy?: boolean, attributes?: FrontendModelResourceAttributePayload, attachments?: FrontendModelResourceAttributePayload, nestedAttributes?: FrontendModelResourceAttributePayload}} FrontendModelResourceNestedEntry
|
|
92
|
+
*/
|
|
93
|
+
|
|
38
94
|
/**
|
|
39
95
|
* Base class for backend frontend-model resources.
|
|
40
96
|
* @template {typeof import("../database/record/index.js").default} [TModelClass=typeof import("../database/record/index.js").default]
|
|
41
97
|
*/
|
|
42
98
|
export default class FrontendModelBaseResource extends AuthorizationBaseResource {
|
|
43
|
-
/**
|
|
44
|
-
* Backing model class.
|
|
45
|
-
@type {typeof import("../database/record/index.js").default | undefined} */
|
|
99
|
+
/** @type {typeof import("../database/record/index.js").default | undefined} */
|
|
46
100
|
static ModelClass = undefined
|
|
47
101
|
|
|
48
|
-
/**
|
|
49
|
-
* Attributes.
|
|
50
|
-
@type {Record<string, ?> | string[] | undefined} */
|
|
102
|
+
/** @type {Record<string, ?> | string[] | undefined} */
|
|
51
103
|
static attributes = undefined
|
|
52
|
-
/**
|
|
53
|
-
* Abilities.
|
|
54
|
-
@type {string[] | undefined} */
|
|
104
|
+
/** @type {string[] | undefined} */
|
|
55
105
|
static abilities = undefined
|
|
56
|
-
/**
|
|
57
|
-
* Attachments.
|
|
58
|
-
@type {Record<string, ?> | undefined} */
|
|
106
|
+
/** @type {Record<string, ?> | undefined} */
|
|
59
107
|
static attachments = undefined
|
|
60
|
-
/**
|
|
61
|
-
* Collection commands.
|
|
62
|
-
@type {string[] | undefined} */
|
|
108
|
+
/** @type {string[] | undefined} */
|
|
63
109
|
static collectionCommands = undefined
|
|
64
|
-
/**
|
|
65
|
-
* Built in collection commands.
|
|
66
|
-
@type {string[] | undefined} */
|
|
110
|
+
/** @type {string[] | undefined} */
|
|
67
111
|
static builtInCollectionCommands = undefined
|
|
68
|
-
/**
|
|
69
|
-
* Member commands.
|
|
70
|
-
@type {string[] | undefined} */
|
|
112
|
+
/** @type {string[] | undefined} */
|
|
71
113
|
static memberCommands = undefined
|
|
72
|
-
/**
|
|
73
|
-
* Built in member commands.
|
|
74
|
-
@type {string[] | undefined} */
|
|
114
|
+
/** @type {string[] | undefined} */
|
|
75
115
|
static builtInMemberCommands = undefined
|
|
76
|
-
/**
|
|
77
|
-
* Relationships.
|
|
78
|
-
@type {string[] | undefined} */
|
|
116
|
+
/** @type {string[] | undefined} */
|
|
79
117
|
static relationships = undefined
|
|
80
|
-
/**
|
|
81
|
-
* Translated attributes.
|
|
82
|
-
@type {string[] | undefined} */
|
|
118
|
+
/** @type {string[] | undefined} */
|
|
83
119
|
static translatedAttributes = undefined
|
|
84
120
|
|
|
85
121
|
/**
|
|
@@ -93,32 +129,22 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
93
129
|
locals: "locals" in args ? args.locals || {} : {}
|
|
94
130
|
})
|
|
95
131
|
|
|
132
|
+
const ResourceClass = /** @type {typeof FrontendModelBaseResource} */ (this.constructor)
|
|
133
|
+
const defaultResourceConfiguration = /** @type {import("../configuration-types.js").FrontendModelResourceConfiguration} */ ({attributes: []})
|
|
134
|
+
|
|
96
135
|
this.controller = "controller" in args ? args.controller : undefined
|
|
97
|
-
this.modelClassValue = "modelClass" in args ? args.modelClass :
|
|
98
|
-
* Narrows the runtime value to the documented type.
|
|
99
|
-
@type {typeof import("../database/record/index.js").default | undefined} */ (/**
|
|
100
|
-
* Narrows the runtime value to the documented type.
|
|
101
|
-
@type {typeof FrontendModelBaseResource} */ (this.constructor).modelClass())
|
|
136
|
+
this.modelClassValue = "modelClass" in args ? args.modelClass : ResourceClass.modelClass()
|
|
102
137
|
this.modelNameValue = "modelName" in args ? args.modelName : (this.modelClassValue?.getModelName ? this.modelClassValue.getModelName() : this.modelClassValue?.name || "")
|
|
103
138
|
this.paramsValue = "params" in args ? args.params : undefined
|
|
104
|
-
this.resourceConfigurationValue = "resourceConfiguration" in args ? args.resourceConfiguration :
|
|
105
|
-
* Narrows the runtime value to the documented type.
|
|
106
|
-
@type {import("../configuration-types.js").FrontendModelResourceConfiguration} */ ({attributes: []})
|
|
139
|
+
this.resourceConfigurationValue = "resourceConfiguration" in args ? args.resourceConfiguration : defaultResourceConfiguration
|
|
107
140
|
}
|
|
108
141
|
|
|
109
142
|
/**
|
|
110
143
|
* Runs typed controller instance.
|
|
111
|
-
* @returns {
|
|
112
|
-
* frontendModelAuthorizedQuery: (action: "index" | "find" | "create" | "update" | "destroy" | "attach" | "download" | "url") => import("../database/query/model-class-query.js").default<TModelClass>,
|
|
113
|
-
* frontendModelAbilityAction: (action: string) => string,
|
|
114
|
-
* currentAbility: () => import("../authorization/ability.js").default | undefined,
|
|
115
|
-
* frontendModelIndexQuery: () => import("../database/query/model-class-query.js").default<TModelClass>,
|
|
116
|
-
* frontendModelPreload: () => import("../database/query/index.js").NestedPreloadRecord | null,
|
|
117
|
-
* serializeFrontendModel: (model: import("../database/record/index.js").default) => Promise<Record<string, unknown>>
|
|
118
|
-
* }} - Controller instance with frontend-model helpers.
|
|
144
|
+
* @returns {FrontendModelResourceController} - Controller instance with frontend-model helpers.
|
|
119
145
|
*/
|
|
120
146
|
typedControllerInstance() {
|
|
121
|
-
return /**
|
|
147
|
+
return /** @type {FrontendModelResourceController} */ (this.controller)
|
|
122
148
|
}
|
|
123
149
|
|
|
124
150
|
/**
|
|
@@ -126,9 +152,7 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
126
152
|
* @returns {import("../configuration-types.js").FrontendModelResourceConfiguration} - Static resource config (raw user input shape; consumers normalize).
|
|
127
153
|
*/
|
|
128
154
|
static resourceConfig() {
|
|
129
|
-
/**
|
|
130
|
-
* Config.
|
|
131
|
-
@type {import("../configuration-types.js").FrontendModelResourceConfiguration} */
|
|
155
|
+
/** @type {import("../configuration-types.js").FrontendModelResourceConfiguration} */
|
|
132
156
|
const config = {
|
|
133
157
|
attributes: this.attributes || []
|
|
134
158
|
}
|
|
@@ -244,6 +268,118 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
244
268
|
return []
|
|
245
269
|
}
|
|
246
270
|
|
|
271
|
+
/**
|
|
272
|
+
* Normalizes create attributes before permission filtering and saving.
|
|
273
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Incoming create attributes.
|
|
274
|
+
* @param {FrontendModelResourceSaveOptions} options - Save options.
|
|
275
|
+
* @returns {FrontendModelResourceAttributePayload | Promise<FrontendModelResourceAttributePayload>} - Normalized attributes.
|
|
276
|
+
*/
|
|
277
|
+
normalizeCreateAttributes(attributes, options) {
|
|
278
|
+
void options
|
|
279
|
+
|
|
280
|
+
return attributes
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Normalizes update attributes before permission filtering and saving.
|
|
285
|
+
* @param {import("../database/record/index.js").default} model - Existing model.
|
|
286
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Incoming update attributes.
|
|
287
|
+
* @param {FrontendModelResourceSaveOptions} options - Save options.
|
|
288
|
+
* @returns {FrontendModelResourceAttributePayload | Promise<FrontendModelResourceAttributePayload>} - Normalized attributes.
|
|
289
|
+
*/
|
|
290
|
+
normalizeUpdateAttributes(model, attributes, options) {
|
|
291
|
+
void model
|
|
292
|
+
void options
|
|
293
|
+
|
|
294
|
+
return attributes
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Runs before create.
|
|
299
|
+
* @param {import("../database/record/index.js").default} model - New model before assignment/save.
|
|
300
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Normalized create attributes.
|
|
301
|
+
* @param {FrontendModelResourceSaveOptions} options - Save options.
|
|
302
|
+
* @returns {void | Promise<void>} - Resolves when the hook finishes.
|
|
303
|
+
*/
|
|
304
|
+
beforeCreate(model, attributes, options) {
|
|
305
|
+
void model
|
|
306
|
+
void attributes
|
|
307
|
+
void options
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Runs after create.
|
|
312
|
+
* @param {import("../database/record/index.js").default} model - Created model.
|
|
313
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Normalized create attributes.
|
|
314
|
+
* @param {FrontendModelResourceSaveOptions} options - Save options.
|
|
315
|
+
* @returns {void | Promise<void>} - Resolves when the hook finishes.
|
|
316
|
+
*/
|
|
317
|
+
afterCreate(model, attributes, options) {
|
|
318
|
+
void model
|
|
319
|
+
void attributes
|
|
320
|
+
void options
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Runs before update.
|
|
325
|
+
* @param {import("../database/record/index.js").default} model - Existing model before assignment/save.
|
|
326
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Normalized update attributes.
|
|
327
|
+
* @param {FrontendModelResourceSaveOptions} options - Save options.
|
|
328
|
+
* @returns {void | Promise<void>} - Resolves when the hook finishes.
|
|
329
|
+
*/
|
|
330
|
+
beforeUpdate(model, attributes, options) {
|
|
331
|
+
void model
|
|
332
|
+
void attributes
|
|
333
|
+
void options
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Runs after update.
|
|
338
|
+
* @param {import("../database/record/index.js").default} model - Updated model.
|
|
339
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Normalized update attributes.
|
|
340
|
+
* @param {FrontendModelResourceSaveOptions} options - Save options.
|
|
341
|
+
* @returns {void | Promise<void>} - Resolves when the hook finishes.
|
|
342
|
+
*/
|
|
343
|
+
afterUpdate(model, attributes, options) {
|
|
344
|
+
void model
|
|
345
|
+
void attributes
|
|
346
|
+
void options
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Runs before destroy.
|
|
351
|
+
* @param {import("../database/record/index.js").default} model - Model before destroy.
|
|
352
|
+
* @returns {void | Promise<void>} - Resolves when the hook finishes.
|
|
353
|
+
*/
|
|
354
|
+
beforeDestroy(model) {
|
|
355
|
+
void model
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Runs after destroy.
|
|
360
|
+
* @param {import("../database/record/index.js").default} model - Destroyed model.
|
|
361
|
+
* @returns {void | Promise<void>} - Resolves when the hook finishes.
|
|
362
|
+
*/
|
|
363
|
+
afterDestroy(model) {
|
|
364
|
+
void model
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Wraps create/update/destroy resource mutations.
|
|
369
|
+
* @template Result
|
|
370
|
+
* @param {object} args - Transaction args.
|
|
371
|
+
* @param {"create" | "update" | "destroy"} args.action - Mutation action.
|
|
372
|
+
* @param {import("../database/record/index.js").default} args.model - Mutated model.
|
|
373
|
+
* @param {() => Promise<Result>} args.callback - Mutation callback.
|
|
374
|
+
* @returns {Promise<Result>} - Callback result.
|
|
375
|
+
*/
|
|
376
|
+
async runMutationTransaction({action, model, callback}) {
|
|
377
|
+
void action
|
|
378
|
+
void model
|
|
379
|
+
|
|
380
|
+
return await callback()
|
|
381
|
+
}
|
|
382
|
+
|
|
247
383
|
/**
|
|
248
384
|
* Runs primary key.
|
|
249
385
|
* @returns {string} - Primary key.
|
|
@@ -252,11 +388,12 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
252
388
|
|
|
253
389
|
/**
|
|
254
390
|
* Runs authorized query.
|
|
255
|
-
* @param {
|
|
391
|
+
* @param {FrontendModelResourceAction} action - Ability action.
|
|
256
392
|
* @returns {import("../database/query/model-class-query.js").default<TModelClass>} - Authorized query.
|
|
257
393
|
*/
|
|
258
394
|
authorizedQuery(action) {
|
|
259
|
-
|
|
395
|
+
// Narrows the controller query to this resource's model class.
|
|
396
|
+
return /** @type {import("../database/query/model-class-query.js").default<TModelClass>} */ (this.typedControllerInstance().frontendModelAuthorizedQuery(action))
|
|
260
397
|
}
|
|
261
398
|
|
|
262
399
|
|
|
@@ -329,18 +466,30 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
329
466
|
|
|
330
467
|
/**
|
|
331
468
|
* Runs create.
|
|
332
|
-
* @param {
|
|
333
|
-
* @param {
|
|
469
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Create attributes.
|
|
470
|
+
* @param {FrontendModelResourceSaveOptions} [options] - Save options.
|
|
334
471
|
* @returns {Promise<import("../database/record/index.js").default>} - Created model.
|
|
335
472
|
*/
|
|
336
473
|
async create(attributes, options = {}) {
|
|
337
|
-
const
|
|
338
|
-
const
|
|
474
|
+
const normalizedAttributes = await this.normalizeCreateAttributes(attributes, options)
|
|
475
|
+
const attachmentSplit = this._extractAttachmentAttributes(normalizedAttributes, options.attachments ?? null)
|
|
476
|
+
const permit = parsePermittedParams(this.permittedParams({action: "create", ability: this.ability, locals: this.locals, params: normalizedAttributes}))
|
|
339
477
|
const filtered = filterWritableFrontendModelAttributes(this.modelClass().prototype, attachmentSplit.attributes, this, permit.attributes)
|
|
340
478
|
const ModelClass = this.modelClass()
|
|
341
479
|
const model = new ModelClass()
|
|
342
480
|
|
|
343
|
-
return await this.
|
|
481
|
+
return await this.runMutationTransaction({
|
|
482
|
+
action: "create",
|
|
483
|
+
model,
|
|
484
|
+
callback: async () => {
|
|
485
|
+
await this.beforeCreate(model, normalizedAttributes, options)
|
|
486
|
+
const savedModel = await this._saveWithNestedAttributes({filtered, model, options: {...options, attachments: attachmentSplit.attachments}, permit})
|
|
487
|
+
|
|
488
|
+
await this.afterCreate(savedModel, normalizedAttributes, options)
|
|
489
|
+
|
|
490
|
+
return savedModel
|
|
491
|
+
}
|
|
492
|
+
})
|
|
344
493
|
}
|
|
345
494
|
|
|
346
495
|
/**
|
|
@@ -355,21 +504,33 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
355
504
|
/**
|
|
356
505
|
* Runs update.
|
|
357
506
|
* @param {import("../database/record/index.js").default} model - Existing model.
|
|
358
|
-
* @param {
|
|
359
|
-
* @param {
|
|
507
|
+
* @param {FrontendModelResourceAttributePayload} attributes - Update attributes.
|
|
508
|
+
* @param {FrontendModelResourceSaveOptions} [options] - Save options.
|
|
360
509
|
* @returns {Promise<import("../database/record/index.js").default>} - Updated model.
|
|
361
510
|
*/
|
|
362
511
|
async update(model, attributes, options = {}) {
|
|
363
|
-
const
|
|
364
|
-
const
|
|
512
|
+
const normalizedAttributes = await this.normalizeUpdateAttributes(model, attributes, options)
|
|
513
|
+
const attachmentSplit = this._extractAttachmentAttributes(normalizedAttributes, options.attachments ?? null)
|
|
514
|
+
const permit = parsePermittedParams(this.permittedParams({action: "update", ability: this.ability, locals: this.locals, params: normalizedAttributes}))
|
|
365
515
|
const filtered = filterWritableFrontendModelAttributes(model, attachmentSplit.attributes, this, permit.attributes)
|
|
366
516
|
|
|
367
|
-
return await this.
|
|
517
|
+
return await this.runMutationTransaction({
|
|
518
|
+
action: "update",
|
|
519
|
+
model,
|
|
520
|
+
callback: async () => {
|
|
521
|
+
await this.beforeUpdate(model, normalizedAttributes, options)
|
|
522
|
+
const savedModel = await this._saveWithNestedAttributes({filtered, model, options: {...options, attachments: attachmentSplit.attachments}, permit})
|
|
523
|
+
|
|
524
|
+
await this.afterUpdate(savedModel, normalizedAttributes, options)
|
|
525
|
+
|
|
526
|
+
return savedModel
|
|
527
|
+
}
|
|
528
|
+
})
|
|
368
529
|
}
|
|
369
530
|
|
|
370
531
|
/**
|
|
371
532
|
* Saves a model and applies nested attributes in one transaction.
|
|
372
|
-
* @param {{filtered: Record<string, ?>, model: import("../database/record/index.js").default, options:
|
|
533
|
+
* @param {{filtered: Record<string, ?>, model: import("../database/record/index.js").default, options: FrontendModelResourceSaveOptions, permit: {attributes: string[], nested: Record<string, ?>}}} args - Save arguments.
|
|
373
534
|
* @returns {Promise<import("../database/record/index.js").default>} - Saved model.
|
|
374
535
|
*/
|
|
375
536
|
async _saveWithNestedAttributes({filtered, model, options, permit}) {
|
|
@@ -400,27 +561,17 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
400
561
|
* @returns {Promise<void>}
|
|
401
562
|
*/
|
|
402
563
|
async _assignWithVirtualSetters(model, attributes) {
|
|
403
|
-
/**
|
|
404
|
-
* Direct attributes.
|
|
405
|
-
@type {Record<string, ?>} */
|
|
564
|
+
/** @type {Record<string, ?>} */
|
|
406
565
|
const directAttributes = {}
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
@type {typeof FrontendModelBaseResource} */ (this.constructor).translatedAttributes || [])
|
|
566
|
+
const ResourceClass = /** @type {typeof FrontendModelBaseResource} */ (this.constructor)
|
|
567
|
+
const translatedSet = new Set(ResourceClass.translatedAttributes || [])
|
|
410
568
|
|
|
411
569
|
for (const [name, value] of Object.entries(attributes)) {
|
|
412
570
|
const resourceSetterName = `set${inflection.camelize(name)}Attribute`
|
|
571
|
+
const resourceSetter = virtualSetterLookup(this)[resourceSetterName]
|
|
413
572
|
|
|
414
|
-
if (typeof
|
|
415
|
-
|
|
416
|
-
@type {Record<string, ?>} */ (/**
|
|
417
|
-
* Narrows the runtime value to the documented type.
|
|
418
|
-
@type {?} */ (this))[resourceSetterName] === "function") {
|
|
419
|
-
await /**
|
|
420
|
-
* Narrows the runtime value to the documented type.
|
|
421
|
-
@type {Record<string, ?>} */ (/**
|
|
422
|
-
* Narrows the runtime value to the documented type.
|
|
423
|
-
@type {?} */ (this))[resourceSetterName](model, value)
|
|
573
|
+
if (typeof resourceSetter === "function") {
|
|
574
|
+
await resourceSetter.call(this, model, value)
|
|
424
575
|
} else if (translatedSet.has(name)) {
|
|
425
576
|
await this._setTranslatedAttributeOnModel(model, name, value)
|
|
426
577
|
} else {
|
|
@@ -516,25 +667,21 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
516
667
|
* Sets a translated attribute on a model via the translations relationship.
|
|
517
668
|
* @param {import("../database/record/index.js").default} model - Model instance.
|
|
518
669
|
* @param {string} name - Attribute name.
|
|
519
|
-
* @param {
|
|
670
|
+
* @param {FrontendModelResourcePayloadValue} value - Attribute value.
|
|
520
671
|
* @returns {Promise<void>}
|
|
521
672
|
*/
|
|
522
673
|
async _setTranslatedAttributeOnModel(model, name, value) {
|
|
523
674
|
const locale = this.context?.configuration?.getLocale?.() || "en"
|
|
524
675
|
const instanceRelationship = model.getRelationshipByName("translations")
|
|
525
676
|
|
|
526
|
-
/**
|
|
527
|
-
* Defines translation.
|
|
528
|
-
@type {import("../database/record/index.js").default | undefined} */
|
|
677
|
+
/** @type {import("../database/record/index.js").default | undefined} */
|
|
529
678
|
let translation
|
|
530
679
|
|
|
531
680
|
if (model.isNewRecord()) {
|
|
532
681
|
const loaded = instanceRelationship.loaded()
|
|
533
682
|
|
|
534
683
|
if (Array.isArray(loaded)) {
|
|
535
|
-
translation = loaded.find((/**
|
|
536
|
-
* Narrows the runtime value to the documented type.
|
|
537
|
-
@type {Record<string, ?>} */ t) => t.locale() === locale)
|
|
684
|
+
translation = loaded.find((t) => /** @type {Record<string, ?>} */ (t).locale() === locale)
|
|
538
685
|
}
|
|
539
686
|
} else {
|
|
540
687
|
if (!instanceRelationship.getPreloaded()) {
|
|
@@ -544,9 +691,7 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
544
691
|
const loaded = instanceRelationship.loaded()
|
|
545
692
|
|
|
546
693
|
if (Array.isArray(loaded)) {
|
|
547
|
-
translation = loaded.find((/**
|
|
548
|
-
* Narrows the runtime value to the documented type.
|
|
549
|
-
@type {Record<string, ?>} */ t) => t.locale() === locale)
|
|
694
|
+
translation = loaded.find((t) => /** @type {Record<string, ?>} */ (t).locale() === locale)
|
|
550
695
|
}
|
|
551
696
|
}
|
|
552
697
|
|
|
@@ -554,9 +699,7 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
554
699
|
translation = instanceRelationship.build({locale})
|
|
555
700
|
}
|
|
556
701
|
|
|
557
|
-
/**
|
|
558
|
-
* Assignments.
|
|
559
|
-
@type {Record<string, ?>} */
|
|
702
|
+
/** @type {Record<string, ?>} */
|
|
560
703
|
const assignments = {}
|
|
561
704
|
|
|
562
705
|
assignments[name] = value
|
|
@@ -569,7 +712,15 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
569
712
|
* @returns {Promise<void>} - No return value.
|
|
570
713
|
*/
|
|
571
714
|
async destroy(model) {
|
|
572
|
-
await
|
|
715
|
+
await this.runMutationTransaction({
|
|
716
|
+
action: "destroy",
|
|
717
|
+
model,
|
|
718
|
+
callback: async () => {
|
|
719
|
+
await this.beforeDestroy(model)
|
|
720
|
+
await model.destroy()
|
|
721
|
+
await this.afterDestroy(model)
|
|
722
|
+
}
|
|
723
|
+
})
|
|
573
724
|
}
|
|
574
725
|
|
|
575
726
|
/**
|
|
@@ -589,10 +740,10 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
589
740
|
* @param {object} args - Nested relationship inputs.
|
|
590
741
|
* @param {import("../database/record/index.js").default} args.parent - Parent model instance.
|
|
591
742
|
* @param {string} args.relationshipName - Relationship receiving nested attributes.
|
|
592
|
-
* @param {
|
|
743
|
+
* @param {FrontendModelResourcePayloadValue} args.rawEntries - Raw nested entries from the request payload.
|
|
593
744
|
* @param {{attributes: string[], nested: Record<string, ?>}} args.childPermit - Parsed child permit.
|
|
594
|
-
* @param {
|
|
595
|
-
* @returns {{ability: import("../authorization/ability.js").default | undefined, childResource: FrontendModelBaseResource, childResourceConfig: FrontendModelResolvedResourceConfiguration, childWritableAttributes: string[], destroyPermitted: boolean, entries: Array<
|
|
745
|
+
* @param {FrontendModelResourceController | null | undefined} args.controller - Controller instance for child resource lookup.
|
|
746
|
+
* @returns {{ability: import("../authorization/ability.js").default | undefined, childResource: FrontendModelBaseResource, childResourceConfig: FrontendModelResolvedResourceConfiguration, childWritableAttributes: string[], destroyPermitted: boolean, entries: Array<FrontendModelResourceNestedEntry>, relationship: import("../database/record/relationships/base.js").default, targetModelClass: typeof import("../database/record/index.js").default}} Nested relationship context.
|
|
596
747
|
*/
|
|
597
748
|
_nestedRelationshipContext({parent, relationshipName, rawEntries, childPermit, controller}) {
|
|
598
749
|
const parentModelClass = parent.getModelClass()
|
|
@@ -631,7 +782,7 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
631
782
|
|
|
632
783
|
const childResource = new childResourceConfig.resourceClass({
|
|
633
784
|
ability: this.ability,
|
|
634
|
-
controller,
|
|
785
|
+
controller: controller || undefined,
|
|
635
786
|
context: this.context || {},
|
|
636
787
|
locals: this.locals || {},
|
|
637
788
|
modelClass: targetModelClass,
|
|
@@ -663,10 +814,10 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
663
814
|
/**
|
|
664
815
|
* Normalizes nested entries for collection and singular relationships.
|
|
665
816
|
* @param {object} args - Nested entries inputs.
|
|
666
|
-
* @param {
|
|
817
|
+
* @param {FrontendModelResourcePayloadValue} args.rawEntries - Raw nested entries value.
|
|
667
818
|
* @param {string} args.relationshipName - Relationship name.
|
|
668
819
|
* @param {string} args.relationshipType - Relationship type.
|
|
669
|
-
* @returns {Array<
|
|
820
|
+
* @returns {Array<FrontendModelResourceNestedEntry>} Normalized nested entry objects.
|
|
670
821
|
*/
|
|
671
822
|
_nestedRelationshipEntries({rawEntries, relationshipName, relationshipType}) {
|
|
672
823
|
if (relationshipType === "hasMany") {
|
|
@@ -677,7 +828,8 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
677
828
|
return rawEntries.map((entry) => {
|
|
678
829
|
if (!isPlainObject(entry)) throw new Error(`nestedAttributes['${relationshipName}'] entries must be objects.`)
|
|
679
830
|
|
|
680
|
-
|
|
831
|
+
// Narrows the plain-object payload to a normalized nested-entry object.
|
|
832
|
+
return /** @type {FrontendModelResourceNestedEntry} */ (entry)
|
|
681
833
|
})
|
|
682
834
|
}
|
|
683
835
|
|
|
@@ -686,14 +838,16 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
686
838
|
return rawEntries.map((entry) => {
|
|
687
839
|
if (!isPlainObject(entry)) throw new Error(`nestedAttributes['${relationshipName}'] entries must be objects.`)
|
|
688
840
|
|
|
689
|
-
|
|
841
|
+
// Narrows the plain-object payload to a normalized nested-entry object.
|
|
842
|
+
return /** @type {FrontendModelResourceNestedEntry} */ (entry)
|
|
690
843
|
})
|
|
691
844
|
}
|
|
692
845
|
if (!isPlainObject(rawEntries)) {
|
|
693
846
|
throw new Error(`Expected object for nestedAttributes['${relationshipName}'] but got: ${typeof rawEntries}`)
|
|
694
847
|
}
|
|
695
848
|
|
|
696
|
-
|
|
849
|
+
// Narrows the plain-object payload to a normalized nested-entry object.
|
|
850
|
+
return [/** @type {FrontendModelResourceNestedEntry} */ (rawEntries)]
|
|
697
851
|
}
|
|
698
852
|
|
|
699
853
|
/**
|
|
@@ -702,25 +856,38 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
702
856
|
* fields (`{name, file, commentsAttributes}`).
|
|
703
857
|
* @param {object} args - Normalization inputs.
|
|
704
858
|
* @param {{attributes: string[], nested: Record<string, ?>}} args.childPermit - Parsed child permit spec.
|
|
705
|
-
* @param {
|
|
859
|
+
* @param {FrontendModelResourceNestedEntry} args.entry - Raw nested entry.
|
|
706
860
|
* @param {string} args.relationshipName - Relationship name for error messages.
|
|
707
861
|
* @param {typeof import("../database/record/index.js").default} args.targetModelClass - Child model class.
|
|
708
|
-
* @returns {
|
|
862
|
+
* @returns {FrontendModelResourceNestedEntry} Normalized nested entry.
|
|
709
863
|
*/
|
|
710
864
|
_normalizeNestedRelationshipEntry({childPermit, entry, relationshipName, targetModelClass}) {
|
|
711
|
-
/** @type {
|
|
865
|
+
/** @type {FrontendModelResourceAttributePayload} */
|
|
712
866
|
const attributes = {}
|
|
713
|
-
/** @type {
|
|
867
|
+
/** @type {FrontendModelResourceAttributePayload} */
|
|
714
868
|
const attachments = {}
|
|
715
|
-
/** @type {
|
|
869
|
+
/** @type {FrontendModelResourceAttributePayload} */
|
|
716
870
|
const nestedAttributes = {}
|
|
717
|
-
/** @type {
|
|
871
|
+
/** @type {FrontendModelResourceNestedEntry} */
|
|
718
872
|
const normalized = {}
|
|
719
873
|
const attachmentDefinitions = targetModelClass.getAttachmentsMap?.() || {}
|
|
720
874
|
|
|
721
875
|
for (const [attributeName, value] of Object.entries(entry)) {
|
|
722
|
-
if (attributeName === "id"
|
|
723
|
-
|
|
876
|
+
if (attributeName === "id") {
|
|
877
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
878
|
+
throw new Error(`nestedAttributes['${relationshipName}'] entry id must be a string or number.`)
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
normalized.id = value
|
|
882
|
+
continue
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
if (attributeName === "_destroy") {
|
|
886
|
+
if (typeof value !== "boolean") {
|
|
887
|
+
throw new Error(`nestedAttributes['${relationshipName}'] entry _destroy must be a boolean.`)
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
normalized._destroy = value
|
|
724
891
|
continue
|
|
725
892
|
}
|
|
726
893
|
|
|
@@ -771,8 +938,8 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
771
938
|
/**
|
|
772
939
|
* Applies belongs-to nested attributes before the parent save so the parent FK can be set.
|
|
773
940
|
* @param {import("../database/record/index.js").default} parent - Parent model instance.
|
|
774
|
-
* @param {
|
|
775
|
-
* @param {
|
|
941
|
+
* @param {FrontendModelResourceAttributePayload} nestedAttributes - Nested-attribute payload keyed by relationship name.
|
|
942
|
+
* @param {FrontendModelResourceController | null | undefined} controller - Controller instance for resource resolution and authorization.
|
|
776
943
|
* @param {{attributes: string[], nested: Record<string, ?>} | null} [parentPermit] - Parsed parent permit spec.
|
|
777
944
|
* @returns {Promise<void>}
|
|
778
945
|
*/
|
|
@@ -802,13 +969,15 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
802
969
|
if (!context.destroyPermitted) {
|
|
803
970
|
throw new Error(`nestedAttributes['${relationshipName}'] entry requested _destroy but "_destroy" is not in the permit for this relationship.`)
|
|
804
971
|
}
|
|
805
|
-
|
|
972
|
+
const id = entry.id
|
|
973
|
+
|
|
974
|
+
if (id == undefined) throw new Error(`nestedAttributes['${relationshipName}'] _destroy entry is missing an id.`)
|
|
806
975
|
|
|
807
976
|
const existing = await this._findNestedRecord({
|
|
808
977
|
ability: context.ability,
|
|
809
978
|
action: "destroy",
|
|
810
979
|
childResourceConfiguration: context.childResourceConfig.resourceConfiguration,
|
|
811
|
-
id
|
|
980
|
+
id,
|
|
812
981
|
relationshipName,
|
|
813
982
|
targetModelClass: context.targetModelClass
|
|
814
983
|
})
|
|
@@ -818,12 +987,13 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
818
987
|
continue
|
|
819
988
|
}
|
|
820
989
|
|
|
821
|
-
const
|
|
990
|
+
const id = entry.id
|
|
991
|
+
const child = id != undefined
|
|
822
992
|
? await this._findNestedRecord({
|
|
823
993
|
ability: context.ability,
|
|
824
994
|
action: "update",
|
|
825
995
|
childResourceConfiguration: context.childResourceConfig.resourceConfiguration,
|
|
826
|
-
id
|
|
996
|
+
id,
|
|
827
997
|
relationshipName,
|
|
828
998
|
targetModelClass: context.targetModelClass
|
|
829
999
|
})
|
|
@@ -837,7 +1007,7 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
837
1007
|
await context.childResource._applyBelongsToNestedAttributes(child, entry.nestedAttributes || {}, controller, childPermit)
|
|
838
1008
|
await child.save()
|
|
839
1009
|
|
|
840
|
-
if (
|
|
1010
|
+
if (id == undefined) {
|
|
841
1011
|
await this._authorizeCreatedChild({
|
|
842
1012
|
ability: context.ability,
|
|
843
1013
|
child,
|
|
@@ -869,8 +1039,8 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
869
1039
|
* (allowDestroy, limit, rejectIf) come from the MODEL's
|
|
870
1040
|
* `acceptedNestedAttributesFor(name)` declaration.
|
|
871
1041
|
* @param {import("../database/record/index.js").default} parent - Parent model instance.
|
|
872
|
-
* @param {
|
|
873
|
-
* @param {
|
|
1042
|
+
* @param {FrontendModelResourceAttributePayload} nestedAttributes - Nested-attribute payload keyed by relationship name.
|
|
1043
|
+
* @param {FrontendModelResourceController | null | undefined} controller - Controller instance for resource resolution and authorization.
|
|
874
1044
|
* @param {{attributes: string[], nested: Record<string, ?>} | null} [parentPermit] - Parsed parent permit spec.
|
|
875
1045
|
* @returns {Promise<void>}
|
|
876
1046
|
*/
|
|
@@ -922,11 +1092,17 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
922
1092
|
}
|
|
923
1093
|
|
|
924
1094
|
for (const entry of destroyEntries) {
|
|
1095
|
+
const id = entry.id
|
|
1096
|
+
|
|
1097
|
+
if (id == undefined) {
|
|
1098
|
+
throw new Error(`nestedAttributes['${relationshipName}'] _destroy entry is missing an id.`)
|
|
1099
|
+
}
|
|
1100
|
+
|
|
925
1101
|
const existing = await this._findScopedChild({
|
|
926
1102
|
ability: context.ability,
|
|
927
1103
|
action: "destroy",
|
|
928
1104
|
childResourceConfiguration: context.childResourceConfig.resourceConfiguration,
|
|
929
|
-
id
|
|
1105
|
+
id,
|
|
930
1106
|
parent,
|
|
931
1107
|
parentLinkAttributes,
|
|
932
1108
|
relationshipName,
|
|
@@ -937,11 +1113,17 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
937
1113
|
}
|
|
938
1114
|
|
|
939
1115
|
for (const entry of updateEntries) {
|
|
1116
|
+
const id = entry.id
|
|
1117
|
+
|
|
1118
|
+
if (id == undefined) {
|
|
1119
|
+
throw new Error(`nestedAttributes['${relationshipName}'] update entry is missing an id.`)
|
|
1120
|
+
}
|
|
1121
|
+
|
|
940
1122
|
const existing = await this._findScopedChild({
|
|
941
1123
|
ability: context.ability,
|
|
942
1124
|
action: "update",
|
|
943
1125
|
childResourceConfiguration: context.childResourceConfig.resourceConfiguration,
|
|
944
|
-
id
|
|
1126
|
+
id,
|
|
945
1127
|
parent,
|
|
946
1128
|
parentLinkAttributes,
|
|
947
1129
|
relationshipName,
|
|
@@ -1098,9 +1280,7 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
1098
1280
|
throw new Error(`Nested child resource must define an 'abilities' object to authorize nested ${action}.`)
|
|
1099
1281
|
}
|
|
1100
1282
|
|
|
1101
|
-
const abilityAction = /**
|
|
1102
|
-
* Narrows the runtime value to the documented type.
|
|
1103
|
-
@type {Record<string, string>} */ (abilities)[action]
|
|
1283
|
+
const abilityAction = /** @type {Record<string, string>} */ (abilities)[action]
|
|
1104
1284
|
|
|
1105
1285
|
if (typeof abilityAction !== "string" || abilityAction.length < 1) {
|
|
1106
1286
|
throw new Error(`Nested child resource must define abilities.${action}.`)
|
|
@@ -1130,12 +1310,8 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
1130
1310
|
const primaryKey = targetModelClass.primaryKey()
|
|
1131
1311
|
const lookup = {[primaryKey]: id, ...parentLinkAttributes}
|
|
1132
1312
|
const query = ability
|
|
1133
|
-
?
|
|
1134
|
-
|
|
1135
|
-
@type {?} */ (targetModelClass).accessibleFor(this._resolveChildAbilityAction(childResourceConfiguration, action), ability)
|
|
1136
|
-
: /**
|
|
1137
|
-
* Narrows the runtime value to the documented type.
|
|
1138
|
-
@type {?} */ (targetModelClass).where({})
|
|
1313
|
+
? targetModelClass.accessibleFor(this._resolveChildAbilityAction(childResourceConfiguration, action), ability)
|
|
1314
|
+
: targetModelClass.where({})
|
|
1139
1315
|
|
|
1140
1316
|
const existing = await query.findBy(lookup)
|
|
1141
1317
|
|
|
@@ -1163,9 +1339,7 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
1163
1339
|
|
|
1164
1340
|
const abilityAction = this._resolveChildAbilityAction(childResourceConfiguration, "create")
|
|
1165
1341
|
const primaryKey = targetModelClass.primaryKey()
|
|
1166
|
-
const authorizedIds = await
|
|
1167
|
-
* Narrows the runtime value to the documented type.
|
|
1168
|
-
@type {?} */ (targetModelClass)
|
|
1342
|
+
const authorizedIds = await targetModelClass
|
|
1169
1343
|
.accessibleFor(abilityAction, ability)
|
|
1170
1344
|
.where({[primaryKey]: child.readAttribute(primaryKey)})
|
|
1171
1345
|
.pluck(primaryKey)
|
|
@@ -1189,12 +1363,8 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
1189
1363
|
if (relationshipNames.length === 0) return
|
|
1190
1364
|
|
|
1191
1365
|
for (const relationshipName of relationshipNames) {
|
|
1192
|
-
if (typeof
|
|
1193
|
-
|
|
1194
|
-
@type {?} */ (model).loadRelationship === "function") {
|
|
1195
|
-
await /**
|
|
1196
|
-
* Narrows the runtime value to the documented type.
|
|
1197
|
-
@type {?} */ (model).loadRelationship(relationshipName)
|
|
1366
|
+
if (typeof model.loadRelationship === "function") {
|
|
1367
|
+
await model.loadRelationship(relationshipName)
|
|
1198
1368
|
}
|
|
1199
1369
|
}
|
|
1200
1370
|
}
|
|
@@ -1220,13 +1390,9 @@ export default class FrontendModelBaseResource extends AuthorizationBaseResource
|
|
|
1220
1390
|
* @returns {{attributes: string[], nested: Record<string, {attributes: string[], nested: Record<string, ?>}>}} - Parsed structure.
|
|
1221
1391
|
*/
|
|
1222
1392
|
function parsePermittedParams(permitSpec) {
|
|
1223
|
-
/**
|
|
1224
|
-
* Attributes.
|
|
1225
|
-
@type {string[]} */
|
|
1393
|
+
/** @type {string[]} */
|
|
1226
1394
|
const attributes = []
|
|
1227
|
-
/**
|
|
1228
|
-
* Nested.
|
|
1229
|
-
@type {Record<string, {attributes: string[], nested: Record<string, ?>}>} */
|
|
1395
|
+
/** @type {Record<string, {attributes: string[], nested: Record<string, ?>}>} */
|
|
1230
1396
|
const nested = {}
|
|
1231
1397
|
|
|
1232
1398
|
if (!Array.isArray(permitSpec)) return {attributes, nested}
|
|
@@ -1258,6 +1424,15 @@ function parsePermittedParams(permitSpec) {
|
|
|
1258
1424
|
return {attributes, nested}
|
|
1259
1425
|
}
|
|
1260
1426
|
|
|
1427
|
+
/**
|
|
1428
|
+
* Narrows a resource to its dynamic virtual setter lookup surface.
|
|
1429
|
+
* @param {FrontendModelBaseResource} resource - Resource instance.
|
|
1430
|
+
* @returns {Record<string, FrontendModelResourceVirtualSetter>} Dynamic virtual setter lookup.
|
|
1431
|
+
*/
|
|
1432
|
+
function virtualSetterLookup(resource) {
|
|
1433
|
+
return /** @type {Record<string, FrontendModelResourceVirtualSetter>} */ (/** @type {unknown} */ (resource))
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1261
1436
|
/**
|
|
1262
1437
|
* Runs filter writable frontend model attributes.
|
|
1263
1438
|
* @param {Record<string, ?>} receiver - Model instance or prototype.
|
|
@@ -1266,28 +1441,32 @@ function parsePermittedParams(permitSpec) {
|
|
|
1266
1441
|
* @param {string[] | null} [permittedAttributeNames] - Optional explicit permit list. `null` falls back to setter-existence checks only.
|
|
1267
1442
|
* @returns {Record<string, ?>} - Writable attributes only.
|
|
1268
1443
|
*/
|
|
1269
|
-
function filterWritableFrontendModelAttributes(
|
|
1270
|
-
|
|
1271
|
-
|
|
1444
|
+
function filterWritableFrontendModelAttributes(
|
|
1445
|
+
receiver,
|
|
1446
|
+
attributes,
|
|
1447
|
+
resource = /** @type {FrontendModelBaseResource | null} */ (null),
|
|
1448
|
+
permittedAttributeNames = null
|
|
1449
|
+
) {
|
|
1272
1450
|
// Frontend-model writes should fail fast when callers submit read-only or unknown attrs.
|
|
1273
1451
|
// Silent drops hide contract mistakes in generated models and app-side wrapper code.
|
|
1274
|
-
/**
|
|
1275
|
-
* Writable attributes.
|
|
1276
|
-
@type {Record<string, ?>} */
|
|
1452
|
+
/** @type {Record<string, ?>} */
|
|
1277
1453
|
const writableAttributes = {}
|
|
1278
|
-
/**
|
|
1279
|
-
* Invalid attributes.
|
|
1280
|
-
@type {string[]} */
|
|
1454
|
+
/** @type {string[]} */
|
|
1281
1455
|
const invalidAttributes = []
|
|
1282
|
-
/**
|
|
1283
|
-
* Not permitted attributes.
|
|
1284
|
-
@type {string[]} */
|
|
1456
|
+
/** @type {string[]} */
|
|
1285
1457
|
const notPermittedAttributes = []
|
|
1286
1458
|
|
|
1287
1459
|
const permitSet = Array.isArray(permittedAttributeNames) ? new Set(permittedAttributeNames) : null
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1460
|
+
/** @type {string[]} */
|
|
1461
|
+
let translatedAttributes = []
|
|
1462
|
+
|
|
1463
|
+
if (resource) {
|
|
1464
|
+
const ResourceClass = /** @type {typeof FrontendModelBaseResource} */ (resource.constructor)
|
|
1465
|
+
|
|
1466
|
+
translatedAttributes = ResourceClass.translatedAttributes || []
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
const translatedSet = new Set(translatedAttributes)
|
|
1291
1470
|
|
|
1292
1471
|
for (const [attributeName, value] of Object.entries(attributes)) {
|
|
1293
1472
|
if (permitSet && !permitSet.has(attributeName)) {
|
|
@@ -1295,19 +1474,16 @@ function filterWritableFrontendModelAttributes(receiver, attributes, resource =
|
|
|
1295
1474
|
continue
|
|
1296
1475
|
}
|
|
1297
1476
|
|
|
1298
|
-
const modelClass = /**
|
|
1477
|
+
const modelClass = /** @type {WritableAttributeReceiverClass} */ (receiver.constructor)
|
|
1299
1478
|
const resolvedAttributeName = (modelClass && typeof modelClass.resolveAttributeName === "function" && modelClass.resolveAttributeName(attributeName)) || attributeName
|
|
1300
1479
|
const requestedSetterName = `set${inflection.camelize(resolvedAttributeName)}`
|
|
1301
1480
|
const setterName = (modelClass && typeof modelClass.findMemberNameInsensitive === "function" && modelClass.findMemberNameInsensitive(receiver, requestedSetterName)) || requestedSetterName
|
|
1302
1481
|
const resourceSetterName = `set${inflection.camelize(attributeName)}Attribute`
|
|
1482
|
+
const resourceSetter = resource ? virtualSetterLookup(resource)[resourceSetterName] : undefined
|
|
1303
1483
|
|
|
1304
1484
|
if (setterName in receiver) {
|
|
1305
1485
|
writableAttributes[attributeName] = value
|
|
1306
|
-
} else if (
|
|
1307
|
-
* Narrows the runtime value to the documented type.
|
|
1308
|
-
@type {Record<string, ?>} */ (/**
|
|
1309
|
-
* Narrows the runtime value to the documented type.
|
|
1310
|
-
@type {?} */ (resource))[resourceSetterName] === "function") {
|
|
1486
|
+
} else if (typeof resourceSetter === "function") {
|
|
1311
1487
|
writableAttributes[attributeName] = value
|
|
1312
1488
|
} else if (translatedSet.has(attributeName)) {
|
|
1313
1489
|
writableAttributes[attributeName] = value
|