@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.
Files changed (336) hide show
  1. package/dist/ai/chat/constants/system-prompt.d.ts +1 -0
  2. package/dist/ai/chat/constants/system-prompt.js +51 -0
  3. package/dist/ai/chat/controllers/chat.post.d.ts +2 -0
  4. package/dist/ai/chat/controllers/chat.post.js +47 -0
  5. package/dist/ai/chat/lib/create-ui-stream.d.ts +15 -0
  6. package/dist/ai/chat/lib/create-ui-stream.js +42 -0
  7. package/dist/ai/chat/middleware/load-settings.d.ts +2 -0
  8. package/dist/ai/chat/middleware/load-settings.js +18 -0
  9. package/dist/ai/chat/models/chat-request.d.ts +34 -0
  10. package/dist/ai/chat/models/chat-request.js +26 -0
  11. package/dist/ai/chat/models/providers.d.ts +9 -0
  12. package/dist/ai/chat/models/providers.js +9 -0
  13. package/dist/ai/chat/router.d.ts +1 -0
  14. package/dist/ai/chat/router.js +5 -0
  15. package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.d.ts +9 -0
  16. package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.js +38 -0
  17. package/dist/ai/chat/utils/fix-error-tool-calls.d.ts +12 -0
  18. package/dist/ai/chat/utils/fix-error-tool-calls.js +30 -0
  19. package/dist/ai/chat/utils/parse-json-schema-7.d.ts +13 -0
  20. package/dist/ai/chat/utils/parse-json-schema-7.js +75 -0
  21. package/dist/{mcp → ai/mcp}/server.d.ts +13 -16
  22. package/dist/{mcp → ai/mcp}/server.js +4 -13
  23. package/dist/ai/mcp/types.d.ts +15 -0
  24. package/dist/{mcp/tools/assets.js → ai/tools/assets/index.js} +8 -5
  25. package/dist/{mcp/tools/collections.js → ai/tools/collections/index.js} +7 -4
  26. package/dist/{mcp/tools/fields.js → ai/tools/fields/index.js} +12 -9
  27. package/dist/{mcp/tools/files.js → ai/tools/files/index.js} +11 -5
  28. package/dist/{mcp/tools/flows.js → ai/tools/flows/index.js} +11 -5
  29. package/dist/{mcp/tools/folders.js → ai/tools/folders/index.js} +12 -5
  30. package/dist/ai/tools/index.d.ts +15 -0
  31. package/dist/ai/tools/index.js +29 -0
  32. package/dist/{mcp/tools/items.js → ai/tools/items/index.js} +13 -6
  33. package/dist/{mcp/tools/prompts/items.md → ai/tools/items/prompt.md} +19 -15
  34. package/dist/{mcp/tools/operations.d.ts → ai/tools/operations/index.d.ts} +46 -0
  35. package/dist/{mcp/tools/operations.js → ai/tools/operations/index.js} +12 -5
  36. package/dist/{mcp/tools/relations.js → ai/tools/relations/index.js} +7 -4
  37. package/dist/{mcp/tools/schema.d.ts → ai/tools/schema/index.d.ts} +1 -1
  38. package/dist/{mcp/tools/schema.js → ai/tools/schema/index.js} +9 -6
  39. package/dist/{mcp/tools/system.js → ai/tools/system/index.js} +7 -4
  40. package/dist/{mcp/tools/trigger-flow.js → ai/tools/trigger-flow/index.js} +8 -5
  41. package/dist/{mcp → ai/tools}/types.d.ts +1 -17
  42. package/dist/ai/tools/utils.d.ts +9 -0
  43. package/dist/ai/tools/utils.js +17 -0
  44. package/dist/app.js +11 -6
  45. package/dist/auth/drivers/ldap.js +2 -2
  46. package/dist/auth/drivers/local.js +1 -1
  47. package/dist/auth/drivers/oauth2.d.ts +1 -2
  48. package/dist/auth/drivers/oauth2.js +22 -17
  49. package/dist/auth/drivers/openid.d.ts +1 -2
  50. package/dist/auth/drivers/openid.js +18 -13
  51. package/dist/auth/drivers/saml.js +6 -3
  52. package/dist/auth/utils/generate-callback-url.d.ts +11 -0
  53. package/dist/auth/utils/generate-callback-url.js +40 -0
  54. package/dist/auth/utils/is-login-redirect-allowed.d.ts +7 -0
  55. package/dist/{utils → auth/utils}/is-login-redirect-allowed.js +12 -9
  56. package/dist/cache.js +2 -2
  57. package/dist/cli/commands/bootstrap/index.js +2 -2
  58. package/dist/cli/commands/database/install.js +1 -1
  59. package/dist/cli/commands/database/migrate.js +1 -1
  60. package/dist/cli/commands/init/index.js +2 -2
  61. package/dist/cli/commands/roles/create.js +4 -4
  62. package/dist/cli/commands/schema/apply.js +3 -3
  63. package/dist/cli/commands/schema/snapshot.js +1 -1
  64. package/dist/cli/utils/create-db-connection.d.ts +1 -1
  65. package/dist/cli/utils/create-db-connection.js +1 -1
  66. package/dist/cli/utils/create-env/index.js +1 -1
  67. package/dist/constants.d.ts +7 -3
  68. package/dist/constants.js +7 -3
  69. package/dist/controllers/access.js +1 -1
  70. package/dist/controllers/assets.js +40 -3
  71. package/dist/controllers/extensions.js +1 -1
  72. package/dist/controllers/fields.js +2 -2
  73. package/dist/controllers/files.js +1 -1
  74. package/dist/controllers/items.js +1 -1
  75. package/dist/controllers/mcp.js +1 -1
  76. package/dist/controllers/not-found.js +1 -1
  77. package/dist/controllers/relations.js +1 -1
  78. package/dist/database/errors/dialects/mysql.d.ts +1 -1
  79. package/dist/database/errors/dialects/postgres.d.ts +1 -1
  80. package/dist/database/errors/dialects/sqlite.d.ts +1 -1
  81. package/dist/database/errors/translate.d.ts +1 -1
  82. package/dist/database/errors/translate.js +1 -1
  83. package/dist/database/helpers/date/dialects/mssql.js +1 -1
  84. package/dist/database/helpers/date/dialects/mysql.js +1 -1
  85. package/dist/database/helpers/date/types.js +1 -1
  86. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +1 -0
  87. package/dist/database/helpers/schema/dialects/cockroachdb.js +24 -1
  88. package/dist/database/helpers/schema/dialects/mssql.d.ts +1 -1
  89. package/dist/database/helpers/schema/dialects/mysql.d.ts +2 -1
  90. package/dist/database/helpers/schema/dialects/mysql.js +16 -3
  91. package/dist/database/helpers/schema/dialects/postgres.d.ts +1 -1
  92. package/dist/database/helpers/schema/types.d.ts +13 -0
  93. package/dist/database/helpers/schema/types.js +24 -0
  94. package/dist/database/index.js +4 -4
  95. package/dist/database/migrations/20220429A-add-flows.js +1 -1
  96. package/dist/database/migrations/20230526A-migrate-translation-strings.js +1 -1
  97. package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +1 -1
  98. package/dist/database/migrations/20240204A-marketplace.js +9 -7
  99. package/dist/database/migrations/20240311A-deprecate-webhooks.d.ts +15 -0
  100. package/dist/database/migrations/20240311A-deprecate-webhooks.js +1 -1
  101. package/dist/database/migrations/20240806A-permissions-policies.js +3 -3
  102. package/dist/database/migrations/20240924A-migrate-legacy-comments.js +1 -1
  103. package/dist/database/migrations/20251014A-add-project-owner.js +1 -1
  104. package/dist/database/migrations/20251103A-add-ai-settings.d.ts +3 -0
  105. package/dist/database/migrations/20251103A-add-ai-settings.js +14 -0
  106. package/dist/database/migrations/20251224A-remove-webhooks.d.ts +3 -0
  107. package/dist/database/migrations/20251224A-remove-webhooks.js +19 -0
  108. package/dist/database/migrations/20260113A-add-revisions-index.d.ts +3 -0
  109. package/dist/database/migrations/20260113A-add-revisions-index.js +41 -0
  110. package/dist/database/migrations/run.js +3 -3
  111. package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.d.ts +2 -2
  112. package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.js +1 -1
  113. package/dist/database/run-ast/lib/apply-query/filter/operator.js +1 -1
  114. package/dist/database/run-ast/lib/apply-query/sort.js +1 -1
  115. package/dist/database/run-ast/run-ast.js +1 -1
  116. package/dist/database/run-ast/utils/get-column-pre-processor.js +2 -2
  117. package/dist/database/run-ast/utils/get-column.js +1 -1
  118. package/dist/database/seeds/run.js +3 -3
  119. package/dist/extensions/lib/get-extensions-path.js +1 -1
  120. package/dist/extensions/lib/get-extensions-settings.js +1 -1
  121. package/dist/extensions/lib/get-extensions.js +1 -1
  122. package/dist/extensions/lib/get-shared-deps-mapping.js +3 -3
  123. package/dist/extensions/lib/installation/manager.js +8 -12
  124. package/dist/extensions/lib/sandbox/register/route.d.ts +1 -1
  125. package/dist/extensions/lib/sync/status.d.ts +11 -0
  126. package/dist/extensions/lib/sync/status.js +34 -0
  127. package/dist/extensions/lib/sync/sync.d.ts +6 -0
  128. package/dist/extensions/lib/sync/sync.js +90 -0
  129. package/dist/extensions/lib/sync/tracker.d.ts +18 -0
  130. package/dist/extensions/lib/sync/tracker.js +71 -0
  131. package/dist/extensions/lib/sync/utils.d.ts +24 -0
  132. package/dist/extensions/lib/sync/utils.js +62 -0
  133. package/dist/extensions/manager.d.ts +9 -5
  134. package/dist/extensions/manager.js +36 -19
  135. package/dist/flows.d.ts +1 -1
  136. package/dist/logger/index.js +1 -1
  137. package/dist/logger/logs-stream.d.ts +1 -1
  138. package/dist/logger/logs-stream.js +1 -1
  139. package/dist/mailer.js +1 -1
  140. package/dist/metrics/lib/create-metrics.js +2 -2
  141. package/dist/middleware/authenticate.js +3 -3
  142. package/dist/middleware/collection-exists.js +1 -1
  143. package/dist/middleware/extract-token.js +1 -1
  144. package/dist/middleware/graphql.js +2 -2
  145. package/dist/middleware/respond.js +2 -2
  146. package/dist/middleware/validate-batch.js +1 -1
  147. package/dist/operations/exec/index.js +2 -1
  148. package/dist/operations/mail/index.js +1 -1
  149. package/dist/operations/mail/rate-limiter.js +2 -2
  150. package/dist/permissions/cache.js +5 -0
  151. package/dist/permissions/lib/fetch-policies.d.ts +1 -1
  152. package/dist/permissions/lib/fetch-roles-tree.d.ts +6 -3
  153. package/dist/permissions/lib/fetch-roles-tree.js +5 -27
  154. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +1 -1
  155. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +1 -1
  156. package/dist/permissions/modules/fetch-global-access/fetch-global-access.d.ts +9 -7
  157. package/dist/permissions/modules/fetch-global-access/fetch-global-access.js +17 -9
  158. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +2 -2
  159. package/dist/permissions/modules/fetch-policies-ip-access/fetch-policies-ip-access.d.ts +1 -1
  160. package/dist/permissions/modules/process-ast/lib/inject-cases.js +1 -1
  161. package/dist/permissions/modules/process-ast/process-ast.js +1 -1
  162. package/dist/permissions/modules/process-payload/process-payload.js +1 -1
  163. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +13 -1
  164. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +54 -6
  165. package/dist/permissions/modules/validate-access/validate-access.js +3 -2
  166. package/dist/permissions/utils/fetch-raw-permissions.d.ts +1 -1
  167. package/dist/permissions/utils/fetch-share-info.d.ts +1 -1
  168. package/dist/permissions/utils/fetch-share-info.js +1 -1
  169. package/dist/permissions/utils/filter-policies-by-ip.js +1 -1
  170. package/dist/permissions/utils/get-permissions-for-share.js +8 -8
  171. package/dist/permissions/utils/with-cache.d.ts +8 -6
  172. package/dist/permissions/utils/with-cache.js +12 -10
  173. package/dist/rate-limiter.js +1 -1
  174. package/dist/request/is-denied-ip.js +2 -2
  175. package/dist/schedules/project.js +1 -1
  176. package/dist/schedules/telemetry.js +1 -1
  177. package/dist/schedules/tus.js +1 -1
  178. package/dist/server.js +4 -4
  179. package/dist/services/assets/name-deduper.d.ts +7 -0
  180. package/dist/services/assets/name-deduper.js +23 -0
  181. package/dist/services/assets.d.ts +17 -3
  182. package/dist/services/assets.js +133 -13
  183. package/dist/services/authentication.js +6 -6
  184. package/dist/services/collections.js +1 -1
  185. package/dist/services/comments.js +2 -2
  186. package/dist/services/extensions.d.ts +1 -1
  187. package/dist/services/extensions.js +4 -0
  188. package/dist/services/files/utils/get-metadata.d.ts +1 -1
  189. package/dist/services/files/utils/get-metadata.js +1 -1
  190. package/dist/services/files.d.ts +1 -1
  191. package/dist/services/files.js +4 -4
  192. package/dist/services/folders.d.ts +27 -2
  193. package/dist/services/folders.js +75 -0
  194. package/dist/services/graphql/index.d.ts +1 -1
  195. package/dist/services/graphql/index.js +1 -1
  196. package/dist/services/graphql/resolvers/mutation.js +1 -1
  197. package/dist/services/graphql/schema/get-types.d.ts +1 -1
  198. package/dist/services/graphql/schema/read.js +1 -1
  199. package/dist/services/graphql/subscription.d.ts +1 -1
  200. package/dist/services/graphql/types/date.js +1 -1
  201. package/dist/services/graphql/types/hash.js +1 -1
  202. package/dist/services/graphql/utils/add-path-to-validation-error.js +1 -1
  203. package/dist/services/import-export.d.ts +2 -2
  204. package/dist/services/import-export.js +6 -7
  205. package/dist/services/index.d.ts +0 -1
  206. package/dist/services/index.js +0 -1
  207. package/dist/services/mail/index.js +2 -2
  208. package/dist/services/mail/rate-limiter.js +2 -2
  209. package/dist/services/notifications.js +2 -2
  210. package/dist/services/payload.js +21 -1
  211. package/dist/services/roles.js +2 -2
  212. package/dist/services/schema.js +1 -1
  213. package/dist/services/server.js +12 -4
  214. package/dist/services/settings.js +2 -2
  215. package/dist/services/tfa.js +1 -1
  216. package/dist/services/translations.js +1 -1
  217. package/dist/services/tus/data-store.d.ts +1 -3
  218. package/dist/services/tus/data-store.js +2 -5
  219. package/dist/services/tus/server.js +9 -9
  220. package/dist/services/users.js +4 -4
  221. package/dist/services/versions.js +1 -1
  222. package/dist/telemetry/lib/send-report.d.ts +1 -1
  223. package/dist/telemetry/lib/send-report.js +1 -1
  224. package/dist/telemetry/lib/track.js +1 -1
  225. package/dist/telemetry/utils/get-settings.d.ts +15 -0
  226. package/dist/telemetry/utils/get-settings.js +13 -1
  227. package/dist/test-utils/README.md +95 -24
  228. package/dist/test-utils/cache.d.ts +2 -2
  229. package/dist/test-utils/cache.js +2 -2
  230. package/dist/test-utils/knex.js +1 -1
  231. package/dist/test-utils/{fields-service.d.ts → services/fields-service.d.ts} +1 -1
  232. package/dist/test-utils/{fields-service.js → services/fields-service.js} +3 -2
  233. package/dist/test-utils/services/files-service.d.ts +28 -0
  234. package/dist/test-utils/services/files-service.js +34 -0
  235. package/dist/test-utils/services/folders-service.d.ts +28 -0
  236. package/dist/test-utils/services/folders-service.js +33 -0
  237. package/dist/types/collection.d.ts +1 -1
  238. package/dist/utils/async-handler.d.ts +1 -1
  239. package/dist/utils/calculate-field-depth.js +1 -1
  240. package/dist/utils/compress.js +1 -1
  241. package/dist/utils/deep-map-response.js +2 -2
  242. package/dist/utils/encrypt.d.ts +2 -0
  243. package/dist/utils/encrypt.js +64 -0
  244. package/dist/utils/get-accountability-for-role.js +2 -2
  245. package/dist/utils/get-accountability-for-token.js +4 -4
  246. package/dist/utils/get-cache-key.js +3 -3
  247. package/dist/utils/get-field-system-rows.js +1 -1
  248. package/dist/utils/get-ip-from-req.d.ts +1 -1
  249. package/dist/utils/get-ip-from-req.js +1 -1
  250. package/dist/utils/get-local-type.js +7 -3
  251. package/dist/utils/get-service.js +1 -3
  252. package/dist/utils/get-snapshot-diff.js +1 -1
  253. package/dist/utils/is-url-allowed.js +1 -1
  254. package/dist/utils/jwt.js +1 -1
  255. package/dist/utils/require-text.d.ts +1 -0
  256. package/dist/utils/require-text.js +4 -0
  257. package/dist/utils/require-yaml.js +2 -2
  258. package/dist/utils/sanitize-schema.d.ts +1 -1
  259. package/dist/utils/should-clear-cache.d.ts +1 -1
  260. package/dist/utils/should-skip-cache.js +2 -2
  261. package/dist/utils/validate-diff.js +1 -1
  262. package/dist/utils/validate-snapshot.js +3 -3
  263. package/dist/utils/validate-storage.js +2 -2
  264. package/dist/utils/verify-session-jwt.js +1 -1
  265. package/dist/utils/versioning/deep-map-with-schema.js +2 -2
  266. package/dist/websocket/controllers/base.d.ts +2 -2
  267. package/dist/websocket/controllers/base.js +3 -3
  268. package/dist/websocket/controllers/graphql.d.ts +1 -1
  269. package/dist/websocket/controllers/graphql.js +1 -1
  270. package/dist/websocket/controllers/logs.d.ts +1 -1
  271. package/dist/websocket/controllers/rest.d.ts +1 -1
  272. package/dist/websocket/controllers/rest.js +2 -2
  273. package/dist/websocket/handlers/heartbeat.js +1 -1
  274. package/dist/websocket/handlers/items.js +2 -2
  275. package/dist/websocket/handlers/subscribe.js +1 -1
  276. package/dist/websocket/types.d.ts +1 -1
  277. package/dist/websocket/utils/wait-for-message.js +1 -1
  278. package/package.json +34 -28
  279. package/dist/controllers/webhooks.d.ts +0 -2
  280. package/dist/controllers/webhooks.js +0 -74
  281. package/dist/extensions/lib/sync-extensions.d.ts +0 -3
  282. package/dist/extensions/lib/sync-extensions.js +0 -70
  283. package/dist/extensions/lib/sync-status.d.ts +0 -10
  284. package/dist/extensions/lib/sync-status.js +0 -27
  285. package/dist/mcp/tools/index.d.ts +0 -15
  286. package/dist/mcp/tools/index.js +0 -29
  287. package/dist/mcp/tools/prompts/index.d.ts +0 -16
  288. package/dist/mcp/tools/prompts/index.js +0 -19
  289. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.d.ts +0 -5
  290. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-roles.js +0 -7
  291. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.d.ts +0 -5
  292. package/dist/permissions/modules/fetch-global-access/lib/fetch-global-access-for-user.js +0 -10
  293. package/dist/permissions/modules/fetch-global-access/types.d.ts +0 -4
  294. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.d.ts +0 -4
  295. package/dist/permissions/modules/fetch-global-access/utils/fetch-global-access-for-query.js +0 -27
  296. package/dist/services/webhooks.d.ts +0 -14
  297. package/dist/services/webhooks.js +0 -32
  298. package/dist/utils/get-date-formatted.d.ts +0 -1
  299. package/dist/utils/get-date-formatted.js +0 -10
  300. package/dist/utils/ip-in-networks.d.ts +0 -6
  301. package/dist/utils/ip-in-networks.js +0 -13
  302. package/dist/utils/is-login-redirect-allowed.d.ts +0 -4
  303. /package/dist/{mcp → ai/mcp}/index.d.ts +0 -0
  304. /package/dist/{mcp → ai/mcp}/index.js +0 -0
  305. /package/dist/{mcp → ai/mcp}/transport.d.ts +0 -0
  306. /package/dist/{mcp → ai/mcp}/transport.js +0 -0
  307. /package/dist/{mcp → ai/mcp}/types.js +0 -0
  308. /package/dist/{mcp/tools/assets.d.ts → ai/tools/assets/index.d.ts} +0 -0
  309. /package/dist/{mcp/tools/prompts/assets.md → ai/tools/assets/prompt.md} +0 -0
  310. /package/dist/{mcp/tools/collections.d.ts → ai/tools/collections/index.d.ts} +0 -0
  311. /package/dist/{mcp/tools/prompts/collections.md → ai/tools/collections/prompt.md} +0 -0
  312. /package/dist/{mcp/define.d.ts → ai/tools/define-tool.d.ts} +0 -0
  313. /package/dist/{mcp/define.js → ai/tools/define-tool.js} +0 -0
  314. /package/dist/{mcp/tools/fields.d.ts → ai/tools/fields/index.d.ts} +0 -0
  315. /package/dist/{mcp/tools/prompts/fields.md → ai/tools/fields/prompt.md} +0 -0
  316. /package/dist/{mcp/tools/files.d.ts → ai/tools/files/index.d.ts} +0 -0
  317. /package/dist/{mcp/tools/prompts/files.md → ai/tools/files/prompt.md} +0 -0
  318. /package/dist/{mcp/tools/flows.d.ts → ai/tools/flows/index.d.ts} +0 -0
  319. /package/dist/{mcp/tools/prompts/flows.md → ai/tools/flows/prompt.md} +0 -0
  320. /package/dist/{mcp/tools/folders.d.ts → ai/tools/folders/index.d.ts} +0 -0
  321. /package/dist/{mcp/tools/prompts/folders.md → ai/tools/folders/prompt.md} +0 -0
  322. /package/dist/{mcp/tools/items.d.ts → ai/tools/items/index.d.ts} +0 -0
  323. /package/dist/{mcp/tools/prompts/operations.md → ai/tools/operations/prompt.md} +0 -0
  324. /package/dist/{mcp/tools/relations.d.ts → ai/tools/relations/index.d.ts} +0 -0
  325. /package/dist/{mcp/tools/prompts/relations.md → ai/tools/relations/prompt.md} +0 -0
  326. /package/dist/{mcp/tools/prompts/schema.md → ai/tools/schema/prompt.md} +0 -0
  327. /package/dist/{mcp → ai/tools}/schema.d.ts +0 -0
  328. /package/dist/{mcp → ai/tools}/schema.js +0 -0
  329. /package/dist/{mcp/tools/system.d.ts → ai/tools/system/index.d.ts} +0 -0
  330. /package/dist/{mcp/tools/prompts/system-prompt-description.md → ai/tools/system/prompt-description.md} +0 -0
  331. /package/dist/{mcp/tools/prompts/system-prompt.md → ai/tools/system/prompt.md} +0 -0
  332. /package/dist/{mcp/tools/trigger-flow.d.ts → ai/tools/trigger-flow/index.d.ts} +0 -0
  333. /package/dist/{mcp/tools/prompts/trigger-flow.md → ai/tools/trigger-flow/prompt.md} +0 -0
  334. /package/dist/{permissions/modules/fetch-global-access → ai/tools}/types.js +0 -0
  335. /package/dist/test-utils/{items-service.d.ts → services/items-service.d.ts} +0 -0
  336. /package/dist/test-utils/{items-service.js → services/items-service.js} +0 -0
