@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
@@ -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 { parseJSON } from '@directus/utils';
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,5 +1,5 @@
1
- import type { Knex } from 'knex';
2
1
  import type { Driver } from '@directus/types';
2
+ import type { Knex } from 'knex';
3
3
  export type Credentials = {
4
4
  filename?: string;
5
5
  host?: string;
@@ -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);
@@ -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
- /** Resumable uploads */
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
- /** Resumable uploads */
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, RouteNotFoundError, isDirectusError } from '@directus/errors';
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';
@@ -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,6 +1,6 @@
1
+ import { RouteNotFoundError } from '@directus/errors';
1
2
  import getDatabase from '../database/index.js';
2
3
  import emitter from '../emitter.js';
3
- import { RouteNotFoundError } from '@directus/errors';
4
4
  /**
5
5
  * Handles not found routes.
6
6
  *
@@ -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,3 +1,3 @@
1
- import type { MySQLError } from './types.js';
2
1
  import type { Item } from '@directus/types';
2
+ import type { MySQLError } from './types.js';
3
3
  export declare function extractError(error: MySQLError, data: Partial<Item>): MySQLError | Error;
@@ -1,3 +1,3 @@
1
- import type { PostgresError } from './types.js';
2
1
  import type { Item } from '@directus/types';
2
+ import type { PostgresError } from './types.js';
3
3
  export declare function extractError(error: PostgresError, data: Partial<Item>): PostgresError | Error;
@@ -1,3 +1,3 @@
1
- import type { SQLiteError } from './types.js';
2
1
  import type { Item } from '@directus/types';
2
+ import type { SQLiteError } from './types.js';
3
3
  export declare function extractError(error: SQLiteError, data: Partial<Item>): SQLiteError | Error;
@@ -1,5 +1,5 @@
1
- import type { SQLError } from './dialects/types.js';
2
1
  import type { Item } from '@directus/types';
2
+ import type { SQLError } from './dialects/types.js';
3
3
  /**
4
4
  * Translates an error thrown by any of the databases into a pre-defined Exception. Currently
5
5
  * supports:
@@ -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';
@@ -1,5 +1,5 @@
1
- import { DateHelper } from '../types.js';
2
1
  import { parseISO } from 'date-fns';
2
+ import { DateHelper } from '../types.js';
3
3
  export class DateHelperMSSQL extends DateHelper {
4
4
  writeTimestamp(date) {
5
5
  const parsedDate = parseISO(date);
@@ -1,5 +1,5 @@
1
- import { DateHelper } from '../types.js';
2
1
  import { parseISO } from 'date-fns';
2
+ import { DateHelper } from '../types.js';
3
3
  export class DateHelperMySQL extends DateHelper {
4
4
  readTimestampString(date) {
5
5
  const parsedDate = new Date(date);
@@ -1,5 +1,5 @@
1
- import { DatabaseHelper } from '../types.js';
2
1
  import { parseISO } from 'date-fns';
2
+ import { DatabaseHelper } from '../types.js';
3
3
  export class DateHelper extends DatabaseHelper {
4
4
  parse(date) {
5
5
  // Date generated from NOW()
@@ -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 { SchemaHelper, type CreateIndexOptions, type SortRecord, type Sql } from '../types.js';
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 { SchemaHelper, type CreateIndexOptions, type SortRecord } from '../types.js';
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
- MySQL rejects queries for which the select list, HAVING condition, or ORDER BY list refer to
33
- nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on them.
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 { SchemaHelper, type CreateIndexOptions, type SortRecord } from '../types.js';
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) => {
@@ -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 { set } from 'lodash-es';
2
1
  import { randomUUID } from 'node:crypto';
2
+ import { set } from 'lodash-es';
3
3
  function transformStringsNewFormat(oldStrings) {
4
4
  return oldStrings.reduce((result, item) => {
5
5
  if (!item.key || !item.translations)
@@ -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.alterTable('directus_extensions', (table) => {
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().primary().notNullable();
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
@@ -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
  // To avoid typos
4
4
  const TABLE_WEBHOOKS = 'directus_webhooks';
5
5
  const TABLE_FLOWS = 'directus_flows';