directus 9.22.4 → 9.23.3
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/dist/app.js +19 -14
- package/dist/auth/auth.d.ts +3 -3
- package/dist/auth/auth.js +2 -0
- package/dist/auth/drivers/ldap.d.ts +2 -2
- package/dist/auth/drivers/ldap.js +47 -36
- package/dist/auth/drivers/local.d.ts +1 -1
- package/dist/auth/drivers/local.js +13 -10
- package/dist/auth/drivers/oauth2.d.ts +1 -1
- package/dist/auth/drivers/oauth2.js +22 -15
- package/dist/auth/drivers/openid.d.ts +1 -1
- package/dist/auth/drivers/openid.js +23 -16
- package/dist/auth/drivers/saml.d.ts +1 -1
- package/dist/auth/drivers/saml.js +10 -7
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +4 -4
- package/dist/cache.d.ts +9 -1
- package/dist/cache.js +59 -16
- package/dist/cli/commands/bootstrap/index.js +2 -2
- package/dist/cli/commands/init/index.js +3 -3
- package/dist/cli/commands/schema/apply.js +21 -20
- package/dist/cli/commands/schema/snapshot.js +2 -2
- package/dist/cli/utils/create-db-connection.d.ts +2 -1
- package/dist/cli/utils/create-db-connection.js +2 -1
- package/dist/cli/utils/create-env/env-stub.liquid +1 -1
- package/dist/cli/utils/create-env/index.d.ts +2 -2
- package/dist/cli/utils/drivers.d.ts +3 -9
- package/dist/constants.d.ts +3 -9
- package/dist/constants.js +5 -10
- package/dist/controllers/activity.js +1 -2
- package/dist/controllers/assets.js +17 -12
- package/dist/controllers/auth.js +29 -15
- package/dist/controllers/dashboards.js +5 -2
- package/dist/controllers/extensions.js +7 -7
- package/dist/controllers/fields.js +4 -4
- package/dist/controllers/files.js +11 -6
- package/dist/controllers/flows.js +5 -2
- package/dist/controllers/folders.js +5 -2
- package/dist/controllers/graphql.js +6 -0
- package/dist/controllers/items.js +5 -2
- package/dist/controllers/not-found.d.ts +1 -1
- package/dist/controllers/not-found.js +1 -2
- package/dist/controllers/notifications.js +5 -2
- package/dist/controllers/operations.js +5 -2
- package/dist/controllers/panels.js +5 -2
- package/dist/controllers/permissions.js +5 -2
- package/dist/controllers/presets.js +5 -2
- package/dist/controllers/roles.js +5 -2
- package/dist/controllers/schema.d.ts +2 -0
- package/dist/controllers/schema.js +98 -0
- package/dist/controllers/shares.js +8 -5
- package/dist/controllers/users.js +16 -20
- package/dist/controllers/utils.js +6 -11
- package/dist/controllers/webhooks.js +5 -2
- package/dist/database/helpers/fn/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/mssql.js +10 -11
- package/dist/database/helpers/fn/dialects/mysql.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/mysql.js +2 -3
- package/dist/database/helpers/fn/dialects/oracle.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/oracle.js +10 -11
- package/dist/database/helpers/fn/dialects/postgres.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/postgres.js +10 -11
- package/dist/database/helpers/fn/dialects/sqlite.d.ts +1 -1
- package/dist/database/helpers/fn/dialects/sqlite.js +10 -11
- package/dist/database/helpers/fn/types.d.ts +5 -5
- package/dist/database/helpers/fn/types.js +5 -4
- package/dist/database/helpers/geometry/dialects/mssql.d.ts +3 -3
- package/dist/database/helpers/geometry/dialects/mysql.d.ts +1 -1
- package/dist/database/helpers/geometry/dialects/oracle.d.ts +3 -3
- package/dist/database/helpers/geometry/dialects/postgres.d.ts +3 -3
- package/dist/database/helpers/geometry/dialects/postgres.js +1 -2
- package/dist/database/helpers/geometry/dialects/redshift.d.ts +2 -2
- package/dist/database/helpers/geometry/dialects/sqlite.d.ts +1 -1
- package/dist/database/helpers/geometry/types.d.ts +2 -2
- package/dist/database/helpers/geometry/types.js +1 -2
- package/dist/database/helpers/index.d.ts +5 -5
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +2 -2
- package/dist/database/helpers/schema/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/schema/dialects/mysql.d.ts +1 -1
- package/dist/database/helpers/schema/dialects/mysql.js +1 -2
- package/dist/database/helpers/schema/dialects/oracle.d.ts +5 -2
- package/dist/database/helpers/schema/dialects/oracle.js +23 -0
- package/dist/database/helpers/schema/types.d.ts +9 -7
- package/dist/database/helpers/schema/types.js +7 -1
- package/dist/database/helpers/types.d.ts +1 -1
- package/dist/database/helpers/types.js +1 -0
- package/dist/database/index.d.ts +2 -1
- package/dist/database/index.js +8 -8
- package/dist/database/migrations/20201028A-remove-collection-foreign-keys.d.ts +1 -1
- package/dist/database/migrations/20201029A-remove-system-relations.d.ts +1 -1
- package/dist/database/migrations/20201029B-remove-system-collections.d.ts +1 -1
- package/dist/database/migrations/20201029C-remove-system-fields.d.ts +1 -1
- package/dist/database/migrations/20201105A-add-cascade-system-relations.d.ts +1 -1
- package/dist/database/migrations/20201105B-change-webhook-url-type.d.ts +1 -1
- package/dist/database/migrations/20210225A-add-relations-sort-field.d.ts +1 -1
- package/dist/database/migrations/20210225A-add-relations-sort-field.js +1 -2
- package/dist/database/migrations/20210304A-remove-locked-fields.d.ts +1 -1
- package/dist/database/migrations/20210312A-webhooks-collections-text.d.ts +1 -1
- package/dist/database/migrations/20210331A-add-refresh-interval.d.ts +1 -1
- package/dist/database/migrations/20210415A-make-filesize-nullable.d.ts +1 -1
- package/dist/database/migrations/20210416A-add-collections-accountability.d.ts +1 -1
- package/dist/database/migrations/20210422A-remove-files-interface.d.ts +1 -1
- package/dist/database/migrations/20210506A-rename-interfaces.d.ts +1 -1
- package/dist/database/migrations/20210510A-restructure-relations.d.ts +1 -1
- package/dist/database/migrations/20210518A-add-foreign-key-constraints.d.ts +1 -1
- package/dist/database/migrations/20210518A-add-foreign-key-constraints.js +1 -1
- package/dist/database/migrations/20210519A-add-system-fk-triggers.d.ts +1 -1
- package/dist/database/migrations/20210519A-add-system-fk-triggers.js +2 -2
- package/dist/database/migrations/20210521A-add-collections-icon-color.d.ts +1 -1
- package/dist/database/migrations/20210525A-add-insights.d.ts +1 -1
- package/dist/database/migrations/20210608A-add-deep-clone-config.d.ts +1 -1
- package/dist/database/migrations/20210626A-change-filesize-bigint.d.ts +1 -1
- package/dist/database/migrations/20210716A-add-conditions-to-fields.d.ts +1 -1
- package/dist/database/migrations/20210721A-add-default-folder.d.ts +1 -1
- package/dist/database/migrations/20210802A-replace-groups.d.ts +1 -1
- package/dist/database/migrations/20210803A-add-required-to-fields.d.ts +1 -1
- package/dist/database/migrations/20210805A-update-groups.d.ts +1 -1
- package/dist/database/migrations/20210805B-change-image-metadata-structure.d.ts +1 -1
- package/dist/database/migrations/20210811A-add-geometry-config.d.ts +1 -1
- package/dist/database/migrations/20210831A-remove-limit-column.d.ts +1 -1
- package/dist/database/migrations/20210903A-add-auth-provider.d.ts +1 -1
- package/dist/database/migrations/20210907A-webhooks-collections-not-null.d.ts +1 -1
- package/dist/database/migrations/20210910A-move-module-setup.d.ts +1 -1
- package/dist/database/migrations/20210920A-webhooks-url-not-null.d.ts +1 -1
- package/dist/database/migrations/20210924A-add-collection-organization.d.ts +1 -1
- package/dist/database/migrations/20210927A-replace-fields-group.d.ts +1 -1
- package/dist/database/migrations/20210927B-replace-m2m-interface.d.ts +1 -1
- package/dist/database/migrations/20210929A-rename-login-action.d.ts +1 -1
- package/dist/database/migrations/20211007A-update-presets.d.ts +1 -1
- package/dist/database/migrations/20211007A-update-presets.js +7 -9
- package/dist/database/migrations/20211009A-add-auth-data.d.ts +1 -1
- package/dist/database/migrations/20211016A-add-webhook-headers.d.ts +1 -1
- package/dist/database/migrations/20211103A-set-unique-to-user-token.d.ts +1 -1
- package/dist/database/migrations/20211103B-update-special-geometry.d.ts +1 -1
- package/dist/database/migrations/20211104A-remove-collections-listing.d.ts +1 -1
- package/dist/database/migrations/20211118A-add-notifications.d.ts +1 -1
- package/dist/database/migrations/20211211A-add-shares.d.ts +1 -1
- package/dist/database/migrations/20211230A-add-project-descriptor.d.ts +1 -1
- package/dist/database/migrations/20220303A-remove-default-project-color.d.ts +1 -1
- package/dist/database/migrations/20220308A-add-bookmark-icon-and-color.d.ts +1 -1
- package/dist/database/migrations/20220314A-add-translation-strings.d.ts +1 -1
- package/dist/database/migrations/20220322A-rename-field-typecast-flags.d.ts +1 -1
- package/dist/database/migrations/20220323A-add-field-validation.d.ts +1 -1
- package/dist/database/migrations/20220325A-fix-typecast-flags.d.ts +1 -1
- package/dist/database/migrations/20220325B-add-default-language.d.ts +1 -1
- package/dist/database/migrations/20220402A-remove-default-value-panel-icon.d.ts +1 -1
- package/dist/database/migrations/20220429A-add-flows.d.ts +1 -1
- package/dist/database/migrations/20220429B-add-color-to-insights-icon.d.ts +1 -1
- package/dist/database/migrations/20220429C-drop-non-null-from-ip-of-activity.d.ts +1 -1
- package/dist/database/migrations/20220429D-drop-non-null-from-sender-of-notifications.d.ts +1 -1
- package/dist/database/migrations/20220614A-rename-hook-trigger-to-event.d.ts +1 -1
- package/dist/database/migrations/20220801A-update-notifications-timestamp-column.d.ts +1 -1
- package/dist/database/migrations/20220802A-add-custom-aspect-ratios.d.ts +1 -1
- package/dist/database/migrations/20220826A-add-origin-to-accountability.d.ts +1 -1
- package/dist/database/migrations/run.d.ts +1 -1
- package/dist/database/run-ast.d.ts +3 -3
- package/dist/database/run-ast.js +19 -28
- package/dist/database/seeds/run.d.ts +1 -1
- package/dist/database/seeds/run.js +1 -2
- package/dist/database/system-data/app-access-permissions/index.d.ts +1 -1
- package/dist/database/system-data/collections/index.d.ts +1 -1
- package/dist/database/system-data/fields/collections.yaml +2 -0
- package/dist/database/system-data/fields/index.d.ts +1 -1
- package/dist/database/system-data/fields/index.js +1 -2
- package/dist/database/system-data/fields/settings.yaml +4 -0
- package/dist/database/system-data/relations/index.d.ts +1 -1
- package/dist/emitter.d.ts +1 -1
- package/dist/emitter.js +3 -0
- package/dist/env.js +19 -4
- package/dist/exceptions/database/dialects/mssql.d.ts +1 -1
- package/dist/exceptions/database/dialects/mssql.js +5 -6
- package/dist/exceptions/database/dialects/mysql.d.ts +1 -1
- package/dist/exceptions/database/dialects/mysql.js +19 -25
- package/dist/exceptions/database/dialects/oracle.d.ts +1 -1
- package/dist/exceptions/database/dialects/postgres.d.ts +1 -1
- package/dist/exceptions/database/dialects/sqlite.d.ts +1 -1
- package/dist/exceptions/database/translate.d.ts +1 -1
- package/dist/exceptions/database/value-out-of-range.js +1 -1
- package/dist/exceptions/range-not-satisfiable.js +2 -3
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +34 -24
- package/dist/flows.js +56 -30
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +19 -3
- package/dist/messenger.js +8 -6
- package/dist/middleware/authenticate.d.ts +1 -1
- package/dist/middleware/authenticate.js +12 -5
- package/dist/middleware/cache.d.ts +1 -1
- package/dist/middleware/cache.js +7 -7
- package/dist/middleware/check-ip.d.ts +1 -1
- package/dist/middleware/check-ip.js +1 -1
- package/dist/middleware/collection-exists.d.ts +1 -1
- package/dist/middleware/collection-exists.js +2 -2
- package/dist/middleware/cors.d.ts +1 -1
- package/dist/middleware/error-handler.d.ts +1 -1
- package/dist/middleware/error-handler.js +9 -10
- package/dist/middleware/extract-token.d.ts +1 -1
- package/dist/middleware/get-permissions.d.ts +1 -1
- package/dist/middleware/graphql.d.ts +1 -1
- package/dist/middleware/graphql.js +3 -3
- package/dist/middleware/rate-limiter-global.d.ts +5 -0
- package/dist/middleware/rate-limiter-global.js +48 -0
- package/dist/middleware/{rate-limiter.d.ts → rate-limiter-ip.d.ts} +2 -2
- package/dist/middleware/{rate-limiter.js → rate-limiter-ip.js} +3 -3
- package/dist/middleware/respond.d.ts +1 -1
- package/dist/middleware/respond.js +18 -14
- package/dist/middleware/sanitize-query.d.ts +1 -1
- package/dist/middleware/schema.d.ts +1 -1
- package/dist/middleware/use-collection.d.ts +1 -1
- package/dist/operations/condition/index.d.ts +1 -1
- package/dist/operations/exec/index.js +14 -3
- package/dist/operations/item-create/index.js +1 -2
- package/dist/operations/item-delete/index.d.ts +1 -1
- package/dist/operations/item-read/index.d.ts +1 -1
- package/dist/operations/item-update/index.d.ts +1 -1
- package/dist/operations/item-update/index.js +1 -2
- package/dist/operations/notification/index.js +1 -2
- package/dist/operations/request/index.js +21 -20
- package/dist/operations/trigger/index.d.ts +2 -0
- package/dist/operations/trigger/index.js +27 -11
- package/dist/rate-limiter.d.ts +1 -1
- package/dist/rate-limiter.js +8 -8
- package/dist/request/index.d.ts +5 -0
- package/dist/request/index.js +18 -0
- package/dist/request/index.test.d.ts +1 -0
- package/dist/request/request-interceptor.d.ts +2 -0
- package/dist/request/request-interceptor.js +33 -0
- package/dist/request/request-interceptor.test.d.ts +1 -0
- package/dist/request/response-interceptor.d.ts +2 -0
- package/dist/request/response-interceptor.js +9 -0
- package/dist/request/response-interceptor.test.d.ts +1 -0
- package/dist/request/validate-ip.d.ts +1 -0
- package/dist/request/validate-ip.js +27 -0
- package/dist/request/validate-ip.test.d.ts +1 -0
- package/dist/server.js +8 -9
- package/dist/services/activity.d.ts +1 -1
- package/dist/services/activity.js +7 -6
- package/dist/services/assets.d.ts +3 -3
- package/dist/services/assets.js +33 -26
- package/dist/services/authentication.d.ts +2 -2
- package/dist/services/authentication.js +18 -15
- package/dist/services/authorization.d.ts +3 -3
- package/dist/services/authorization.js +27 -31
- package/dist/services/collections.d.ts +5 -5
- package/dist/services/collections.js +52 -48
- package/dist/services/dashboards.d.ts +1 -1
- package/dist/services/fields.d.ts +5 -5
- package/dist/services/fields.js +49 -48
- package/dist/services/files.d.ts +1 -2
- package/dist/services/files.js +70 -108
- package/dist/services/flows.d.ts +2 -2
- package/dist/services/folders.d.ts +1 -1
- package/dist/services/graphql/index.d.ts +4 -4
- package/dist/services/graphql/index.js +181 -170
- package/dist/services/graphql/utils/add-path-to-validation-error.js +1 -2
- package/dist/services/graphql/utils/process-error.d.ts +2 -2
- package/dist/services/graphql/utils/process-error.js +29 -9
- package/dist/services/import-export.d.ts +7 -5
- package/dist/services/import-export.js +41 -24
- package/dist/services/import-export.test.d.ts +1 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/items.d.ts +3 -3
- package/dist/services/items.js +67 -42
- package/dist/services/mail/index.d.ts +4 -4
- package/dist/services/mail/index.js +9 -5
- package/dist/services/meta.d.ts +3 -3
- package/dist/services/meta.js +10 -9
- package/dist/services/notifications.d.ts +3 -3
- package/dist/services/notifications.js +7 -6
- package/dist/services/operations.d.ts +2 -2
- package/dist/services/panels.d.ts +1 -1
- package/dist/services/payload.d.ts +3 -3
- package/dist/services/payload.js +124 -122
- package/dist/services/permissions.d.ts +3 -3
- package/dist/services/permissions.js +11 -11
- package/dist/services/presets.d.ts +1 -1
- package/dist/services/relations.d.ts +6 -6
- package/dist/services/relations.js +47 -43
- package/dist/services/revisions.d.ts +1 -1
- package/dist/services/roles.d.ts +2 -2
- package/dist/services/roles.js +34 -13
- package/dist/services/schema.d.ts +15 -0
- package/dist/services/schema.js +56 -0
- package/dist/services/schema.test.d.ts +1 -0
- package/dist/services/server.d.ts +3 -3
- package/dist/services/server.js +69 -13
- package/dist/services/settings.d.ts +1 -1
- package/dist/services/shares.d.ts +2 -2
- package/dist/services/shares.js +14 -15
- package/dist/services/specifications.d.ts +4 -4
- package/dist/services/specifications.js +132 -116
- package/dist/services/tfa.d.ts +2 -2
- package/dist/services/tfa.js +7 -5
- package/dist/services/users.d.ts +3 -3
- package/dist/services/users.js +89 -62
- package/dist/services/utils.d.ts +3 -3
- package/dist/services/utils.js +10 -8
- package/dist/services/webhooks.d.ts +2 -2
- package/dist/services/webhooks.js +2 -1
- package/dist/types/assets.d.ts +2 -2
- package/dist/types/ast.d.ts +1 -1
- package/dist/types/auth.d.ts +2 -2
- package/dist/types/collection.d.ts +2 -2
- package/dist/types/database.d.ts +3 -0
- package/dist/types/database.js +4 -0
- package/dist/types/events.d.ts +2 -2
- package/dist/types/graphql.d.ts +2 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/items.d.ts +7 -2
- package/dist/types/services.d.ts +5 -5
- package/dist/types/snapshot.d.ts +25 -3
- package/dist/types/snapshot.js +14 -0
- package/dist/utils/apply-diff.d.ts +9 -0
- package/dist/utils/apply-diff.js +256 -0
- package/dist/utils/apply-diff.test.d.ts +1 -0
- package/dist/utils/apply-query.d.ts +3 -3
- package/dist/utils/apply-query.js +15 -16
- package/dist/utils/apply-snapshot.d.ts +3 -5
- package/dist/utils/apply-snapshot.js +9 -240
- package/dist/utils/construct-flow-tree.d.ts +1 -1
- package/dist/utils/construct-flow-tree.js +2 -2
- package/dist/utils/filter-items.d.ts +1 -1
- package/dist/utils/get-accountability-for-role.d.ts +2 -2
- package/dist/utils/get-accountability-for-role.js +1 -1
- package/dist/utils/get-ast-from-query.d.ts +3 -3
- package/dist/utils/get-ast-from-query.js +22 -28
- package/dist/utils/get-cache-headers.d.ts +4 -2
- package/dist/utils/get-cache-headers.js +21 -21
- package/dist/utils/get-cache-headers.test.d.ts +1 -0
- package/dist/utils/get-cache-key.d.ts +1 -1
- package/dist/utils/get-cache-key.js +2 -3
- package/dist/utils/get-collection-from-alias.d.ts +1 -1
- package/dist/utils/get-column-path.d.ts +2 -2
- package/dist/utils/get-column-path.js +3 -4
- package/dist/utils/get-column.d.ts +4 -4
- package/dist/utils/get-column.js +4 -5
- package/dist/utils/get-default-value.d.ts +2 -2
- package/dist/utils/get-default-value.js +1 -2
- package/dist/utils/get-graphql-query-and-variables.d.ts +1 -1
- package/dist/utils/get-graphql-query-and-variables.js +1 -2
- package/dist/utils/get-graphql-type.d.ts +2 -2
- package/dist/utils/get-graphql-type.js +1 -1
- package/dist/utils/get-ip-from-req.d.ts +1 -1
- package/dist/utils/get-local-type.d.ts +1 -1
- package/dist/utils/get-local-type.js +3 -3
- package/dist/utils/get-milliseconds.d.ts +4 -0
- package/dist/utils/get-milliseconds.js +14 -0
- package/dist/utils/get-milliseconds.test.d.ts +1 -0
- package/dist/utils/get-permissions.d.ts +1 -1
- package/dist/utils/get-permissions.js +1 -1
- package/dist/utils/get-relation-info.d.ts +1 -1
- package/dist/utils/get-relation-info.js +3 -5
- package/dist/utils/get-relation-type.d.ts +1 -1
- package/dist/utils/get-relation-type.js +3 -4
- package/dist/utils/get-schema.d.ts +2 -2
- package/dist/utils/get-schema.js +19 -21
- package/dist/utils/get-snapshot-diff.js +10 -7
- package/dist/utils/get-snapshot.d.ts +3 -3
- package/dist/utils/get-snapshot.js +35 -14
- package/dist/utils/get-versioned-hash.d.ts +1 -0
- package/dist/utils/get-versioned-hash.js +12 -0
- package/dist/utils/get-versioned-hash.test.d.ts +1 -0
- package/dist/utils/is-directus-jwt.js +1 -1
- package/dist/utils/job-queue.js +2 -0
- package/dist/utils/jwt.d.ts +1 -1
- package/dist/utils/map-values-deep.d.ts +1 -0
- package/dist/utils/map-values-deep.js +29 -0
- package/dist/utils/map-values-deep.test.d.ts +1 -0
- package/dist/utils/merge-permissions-for-share.d.ts +1 -1
- package/dist/utils/merge-permissions-for-share.js +3 -4
- package/dist/utils/merge-permissions.d.ts +3 -3
- package/dist/utils/redact-header-cookies.d.ts +1 -0
- package/dist/utils/redact-header-cookies.js +11 -0
- package/dist/utils/redact-header-cookies.test.d.ts +1 -0
- package/dist/utils/reduce-schema.d.ts +1 -1
- package/dist/utils/reduce-schema.js +12 -12
- package/dist/utils/sanitize-query.d.ts +1 -1
- package/dist/utils/sanitize-query.js +1 -1
- package/dist/utils/sanitize-schema.d.ts +30 -0
- package/dist/utils/sanitize-schema.js +80 -0
- package/dist/utils/sanitize-schema.test.d.ts +1 -0
- package/dist/utils/should-skip-cache.d.ts +7 -0
- package/dist/utils/should-skip-cache.js +21 -0
- package/dist/utils/should-skip-cache.test.d.ts +1 -0
- package/dist/utils/track.js +3 -3
- package/dist/utils/transformations.d.ts +1 -1
- package/dist/utils/transformations.js +2 -4
- package/dist/utils/url.js +9 -8
- package/dist/utils/url.test.d.ts +1 -0
- package/dist/utils/user-name.d.ts +1 -1
- package/dist/utils/validate-diff.d.ts +7 -0
- package/dist/utils/validate-diff.js +113 -0
- package/dist/utils/validate-diff.test.d.ts +1 -0
- package/dist/utils/validate-keys.d.ts +2 -2
- package/dist/utils/validate-keys.js +1 -1
- package/dist/utils/validate-query.d.ts +1 -1
- package/dist/utils/validate-query.js +3 -3
- package/dist/utils/validate-query.test.d.ts +1 -0
- package/dist/utils/validate-snapshot.d.ts +5 -0
- package/dist/utils/validate-snapshot.js +71 -0
- package/dist/utils/validate-snapshot.test.d.ts +1 -0
- package/dist/webhooks.js +4 -3
- package/package.json +62 -62
|
@@ -3,251 +3,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const
|
|
6
|
+
exports.applySnapshot = void 0;
|
|
7
|
+
const cache_1 = require("../cache");
|
|
8
8
|
const database_1 = __importDefault(require("../database"));
|
|
9
|
-
const
|
|
10
|
-
const services_1 = require("../services");
|
|
9
|
+
const apply_diff_1 = require("./apply-diff");
|
|
11
10
|
const get_schema_1 = require("./get-schema");
|
|
12
11
|
const get_snapshot_1 = require("./get-snapshot");
|
|
13
12
|
const get_snapshot_diff_1 = require("./get-snapshot-diff");
|
|
14
|
-
const cache_1 = require("../cache");
|
|
15
|
-
const emitter_1 = __importDefault(require("../emitter"));
|
|
16
13
|
async function applySnapshot(snapshot, options) {
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
const schema = (_b = options === null || options === void 0 ? void 0 : options.schema) !== null && _b !== void 0 ? _b : (await (0, get_schema_1.getSchema)({ database, bypassCache: true }));
|
|
14
|
+
const database = options?.database ?? (0, database_1.default)();
|
|
15
|
+
const schema = options?.schema ?? (await (0, get_schema_1.getSchema)({ database, bypassCache: true }));
|
|
20
16
|
const { systemCache } = (0, cache_1.getCache)();
|
|
21
|
-
const current =
|
|
22
|
-
const snapshotDiff =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
autoPurgeSystemCache: false,
|
|
26
|
-
bypassEmitAction: (params) => nestedActionEvents.push(params),
|
|
27
|
-
};
|
|
28
|
-
await database.transaction(async (trx) => {
|
|
29
|
-
const collectionsService = new services_1.CollectionsService({ knex: trx, schema });
|
|
30
|
-
const getNestedCollectionsToCreate = (currentLevelCollection) => snapshotDiff.collections.filter(({ diff }) => { var _a, _b; return ((_b = (_a = diff[0].rhs) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.group) === currentLevelCollection; });
|
|
31
|
-
const getNestedCollectionsToDelete = (currentLevelCollection) => snapshotDiff.collections.filter(({ diff }) => { var _a, _b; return ((_b = (_a = diff[0].lhs) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.group) === currentLevelCollection; });
|
|
32
|
-
const createCollections = async (collections) => {
|
|
33
|
-
for (const { collection, diff } of collections) {
|
|
34
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N' && diff[0].rhs) {
|
|
35
|
-
// We'll nest the to-be-created fields in the same collection creation, to prevent
|
|
36
|
-
// creating a collection without a primary key
|
|
37
|
-
const fields = snapshotDiff.fields
|
|
38
|
-
.filter((fieldDiff) => fieldDiff.collection === collection)
|
|
39
|
-
.map((fieldDiff) => fieldDiff.diff[0].rhs)
|
|
40
|
-
.map((fieldDiff) => {
|
|
41
|
-
var _a, _b, _c, _d, _e;
|
|
42
|
-
// Casts field type to UUID when applying non-PostgreSQL schema onto PostgreSQL database.
|
|
43
|
-
// This is needed because they snapshots UUID fields as char with length 36.
|
|
44
|
-
if (((_a = fieldDiff.schema) === null || _a === void 0 ? void 0 : _a.data_type) === 'char' &&
|
|
45
|
-
((_b = fieldDiff.schema) === null || _b === void 0 ? void 0 : _b.max_length) === 36 &&
|
|
46
|
-
(((_c = fieldDiff.schema) === null || _c === void 0 ? void 0 : _c.is_primary_key) ||
|
|
47
|
-
(((_d = fieldDiff.schema) === null || _d === void 0 ? void 0 : _d.foreign_key_table) && ((_e = fieldDiff.schema) === null || _e === void 0 ? void 0 : _e.foreign_key_column)))) {
|
|
48
|
-
return (0, lodash_1.merge)(fieldDiff, { type: 'uuid', schema: { data_type: 'uuid', max_length: null } });
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
return fieldDiff;
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
try {
|
|
55
|
-
await collectionsService.createOne({
|
|
56
|
-
...diff[0].rhs,
|
|
57
|
-
fields,
|
|
58
|
-
}, mutationOptions);
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
logger_1.default.error(`Failed to create collection "${collection}"`);
|
|
62
|
-
throw err;
|
|
63
|
-
}
|
|
64
|
-
// Now that the fields are in for this collection, we can strip them from the field edits
|
|
65
|
-
snapshotDiff.fields = snapshotDiff.fields.filter((fieldDiff) => fieldDiff.collection !== collection);
|
|
66
|
-
await createCollections(getNestedCollectionsToCreate(collection));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
const deleteCollections = async (collections) => {
|
|
71
|
-
for (const { collection, diff } of collections) {
|
|
72
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
|
|
73
|
-
const relations = schema.relations.filter((r) => r.related_collection === collection || r.collection === collection);
|
|
74
|
-
if (relations.length > 0) {
|
|
75
|
-
const relationsService = new services_1.RelationsService({ knex: trx, schema });
|
|
76
|
-
for (const relation of relations) {
|
|
77
|
-
try {
|
|
78
|
-
await relationsService.deleteOne(relation.collection, relation.field, mutationOptions);
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
logger_1.default.error(`Failed to delete collection "${collection}" due to relation "${relation.collection}.${relation.field}"`);
|
|
82
|
-
throw err;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// clean up deleted relations from existing schema
|
|
86
|
-
schema.relations = schema.relations.filter((r) => r.related_collection !== collection && r.collection !== collection);
|
|
87
|
-
}
|
|
88
|
-
await deleteCollections(getNestedCollectionsToDelete(collection));
|
|
89
|
-
try {
|
|
90
|
-
await collectionsService.deleteOne(collection, mutationOptions);
|
|
91
|
-
}
|
|
92
|
-
catch (err) {
|
|
93
|
-
logger_1.default.error(`Failed to delete collection "${collection}"`);
|
|
94
|
-
throw err;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
// Finds all collections that need to be created
|
|
100
|
-
const filterCollectionsForCreation = ({ diff }) => {
|
|
101
|
-
var _a;
|
|
102
|
-
// Check new collections only
|
|
103
|
-
const isNewCollection = diff[0].kind === 'N';
|
|
104
|
-
if (!isNewCollection)
|
|
105
|
-
return false;
|
|
106
|
-
// Create now if no group
|
|
107
|
-
const groupName = (_a = diff[0].rhs.meta) === null || _a === void 0 ? void 0 : _a.group;
|
|
108
|
-
if (!groupName)
|
|
109
|
-
return true;
|
|
110
|
-
// Check if parent collection already exists in schema
|
|
111
|
-
const parentExists = current.collections.find((c) => c.collection === groupName) !== undefined;
|
|
112
|
-
// If this is a new collection and the parent collection doesn't exist in current schema ->
|
|
113
|
-
// Check if the parent collection will be created as part of applying this snapshot ->
|
|
114
|
-
// If yes -> this collection will be created recursively
|
|
115
|
-
// If not -> create now
|
|
116
|
-
// (ex.)
|
|
117
|
-
// TopLevelCollection - I exist in current schema
|
|
118
|
-
// NestedCollection - I exist in snapshotDiff as a new collection
|
|
119
|
-
// TheCurrentCollectionInIteration - I exist in snapshotDiff as a new collection but will be created as part of NestedCollection
|
|
120
|
-
const parentWillBeCreatedInThisApply = snapshotDiff.collections.filter(({ collection, diff }) => diff[0].kind === 'N' && collection === groupName)
|
|
121
|
-
.length > 0;
|
|
122
|
-
// Has group, but parent is not new, parent is also not being created in this snapshot apply
|
|
123
|
-
if (parentExists && !parentWillBeCreatedInThisApply)
|
|
124
|
-
return true;
|
|
125
|
-
return false;
|
|
126
|
-
};
|
|
127
|
-
// Create top level collections (no group, or highest level in existing group) first,
|
|
128
|
-
// then continue with nested collections recursively
|
|
129
|
-
await createCollections(snapshotDiff.collections.filter(filterCollectionsForCreation));
|
|
130
|
-
// delete top level collections (no group) first, then continue with nested collections recursively
|
|
131
|
-
await deleteCollections(snapshotDiff.collections.filter(({ diff }) => { var _a; return diff[0].kind === 'D' && ((_a = diff[0].lhs.meta) === null || _a === void 0 ? void 0 : _a.group) === null; }));
|
|
132
|
-
for (const { collection, diff } of snapshotDiff.collections) {
|
|
133
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
|
|
134
|
-
const newValues = snapshot.collections.find((field) => {
|
|
135
|
-
return field.collection === collection;
|
|
136
|
-
});
|
|
137
|
-
if (newValues) {
|
|
138
|
-
try {
|
|
139
|
-
await collectionsService.updateOne(collection, newValues, mutationOptions);
|
|
140
|
-
}
|
|
141
|
-
catch (err) {
|
|
142
|
-
logger_1.default.error(`Failed to update collection "${collection}"`);
|
|
143
|
-
throw err;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
const fieldsService = new services_1.FieldsService({
|
|
149
|
-
knex: trx,
|
|
150
|
-
schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
|
|
151
|
-
});
|
|
152
|
-
for (const { collection, field, diff } of snapshotDiff.fields) {
|
|
153
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
154
|
-
try {
|
|
155
|
-
await fieldsService.createField(collection, diff[0].rhs, undefined, mutationOptions);
|
|
156
|
-
}
|
|
157
|
-
catch (err) {
|
|
158
|
-
logger_1.default.error(`Failed to create field "${collection}.${field}"`);
|
|
159
|
-
throw err;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A' || isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
163
|
-
const newValues = snapshot.fields.find((snapshotField) => {
|
|
164
|
-
return snapshotField.collection === collection && snapshotField.field === field;
|
|
165
|
-
});
|
|
166
|
-
if (newValues) {
|
|
167
|
-
try {
|
|
168
|
-
await fieldsService.updateField(collection, {
|
|
169
|
-
...newValues,
|
|
170
|
-
}, mutationOptions);
|
|
171
|
-
}
|
|
172
|
-
catch (err) {
|
|
173
|
-
logger_1.default.error(`Failed to update field "${collection}.${field}"`);
|
|
174
|
-
throw err;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
|
|
179
|
-
try {
|
|
180
|
-
await fieldsService.deleteField(collection, field, mutationOptions);
|
|
181
|
-
}
|
|
182
|
-
catch (err) {
|
|
183
|
-
logger_1.default.error(`Failed to delete field "${collection}.${field}"`);
|
|
184
|
-
throw err;
|
|
185
|
-
}
|
|
186
|
-
// Field deletion also cleans up the relationship. We should ignore any relationship
|
|
187
|
-
// changes attached to this now non-existing field
|
|
188
|
-
snapshotDiff.relations = snapshotDiff.relations.filter((relation) => (relation.collection === collection && relation.field === field) === false);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
const relationsService = new services_1.RelationsService({
|
|
192
|
-
knex: trx,
|
|
193
|
-
schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
|
|
194
|
-
});
|
|
195
|
-
for (const { collection, field, diff } of snapshotDiff.relations) {
|
|
196
|
-
const structure = {};
|
|
197
|
-
for (const diffEdit of diff) {
|
|
198
|
-
(0, lodash_1.set)(structure, diffEdit.path, undefined);
|
|
199
|
-
}
|
|
200
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N') {
|
|
201
|
-
try {
|
|
202
|
-
await relationsService.createOne(diff[0].rhs, mutationOptions);
|
|
203
|
-
}
|
|
204
|
-
catch (err) {
|
|
205
|
-
logger_1.default.error(`Failed to create relation "${collection}.${field}"`);
|
|
206
|
-
throw err;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'E' || (diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'A') {
|
|
210
|
-
const newValues = snapshot.relations.find((relation) => {
|
|
211
|
-
return relation.collection === collection && relation.field === field;
|
|
212
|
-
});
|
|
213
|
-
if (newValues) {
|
|
214
|
-
try {
|
|
215
|
-
await relationsService.updateOne(collection, field, newValues, mutationOptions);
|
|
216
|
-
}
|
|
217
|
-
catch (err) {
|
|
218
|
-
logger_1.default.error(`Failed to update relation "${collection}.${field}"`);
|
|
219
|
-
throw err;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
|
|
224
|
-
try {
|
|
225
|
-
await relationsService.deleteOne(collection, field, mutationOptions);
|
|
226
|
-
}
|
|
227
|
-
catch (err) {
|
|
228
|
-
logger_1.default.error(`Failed to delete relation "${collection}.${field}"`);
|
|
229
|
-
throw err;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
await (systemCache === null || systemCache === void 0 ? void 0 : systemCache.clear());
|
|
235
|
-
if (nestedActionEvents.length > 0) {
|
|
236
|
-
const updatedSchema = await (0, get_schema_1.getSchema)({ database, bypassCache: true });
|
|
237
|
-
for (const nestedActionEvent of nestedActionEvents) {
|
|
238
|
-
nestedActionEvent.context.schema = updatedSchema;
|
|
239
|
-
emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
17
|
+
const current = options?.current ?? (await (0, get_snapshot_1.getSnapshot)({ database, schema }));
|
|
18
|
+
const snapshotDiff = options?.diff ?? (0, get_snapshot_diff_1.getSnapshotDiff)(current, snapshot);
|
|
19
|
+
await (0, apply_diff_1.applyDiff)(current, snapshotDiff, { database, schema });
|
|
20
|
+
await systemCache?.clear();
|
|
242
21
|
}
|
|
243
22
|
exports.applySnapshot = applySnapshot;
|
|
244
|
-
function isNestedMetaUpdate(diff) {
|
|
245
|
-
if (!diff)
|
|
246
|
-
return false;
|
|
247
|
-
if (diff.kind !== 'N' && diff.kind !== 'D')
|
|
248
|
-
return false;
|
|
249
|
-
if (!diff.path || diff.path.length < 2 || diff.path[0] !== 'meta')
|
|
250
|
-
return false;
|
|
251
|
-
return true;
|
|
252
|
-
}
|
|
253
|
-
exports.isNestedMetaUpdate = isNestedMetaUpdate;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Flow, FlowRaw } from '@directus/shared/types';
|
|
1
|
+
import type { Flow, FlowRaw } from '@directus/shared/types';
|
|
2
2
|
export declare function constructFlowTree(flow: FlowRaw): Flow;
|
|
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.constructFlowTree = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
function constructFlowTree(flow) {
|
|
6
|
-
|
|
7
|
-
const rootOperation = (_a = flow.operations.find((operation) => operation.id === flow.operation)) !== null && _a !== void 0 ? _a : null;
|
|
6
|
+
const rootOperation = flow.operations.find((operation) => operation.id === flow.operation) ?? null;
|
|
8
7
|
const operationTree = constructOperationTree(rootOperation, flow.operations);
|
|
9
8
|
const flowTree = {
|
|
10
9
|
...(0, lodash_1.omit)(flow, 'operations'),
|
|
11
10
|
operation: operationTree,
|
|
11
|
+
options: flow.options ?? {},
|
|
12
12
|
};
|
|
13
13
|
return flowTree;
|
|
14
14
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Query } from '@directus/shared/types';
|
|
1
|
+
import type { Query } from '@directus/shared/types';
|
|
2
2
|
export declare function filterItems(items: Record<string, any>[], filter: Query['filter']): Record<string, any>[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Accountability, SchemaOverview } from '@directus/shared/types';
|
|
2
|
-
import { Knex } from 'knex';
|
|
1
|
+
import type { Accountability, SchemaOverview } from '@directus/shared/types';
|
|
2
|
+
import type { Knex } from 'knex';
|
|
3
3
|
export declare function getAccountabilityForRole(role: null | string, context: {
|
|
4
4
|
accountability: null | Accountability;
|
|
5
5
|
schema: SchemaOverview;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getAccountabilityForRole = void 0;
|
|
4
|
-
const get_permissions_1 = require("./get-permissions");
|
|
5
4
|
const exceptions_1 = require("../exceptions");
|
|
5
|
+
const get_permissions_1 = require("./get-permissions");
|
|
6
6
|
async function getAccountabilityForRole(role, context) {
|
|
7
7
|
let generatedAccountability = context.accountability;
|
|
8
8
|
if (role === null) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Generate an AST based on a given collection and query
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import type { Accountability, PermissionsAction, Query, SchemaOverview } from '@directus/shared/types';
|
|
5
|
+
import type { Knex } from 'knex';
|
|
6
|
+
import type { AST } from '../types';
|
|
7
7
|
type GetASTOptions = {
|
|
8
8
|
accountability?: Accountability | null;
|
|
9
9
|
action?: PermissionsAction;
|
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
* Generate an AST based on a given collection and query
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const constants_1 = require("@directus/shared/constants");
|
|
6
7
|
const lodash_1 = require("lodash");
|
|
7
8
|
const get_relation_type_1 = require("../utils/get-relation-type");
|
|
8
|
-
const constants_1 = require("@directus/shared/constants");
|
|
9
9
|
async function getASTFromQuery(collection, query, schema, options) {
|
|
10
|
-
var _a, _b, _c, _d, _e;
|
|
11
10
|
query = (0, lodash_1.cloneDeep)(query);
|
|
12
|
-
const accountability = options
|
|
13
|
-
const action =
|
|
11
|
+
const accountability = options?.accountability;
|
|
12
|
+
const action = options?.action || 'read';
|
|
14
13
|
const permissions = accountability && accountability.admin !== true
|
|
15
|
-
?
|
|
14
|
+
? accountability?.permissions?.filter((permission) => {
|
|
16
15
|
return permission.action === action;
|
|
17
|
-
})
|
|
16
|
+
}) ?? []
|
|
18
17
|
: null;
|
|
19
18
|
const ast = {
|
|
20
19
|
type: 'root',
|
|
@@ -49,24 +48,23 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
49
48
|
// We'll default to the primary key for the standard sort output
|
|
50
49
|
let sortField = schema.collections[collection].primary;
|
|
51
50
|
// If a custom manual sort field is configured, use that
|
|
52
|
-
if (
|
|
51
|
+
if (schema.collections[collection]?.sortField) {
|
|
53
52
|
sortField = schema.collections[collection].sortField;
|
|
54
53
|
}
|
|
55
54
|
// When group by is used, default to the first column provided in the group by clause
|
|
56
|
-
if (
|
|
55
|
+
if (query.group?.[0]) {
|
|
57
56
|
sortField = query.group[0];
|
|
58
57
|
}
|
|
59
58
|
query.sort = [sortField];
|
|
60
59
|
}
|
|
61
60
|
// When no group by is supplied, but an aggregate function is used, only a single row will be
|
|
62
61
|
// returned. In those cases, we'll ignore the sort field altogether
|
|
63
|
-
if (query.aggregate && Object.keys(query.aggregate).length && !
|
|
62
|
+
if (query.aggregate && Object.keys(query.aggregate).length && !query.group?.[0]) {
|
|
64
63
|
delete query.sort;
|
|
65
64
|
}
|
|
66
65
|
ast.children = await parseFields(collection, fields, deep);
|
|
67
66
|
return ast;
|
|
68
67
|
async function parseFields(parentCollection, fields, deep) {
|
|
69
|
-
var _a, _b;
|
|
70
68
|
if (!fields)
|
|
71
69
|
return [];
|
|
72
70
|
fields = await convertWildcards(parentCollection, fields);
|
|
@@ -85,7 +83,7 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
85
83
|
const isRelational = name.includes('.') ||
|
|
86
84
|
// We'll always treat top level o2m fields as a related item. This is an alias field, otherwise it won't return
|
|
87
85
|
// anything
|
|
88
|
-
!!schema.relations.find((relation) =>
|
|
86
|
+
!!schema.relations.find((relation) => relation.related_collection === parentCollection && relation.meta?.one_field === name);
|
|
89
87
|
if (isRelational) {
|
|
90
88
|
// field is relational
|
|
91
89
|
const parts = fieldKey.split('.');
|
|
@@ -123,7 +121,7 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
123
121
|
const columnName = fieldKey.match(constants_1.REGEX_BETWEEN_PARENS)[1];
|
|
124
122
|
const foundField = schema.collections[parentCollection].fields[columnName];
|
|
125
123
|
if (foundField && foundField.type === 'alias') {
|
|
126
|
-
const foundRelation = schema.relations.find((relation) =>
|
|
124
|
+
const foundRelation = schema.relations.find((relation) => relation.related_collection === parentCollection && relation.meta?.one_field === columnName);
|
|
127
125
|
if (foundRelation) {
|
|
128
126
|
children.push({
|
|
129
127
|
type: 'functionField',
|
|
@@ -173,8 +171,8 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
173
171
|
relation: relation,
|
|
174
172
|
};
|
|
175
173
|
for (const relatedCollection of allowedCollections) {
|
|
176
|
-
child.children[relatedCollection] = await parseFields(relatedCollection, Array.isArray(nestedFields) ? nestedFields : nestedFields[relatedCollection] || [
|
|
177
|
-
child.query[relatedCollection] = getDeepQuery(
|
|
174
|
+
child.children[relatedCollection] = await parseFields(relatedCollection, Array.isArray(nestedFields) ? nestedFields : nestedFields[relatedCollection] || [], deep?.[`${fieldKey}:${relatedCollection}`]);
|
|
175
|
+
child.query[relatedCollection] = getDeepQuery(deep?.[`${fieldKey}:${relatedCollection}`] || {});
|
|
178
176
|
child.relatedKey[relatedCollection] = schema.collections[relatedCollection].primary;
|
|
179
177
|
}
|
|
180
178
|
}
|
|
@@ -183,7 +181,7 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
183
181
|
continue;
|
|
184
182
|
}
|
|
185
183
|
// update query alias for children parseFields
|
|
186
|
-
const deepAlias =
|
|
184
|
+
const deepAlias = getDeepQuery(deep?.[fieldKey] || {})?.alias;
|
|
187
185
|
if (!(0, lodash_1.isEmpty)(deepAlias))
|
|
188
186
|
query.alias = deepAlias;
|
|
189
187
|
child = {
|
|
@@ -193,11 +191,11 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
193
191
|
parentKey: schema.collections[parentCollection].primary,
|
|
194
192
|
relatedKey: schema.collections[relatedCollection].primary,
|
|
195
193
|
relation: relation,
|
|
196
|
-
query: getDeepQuery(
|
|
197
|
-
children: await parseFields(relatedCollection, nestedFields,
|
|
194
|
+
query: getDeepQuery(deep?.[fieldKey] || {}),
|
|
195
|
+
children: await parseFields(relatedCollection, nestedFields, deep?.[fieldKey] || {}),
|
|
198
196
|
};
|
|
199
197
|
if (relationType === 'o2m' && !child.query.sort) {
|
|
200
|
-
child.query.sort = [
|
|
198
|
+
child.query.sort = [relation.meta?.sort_field || schema.collections[relation.collection].primary];
|
|
201
199
|
}
|
|
202
200
|
}
|
|
203
201
|
if (child) {
|
|
@@ -214,12 +212,11 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
214
212
|
});
|
|
215
213
|
}
|
|
216
214
|
async function convertWildcards(parentCollection, fields) {
|
|
217
|
-
var _a, _b, _c;
|
|
218
215
|
fields = (0, lodash_1.cloneDeep)(fields);
|
|
219
216
|
const fieldsInCollection = Object.entries(schema.collections[parentCollection].fields).map(([name]) => name);
|
|
220
217
|
let allowedFields = fieldsInCollection;
|
|
221
218
|
if (permissions) {
|
|
222
|
-
const permittedFields =
|
|
219
|
+
const permittedFields = permissions.find((permission) => parentCollection === permission.collection)?.fields;
|
|
223
220
|
if (permittedFields !== undefined)
|
|
224
221
|
allowedFields = permittedFields;
|
|
225
222
|
}
|
|
@@ -233,7 +230,7 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
233
230
|
if (fieldKey.includes('*') === false)
|
|
234
231
|
continue;
|
|
235
232
|
if (fieldKey === '*') {
|
|
236
|
-
const aliases = Object.keys(
|
|
233
|
+
const aliases = Object.keys(query.alias ?? {});
|
|
237
234
|
// Set to all fields in collection
|
|
238
235
|
if (allowedFields.includes('*')) {
|
|
239
236
|
fields.splice(index, 1, ...fieldsInCollection, ...aliases);
|
|
@@ -254,13 +251,12 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
254
251
|
? schema.relations
|
|
255
252
|
.filter((relation) => relation.collection === parentCollection || relation.related_collection === parentCollection)
|
|
256
253
|
.map((relation) => {
|
|
257
|
-
var _a;
|
|
258
254
|
const isMany = relation.collection === parentCollection;
|
|
259
|
-
return isMany ? relation.field :
|
|
255
|
+
return isMany ? relation.field : relation.meta?.one_field;
|
|
260
256
|
})
|
|
261
257
|
: allowedFields.filter((fieldKey) => !!getRelation(parentCollection, fieldKey));
|
|
262
258
|
const nonRelationalFields = allowedFields.filter((fieldKey) => relationalFields.includes(fieldKey) === false);
|
|
263
|
-
const aliasFields = Object.keys(
|
|
259
|
+
const aliasFields = Object.keys(query.alias ?? {}).map((fieldKey) => {
|
|
264
260
|
const name = query.alias[fieldKey];
|
|
265
261
|
if (relationalFields.includes(name)) {
|
|
266
262
|
return `${fieldKey}.${parts.slice(1).join('.')}`;
|
|
@@ -280,21 +276,19 @@ async function getASTFromQuery(collection, query, schema, options) {
|
|
|
280
276
|
}
|
|
281
277
|
function getRelation(collection, field) {
|
|
282
278
|
const relation = schema.relations.find((relation) => {
|
|
283
|
-
var _a;
|
|
284
279
|
return ((relation.collection === collection && relation.field === field) ||
|
|
285
|
-
(relation.related_collection === collection &&
|
|
280
|
+
(relation.related_collection === collection && relation.meta?.one_field === field));
|
|
286
281
|
});
|
|
287
282
|
return relation;
|
|
288
283
|
}
|
|
289
284
|
function getRelatedCollection(collection, field) {
|
|
290
|
-
var _a;
|
|
291
285
|
const relation = getRelation(collection, field);
|
|
292
286
|
if (!relation)
|
|
293
287
|
return null;
|
|
294
288
|
if (relation.collection === collection && relation.field === field) {
|
|
295
289
|
return relation.related_collection || null;
|
|
296
290
|
}
|
|
297
|
-
if (relation.related_collection === collection &&
|
|
291
|
+
if (relation.related_collection === collection && relation.meta?.one_field === field) {
|
|
298
292
|
return relation.collection || null;
|
|
299
293
|
}
|
|
300
294
|
return null;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { Request } from 'express';
|
|
1
|
+
import type { Request } from 'express';
|
|
2
2
|
/**
|
|
3
3
|
* Returns the Cache-Control header for the current request
|
|
4
4
|
*
|
|
5
5
|
* @param req Express request object
|
|
6
6
|
* @param ttl TTL of the cache in ms
|
|
7
|
+
* @param globalCacheSettings Whether requests are affected by the global cache settings (i.e. for dynamic API requests)
|
|
8
|
+
* @param personalized Whether requests depend on the authentication status of users
|
|
7
9
|
*/
|
|
8
|
-
export declare function getCacheControlHeader(req: Request, ttl: number |
|
|
10
|
+
export declare function getCacheControlHeader(req: Request, ttl: number | undefined, globalCacheSettings: boolean, personalized: boolean): string;
|
|
@@ -5,39 +5,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getCacheControlHeader = void 0;
|
|
7
7
|
const env_1 = __importDefault(require("../env"));
|
|
8
|
+
const should_skip_cache_1 = require("./should-skip-cache");
|
|
8
9
|
/**
|
|
9
10
|
* Returns the Cache-Control header for the current request
|
|
10
11
|
*
|
|
11
12
|
* @param req Express request object
|
|
12
13
|
* @param ttl TTL of the cache in ms
|
|
14
|
+
* @param globalCacheSettings Whether requests are affected by the global cache settings (i.e. for dynamic API requests)
|
|
15
|
+
* @param personalized Whether requests depend on the authentication status of users
|
|
13
16
|
*/
|
|
14
|
-
function getCacheControlHeader(req, ttl) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
function getCacheControlHeader(req, ttl, globalCacheSettings, personalized) {
|
|
18
|
+
// When the user explicitly asked to skip the cache
|
|
19
|
+
if ((0, should_skip_cache_1.shouldSkipCache)(req))
|
|
20
|
+
return 'no-store';
|
|
21
|
+
// When the resource / current request shouldn't be cached
|
|
22
|
+
if (ttl === undefined || ttl < 0)
|
|
18
23
|
return 'no-cache';
|
|
19
24
|
// When the API cache can invalidate at any moment
|
|
20
|
-
if (env_1.default.CACHE_AUTO_PURGE === true)
|
|
25
|
+
if (globalCacheSettings && env_1.default.CACHE_AUTO_PURGE === true)
|
|
21
26
|
return 'no-cache';
|
|
22
|
-
const
|
|
23
|
-
// When
|
|
24
|
-
if (
|
|
25
|
-
|
|
27
|
+
const headerValues = [];
|
|
28
|
+
// When caching depends on the authentication status of the users
|
|
29
|
+
if (personalized) {
|
|
30
|
+
// Allow response to be stored in shared cache (public) or local cache only (private)
|
|
31
|
+
const access = !!req.accountability?.role === false ? 'public' : 'private';
|
|
32
|
+
headerValues.push(access);
|
|
33
|
+
}
|
|
26
34
|
// Cache control header uses seconds for everything
|
|
27
35
|
const ttlSeconds = Math.round(ttl / 1000);
|
|
28
|
-
|
|
29
|
-
let headerValue = `${access}, max-age=${ttlSeconds}`;
|
|
36
|
+
headerValues.push(`max-age=${ttlSeconds}`);
|
|
30
37
|
// When the s-maxage flag should be included
|
|
31
|
-
if (env_1.default.CACHE_CONTROL_S_MAXAGE
|
|
32
|
-
|
|
33
|
-
if (env_1.default.CACHE_CONTROL_S_MAXAGE === true) {
|
|
34
|
-
headerValue += `, s-maxage=${ttlSeconds}`;
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
// Set to custom value
|
|
38
|
-
headerValue += `, s-maxage=${env_1.default.CACHE_CONTROL_S_MAXAGE}`;
|
|
39
|
-
}
|
|
38
|
+
if (globalCacheSettings && Number.isInteger(env_1.default.CACHE_CONTROL_S_MAXAGE) && env_1.default.CACHE_CONTROL_S_MAXAGE >= 0) {
|
|
39
|
+
headerValues.push(`s-maxage=${env_1.default.CACHE_CONTROL_S_MAXAGE}`);
|
|
40
40
|
}
|
|
41
|
-
return
|
|
41
|
+
return headerValues.join(', ');
|
|
42
42
|
}
|
|
43
43
|
exports.getCacheControlHeader = getCacheControlHeader;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Request } from 'express';
|
|
1
|
+
import type { Request } from 'express';
|
|
2
2
|
export declare function getCacheKey(req: Request): string;
|
|
@@ -8,11 +8,10 @@ const object_hash_1 = __importDefault(require("object-hash"));
|
|
|
8
8
|
const url_1 = __importDefault(require("url"));
|
|
9
9
|
const get_graphql_query_and_variables_1 = require("./get-graphql-query-and-variables");
|
|
10
10
|
function getCacheKey(req) {
|
|
11
|
-
var _a;
|
|
12
11
|
const path = url_1.default.parse(req.originalUrl).pathname;
|
|
13
|
-
const isGraphQl = path
|
|
12
|
+
const isGraphQl = path?.startsWith('/graphql');
|
|
14
13
|
const info = {
|
|
15
|
-
user:
|
|
14
|
+
user: req.accountability?.user || null,
|
|
16
15
|
path,
|
|
17
16
|
query: isGraphQl ? (0, get_graphql_query_and_variables_1.getGraphqlQueryAndVariables)(req) : req.sanitizedQuery,
|
|
18
17
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Relation, SchemaOverview } from '@directus/shared/types';
|
|
1
|
+
import type { Relation, SchemaOverview } from '@directus/shared/types';
|
|
2
2
|
export type AliasMap = {
|
|
3
3
|
[key: string]: {
|
|
4
4
|
alias: string;
|
|
@@ -15,7 +15,7 @@ export type ColPathProps = {
|
|
|
15
15
|
export type ColPathResult = {
|
|
16
16
|
columnPath: string;
|
|
17
17
|
targetCollection: string;
|
|
18
|
-
addNestedPkField
|
|
18
|
+
addNestedPkField: string | undefined;
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
21
|
* Converts a Directus field list path to the correct SQL names based on the constructed alias map.
|