@@ -63,10 +63,10 @@ export class CommentsService extends ItemsService {
63
63
  role: user['role']?.id ?? null,
64
64
  admin: false,
65
65
  app: false,
66
- roles: await fetchRolesTree(user['role']?.id ?? null, this.knex),
66
+ roles: await fetchRolesTree(user['role']?.id ?? null, { knex: this.knex }),
67
67
  ip: null,
68
68
  };
69
- const userGlobalAccess = await fetchGlobalAccess(accountability, this.knex);
69
+ const userGlobalAccess = await fetchGlobalAccess(accountability, { knex: this.knex });
70
70
  accountability.admin = userGlobalAccess.admin;
71
71
  accountability.app = userGlobalAccess.app;
72
72
  const usersService = new UsersService({ schema: this.schema, accountability });
@@ -1,4 +1,4 @@
1
- import type { ApiOutput, ExtensionSettings, ExtensionManager } from '@directus/types';
1
+ import type { ApiOutput, ExtensionManager, ExtensionSettings } from '@directus/types';
2
2
  import type { AbstractServiceOptions, Accountability, DeepPartial, SchemaOverview } from '@directus/types';
3
3
  import type { Knex } from 'knex';
4
4
  import { ItemsService } from './items.js';
@@ -109,6 +109,8 @@ export class ExtensionsService {
109
109
  await this.extensionsManager.install(versionId);
110
110
  }
