@directus/api 32.1.1 → 33.0.0
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/ai/chat/constants/system-prompt.d.ts +1 -0
- package/dist/ai/chat/constants/system-prompt.js +51 -0
- package/dist/ai/chat/controllers/chat.post.d.ts +2 -0
- package/dist/ai/chat/controllers/chat.post.js +47 -0
- package/dist/ai/chat/lib/create-ui-stream.d.ts +15 -0
- package/dist/ai/chat/lib/create-ui-stream.js +42 -0
- package/dist/ai/chat/middleware/load-settings.d.ts +2 -0
- package/dist/ai/chat/middleware/load-settings.js +18 -0
- package/dist/ai/chat/models/chat-request.d.ts +34 -0
- package/dist/ai/chat/models/chat-request.js +26 -0
- package/dist/ai/chat/models/providers.d.ts +9 -0
- package/dist/ai/chat/models/providers.js +9 -0
- package/dist/ai/chat/router.d.ts +1 -0
- package/dist/ai/chat/router.js +5 -0
- package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.d.ts +9 -0
- package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.js +38 -0
- package/dist/ai/chat/utils/fix-error-tool-calls.d.ts +12 -0
- package/dist/ai/chat/utils/fix-error-tool-calls.js +30 -0
- package/dist/ai/chat/utils/parse-json-schema-7.d.ts +13 -0
- package/dist/ai/chat/utils/parse-json-schema-7.js +75 -0
- package/dist/{mcp → ai/mcp}/server.d.ts +13 -16
- package/dist/{mcp → ai/mcp}/server.js +4 -13
- package/dist/ai/mcp/types.d.ts +15 -0
- package/dist/{mcp/tools/assets.js → ai/tools/assets/index.js} +8 -5
- package/dist/{mcp/tools/collections.js → ai/tools/collections/index.js} +7 -4
- package/dist/{mcp/tools/fields.js → ai/tools/fields/index.js} +12 -9
- package/dist/{mcp/tools/files.js → ai/tools/files/index.js} +11 -5
- package/dist/{mcp/tools/flows.js → ai/tools/flows/index.js} +11 -5
- package/dist/{mcp/tools/folders.js → ai/tools/folders/index.js} +12 -5
- package/dist/ai/tools/index.d.ts +15 -0
- package/dist/ai/tools/index.js +29 -0
- package/dist/{mcp/tools/items.js → ai/tools/items/index.js} +13 -6
- package/dist/{mcp/tools/prompts/items.md → ai/tools/items/prompt.md} +19 -15
- package/dist/{mcp/tools/operations.d.ts → ai/tools/operations/index.d.ts} +46 -0
- package/dist/{mcp/tools/operations.js → ai/tools/operations/index.js} +12 -5
- package/dist/{mcp/tools/relations.js → ai/tools/relations/index.js} +7 -4
- package/dist/{mcp/tools/schema.d.ts → ai/tools/schema/index.d.ts} +1 -1
- package/dist/{mcp/tools/schema.js → ai/tools/schema/index.js} +9 -6
- package/dist/{mcp/tools/system.js → ai/tools/system/index.js} +7 -4
- package/dist/{mcp/tools/trigger-flow.js → ai/tools/trigger-flow/index.js} +8 -5
- package/dist/{mcp → ai/tools}/types.d.ts +1 -17
- package/dist/ai/tools/utils.d.ts +9 -0
- package/dist/ai/tools/utils.js +17 -0
- package/dist/app.js +11 -6
- package/dist/auth/drivers/ldap.js +2 -2
- package/dist/auth/drivers/local.js +1 -1
- package/dist/auth/drivers/oauth2.d.ts +1 -2
- package/dist/auth/drivers/oauth2.js +22 -17
- package/dist/auth/drivers/openid.d.ts +1 -2
- package/dist/auth/drivers/openid.js +18 -13
- package/dist/auth/drivers/saml.js +6 -3
- package/dist/auth/utils/generate-callback-url.d.ts +11 -0
- package/dist/auth/utils/generate-callback-url.js +40 -0
- package/dist/auth/utils/is-login-redirect-allowed.d.ts +7 -0
- package/dist/{utils → auth/utils}/is-login-redirect-allowed.js +12 -9
- package/dist/cache.js +2 -2
- package/dist/cli/commands/bootstrap/index.js +2 -2
- package/dist/cli/commands/database/install.js +1 -1
- package/dist/cli/commands/database/migrate.js +1 -1
- package/dist/cli/commands/init/index.js +2 -2
- package/dist/cli/commands/roles/create.js +4 -4
- package/dist/cli/commands/schema/apply.js +3 -3
- package/dist/cli/commands/schema/snapshot.js +1 -1
- package/dist/cli/utils/create-db-connection.d.ts +1 -1
- package/dist/cli/utils/create-db-connection.js +1 -1
- package/dist/cli/utils/create-env/index.js +1 -1
- package/dist/constants.d.ts +7 -3
- package/dist/constants.js +7 -3
- package/dist/controllers/access.js +1 -1
- package/dist/controllers/assets.js +40 -3
- package/dist/controllers/extensions.js +1 -1
- package/dist/controllers/fields.js +2 -2
- package/dist/controllers/files.js +1 -1
- package/dist/controllers/items.js +1 -1
- package/dist/controllers/mcp.js +1 -1
- package/dist/controllers/not-found.js +1 -1
- package/dist/controllers/relations.js +1 -1
- package/dist/database/errors/dialects/mysql.d.ts +1 -1
- package/dist/database/errors/dialects/postgres.d.ts +1 -1
- package/dist/database/errors/dialects/sqlite.d.ts +1 -1
- package/dist/database/errors/translate.d.ts +1 -1
- package/dist/database/errors/translate.js +1 -1
- package/dist/database/helpers/date/dialects/mssql.js +1 -1
- package/dist/database/helpers/date/dialects/mysql.js +1 -1
- package/dist/database/helpers/date/types.js +1 -1
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +1 -0
- package/dist/database/helpers/schema/dialects/cockroachdb.js +24 -1
- package/dist/database/helpers/schema/dialects/mssql.d.ts +1 -1
- package/dist/database/helpers/schema/dialects/mysql.d.ts +2 -1
- package/dist/database/helpers/schema/dialects/mysql.js +16 -3
- package/dist/database/helpers/schema/dialects/postgres.d.ts +1 -1
- package/dist/database/helpers/schema/types.d.ts +13 -0
- package/dist/database/helpers/schema/types.js +24 -0
- package/dist/database/index.js +4 -4
- package/dist/database/migrations/20220429A-add-flows.js +1 -1
- package/dist/database/migrations/20230526A-migrate-translation-strings.js +1 -1
- package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +1 -1
- package/dist/database/migrations/20240204A-marketplace.js +9 -7
- package/dist/database/migrations/20240311A-deprecate-webhooks.d.ts +15 -0
- package/dist/database/migrations/20240311A-deprecate-webhooks.js +1 -1
- package/dist/database/migrations/20240806A-permissions-policies.js +3 -3
- package/dist/database/migrations/20240924A-migrate-legacy-comments.js +1 -1
- package/dist/database/migrations/20251014A-add-project-owner.js +1 -1
- package/dist/database/migrations/20251103A-add-ai-settings.d.ts +3 -0
- package/dist/database/migrations/20251103A-add-ai-settings.js +14 -0
- package/dist/database/migrations/20251224A-remove-webhooks.d.ts +3 -0
- package/dist/database/migrations/20251224A-remove-webhooks.js +19 -0
- package/dist/database/migrations/20260113A-add-revisions-index.d.ts +3 -0
- package/dist/database/migrations/20260113A-add-revisions-index.js +41 -0
- package/dist/database/migrations/run.js +3 -3
- package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.d.ts +2 -2
- package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.js +1 -1
- package/dist/database/run-ast/lib/apply-query/filter/operator.js +1 -1
- package/dist/database/run-ast/lib/apply-query/sort.js +1 -1
- package/dist/database/run-ast/run-ast.js +1 -1
- package/dist/database/run-ast/utils/get-column-pre-processor.js +2 -2
- package/dist/database/run-ast/utils/get-column.js +1 -1
- package/dist/database/seeds/run.js +3 -3
- package/dist/extensions/lib/get-extensions-path.js +1 -1
- package/dist/extensions/lib/get-extensions-settings.js +1 -1
- package/dist/extensions/lib/get-extensions.js +1 -1
- package/dist/extensions/lib/get-shared-deps-mapping.js +3 -3
- package/dist/extensions/lib/installation/manager.js +8 -12
- package/dist/extensions/lib/sandbox/register/route.d.ts +1 -1
- package/dist/extensions/lib/sync/status.d.ts +11 -0
- package/dist/extensions/lib/sync/status.js +34 -0
- package/dist/extensions/lib/sync/sync.d.ts +6 -0
- package/dist/extensions/lib/sync/sync.js +90 -0
- package/dist/extensions/lib/sync/tracker.d.ts +18 -0
- package/dist/extensions/lib/sync/tracker.js +71 -0
- package/dist/extensions/lib/sync/utils.d.ts +24 -0
- package/dist/extensions/lib/sync/utils.js +62 -0
- package/dist/extensions/manager.d.ts +9 -5
- package/dist/extensions/manager.js +36 -19
- package/dist/flows.d.ts +1 -1
- package/dist/logger/index.js +1 -1
- package/dist/logger/logs-stream.d.ts +1 -1
- package/dist/logger/logs-stream.js +1 -1
- package/dist/mailer.js +1 -1
- package/dist/metrics/lib/create-metrics.js +2 -2
- package/dist/middleware/authenticate.js +3 -3
- package/dist/middleware/collection-exists.js +1 -1
- package/dist/middleware/extract-token.js +1 -1
- package/dist/middleware/graphql.js +2 -2
- package/dist/middleware/respond.js +2 -2
- package/dist/middleware/validate-batch.js +1 -1
- package/dist/operations/exec/index.js +2 -1
- package/dist/operations/mail/index.js +1 -1
- package/dist/operations/mail/rate-limiter.js +2 -2
- package/dist/permissions/cache.js +5 -0
- package/dist/permissions/lib/fetch-policies.d.ts +1 -1
- package/dist/permissions/lib/fetch-roles-tree.d.ts +6 -3
- package/dist/permissions/lib/fetch-roles-tree.js +5 -27
- package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +1 -1
- package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +1 -1
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +9 -7
- package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +17 -9
- package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +2 -2
- package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +1 -1
- package/dist/permissions/modules/process-ast/lib/inject-cases.js +1 -1
- package/dist/permissions/modules/process-ast/process-ast.js +1 -1
- package/dist/permissions/modules/process-payload/process-payload.js +1 -1
- package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +13 -1
- package/dist/permissions/modules/validate-access/lib/validate-item-access.js +54 -6
- package/dist/permissions/modules/validate-access/validate-access.js +3 -2
- package/dist/permissions/utils/fetch-raw-permissions.d.ts +1 -1
- package/dist/permissions/utils/fetch-share-info.d.ts +1 -1
- package/dist/permissions/utils/fetch-share-info.js +1 -1
- package/dist/permissions/utils/filter-policies-by-ip.js +1 -1
- package/dist/permissions/utils/get-permissions-for-share.js +8 -8
- package/dist/permissions/utils/with-cache.d.ts +8 -6
- package/dist/permissions/utils/with-cache.js +12 -10
- package/dist/rate-limiter.js +1 -1
- package/dist/request/is-denied-ip.js +2 -2
- package/dist/schedules/project.js +1 -1
- package/dist/schedules/telemetry.js +1 -1
- package/dist/schedules/tus.js +1 -1
- package/dist/server.js +4 -4
- package/dist/services/assets/name-deduper.d.ts +7 -0
- package/dist/services/assets/name-deduper.js +23 -0
- package/dist/services/assets.d.ts +17 -3
- package/dist/services/assets.js +133 -13
- package/dist/services/authentication.js +6 -6
- package/dist/services/collections.js +1 -1
- package/dist/services/comments.js +2 -2
- package/dist/services/extensions.d.ts +1 -1
- package/dist/services/extensions.js +4 -0
- package/dist/services/files/utils/get-metadata.d.ts +1 -1
- package/dist/services/files/utils/get-metadata.js +1 -1
- package/dist/services/files.d.ts +1 -1
- package/dist/services/files.js +4 -4
- package/dist/services/folders.d.ts +27 -2
- package/dist/services/folders.js +75 -0
- package/dist/services/graphql/index.d.ts +1 -1
- package/dist/services/graphql/index.js +1 -1
- package/dist/services/graphql/resolvers/mutation.js +1 -1
- package/dist/services/graphql/schema/get-types.d.ts +1 -1
- package/dist/services/graphql/schema/read.js +1 -1
- package/dist/services/graphql/subscription.d.ts +1 -1
- package/dist/services/graphql/types/date.js +1 -1
- package/dist/services/graphql/types/hash.js +1 -1
- package/dist/services/graphql/utils/add-path-to-validation-error.js +1 -1
- package/dist/services/import-export.d.ts +2 -2
- package/dist/services/import-export.js +6 -7
- package/dist/services/index.d.ts +0 -1
- package/dist/services/index.js +0 -1
- package/dist/services/mail/index.js +2 -2
- package/dist/services/mail/rate-limiter.js +2 -2
- package/dist/services/notifications.js +2 -2
- package/dist/services/payload.js +21 -1
- package/dist/services/roles.js +2 -2
- package/dist/services/schema.js +1 -1
- package/dist/services/server.js +12 -4
- package/dist/services/settings.js +2 -2
- package/dist/services/tfa.js +1 -1
- package/dist/services/translations.js +1 -1
- package/dist/services/tus/data-store.d.ts +1 -3
- package/dist/services/tus/data-store.js +2 -5
- package/dist/services/tus/server.js +9 -9
- package/dist/services/users.js +4 -4
- package/dist/services/versions.js +1 -1
- package/dist/telemetry/lib/send-report.d.ts +1 -1
- package/dist/telemetry/lib/send-report.js +1 -1
- package/dist/telemetry/lib/track.js +1 -1
- package/dist/telemetry/utils/get-settings.d.ts +15 -0
- package/dist/telemetry/utils/get-settings.js +13 -1
- package/dist/test-utils/README.md +95 -24
- package/dist/test-utils/cache.d.ts +2 -2
- package/dist/test-utils/cache.js +2 -2
- package/dist/test-utils/knex.js +1 -1
- package/dist/test-utils/{fields-service.d.ts → services/fields-service.d.ts} +1 -1
- package/dist/test-utils/{fields-service.js → services/fields-service.js} +3 -2
- package/dist/test-utils/services/files-service.d.ts +28 -0
- package/dist/test-utils/services/files-service.js +34 -0
- package/dist/test-utils/services/folders-service.d.ts +28 -0
- package/dist/test-utils/services/folders-service.js +33 -0
- package/dist/types/collection.d.ts +1 -1
- package/dist/utils/async-handler.d.ts +1 -1
- package/dist/utils/calculate-field-depth.js +1 -1
- package/dist/utils/compress.js +1 -1
- package/dist/utils/deep-map-response.js +2 -2
- package/dist/utils/encrypt.d.ts +2 -0
- package/dist/utils/encrypt.js +64 -0
- package/dist/utils/get-accountability-for-role.js +2 -2
- package/dist/utils/get-accountability-for-token.js +4 -4
- package/dist/utils/get-cache-key.js +3 -3
- package/dist/utils/get-field-system-rows.js +1 -1
- package/dist/utils/get-ip-from-req.d.ts +1 -1
- package/dist/utils/get-ip-from-req.js +1 -1
- package/dist/utils/get-local-type.js +7 -3
- package/dist/utils/get-service.js +1 -3
- package/dist/utils/get-snapshot-diff.js +1 -1
- package/dist/utils/is-url-allowed.js +1 -1
- package/dist/utils/jwt.js +1 -1
- package/dist/utils/require-text.d.ts +1 -0
- package/dist/utils/require-text.js +4 -0
- package/dist/utils/require-yaml.js +2 -2
- package/dist/utils/sanitize-schema.d.ts +1 -1
- package/dist/utils/should-clear-cache.d.ts +1 -1
- package/dist/utils/should-skip-cache.js +2 -2
- package/dist/utils/validate-diff.js +1 -1
- package/dist/utils/validate-snapshot.js +3 -3
- package/dist/utils/validate-storage.js +2 -2
- package/dist/utils/verify-session-jwt.js +1 -1
- package/dist/utils/versioning/deep-map-with-schema.js +2 -2
- package/dist/websocket/controllers/base.d.ts +2 -2
- package/dist/websocket/controllers/base.js +3 -3
- package/dist/websocket/controllers/graphql.d.ts +1 -1
- package/dist/websocket/controllers/graphql.js +1 -1
- package/dist/websocket/controllers/logs.d.ts +1 -1
- package/dist/websocket/controllers/rest.d.ts +1 -1
- package/dist/websocket/controllers/rest.js +2 -2
- package/dist/websocket/handlers/heartbeat.js +1 -1
- package/dist/websocket/handlers/items.js +2 -2
- package/dist/websocket/handlers/subscribe.js +1 -1
- package/dist/websocket/types.d.ts +1 -1
- package/dist/websocket/utils/wait-for-message.js +1 -1
- package/package.json +34 -28
- package/dist/controllers/webhooks.d.ts +0 -2
- package/dist/controllers/webhooks.js +0 -74
- package/dist/extensions/lib/sync-extensions.d.ts +0 -3
- package/dist/extensions/lib/sync-extensions.js +0 -70
- package/dist/extensions/lib/sync-status.d.ts +0 -10
- package/dist/extensions/lib/sync-status.js +0 -27
- package/dist/mcp/tools/index.d.ts +0 -15
- package/dist/mcp/tools/index.js +0 -29
- package/dist/mcp/tools/prompts/index.d.ts +0 -16
- package/dist/mcp/tools/prompts/index.js +0 -19
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
- package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
- package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
- package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
- package/dist/services/webhooks.d.ts +0 -14
- package/dist/services/webhooks.js +0 -32
- package/dist/utils/get-date-formatted.d.ts +0 -1
- package/dist/utils/get-date-formatted.js +0 -10
- package/dist/utils/ip-in-networks.d.ts +0 -6
- package/dist/utils/ip-in-networks.js +0 -13
- package/dist/utils/is-login-redirect-allowed.d.ts +0 -4
- /package/dist/{mcp → ai/mcp}/index.d.ts +0 -0
- /package/dist/{mcp → ai/mcp}/index.js +0 -0
- /package/dist/{mcp → ai/mcp}/transport.d.ts +0 -0
- /package/dist/{mcp → ai/mcp}/transport.js +0 -0
- /package/dist/{mcp → ai/mcp}/types.js +0 -0
- /package/dist/{mcp/tools/assets.d.ts → ai/tools/assets/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/assets.md → ai/tools/assets/prompt.md} +0 -0
- /package/dist/{mcp/tools/collections.d.ts → ai/tools/collections/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/collections.md → ai/tools/collections/prompt.md} +0 -0
- /package/dist/{mcp/define.d.ts → ai/tools/define-tool.d.ts} +0 -0
- /package/dist/{mcp/define.js → ai/tools/define-tool.js} +0 -0
- /package/dist/{mcp/tools/fields.d.ts → ai/tools/fields/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/fields.md → ai/tools/fields/prompt.md} +0 -0
- /package/dist/{mcp/tools/files.d.ts → ai/tools/files/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/files.md → ai/tools/files/prompt.md} +0 -0
- /package/dist/{mcp/tools/flows.d.ts → ai/tools/flows/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/flows.md → ai/tools/flows/prompt.md} +0 -0
- /package/dist/{mcp/tools/folders.d.ts → ai/tools/folders/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/folders.md → ai/tools/folders/prompt.md} +0 -0
- /package/dist/{mcp/tools/items.d.ts → ai/tools/items/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/operations.md → ai/tools/operations/prompt.md} +0 -0
- /package/dist/{mcp/tools/relations.d.ts → ai/tools/relations/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/relations.md → ai/tools/relations/prompt.md} +0 -0
- /package/dist/{mcp/tools/prompts/schema.md → ai/tools/schema/prompt.md} +0 -0
- /package/dist/{mcp → ai/tools}/schema.d.ts +0 -0
- /package/dist/{mcp → ai/tools}/schema.js +0 -0
- /package/dist/{mcp/tools/system.d.ts → ai/tools/system/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/system-prompt-description.md → ai/tools/system/prompt-description.md} +0 -0
- /package/dist/{mcp/tools/prompts/system-prompt.md → ai/tools/system/prompt.md} +0 -0
- /package/dist/{mcp/tools/trigger-flow.d.ts → ai/tools/trigger-flow/index.d.ts} +0 -0
- /package/dist/{mcp/tools/prompts/trigger-flow.md → ai/tools/trigger-flow/prompt.md} +0 -0
- /package/dist/{permissions/modules/fetch-global-access → ai/tools}/types.js +0 -0
- /package/dist/test-utils/{items-service.d.ts → services/items-service.d.ts} +0 -0
- /package/dist/test-utils/{items-service.js → services/items-service.js} +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { getSchema } from '../../../utils/get-schema.js';
|
|
2
|
-
import { RolesService } from '../../../services/roles.js';
|
|
3
|
-
import { PoliciesService } from '../../../services/index.js';
|
|
4
|
-
import { AccessService } from '../../../services/index.js';
|
|
5
1
|
import getDatabase from '../../../database/index.js';
|
|
6
2
|
import { useLogger } from '../../../logger/index.js';
|
|
3
|
+
import { PoliciesService } from '../../../services/index.js';
|
|
4
|
+
import { AccessService } from '../../../services/index.js';
|
|
5
|
+
import { RolesService } from '../../../services/roles.js';
|
|
6
|
+
import { getSchema } from '../../../utils/get-schema.js';
|
|
7
7
|
export default async function rolesCreate({ role: name, admin, app, }) {
|
|
8
8
|
const database = getDatabase();
|
|
9
9
|
const logger = useLogger();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
2
3
|
import { DiffKind } from '@directus/types';
|
|
4
|
+
import { parseJSON } from '@directus/utils';
|
|
3
5
|
import chalk from 'chalk';
|
|
4
|
-
import { promises as fs } from 'fs';
|
|
5
6
|
import inquirer from 'inquirer';
|
|
6
7
|
import { load as loadYaml } from 'js-yaml';
|
|
7
|
-
import path from 'path';
|
|
8
8
|
import getDatabase, { isInstalled, validateDatabaseConnection } from '../../../database/index.js';
|
|
9
9
|
import { useLogger } from '../../../logger/index.js';
|
|
10
10
|
import { isNestedMetaUpdate } from '../../../utils/apply-diff.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs, constants as fsConstants } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
2
3
|
import inquirer from 'inquirer';
|
|
3
4
|
import { dump as toYaml } from 'js-yaml';
|
|
4
|
-
import path from 'path';
|
|
5
5
|
import getDatabase from '../../../database/index.js';
|
|
6
6
|
import { useLogger } from '../../../logger/index.js';
|
|
7
7
|
import { getSnapshot } from '../../../utils/get-snapshot.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import knex from 'knex';
|
|
2
1
|
import { dirname } from 'node:path';
|
|
3
2
|
import { fileURLToPath } from 'node:url';
|
|
4
3
|
import path from 'path';
|
|
4
|
+
import knex from 'knex';
|
|
5
5
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
6
|
export default function createDBConnection(client, credentials) {
|
|
7
7
|
let connection = {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
|
-
import { Liquid } from 'liquidjs';
|
|
3
2
|
import { dirname } from 'node:path';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
5
4
|
import path from 'path';
|
|
6
5
|
import { promisify } from 'util';
|
|
6
|
+
import { Liquid } from 'liquidjs';
|
|
7
7
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
const readFile = promisify(fs.readFile);
|
|
9
9
|
const writeFile = promisify(fs.writeFile);
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { CookieOptions } from 'express';
|
|
2
1
|
import type { TransformationParams } from '@directus/types';
|
|
2
|
+
import type { CookieOptions } from 'express';
|
|
3
3
|
export declare const SYSTEM_ASSET_ALLOW_LIST: TransformationParams[];
|
|
4
4
|
export declare const ASSET_TRANSFORM_QUERY_KEYS: readonly ["key", "transforms", "width", "height", "format", "fit", "quality", "withoutEnlargement", "focal_point_x", "focal_point_y"];
|
|
5
5
|
export declare const FILTER_VARIABLES: string[];
|
|
@@ -15,11 +15,15 @@ export declare const OAS_REQUIRED_SCHEMAS: string[];
|
|
|
15
15
|
export declare const SUPPORTED_IMAGE_TRANSFORM_FORMATS: string[];
|
|
16
16
|
/** Formats where metadata extraction is supported */
|
|
17
17
|
export declare const SUPPORTED_IMAGE_METADATA_FORMATS: string[];
|
|
18
|
-
/**
|
|
18
|
+
/** File uploads */
|
|
19
|
+
export declare const FILE_UPLOADS: {
|
|
20
|
+
MAX_SIZE: number | null;
|
|
21
|
+
MAX_CONCURRENCY: number;
|
|
22
|
+
};
|
|
23
|
+
/** Resumable uploads (TUS) */
|
|
19
24
|
export declare const RESUMABLE_UPLOADS: {
|
|
20
25
|
ENABLED: boolean;
|
|
21
26
|
CHUNK_SIZE: number | null;
|
|
22
|
-
MAX_SIZE: number | null;
|
|
23
27
|
EXPIRATION_TIME: number;
|
|
24
28
|
SCHEDULE: string;
|
|
25
29
|
};
|
package/dist/constants.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getMilliseconds } from './utils/get-milliseconds.js';
|
|
2
1
|
import { useEnv } from '@directus/env';
|
|
3
2
|
import { toBoolean } from '@directus/utils';
|
|
4
3
|
import bytes from 'bytes';
|
|
4
|
+
import { getMilliseconds } from './utils/get-milliseconds.js';
|
|
5
5
|
const env = useEnv();
|
|
6
6
|
export const SYSTEM_ASSET_ALLOW_LIST = [
|
|
7
7
|
{
|
|
@@ -87,11 +87,15 @@ export const SUPPORTED_IMAGE_METADATA_FORMATS = [
|
|
|
87
87
|
'image/tiff',
|
|
88
88
|
'image/avif',
|
|
89
89
|
];
|
|
90
|
-
/**
|
|
90
|
+
/** File uploads */
|
|
91
|
+
export const FILE_UPLOADS = {
|
|
92
|
+
MAX_SIZE: bytes.parse(env['FILES_MAX_UPLOAD_SIZE']),
|
|
93
|
+
MAX_CONCURRENCY: Number(env['FILES_MAX_UPLOAD_CONCURRENCY']),
|
|
94
|
+
};
|
|
95
|
+
/** Resumable uploads (TUS) */
|
|
91
96
|
export const RESUMABLE_UPLOADS = {
|
|
92
97
|
ENABLED: toBoolean(env['TUS_ENABLED']),
|
|
93
98
|
CHUNK_SIZE: bytes.parse(env['TUS_CHUNK_SIZE']),
|
|
94
|
-
MAX_SIZE: bytes.parse(env['FILES_MAX_UPLOAD_SIZE']),
|
|
95
99
|
EXPIRATION_TIME: getMilliseconds(env['TUS_UPLOAD_EXPIRATION'], 600_000 /* 10min */),
|
|
96
100
|
SCHEDULE: String(env['TUS_CLEANUP_SCHEDULE']),
|
|
97
101
|
};
|
|
@@ -3,8 +3,8 @@ import express from 'express';
|
|
|
3
3
|
import { respond } from '../middleware/respond.js';
|
|
4
4
|
import useCollection from '../middleware/use-collection.js';
|
|
5
5
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
6
|
-
import { MetaService } from '../services/meta.js';
|
|
7
6
|
import { AccessService } from '../services/access.js';
|
|
7
|
+
import { MetaService } from '../services/meta.js';
|
|
8
8
|
import asyncHandler from '../utils/async-handler.js';
|
|
9
9
|
import { sanitizeQuery } from '../utils/sanitize-query.js';
|
|
10
10
|
const router = express.Router();
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { useEnv } from '@directus/env';
|
|
2
|
-
import { InvalidQueryError, RangeNotSatisfiableError } from '@directus/errors';
|
|
2
|
+
import { InvalidPayloadError, InvalidQueryError, RangeNotSatisfiableError } from '@directus/errors';
|
|
3
3
|
import { TransformationMethods } from '@directus/types';
|
|
4
|
-
import { parseJSON } from '@directus/utils';
|
|
4
|
+
import { getDateTimeFormatted, parseJSON } from '@directus/utils';
|
|
5
5
|
import contentDisposition from 'content-disposition';
|
|
6
6
|
import { Router } from 'express';
|
|
7
7
|
import { merge, pick } from 'lodash-es';
|
|
8
|
+
import * as z from 'zod';
|
|
9
|
+
import { fromZodError } from 'zod-validation-error';
|
|
8
10
|
import { ASSET_TRANSFORM_QUERY_KEYS, SYSTEM_ASSET_ALLOW_LIST } from '../constants.js';
|
|
9
11
|
import getDatabase from '../database/index.js';
|
|
10
12
|
import { useLogger } from '../logger/index.js';
|
|
@@ -15,9 +17,44 @@ import asyncHandler from '../utils/async-handler.js';
|
|
|
15
17
|
import { getCacheControlHeader } from '../utils/get-cache-headers.js';
|
|
16
18
|
import { getConfigFromEnv } from '../utils/get-config-from-env.js';
|
|
17
19
|
import { getMilliseconds } from '../utils/get-milliseconds.js';
|
|
20
|
+
import { isValidUuid } from '../utils/is-valid-uuid.js';
|
|
18
21
|
const router = Router();
|
|
19
22
|
const env = useEnv();
|
|
20
23
|
router.use(useCollection('directus_files'));
|
|
24
|
+
router.post('/folder/:pk', asyncHandler(async (req, res) => {
|
|
25
|
+
const service = new AssetsService({
|
|
26
|
+
accountability: req.accountability,
|
|
27
|
+
schema: req.schema,
|
|
28
|
+
});
|
|
29
|
+
const { archive, complete, metadata } = await service.zipFolder(req.params['pk']);
|
|
30
|
+
res.setHeader('Content-Type', 'application/zip');
|
|
31
|
+
res.setHeader('Content-Disposition', `attachment; filename="folder-${metadata['name'] ? metadata['name'] : 'unknown'}-${getDateTimeFormatted()}.zip"`);
|
|
32
|
+
archive.pipe(res);
|
|
33
|
+
await complete();
|
|
34
|
+
}));
|
|
35
|
+
router.post('/files/', asyncHandler(async (req, res) => {
|
|
36
|
+
const service = new AssetsService({
|
|
37
|
+
accountability: req.accountability,
|
|
38
|
+
schema: req.schema,
|
|
39
|
+
});
|
|
40
|
+
const { error, data } = z
|
|
41
|
+
.object({
|
|
42
|
+
ids: z
|
|
43
|
+
.array(z.string().refine((v) => isValidUuid(v), {
|
|
44
|
+
error: '"id" must be a uuid',
|
|
45
|
+
}))
|
|
46
|
+
.min(1),
|
|
47
|
+
})
|
|
48
|
+
.safeParse(req.body);
|
|
49
|
+
if (error) {
|
|
50
|
+
throw new InvalidPayloadError({ reason: fromZodError(error).message });
|
|
51
|
+
}
|
|
52
|
+
const { archive, complete } = await service.zipFiles(data.ids);
|
|
53
|
+
res.setHeader('Content-Type', 'application/zip');
|
|
54
|
+
res.setHeader('Content-Disposition', `attachment; filename="files-${getDateTimeFormatted()}.zip"`);
|
|
55
|
+
archive.pipe(res);
|
|
56
|
+
await complete();
|
|
57
|
+
}));
|
|
21
58
|
router.get('/:pk/:filename?',
|
|
22
59
|
// Validate query params
|
|
23
60
|
asyncHandler(async (req, res, next) => {
|
|
@@ -152,7 +189,7 @@ asyncHandler(async (req, res) => {
|
|
|
152
189
|
}
|
|
153
190
|
}
|
|
154
191
|
const { stream, file, stat } = await service.getAsset(id, { transformationParams, acceptFormat }, range, true);
|
|
155
|
-
const filename = req.params['filename'] ?? file.filename_download;
|
|
192
|
+
const filename = req.params['filename'] ?? file.filename_download ?? file.id;
|
|
156
193
|
res.attachment(filename);
|
|
157
194
|
res.setHeader('Content-Type', file.type);
|
|
158
195
|
res.setHeader('Accept-Ranges', 'bytes');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { EXTENSION_TYPES } from '@directus/constants';
|
|
1
2
|
import { useEnv } from '@directus/env';
|
|
2
3
|
import { ErrorCode, ForbiddenError, isDirectusError, RouteNotFoundError } from '@directus/errors';
|
|
3
|
-
import { EXTENSION_TYPES } from '@directus/constants';
|
|
4
4
|
import { account, describe, list, } from '@directus/extensions-registry';
|
|
5
5
|
import { isIn } from '@directus/utils';
|
|
6
6
|
import express from 'express';
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { TYPES } from '@directus/constants';
|
|
2
|
+
import { ErrorCode, InvalidPayloadError } from '@directus/errors';
|
|
2
3
|
import { ForbiddenError, isDirectusError } from '@directus/errors';
|
|
4
|
+
import { isSystemField } from '@directus/system-data';
|
|
3
5
|
import { Router } from 'express';
|
|
4
6
|
import Joi from 'joi';
|
|
5
7
|
import { ALIAS_TYPES } from '../constants.js';
|
|
6
|
-
import { ErrorCode, InvalidPayloadError } from '@directus/errors';
|
|
7
8
|
import validateCollection from '../middleware/collection-exists.js';
|
|
8
9
|
import { respond } from '../middleware/respond.js';
|
|
9
10
|
import useCollection from '../middleware/use-collection.js';
|
|
10
11
|
import { FieldsService, systemFieldUpdateSchema } from '../services/fields.js';
|
|
11
12
|
import asyncHandler from '../utils/async-handler.js';
|
|
12
|
-
import { isSystemField } from '@directus/system-data';
|
|
13
13
|
const router = Router();
|
|
14
14
|
router.use(useCollection('directus_fields'));
|
|
15
15
|
router.get('/', asyncHandler(async (req, res, next) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from 'path';
|
|
1
2
|
import { useEnv } from '@directus/env';
|
|
2
3
|
import { ErrorCode, InvalidPayloadError, isDirectusError } from '@directus/errors';
|
|
3
4
|
import formatTitle from '@directus/format-title';
|
|
@@ -7,7 +8,6 @@ import bytes from 'bytes';
|
|
|
7
8
|
import express from 'express';
|
|
8
9
|
import Joi from 'joi';
|
|
9
10
|
import { minimatch } from 'minimatch';
|
|
10
|
-
import path from 'path';
|
|
11
11
|
import { respond } from '../middleware/respond.js';
|
|
12
12
|
import useCollection from '../middleware/use-collection.js';
|
|
13
13
|
import { validateBatch } from '../middleware/validate-batch.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ErrorCode, ForbiddenError,
|
|
1
|
+
import { ErrorCode, ForbiddenError, isDirectusError, RouteNotFoundError } from '@directus/errors';
|
|
2
2
|
import { isSystemCollection } from '@directus/system-data';
|
|
3
3
|
import express from 'express';
|
|
4
4
|
import collectionExists from '../middleware/collection-exists.js';
|
package/dist/controllers/mcp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ForbiddenError } from '@directus/errors';
|
|
2
2
|
import { Router } from 'express';
|
|
3
|
-
import { DirectusMCP } from '../mcp/index.js';
|
|
3
|
+
import { DirectusMCP } from '../ai/mcp/index.js';
|
|
4
4
|
import { SettingsService } from '../services/settings.js';
|
|
5
5
|
import asyncHandler from '../utils/async-handler.js';
|
|
6
6
|
const router = Router();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ErrorCode, InvalidPayloadError } from '@directus/errors';
|
|
1
2
|
import { isDirectusError } from '@directus/errors';
|
|
2
3
|
import express from 'express';
|
|
3
4
|
import Joi from 'joi';
|
|
4
|
-
import { ErrorCode, InvalidPayloadError } from '@directus/errors';
|
|
5
5
|
import validateCollection from '../middleware/collection-exists.js';
|
|
6
6
|
import { respond } from '../middleware/respond.js';
|
|
7
7
|
import useCollection from '../middleware/use-collection.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import getDatabase, { getDatabaseClient } from '../index.js';
|
|
2
1
|
import emitter from '../../emitter.js';
|
|
2
|
+
import getDatabase, { getDatabaseClient } from '../index.js';
|
|
3
3
|
import { extractError as mssql } from './dialects/mssql.js';
|
|
4
4
|
import { extractError as mysql } from './dialects/mysql.js';
|
|
5
5
|
import { extractError as oracle } from './dialects/oracle.js';
|
|
@@ -5,6 +5,7 @@ import { SchemaHelper } from '../types.js';
|
|
|
5
5
|
export declare class SchemaHelperCockroachDb extends SchemaHelper {
|
|
6
6
|
changeToType(table: string, column: string, type: (typeof KNEX_TYPES)[number], options?: Options): Promise<void>;
|
|
7
7
|
constraintName(existingName: string): string;
|
|
8
|
+
changePrimaryKey(table: string, to: string | string[]): Promise<void>;
|
|
8
9
|
getDatabaseSize(): Promise<number | null>;
|
|
9
10
|
addInnerSortFieldsToGroupBy(groupByFields: (string | Knex.Raw)[], sortRecords: SortRecord[], hasRelationalSort: boolean): void;
|
|
10
11
|
createIndex(collection: string, field: string, options?: CreateIndexOptions): Promise<Knex.SchemaBuilder>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { useEnv } from '@directus/env';
|
|
3
|
+
import { toArray } from '@directus/utils';
|
|
1
4
|
import {} from 'knex';
|
|
2
5
|
import { SchemaHelper } from '../types.js';
|
|
3
|
-
import { useEnv } from '@directus/env';
|
|
4
6
|
const env = useEnv();
|
|
5
7
|
export class SchemaHelperCockroachDb extends SchemaHelper {
|
|
6
8
|
async changeToType(table, column, type, options = {}) {
|
|
@@ -17,6 +19,27 @@ export class SchemaHelperCockroachDb extends SchemaHelper {
|
|
|
17
19
|
return existingName + suffix;
|
|
18
20
|
}
|
|
19
21
|
}
|
|
22
|
+
async changePrimaryKey(table, to) {
|
|
23
|
+
const primaryColumns = toArray(to);
|
|
24
|
+
const placeholders = primaryColumns.map(() => '??').join(', ');
|
|
25
|
+
assert(primaryColumns.length > 0, 'At least 1 "to" column is required');
|
|
26
|
+
assert(primaryColumns[0] && primaryColumns[0].length > 0, '"to" column cannot be empty');
|
|
27
|
+
/* Before adding the new PK field(s) we drop the existing constraint to ensure no leftover secondary index on the original PK field.
|
|
28
|
+
* - https://www.cockroachlabs.com/docs/stable/primary-key#changing-primary-key-columns
|
|
29
|
+
*
|
|
30
|
+
* CockroachDB requires that when changing a PK the current one be dropped and new one added in the same transaction.
|
|
31
|
+
* To prevent this error from being thrown both operations are executed in the same statement via `,`.
|
|
32
|
+
* As it is done in a single operation no need for transaction rollback support.
|
|
33
|
+
* - https://www.cockroachlabs.com/docs/stable/primary-key.html
|
|
34
|
+
* - https://www.cockroachlabs.com/docs/stable/alter-table#synopsis
|
|
35
|
+
*/
|
|
36
|
+
await this.knex.raw(`ALTER TABLE ?? DROP CONSTRAINT ?? , ADD CONSTRAINT ?? PRIMARY KEY (${placeholders})`, [
|
|
37
|
+
table,
|
|
38
|
+
`${table}_pkey`,
|
|
39
|
+
`${table}_pkey`,
|
|
40
|
+
...primaryColumns,
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
20
43
|
async getDatabaseSize() {
|
|
21
44
|
try {
|
|
22
45
|
const result = await this.knex
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import {
|
|
2
|
+
import { type CreateIndexOptions, SchemaHelper, type SortRecord, type Sql } from '../types.js';
|
|
3
3
|
export declare class SchemaHelperMSSQL extends SchemaHelper {
|
|
4
4
|
generateIndexName(type: 'unique' | 'foreign' | 'index', collection: string, fields: string | string[]): string;
|
|
5
5
|
applyLimit(rootQuery: Knex.QueryBuilder, limit: number): void;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import {
|
|
2
|
+
import { type CreateIndexOptions, SchemaHelper, type SortRecord } from '../types.js';
|
|
3
3
|
export declare class SchemaHelperMySQL extends SchemaHelper {
|
|
4
4
|
generateIndexName(type: 'unique' | 'foreign' | 'index', collection: string, fields: string | string[]): string;
|
|
5
|
+
changePrimaryKey(table: string, to: string | string[]): Promise<void>;
|
|
5
6
|
getDatabaseSize(): Promise<number | null>;
|
|
6
7
|
addInnerSortFieldsToGroupBy(groupByFields: (string | Knex.Raw)[], sortRecords: SortRecord[], hasRelationalSort: boolean): void;
|
|
7
8
|
createIndex(collection: string, field: string, options?: CreateIndexOptions): Promise<Knex.SchemaBuilder>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
1
2
|
import { useEnv } from '@directus/env';
|
|
3
|
+
import { toArray } from '@directus/utils';
|
|
2
4
|
import { getDefaultIndexName } from '../../../../utils/get-default-index-name.js';
|
|
3
5
|
import { SchemaHelper } from '../types.js';
|
|
4
6
|
const env = useEnv();
|
|
@@ -6,6 +8,17 @@ export class SchemaHelperMySQL extends SchemaHelper {
|
|
|
6
8
|
generateIndexName(type, collection, fields) {
|
|
7
9
|
return getDefaultIndexName(type, collection, fields, { maxLength: 64 });
|
|
8
10
|
}
|
|
11
|
+
async changePrimaryKey(table, to) {
|
|
12
|
+
const primaryColumns = toArray(to);
|
|
13
|
+
const placeholders = primaryColumns.map(() => '??').join(', ');
|
|
14
|
+
// validate input
|
|
15
|
+
assert(primaryColumns.length > 0, 'At least 1 "to" column is required');
|
|
16
|
+
assert(primaryColumns[0] && primaryColumns[0].length > 0, '"to" column cannot be empty');
|
|
17
|
+
await this.knex.raw(`ALTER TABLE ?? DROP PRIMARY KEY, ADD PRIMARY KEY (${placeholders})`, [
|
|
18
|
+
table,
|
|
19
|
+
...primaryColumns,
|
|
20
|
+
]);
|
|
21
|
+
}
|
|
9
22
|
async getDatabaseSize() {
|
|
10
23
|
try {
|
|
11
24
|
const result = (await this.knex
|
|
@@ -29,8 +42,8 @@ export class SchemaHelperMySQL extends SchemaHelper {
|
|
|
29
42
|
MySQL only requires all selected sort columns that are not functionally dependent on the primary key to be included.
|
|
30
43
|
|
|
31
44
|
> If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default),
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
MySQL rejects queries for which the select list, HAVING condition, or ORDER BY list refer to
|
|
46
|
+
nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on them.
|
|
34
47
|
|
|
35
48
|
https://dev.mysql.com/doc/refman/8.4/en/group-by-handling.html
|
|
36
49
|
|
|
@@ -66,7 +79,7 @@ export class SchemaHelperMySQL extends SchemaHelper {
|
|
|
66
79
|
/*
|
|
67
80
|
Seems it is not possible to determine whether "ALGORITHM=INPLACE LOCK=NONE" will be supported
|
|
68
81
|
so we're just going to send it and fall back to blocking index creation on error
|
|
69
|
-
|
|
82
|
+
|
|
70
83
|
https://dev.mysql.com/doc/refman/8.4/en/create-index.html#:~:text=engine%20is%20changed.-,Table%20Copying%20and%20Locking%20Options,-ALGORITHM%20and%20LOCK
|
|
71
84
|
*/
|
|
72
85
|
return this.knex
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
-
import {
|
|
2
|
+
import { type CreateIndexOptions, SchemaHelper, type SortRecord } from '../types.js';
|
|
3
3
|
export declare class SchemaHelperPostgres extends SchemaHelper {
|
|
4
4
|
generateIndexName(type: 'unique' | 'foreign' | 'index', collection: string, fields: string | string[]): string;
|
|
5
5
|
getDatabaseSize(): Promise<number | null>;
|
|
@@ -25,6 +25,19 @@ export declare abstract class SchemaHelper extends DatabaseHelper {
|
|
|
25
25
|
changeNullable(table: string, column: string, nullable: boolean): Promise<void>;
|
|
26
26
|
generateIndexName(type: 'unique' | 'foreign' | 'index', collection: string, fields: string | string[]): string;
|
|
27
27
|
changeToType(table: string, column: string, type: (typeof KNEX_TYPES)[number], options?: Options): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Change a tables primary key
|
|
30
|
+
*
|
|
31
|
+
* @param table - The name of the table
|
|
32
|
+
* @param to - The new primary key column name(s)
|
|
33
|
+
*
|
|
34
|
+
* * @example
|
|
35
|
+
* // Changing a single primary key
|
|
36
|
+
* await changePrimaryKey('users', 'uuid');
|
|
37
|
+
* * // Creating a composite primary key
|
|
38
|
+
* await changePrimaryKey('order_items', ['order_id', 'product_id']);
|
|
39
|
+
*/
|
|
40
|
+
changePrimaryKey(table: string, to: string | string[]): Promise<void>;
|
|
28
41
|
protected changeToTypeByCopy(table: string, column: string, type: (typeof KNEX_TYPES)[number], options: Options): Promise<void>;
|
|
29
42
|
preColumnChange(): Promise<boolean>;
|
|
30
43
|
postColumnChange(): Promise<void>;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { toArray } from '@directus/utils';
|
|
1
3
|
import { getDefaultIndexName } from '../../../utils/get-default-index-name.js';
|
|
2
4
|
import { getDatabaseClient } from '../../index.js';
|
|
3
5
|
import { DatabaseHelper } from '../types.js';
|
|
@@ -33,6 +35,28 @@ export class SchemaHelper extends DatabaseHelper {
|
|
|
33
35
|
b.alter();
|
|
34
36
|
});
|
|
35
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Change a tables primary key
|
|
40
|
+
*
|
|
41
|
+
* @param table - The name of the table
|
|
42
|
+
* @param to - The new primary key column name(s)
|
|
43
|
+
*
|
|
44
|
+
* * @example
|
|
45
|
+
* // Changing a single primary key
|
|
46
|
+
* await changePrimaryKey('users', 'uuid');
|
|
47
|
+
* * // Creating a composite primary key
|
|
48
|
+
* await changePrimaryKey('order_items', ['order_id', 'product_id']);
|
|
49
|
+
*/
|
|
50
|
+
async changePrimaryKey(table, to) {
|
|
51
|
+
const primaryColumns = toArray(to);
|
|
52
|
+
// validate input
|
|
53
|
+
assert(primaryColumns.length > 0, 'At least 1 "to" column is required');
|
|
54
|
+
assert(primaryColumns[0] && primaryColumns[0].length > 0, '"to" column cannot be empty');
|
|
55
|
+
await this.knex.schema.alterTable(table, (builder) => {
|
|
56
|
+
builder.dropPrimary();
|
|
57
|
+
builder.primary(primaryColumns);
|
|
58
|
+
});
|
|
59
|
+
}
|
|
36
60
|
async changeToTypeByCopy(table, column, type, options) {
|
|
37
61
|
const tempName = `${column}__temp`;
|
|
38
62
|
await this.knex.schema.alterTable(table, (builder) => {
|
package/dist/database/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { dirname } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { performance } from 'perf_hooks';
|
|
1
5
|
import { useEnv } from '@directus/env';
|
|
2
6
|
import { createInspector } from '@directus/schema';
|
|
3
7
|
import { isObject } from '@directus/utils';
|
|
4
8
|
import fse from 'fs-extra';
|
|
5
9
|
import knex from 'knex';
|
|
6
10
|
import { isArray, merge, toArray } from 'lodash-es';
|
|
7
|
-
import { dirname } from 'node:path';
|
|
8
|
-
import { fileURLToPath } from 'node:url';
|
|
9
|
-
import path from 'path';
|
|
10
|
-
import { performance } from 'perf_hooks';
|
|
11
11
|
import { getExtensionsPath } from '../extensions/lib/get-extensions-path.js';
|
|
12
12
|
import { useLogger } from '../logger/index.js';
|
|
13
13
|
import { useMetrics } from '../metrics/index.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parseJSON, toArray } from '@directus/utils';
|
|
2
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { parseJSON, toArray } from '@directus/utils';
|
|
3
3
|
export async function up(knex) {
|
|
4
4
|
await knex.schema.createTable('directus_flows', (table) => {
|
|
5
5
|
table.uuid('id').primary().notNullable();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { getHelpers } from '../helpers/index.js';
|
|
2
1
|
import { createInspector } from '@directus/schema';
|
|
2
|
+
import { getHelpers } from '../helpers/index.js';
|
|
3
3
|
export async function up(knex) {
|
|
4
4
|
const inspector = createInspector(knex);
|
|
5
5
|
const helper = getHelpers(knex).schema;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { resolvePackage } from '@directus/utils/node';
|
|
2
1
|
import { randomUUID } from 'node:crypto';
|
|
3
2
|
import { dirname } from 'node:path';
|
|
4
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { resolvePackage } from '@directus/utils/node';
|
|
5
|
+
import { getHelpers } from '../helpers/index.js';
|
|
5
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
7
|
export async function up(knex) {
|
|
7
8
|
await knex.schema.alterTable('directus_extensions', (table) => {
|
|
@@ -58,11 +59,9 @@ export async function up(knex) {
|
|
|
58
59
|
await knex.schema.alterTable('directus_extensions', (table) => {
|
|
59
60
|
table.uuid('id').alter().notNullable();
|
|
60
61
|
});
|
|
62
|
+
// knex does not bundle the drop + add PK, the transaction ensures they are apart of the same commit for databases that require it
|
|
61
63
|
await knex.transaction(async (trx) => {
|
|
62
|
-
await trx.schema.
|
|
63
|
-
table.dropPrimary();
|
|
64
|
-
table.primary(['id']);
|
|
65
|
-
});
|
|
64
|
+
await getHelpers(trx).schema.changePrimaryKey('directus_extensions', ['id']);
|
|
66
65
|
});
|
|
67
66
|
await knex.schema.alterTable('directus_extensions', (table) => {
|
|
68
67
|
table.dropColumn('name');
|
|
@@ -79,7 +78,7 @@ export async function down(knex) {
|
|
|
79
78
|
await knex.schema.alterTable('directus_extensions', (table) => {
|
|
80
79
|
table.string('name');
|
|
81
80
|
});
|
|
82
|
-
const installedExtensions = await knex.select(['id', 'folder', 'bundle']).from('directus_extensions');
|
|
81
|
+
const installedExtensions = await knex.select(['id', 'folder', 'bundle', 'source']).from('directus_extensions');
|
|
83
82
|
const idMap = new Map(installedExtensions.map((extension) => [extension.id, extension.folder]));
|
|
84
83
|
for (const { id, folder, bundle, source } of installedExtensions) {
|
|
85
84
|
if (source === 'registry') {
|
|
@@ -93,8 +92,11 @@ export async function down(knex) {
|
|
|
93
92
|
}
|
|
94
93
|
await knex('directus_extensions').update({ name }).where({ id });
|
|
95
94
|
}
|
|
95
|
+
await knex.transaction(async (trx) => {
|
|
96
|
+
await getHelpers(trx).schema.changePrimaryKey('directus_extensions', ['name']);
|
|
97
|
+
});
|
|
96
98
|
await knex.schema.alterTable('directus_extensions', (table) => {
|
|
97
99
|
table.dropColumns('id', 'folder', 'source', 'bundle');
|
|
98
|
-
table.string('name').alter().
|
|
100
|
+
table.string('name').alter().notNullable();
|
|
99
101
|
});
|
|
100
102
|
}
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import type { Knex } from 'knex';
|
|
2
|
+
export type Webhook = {
|
|
3
|
+
id: number;
|
|
4
|
+
name: string;
|
|
5
|
+
method: 'GET' | 'POST';
|
|
6
|
+
url: string;
|
|
7
|
+
status: 'active' | 'inactive';
|
|
8
|
+
data: boolean;
|
|
9
|
+
actions: string[];
|
|
10
|
+
collections: string[];
|
|
11
|
+
headers: WebhookHeader[];
|
|
12
|
+
};
|
|
13
|
+
export type WebhookHeader = {
|
|
14
|
+
header: string;
|
|
15
|
+
value: string;
|
|
16
|
+
};
|
|
2
17
|
/**
|
|
3
18
|
* 0. Identify and persist which webhooks were active before deprecation
|
|
4
19
|
* 1. Migrate existing webhooks over to identically behaving Flows
|