111
111
  async readAll() {
112
+ // wait for extensions to be reloaded
113
+ await this.extensionsManager.isReloading();
112
114
  const settings = await this.extensionsItemService.readByQuery({ limit: -1 });
113
115
  const regular = settings.filter(({ bundle }) => bundle === null);
114
116
  const bundled = settings.filter(({ bundle }) => bundle !== null);
@@ -138,6 +140,8 @@ export class ExtensionsService {
138
140
  return output;
139
141
  }
140
142
  async readOne(id) {
143
+ // wait for extensions to be reloaded
144
+ await this.extensionsManager.isReloading();
141
145
  const meta = await this.extensionsItemService.readOne(id);
142
146
  const schema = this.extensionsManager.getExtension(meta.source, meta.folder) ?? null;
143
147
  return {
@@ -1,4 +1,4 @@
1
- import type { File } from '@directus/types';
2
1
  import type { Readable } from 'node:stream';
2
+ import type { File } from '@directus/types';
3
3
  export type Metadata = Partial<Pick<File, 'height' | 'width' | 'description' | 'title' | 'tags' | 'metadata'>>;
4
4
  export declare function getMetadata(stream: Readable, allowList?: string | string[]): Promise<Metadata>;
@@ -1,8 +1,8 @@
1
+ import { pipeline } from 'node:stream/promises';
1
2
  import { useEnv } from '@directus/env';
2
3
  import exif, {} from 'exif-reader';
3
4
  import { parse as parseIcc } from 'icc';
4
5
  import { pick } from 'lodash-es';
5
- import { pipeline } from 'node:stream/promises';
6
6
  import { useLogger } from '../../../logger/index.js';
7
7
  import { getSharpInstance } from '../lib/get-sharp-instance.js';
8
8
  import { parseIptc, parseXmp } from './parse-image-metadata.js';
@@ -1,5 +1,5 @@
1
- import type { AbstractServiceOptions, BusboyFileStream, File, MutationOptions, PrimaryKey, Query, QueryOptions } from '@directus/types';
2
1
  import type { Readable } from 'node:stream';
2
+ import type { AbstractServiceOptions, BusboyFileStream, File, MutationOptions, PrimaryKey, Query, QueryOptions } from '@directus/types';
3
3
  import { ItemsService } from './items.js';
4
4
  export declare class FilesService extends ItemsService<File> {
5
5
  constructor(options: AbstractServiceOptions);
@@ -1,3 +1,7 @@
1
+ import { PassThrough as PassThroughStream, Transform as TransformStream } from 'node:stream';
2
+ import zlib from 'node:zlib';
3
+ import path from 'path';
4
+ import url from 'url';
1
5
  import { useEnv } from '@directus/env';
2
6
  import { ContentTooLargeError, InvalidPayloadError, ServiceUnavailableError } from '@directus/errors';
3
7
  import formatTitle from '@directus/format-title';
@@ -5,10 +9,6 @@ import { toArray } from '@directus/utils';
5
9
  import encodeURL from 'encodeurl';
6
10
  import { clone, cloneDeep } from 'lodash-es';
7
11
  import { extension } from 'mime-types';
8
- import { PassThrough as PassThroughStream, Transform as TransformStream } from 'node:stream';
9
- import zlib from 'node:zlib';
10
- import path from 'path';
11
- import url from 'url';
12
12
  import { RESUMABLE_UPLOADS } from '../constants.js';
13
13
  import emitter from '../emitter.js';
14
14
  import { useLogger } from '../logger/index.js';
@@ -1,5 +1,30 @@
1
- import type { AbstractServiceOptions } from '@directus/types';
1
+ import type { AbstractServiceOptions, Folder } from '@directus/types';
2
2
  import { ItemsService } from './items.js';
3
- export declare class FoldersService extends ItemsService {
3
+ export declare class FoldersService extends ItemsService<Folder> {
4
4
  constructor(options: AbstractServiceOptions);
5
+ /**
6
+ * Builds a full folder tree starting from a given root folder.
7
+ *
8
+ * This method returns a map of folder IDs to their corresponding paths
9
+ * relative to the root. It resolves all nested child folders and ensures
10
+ * that folder names are deduplicated within the same parent.
11
+ *
12
+ * Access control is applied automatically when non-admin, only folders the user has `read`
13
+ * access to are included.
14
+ *
15
+ * @param {string} root - The ID of the root folder to start building the tree from.
16
+ * @returns {Promise<Map<string, string>>} A `Map` where:
17
+ * - Key: folder ID
18
+ * - Value: folder path relative to the root (e.g., "Documents/Photos")
19
+ *
20
+ * @example
21
+ * const foldersService = new FoldersService({ schema, accountability });
22
+ * const tree = await foldersService.buildTree('root-folder-id');
23
+ * console.log(tree.get('folder1')); // e.g., "RootFolder/SubFolder1"
24
+ *
25
+ * @remarks
26
+ * - The returned `Map` includes the root folder itself.
27
+ * - If a folder has no name, its ID will be used as a fallback.
28
+ */
29
+ buildTree(root: string): Promise<Map<string, string>>;
5
30
  }
@@ -1,6 +1,81 @@
1
+ import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
2
+ import { NameDeduper } from './assets/name-deduper.js';
1
3
  import { ItemsService } from './items.js';
2
4
  export class FoldersService extends ItemsService {
3
5
  constructor(options) {
4
6
  super('directus_folders', options);
5
7
  }
8
+ /**
9
+ * Builds a full folder tree starting from a given root folder.
10
+ *
11
+ * This method returns a map of folder IDs to their corresponding paths
12
+ * relative to the root. It resolves all nested child folders and ensures
13
+ * that folder names are deduplicated within the same parent.
14
+ *
15
+ * Access control is applied automatically when non-admin, only folders the user has `read`
16
+ * access to are included.
17
+ *
18
+ * @param {string} root - The ID of the root folder to start building the tree from.
19
+ * @returns {Promise<Map<string, string>>} A `Map` where:
20
+ * - Key: folder ID
21
+ * - Value: folder path relative to the root (e.g., "Documents/Photos")
22
+ *
23
+ * @example
24
+ * const foldersService = new FoldersService({ schema, accountability });
25
+ * const tree = await foldersService.buildTree('root-folder-id');
26
+ * console.log(tree.get('folder1')); // e.g., "RootFolder/SubFolder1"
27
+ *
28
+ * @remarks
29
+ * - The returned `Map` includes the root folder itself.
30
+ * - If a folder has no name, its ID will be used as a fallback.
31
+ */
32
+ async buildTree(root) {
33
+ if (this.accountability && this.accountability.admin !== true) {
34
+ await validateAccess({
35
+ collection: 'directus_folders',
36
+ accountability: this.accountability,
37
+ action: 'read',
38
+ primaryKeys: [root],
39
+ }, {
40
+ knex: this.knex,
41
+ schema: this.schema,
42
+ });
43
+ }
44
+ const folders = await this.readByQuery({ limit: -1 });
45
+ // build folder and child lookup
46
+ const folderLookup = new Map();
47
+ const childFolderLookup = new Map();
48
+ for (const folder of folders) {
49
+ if (!folder['id'])
50
+ continue;
51
+ folderLookup.set(folder['id'], folder);
52
+ // root is always at the top level, we can therfor safely skip any parent references to it.
53
+ if (folder['parent'] && folder['id'] !== root) {
54
+ const children = childFolderLookup.get(folder['parent']) ?? [];
55
+ children.push(folder['id']);
56
+ childFolderLookup.set(folder['parent'], children);
57
+ }
58
+ }
59
+ const deduper = new NameDeduper();
60
+ const rootName = deduper.add(folderLookup.get(root)?.name, { fallback: root });
61
+ const stack = [[root, '']];
62
+ const tree = new Map();
63
+ // build tree from stack
64
+ while (stack.length > 0) {
65
+ const [folderId, path] = stack.pop() ?? [];
66
+ if (!folderId)
67
+ continue;
68
+ const folder = folderLookup.get(folderId);
69
+ if (!folder)
70
+ continue;
71
+ const children = childFolderLookup.get(folderId);
72
+ const folderName = deduper.add(folder['name'], { group: folder['parent'], fallback: folderId });
73
+ const folderPath = path === '' ? rootName : `${path}/${folderName}`;
74
+ tree.set(folderId, folderPath);
75
+ for (const childFolderId of children ?? []) {
76
+ stack.push([childFolderId, folderPath]);
77
+ }
78
+ }
79
+ return tree;
80
+ }
6
81
  }
@@ -1,4 +1,4 @@
1
- import type { AbstractServiceOptions, Accountability, GraphQLParams, GQLScope, Item, Query, SchemaOverview, PrimaryKey } from '@directus/types';
1
+ import type { AbstractServiceOptions, Accountability, GQLScope, GraphQLParams, Item, PrimaryKey, Query, SchemaOverview } from '@directus/types';
2
2
  import type { FormattedExecutionResult, GraphQLSchema } from 'graphql';
3
3
  import type { Knex } from 'knex';
4
4
  export declare class GraphQLService {
@@ -1,5 +1,5 @@
1
1
  import { useEnv } from '@directus/env';
2
- import { NoSchemaIntrospectionCustomRule, execute, specifiedRules, validate } from 'graphql';
2
+ import { execute, NoSchemaIntrospectionCustomRule, specifiedRules, validate } from 'graphql';
3
3
  import getDatabase from '../../database/index.js';
4
4
  import { getService } from '../../utils/get-service.js';
5
5
  import { formatError } from './errors/format.js';
@@ -1,7 +1,7 @@
1
1
  import { getService } from '../../../utils/get-service.js';
2
2
  import { formatError } from '../errors/format.js';
3
- import { replaceFragmentsInSelections } from '../utils/replace-fragments.js';
4
3
  import { getQuery } from '../schema/parse-query.js';
4
+ import { replaceFragmentsInSelections } from '../utils/replace-fragments.js';
5
5
  export async function resolveMutation(gql, args, info) {
6
6
  const action = info.fieldName.split('_')[0];
7
7
  let collection = info.fieldName.substring(action.length + 1);
@@ -1,6 +1,6 @@
1
+ import type { GQLScope } from '@directus/types';
1
2
  import type { SchemaComposer } from 'graphql-compose';
2
3
  import { ObjectTypeComposer } from 'graphql-compose';
3
- import type { GQLScope } from '@directus/types';
4
4
  import { type InconsistentFields, type Schema } from './index.js';
5
5
  /**
6
6
  * Construct an object of types for every collection, using the permitted fields per action type
@@ -9,8 +9,8 @@ import { GraphQLDate } from '../types/date.js';
9
9
  import { GraphQLGeoJSON } from '../types/geojson.js';
10
10
  import { GraphQLHash } from '../types/hash.js';
11
11
  import { GraphQLStringOrFloat } from '../types/string-or-float.js';
12
- import { SYSTEM_DENY_LIST } from './index.js';
13
12
  import { getTypes } from './get-types.js';
13
+ import { SYSTEM_DENY_LIST } from './index.js';
14
14
  /**
15
15
  * Create readable types and attach resolvers for each. Also prepares full filter argument structures
16
16
  */
@@ -1,5 +1,5 @@
1
- import type { GraphQLService } from './index.js';
2
1
  import type { GraphQLResolveInfo } from 'graphql';
2
+ import type { GraphQLService } from './index.js';
3
3
  export declare function bindPubSub(): void;
4
4
  export declare function createSubscriptionGenerator(gql: GraphQLService, event: string): (_x: unknown, _y: unknown, _z: unknown, request: GraphQLResolveInfo) => AsyncGenerator<{
5
5
  [event]: {
@@ -1,4 +1,4 @@
1
- import { GraphQLString, GraphQLScalarType } from 'graphql';
1
+ import { GraphQLScalarType, GraphQLString } from 'graphql';
2
2
  export const GraphQLDate = new GraphQLScalarType({
3
3
  ...GraphQLString,
4
4
  name: 'Date',
@@ -1,4 +1,4 @@
1
- import { GraphQLString, GraphQLScalarType } from 'graphql';
1
+ import { GraphQLScalarType, GraphQLString } from 'graphql';
2
2
  export const GraphQLHash = new GraphQLScalarType({
3
3
  ...GraphQLString,
4
4
  name: 'Hash',
@@ -1,4 +1,4 @@
1
- import { GraphQLError, Token, locatedError } from 'graphql';
1
+ import { GraphQLError, locatedError, Token } from 'graphql';
2
2
  export function addPathToValidationError(validationError) {
3
3
  const token = validationError.nodes?.[0]?.loc?.startToken;
4
4
  if (!token)
@@ -1,7 +1,7 @@
1
+ import type { Readable } from 'node:stream';
1
2
  import type { AbstractServiceOptions, Accountability, DirectusError, ExportFormat, File, Query, SchemaOverview } from '@directus/types';
2
3
  import type { Knex } from 'knex';
3
- import type { Readable } from 'node:stream';
4
- import type { FunctionFieldNode, FieldNode, NestedCollectionNode } from '../types/index.js';
4
+ import type { FieldNode, FunctionFieldNode, NestedCollectionNode } from '../types/index.js';
5
5
  export declare function createErrorTracker(): {
6
6
  addCapturedError: (err: any, rowNumber: number) => void;
7
7
  buildFinalErrors: () => DirectusError<any>[];
@@ -1,22 +1,23 @@
1
+ import { createReadStream, createWriteStream } from 'node:fs';
2
+ import { appendFile } from 'node:fs/promises';
1
3
  import { useEnv } from '@directus/env';
2
4
  import { createError, ErrorCode, ForbiddenError, InvalidPayloadError, ServiceUnavailableError, UnsupportedMediaTypeError, } from '@directus/errors';
3
5
  import { isSystemCollection } from '@directus/system-data';
4
- import { parseJSON, toArray } from '@directus/utils';
6
+ import { getDateTimeFormatted, parseJSON, toArray } from '@directus/utils';
5
7
  import { createTmpFile } from '@directus/utils/node';
6
8
  import { queue } from 'async';
7
9
  import destroyStream from 'destroy';
8
10
  import { dump as toYAML } from 'js-yaml';
9
11
  import { parse as toXML } from 'js2xmlparser';
10
12
  import { Parser as CSVParser, transforms as CSVTransforms } from 'json2csv';
11
- import { createReadStream, createWriteStream } from 'node:fs';
12
- import { appendFile } from 'node:fs/promises';
13
+ import { set } from 'lodash-es';
13
14
  import Papa from 'papaparse';
14
15
  import StreamArray from 'stream-json/streamers/StreamArray.js';
16
+ import { parseFields } from '../database/get-ast-from-query/lib/parse-fields.js';
15
17
  import getDatabase from '../database/index.js';
16
18
  import emitter from '../emitter.js';
17
19
  import { useLogger } from '../logger/index.js';
18
20
  import { validateAccess } from '../permissions/modules/validate-access/validate-access.js';
19
- import { getDateFormatted } from '../utils/get-date-formatted.js';
20
21
  import { getService } from '../utils/get-service.js';
21
22
  import { transaction } from '../utils/transaction.js';
22
23
  import { Url } from '../utils/url.js';
@@ -24,8 +25,6 @@ import { userName } from '../utils/user-name.js';
24
25
  import { FilesService } from './files.js';
25
26
  import { NotificationsService } from './notifications.js';
26
27
  import { UsersService } from './users.js';
27
- import { parseFields } from '../database/get-ast-from-query/lib/parse-fields.js';
28
- import { set } from 'lodash-es';
29
28
  const env = useEnv();
30
29
  const logger = useLogger();
31
30
  const MAX_IMPORT_ERRORS = env['MAX_IMPORT_ERRORS'];
@@ -514,7 +513,7 @@ export class ExportService {
514
513
  schema: this.schema,
515
514
  });
516
515
  const storage = toArray(env['STORAGE_LOCATIONS'])[0];
517
- const title = `export-${collection}-${getDateFormatted()}`;
516
+ const title = `export-${collection}-${getDateTimeFormatted()}`;
518
517
  const filename = `${title}.${format}`;
519
518
  const fileWithDefaults = {
520
519
  ...(options?.file ?? {}),
@@ -35,5 +35,4 @@ export * from './translations.js';
35
35
  export * from './users.js';
36
36
  export * from './utils.js';
37
37
  export * from './versions.js';
38
- export * from './webhooks.js';
39
38
  export * from './websocket.js';
@@ -35,5 +35,4 @@ export * from './translations.js';
35
35
  export * from './users.js';
36
36
  export * from './utils.js';
37
37
  export * from './versions.js';
38
- export * from './webhooks.js';
39
38
  export * from './websocket.js';
@@ -1,10 +1,10 @@
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
1
3
  import { useEnv } from '@directus/env';
2
4
  import { InvalidPayloadError } from '@directus/errors';
3
5
  import { isObject } from '@directus/utils';
4
6
  import fse from 'fs-extra';
5
7
  import { Liquid } from 'liquidjs';
6
- import path from 'path';
7
- import { fileURLToPath } from 'url';
8
8
  import getDatabase from '../../database/index.js';
9
9
  import emitter from '../../emitter.js';
10
10
  import { useLogger } from '../../logger/index.js';
@@ -1,8 +1,8 @@
1
1
  import { useEnv } from '@directus/env';
2
+ import { EmailLimitExceededError } from '@directus/errors';
3
+ import { toBoolean } from '@directus/utils';
2
4
  import { RateLimiterQueue } from 'rate-limiter-flexible';
3
5
  import { createRateLimiter } from '../../rate-limiter.js';
4
- import { toBoolean } from '@directus/utils';
5
- import { EmailLimitExceededError } from '@directus/errors';
6
6
  let emailRateLimiterQueue;
7
7
  const env = useEnv();
8
8
  if (toBoolean(env['RATE_LIMITER_EMAIL_ENABLED']) === true) {
@@ -29,12 +29,12 @@ export class NotificationsService extends ItemsService {
29
29
  .addPath('admin', 'users', user['id'])
30
30
  .toString();
31
31
  const html = data.message ? md(data.message) : '';
32
- const roles = await fetchRolesTree(user['role'], this.knex);
32
+ const roles = await fetchRolesTree(user['role'], { knex: this.knex });
33
33
  const { app: app_access } = await fetchGlobalAccess({
34
34
  user: user['id'],
35
35
  roles,
36
36
  ip: null,
37
- }, this.knex);
37
+ }, { knex: this.knex });
38
38
  const mailService = new MailService({
39
39
  schema: this.schema,
40
40
  knex: this.knex,
@@ -1,3 +1,4 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
2
3
  import { UserIntegrityCheckFlag } from '@directus/types';
3
4
  import { parseJSON, toArray } from '@directus/utils';
@@ -5,11 +6,12 @@ import { format, isValid, parseISO } from 'date-fns';
5
6
  import { unflatten } from 'flat';
6
7
  import Joi from 'joi';
7
8
  import { clone, cloneDeep, isNil, isObject, isPlainObject, pick } from 'lodash-es';
8
- import { randomUUID } from 'node:crypto';
9
9
  import { parse as wktToGeoJSON } from 'wellknown';
10
10
  import { getHelpers } from '../database/helpers/index.js';
11
11
  import getDatabase from '../database/index.js';
12
+ import { decrypt, encrypt } from '../utils/encrypt.js';
12
13
  import { generateHash } from '../utils/generate-hash.js';
14
+ import { getSecret } from '../utils/get-secret.js';
13
15
  /**
14
16
  * Process a given payload for a collection to ensure the special fields (hash, uuid, date etc) are
15
17
  * handled correctly.
@@ -124,6 +126,24 @@ export class PayloadService {
124
126
  }
125
127
  return value;
126
128
  },
129
+ async encrypt({ action, value, accountability }) {
130
+ if (!value)
131
+ return value;
132
+ if (action === 'read') {
133
+ // In-system calls can still get the decrypted value
134
+ if (accountability === null) {
135
+ const key = getSecret();
136
+ return await decrypt(value, key);
137
+ }
138
+ // Requests from the API entrypoints have accountability and shouldn't get the raw value
139
+ return '**********';
140
+ }
141
+ if (typeof value === 'string') {
142
+ const key = getSecret();
143
+ return await encrypt(value, key);
144
+ }
145
+ return value;
146
+ },
127
147
  };
128
148
  async processValues(action, payload, aliasMap = {}, aggregate = {}) {
129
149
  const processedPayload = toArray(payload);
@@ -3,8 +3,8 @@ import { UserIntegrityCheckFlag } from '@directus/types';
3
3
  import { clearSystemCache } from '../cache.js';
4
4
  import { fetchRolesTree } from '../permissions/lib/fetch-roles-tree.js';
5
5
  import { transaction } from '../utils/transaction.js';
6
- import { ItemsService } from './items.js';
7
6
  import { AccessService } from './access.js';
7
+ import { ItemsService } from './items.js';
8
8
  import { PresetsService } from './presets.js';
9
9
  import { UsersService } from './users.js';
10
10
  export class RolesService extends ItemsService {
@@ -72,7 +72,7 @@ export class RolesService extends ItemsService {
72
72
  if (ids.includes(parent)) {
73
73
  throw new InvalidPayloadError({ reason: 'A role cannot be a parent of itself' });
74
74
  }
75
- const roles = await fetchRolesTree(parent, this.knex);
75
+ const roles = await fetchRolesTree(parent, { knex: this.knex });
76
76
  if (ids.some((id) => roles.includes(id))) {
77
77
  // The role tree up from the parent already includes this role, so it would create a circular reference
78
78
  throw new InvalidPayloadError({ reason: 'A role cannot have a parent that is already a descendant of itself' });
@@ -1,5 +1,5 @@
1
- import getDatabase from '../database/index.js';
2
1
  import { ForbiddenError } from '@directus/errors';
2
+ import getDatabase from '../database/index.js';
3
3
  import { applyDiff } from '../utils/apply-diff.js';
4
4
  import { getSnapshotDiff } from '../utils/get-snapshot-diff.js';
5
5
  import { getSnapshot } from '../utils/get-snapshot.js';
@@ -1,11 +1,11 @@
1
+ import { Readable } from 'node:stream';
2
+ import { performance } from 'perf_hooks';
1
3
  import { useEnv } from '@directus/env';
2
4
  import { toArray, toBoolean } from '@directus/utils';
3
5
  import { version } from 'directus/version';
4
6
  import { merge } from 'lodash-es';
5
- import { Readable } from 'node:stream';
6
- import { performance } from 'perf_hooks';
7
7
  import { getCache } from '../cache.js';
8
- import { RESUMABLE_UPLOADS } from '../constants.js';
8
+ import { FILE_UPLOADS, RESUMABLE_UPLOADS } from '../constants.js';
9
9
  import getDatabase, { hasDatabaseConnection } from '../database/index.js';
10
10
  import { useLogger } from '../logger/index.js';
11
11
  import getMailer from '../mailer.js';
@@ -57,9 +57,10 @@ export class ServerService {
57
57
  ],
58
58
  });
59
59
  info['project'] = projectInfo;
60
- info['mcp_enabled'] = toBoolean(env['MCP_ENABLED'] ?? true);
61
60
  info['setupCompleted'] = setupComplete;
62
61
  if (this.accountability?.user) {
62
+ info['mcp_enabled'] = toBoolean(env['MCP_ENABLED'] ?? true);
63
+ info['ai_enabled'] = toBoolean(env['AI_ENABLED'] ?? true);
63
64
  if (env['RATE_LIMITER_ENABLED']) {
64
65
  info['rateLimit'] = {
65
66
  points: env['RATE_LIMITER_POINTS'],
@@ -112,8 +113,15 @@ export class ServerService {
112
113
  else {
113
114
  info['websocket'] = false;
114
115
  }
116
+ if (FILE_UPLOADS.MAX_CONCURRENCY && FILE_UPLOADS.MAX_CONCURRENCY !== Infinity) {
117
+ info['uploads'] = {
118
+ maxConcurrency: FILE_UPLOADS.MAX_CONCURRENCY,
119
+ };
120
+ }
115
121
  if (RESUMABLE_UPLOADS.ENABLED) {
116
122
  info['uploads'] = {
123
+ ...info['uploads'],
124
+ tus: true,
117
125
  chunkSize: RESUMABLE_UPLOADS.CHUNK_SIZE,
118
126
  };
119
127
  }
@@ -1,6 +1,6 @@
1
- import { ItemsService } from './items.js';
2
- import { sendReport } from '../telemetry/index.js';
3
1
  import { version } from 'directus/version';
2
+ import { sendReport } from '../telemetry/index.js';
3
+ import { ItemsService } from './items.js';
4
4
  export class SettingsService extends ItemsService {
5
5
  constructor(options) {
6
6
  super('directus_settings', options);
@@ -1,8 +1,8 @@
1
1
  import { InvalidPayloadError } from '@directus/errors';
2
2
  import { authenticator } from 'otplib';
3
+ import { DEFAULT_AUTH_PROVIDER } from '../constants.js';
3
4
  import getDatabase from '../database/index.js';
4
5
  import { ItemsService } from './items.js';
5
- import { DEFAULT_AUTH_PROVIDER } from '../constants.js';
6
6
  export class TFAService {
7
7
  knex;
8
8
  itemsService;
@@ -1,5 +1,5 @@
1
- import getDatabase from '../database/index.js';
2
1
  import { InvalidPayloadError } from '@directus/errors';
2
+ import getDatabase from '../database/index.js';
3
3
  import { ItemsService } from './items.js';
4
4
  export class TranslationsService extends ItemsService {
5
5
  constructor(options) {
@@ -1,12 +1,11 @@
1
+ import stream from 'node:stream';
1
2
  import type { TusDriver } from '@directus/storage';
2
3
  import type { Accountability, File, SchemaOverview } from '@directus/types';
3
4
  import { DataStore, Upload } from '@tus/utils';
4
- import stream from 'node:stream';
5
5
  export type TusDataStoreConfig = {
6
6
  constants: {
7
7
  ENABLED: boolean;
8
8
  CHUNK_SIZE: number | null;
9
- MAX_SIZE: number | null;
10
9
  EXPIRATION_TIME: number;
11
10
  SCHEDULE: string;
12
11
  };
@@ -18,7 +17,6 @@ export type TusDataStoreConfig = {
18
17
  };
19
18
  export declare class TusDataStore extends DataStore {
20
19
  protected chunkSize: number | undefined;
21
- protected maxSize: number | undefined;
22
20
  protected expirationTime: number;
23
21
  protected location: string;
24
22
  protected storageDriver: TusDriver;
@@ -1,15 +1,14 @@
1
+ import { extname } from 'node:path';
2
+ import stream from 'node:stream';
1
3
  import formatTitle from '@directus/format-title';
2
4
  import { DataStore, ERRORS, Upload } from '@tus/utils';
3
5
  import { omit } from 'lodash-es';
4
6
  import { extension } from 'mime-types';
5
- import { extname } from 'node:path';
6
- import stream from 'node:stream';
7
7
  import getDatabase from '../../database/index.js';
8
8
  import { useLogger } from '../../logger/index.js';
9
9
  import { ItemsService } from '../items.js';
10
10
  export class TusDataStore extends DataStore {
11
11
  chunkSize;
12
- maxSize;
13
12
  expirationTime;
14
13
  location;
15
14
  storageDriver;
@@ -19,8 +18,6 @@ export class TusDataStore extends DataStore {
19
18
  super();
20
19
  if (config.constants.CHUNK_SIZE !== null)
21
20
  this.chunkSize = config.constants.CHUNK_SIZE;
22
- if (config.constants.MAX_SIZE !== null)
23
- this.maxSize = config.constants.MAX_SIZE;
24
21
  this.expirationTime = config.constants.EXPIRATION_TIME;
25
22
  this.location = config.location;
26
23
  this.storageDriver = config.driver;
@@ -7,16 +7,16 @@ import { useEnv } from '@directus/env';
7
7
  import { supportsTus } from '@directus/storage';
8
8
  import { toArray } from '@directus/utils';
9
9
  import { Server } from '@tus/server';
10
- import { RESUMABLE_UPLOADS } from '../../constants.js';
10
+ import { pick } from 'lodash-es';
11
+ import { FILE_UPLOADS, RESUMABLE_UPLOADS } from '../../constants.js';
12
+ import getDatabase from '../../database/index.js';
13
+ import emitter from '../../emitter.js';
11
14
  import { getStorage } from '../../storage/index.js';
15
+ import { getSchema } from '../../utils/get-schema.js';
12
16
  import { extractMetadata } from '../files/lib/extract-metadata.js';
13
17
  import { ItemsService } from '../index.js';
14
18
  import { TusDataStore } from './data-store.js';
15
19
  import { getTusLocker } from './lockers.js';
16
- import { pick } from 'lodash-es';
17
- import emitter from '../../emitter.js';
18
- import getDatabase from '../../database/index.js';
19
- import { getSchema } from '../../utils/get-schema.js';
20
20
  async function createTusStore(context) {
21
21
  const env = useEnv();
22
22
  const storage = await getStorage();
@@ -40,8 +40,8 @@ export async function createTusServer(context) {
40
40
  path: '/files/tus',
41
41
  datastore: store,
42
42
  locker: getTusLocker(),
43
- ...(RESUMABLE_UPLOADS.MAX_SIZE !== null && { maxSize: RESUMABLE_UPLOADS.MAX_SIZE }),
44
- async onUploadFinish(req, upload) {
43
+ ...(FILE_UPLOADS.MAX_SIZE !== null && { maxSize: FILE_UPLOADS.MAX_SIZE }),
44
+ async onUploadFinish(_req, upload) {
45
45
  const schema = await getSchema();
46
46
  const service = new ItemsService('directus_files', {
47
47
  schema,
@@ -92,9 +92,9 @@ export async function createTusServer(context) {
92
92
  key: fileData.id,
93
93
  collection: 'directus_files',
94
94
  }, {
95
- database: getDatabase(),
96
95
  schema,
97
- accountability: req.accountability,
96
+ database: getDatabase(),
97
+ accountability: context.accountability ?? null,
98
98
  });
99
99
  return {
100
100
  headers: {