@directus/api 32.2.0 → 33.1.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 (297) hide show
  1. package/dist/ai/chat/controllers/chat.post.js +19 -4
  2. package/dist/ai/chat/lib/create-ui-stream.d.ts +8 -7
  3. package/dist/ai/chat/lib/create-ui-stream.js +28 -25
  4. package/dist/ai/chat/middleware/load-settings.js +31 -7
  5. package/dist/ai/chat/models/chat-request.d.ts +135 -2
  6. package/dist/ai/chat/models/chat-request.js +56 -2
  7. package/dist/ai/chat/models/providers.d.ts +16 -2
  8. package/dist/ai/chat/models/providers.js +16 -2
  9. package/dist/ai/chat/utils/chat-request-tool-to-ai-sdk-tool.js +3 -4
  10. package/dist/ai/chat/utils/format-context.d.ts +5 -0
  11. package/dist/ai/chat/utils/format-context.js +122 -0
  12. package/dist/ai/mcp/server.d.ts +27 -1
  13. package/dist/ai/providers/index.d.ts +3 -0
  14. package/dist/ai/providers/index.js +3 -0
  15. package/dist/ai/providers/options.d.ts +14 -0
  16. package/dist/ai/providers/options.js +26 -0
  17. package/dist/ai/providers/registry.d.ts +6 -0
  18. package/dist/ai/providers/registry.js +65 -0
  19. package/dist/ai/providers/types.d.ts +34 -0
  20. package/dist/ai/providers/types.js +1 -0
  21. package/dist/ai/tools/assets/index.js +1 -1
  22. package/dist/ai/tools/collections/index.js +2 -2
  23. package/dist/ai/tools/fields/index.js +2 -2
  24. package/dist/ai/tools/files/index.js +1 -1
  25. package/dist/ai/tools/flows/index.js +1 -1
  26. package/dist/ai/tools/folders/index.js +1 -1
  27. package/dist/ai/tools/items/index.js +6 -3
  28. package/dist/ai/tools/items/prompt.md +7 -9
  29. package/dist/ai/tools/relations/index.js +1 -1
  30. package/dist/ai/tools/schema.js +1 -1
  31. package/dist/ai/tools/trigger-flow/index.js +1 -1
  32. package/dist/app.js +12 -8
  33. package/dist/auth/drivers/ldap.d.ts +1 -1
  34. package/dist/auth/drivers/ldap.js +144 -139
  35. package/dist/auth/drivers/local.js +1 -1
  36. package/dist/auth/drivers/oauth2.d.ts +1 -2
  37. package/dist/auth/drivers/oauth2.js +22 -17
  38. package/dist/auth/drivers/openid.d.ts +1 -2
  39. package/dist/auth/drivers/openid.js +18 -13
  40. package/dist/auth/drivers/saml.js +3 -3
  41. package/dist/auth/utils/generate-callback-url.d.ts +11 -0
  42. package/dist/auth/utils/generate-callback-url.js +40 -0
  43. package/dist/auth/utils/is-login-redirect-allowed.d.ts +7 -0
  44. package/dist/{utils → auth/utils}/is-login-redirect-allowed.js +12 -9
  45. package/dist/cache.d.ts +12 -0
  46. package/dist/cache.js +27 -3
  47. package/dist/cli/commands/bootstrap/index.js +2 -2
  48. package/dist/cli/commands/database/install.js +1 -1
  49. package/dist/cli/commands/database/migrate.js +1 -1
  50. package/dist/cli/commands/init/index.js +2 -2
  51. package/dist/cli/commands/roles/create.js +4 -4
  52. package/dist/cli/commands/schema/apply.js +3 -3
  53. package/dist/cli/commands/schema/snapshot.js +1 -1
  54. package/dist/cli/utils/create-db-connection.d.ts +1 -1
  55. package/dist/cli/utils/create-db-connection.js +1 -1
  56. package/dist/cli/utils/create-env/env-stub.liquid +3 -0
  57. package/dist/cli/utils/create-env/index.js +1 -1
  58. package/dist/constants.d.ts +7 -3
  59. package/dist/constants.js +7 -3
  60. package/dist/controllers/access.js +1 -1
  61. package/dist/controllers/assets.js +1 -1
  62. package/dist/controllers/deployment.js +481 -0
  63. package/dist/controllers/extensions.js +1 -1
  64. package/dist/controllers/fields.js +8 -6
  65. package/dist/controllers/files.js +1 -1
  66. package/dist/controllers/items.js +1 -1
  67. package/dist/controllers/not-found.js +1 -1
  68. package/dist/controllers/relations.js +1 -1
  69. package/dist/database/errors/dialects/mysql.d.ts +1 -1
  70. package/dist/database/errors/dialects/postgres.d.ts +1 -1
  71. package/dist/database/errors/dialects/sqlite.d.ts +1 -1
  72. package/dist/database/errors/translate.d.ts +1 -1
  73. package/dist/database/errors/translate.js +1 -1
  74. package/dist/database/get-ast-from-query/lib/parse-fields.js +2 -2
  75. package/dist/database/helpers/date/dialects/mssql.js +1 -1
  76. package/dist/database/helpers/date/dialects/mysql.js +1 -1
  77. package/dist/database/helpers/date/types.js +1 -1
  78. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +1 -0
  79. package/dist/database/helpers/schema/dialects/cockroachdb.js +24 -1
  80. package/dist/database/helpers/schema/dialects/mssql.d.ts +1 -1
  81. package/dist/database/helpers/schema/dialects/mysql.d.ts +2 -1
  82. package/dist/database/helpers/schema/dialects/mysql.js +16 -3
  83. package/dist/database/helpers/schema/dialects/postgres.d.ts +1 -1
  84. package/dist/database/helpers/schema/types.d.ts +13 -0
  85. package/dist/database/helpers/schema/types.js +24 -0
  86. package/dist/database/index.js +4 -4
  87. package/dist/database/migrations/20220429A-add-flows.js +1 -1
  88. package/dist/database/migrations/20230526A-migrate-translation-strings.js +1 -1
  89. package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +1 -1
  90. package/dist/database/migrations/20240204A-marketplace.js +9 -7
  91. package/dist/database/migrations/20240311A-deprecate-webhooks.d.ts +15 -0
  92. package/dist/database/migrations/20240311A-deprecate-webhooks.js +1 -1
  93. package/dist/database/migrations/20240806A-permissions-policies.js +2 -2
  94. package/dist/database/migrations/20240924A-migrate-legacy-comments.js +1 -1
  95. package/dist/database/migrations/20251014A-add-project-owner.js +1 -1
  96. package/dist/database/migrations/20251224A-remove-webhooks.d.ts +3 -0
  97. package/dist/database/migrations/20251224A-remove-webhooks.js +19 -0
  98. package/dist/database/migrations/20260110A-add-ai-provider-settings.d.ts +3 -0
  99. package/dist/database/migrations/20260110A-add-ai-provider-settings.js +35 -0
  100. package/dist/database/migrations/20260113A-add-revisions-index.d.ts +3 -0
  101. package/dist/database/migrations/20260113A-add-revisions-index.js +41 -0
  102. package/dist/database/migrations/20260128A-add-collaborative-editing.d.ts +3 -0
  103. package/dist/database/migrations/20260128A-add-collaborative-editing.js +10 -0
  104. package/dist/database/migrations/20260204A-add-deployment.d.ts +3 -0
  105. package/dist/database/migrations/20260204A-add-deployment.js +32 -0
  106. package/dist/database/migrations/run.js +3 -3
  107. package/dist/database/run-ast/lib/apply-query/add-join.js +1 -1
  108. package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.d.ts +2 -2
  109. package/dist/database/run-ast/lib/apply-query/filter/get-filter-type.js +1 -1
  110. package/dist/database/run-ast/lib/apply-query/filter/index.js +1 -1
  111. package/dist/database/run-ast/lib/apply-query/filter/operator.js +1 -1
  112. package/dist/database/run-ast/lib/apply-query/sort.js +1 -1
  113. package/dist/database/run-ast/utils/get-column-pre-processor.js +2 -2
  114. package/dist/database/run-ast/utils/get-column.js +1 -1
  115. package/dist/database/seeds/run.js +3 -3
  116. package/dist/deployment/deployment.d.ts +94 -0
  117. package/dist/deployment/deployment.js +29 -0
  118. package/dist/deployment/drivers/index.d.ts +1 -0
  119. package/dist/deployment/drivers/index.js +1 -0
  120. package/dist/deployment/drivers/vercel.d.ts +32 -0
  121. package/dist/deployment/drivers/vercel.js +208 -0
  122. package/dist/deployment/index.d.ts +2 -0
  123. package/dist/deployment/index.js +2 -0
  124. package/dist/deployment.d.ts +24 -0
  125. package/dist/deployment.js +39 -0
  126. package/dist/extensions/lib/get-extensions-path.js +1 -1
  127. package/dist/extensions/lib/get-extensions-settings.js +1 -1
  128. package/dist/extensions/lib/get-extensions.js +1 -1
  129. package/dist/extensions/lib/get-shared-deps-mapping.js +3 -3
  130. package/dist/extensions/lib/installation/manager.js +3 -3
  131. package/dist/extensions/lib/sandbox/register/route.d.ts +1 -1
  132. package/dist/extensions/lib/sync/status.js +1 -1
  133. package/dist/extensions/lib/sync/sync.js +7 -7
  134. package/dist/extensions/lib/sync/utils.js +2 -2
  135. package/dist/extensions/manager.d.ts +1 -1
  136. package/dist/extensions/manager.js +8 -8
  137. package/dist/flows.d.ts +1 -1
  138. package/dist/logger/index.js +1 -1
  139. package/dist/logger/logs-stream.d.ts +1 -1
  140. package/dist/logger/logs-stream.js +1 -1
  141. package/dist/mailer.js +1 -1
  142. package/dist/metrics/lib/create-metrics.js +2 -2
  143. package/dist/middleware/authenticate.js +3 -3
  144. package/dist/middleware/collection-exists.js +1 -1
  145. package/dist/middleware/extract-token.js +1 -1
  146. package/dist/middleware/graphql.js +2 -2
  147. package/dist/middleware/respond.js +27 -14
  148. package/dist/middleware/validate-batch.js +1 -1
  149. package/dist/operations/exec/index.js +2 -1
  150. package/dist/operations/mail/index.js +1 -1
  151. package/dist/operations/mail/rate-limiter.js +2 -2
  152. package/dist/permissions/cache.js +5 -0
  153. package/dist/permissions/modules/fetch-allowed-collections/fetch-allowed-collections.js +1 -1
  154. package/dist/permissions/modules/fetch-allowed-field-map/fetch-allowed-field-map.js +1 -1
  155. package/dist/permissions/modules/fetch-inconsistent-field-map/fetch-inconsistent-field-map.js +2 -2
  156. package/dist/permissions/modules/process-ast/lib/inject-cases.js +1 -1
  157. package/dist/permissions/modules/process-ast/process-ast.js +1 -1
  158. package/dist/permissions/modules/process-ast/utils/find-related-collection.js +1 -1
  159. package/dist/permissions/modules/process-payload/process-payload.js +1 -1
  160. package/dist/permissions/modules/validate-access/lib/validate-item-access.d.ts +14 -2
  161. package/dist/permissions/modules/validate-access/lib/validate-item-access.js +72 -13
  162. package/dist/permissions/modules/validate-access/validate-access.js +3 -2
  163. package/dist/rate-limiter.js +1 -1
  164. package/dist/request/is-denied-ip.js +1 -1
  165. package/dist/schedules/project.js +1 -1
  166. package/dist/schedules/telemetry.js +1 -1
  167. package/dist/schedules/tus.js +1 -1
  168. package/dist/server.js +6 -5
  169. package/dist/services/assets.d.ts +2 -1
  170. package/dist/services/assets.js +35 -8
  171. package/dist/services/authentication.js +2 -2
  172. package/dist/services/collections.js +1 -1
  173. package/dist/services/deployment-projects.d.ts +20 -0
  174. package/dist/services/deployment-projects.js +34 -0
  175. package/dist/services/deployment-runs.d.ts +13 -0
  176. package/dist/services/deployment-runs.js +6 -0
  177. package/dist/services/deployment.d.ts +40 -0
  178. package/dist/services/deployment.js +202 -0
  179. package/dist/services/extensions.d.ts +1 -1
  180. package/dist/services/files/utils/get-metadata.d.ts +1 -1
  181. package/dist/services/files/utils/get-metadata.js +1 -1
  182. package/dist/services/files.d.ts +1 -1
  183. package/dist/services/files.js +4 -4
  184. package/dist/services/graphql/index.d.ts +1 -1
  185. package/dist/services/graphql/index.js +1 -1
  186. package/dist/services/graphql/resolvers/mutation.js +1 -1
  187. package/dist/services/graphql/resolvers/system-admin.js +2 -3
  188. package/dist/services/graphql/schema/get-types.d.ts +1 -1
  189. package/dist/services/graphql/schema/read.js +1 -1
  190. package/dist/services/graphql/subscription.d.ts +1 -1
  191. package/dist/services/graphql/types/date.js +1 -1
  192. package/dist/services/graphql/types/hash.js +1 -1
  193. package/dist/services/graphql/utils/add-path-to-validation-error.js +1 -1
  194. package/dist/services/graphql/utils/filter-replace-m2a.js +3 -4
  195. package/dist/services/import-export.d.ts +1 -1
  196. package/dist/services/import-export.js +2 -2
  197. package/dist/services/index.d.ts +3 -1
  198. package/dist/services/index.js +3 -1
  199. package/dist/services/mail/index.js +2 -2
  200. package/dist/services/mail/rate-limiter.js +2 -2
  201. package/dist/services/payload.js +2 -2
  202. package/dist/services/schema.js +1 -1
  203. package/dist/services/server.js +13 -4
  204. package/dist/services/settings.js +2 -2
  205. package/dist/services/specifications.js +2 -2
  206. package/dist/services/tfa.js +1 -1
  207. package/dist/services/translations.js +1 -1
  208. package/dist/services/tus/data-store.d.ts +1 -3
  209. package/dist/services/tus/data-store.js +2 -5
  210. package/dist/services/tus/server.js +6 -6
  211. package/dist/services/users.js +4 -4
  212. package/dist/services/versions.js +1 -1
  213. package/dist/telemetry/lib/get-report.js +2 -0
  214. package/dist/telemetry/lib/send-report.d.ts +1 -1
  215. package/dist/telemetry/lib/send-report.js +1 -1
  216. package/dist/telemetry/lib/track.js +1 -1
  217. package/dist/telemetry/types/report.d.ts +8 -0
  218. package/dist/telemetry/utils/get-settings.d.ts +2 -0
  219. package/dist/telemetry/utils/get-settings.js +5 -0
  220. package/dist/test-utils/knex.js +1 -1
  221. package/dist/types/collection.d.ts +1 -1
  222. package/dist/utils/async-handler.d.ts +1 -1
  223. package/dist/utils/calculate-field-depth.js +1 -1
  224. package/dist/utils/compress.js +1 -1
  225. package/dist/utils/deep-map-response.d.ts +1 -1
  226. package/dist/utils/deep-map-response.js +2 -2
  227. package/dist/utils/get-cache-key.js +1 -1
  228. package/dist/utils/get-column-path.js +1 -1
  229. package/dist/utils/get-field-system-rows.js +1 -1
  230. package/dist/utils/get-ip-from-req.d.ts +1 -1
  231. package/dist/utils/get-ip-from-req.js +1 -1
  232. package/dist/utils/get-local-type.js +7 -3
  233. package/dist/utils/get-service.js +7 -3
  234. package/dist/utils/get-snapshot-diff.js +1 -1
  235. package/dist/utils/is-field-allowed.d.ts +4 -0
  236. package/dist/utils/is-field-allowed.js +9 -0
  237. package/dist/utils/is-url-allowed.js +1 -1
  238. package/dist/utils/jwt.js +1 -1
  239. package/dist/utils/sanitize-schema.d.ts +1 -1
  240. package/dist/utils/should-clear-cache.d.ts +1 -1
  241. package/dist/utils/should-skip-cache.js +2 -2
  242. package/dist/utils/validate-diff.js +1 -1
  243. package/dist/utils/validate-snapshot.js +3 -3
  244. package/dist/utils/validate-storage.js +2 -2
  245. package/dist/utils/verify-session-jwt.js +1 -1
  246. package/dist/utils/versioning/handle-version.js +1 -1
  247. package/dist/websocket/collab/calculate-cache-metadata.d.ts +9 -0
  248. package/dist/websocket/collab/calculate-cache-metadata.js +121 -0
  249. package/dist/websocket/collab/collab.d.ts +63 -0
  250. package/dist/websocket/collab/collab.js +481 -0
  251. package/dist/websocket/collab/constants.d.ts +1 -0
  252. package/dist/websocket/collab/constants.js +13 -0
  253. package/dist/websocket/collab/filter-to-fields.d.ts +2 -0
  254. package/dist/websocket/collab/filter-to-fields.js +11 -0
  255. package/dist/websocket/collab/messenger.d.ts +43 -0
  256. package/dist/websocket/collab/messenger.js +225 -0
  257. package/dist/websocket/collab/payload-permissions.d.ts +18 -0
  258. package/dist/websocket/collab/payload-permissions.js +158 -0
  259. package/dist/websocket/collab/permissions-cache.d.ts +52 -0
  260. package/dist/websocket/collab/permissions-cache.js +204 -0
  261. package/dist/websocket/collab/room.d.ts +125 -0
  262. package/dist/websocket/collab/room.js +593 -0
  263. package/dist/websocket/collab/store.d.ts +7 -0
  264. package/dist/websocket/collab/store.js +33 -0
  265. package/dist/websocket/collab/types.d.ts +21 -0
  266. package/dist/websocket/collab/types.js +1 -0
  267. package/dist/websocket/collab/verify-permissions.d.ts +11 -0
  268. package/dist/websocket/collab/verify-permissions.js +100 -0
  269. package/dist/websocket/controllers/base.d.ts +2 -2
  270. package/dist/websocket/controllers/base.js +3 -3
  271. package/dist/websocket/controllers/graphql.d.ts +1 -1
  272. package/dist/websocket/controllers/graphql.js +1 -1
  273. package/dist/websocket/controllers/logs.d.ts +1 -1
  274. package/dist/websocket/controllers/rest.d.ts +1 -1
  275. package/dist/websocket/controllers/rest.js +2 -2
  276. package/dist/websocket/handlers/heartbeat.js +1 -1
  277. package/dist/websocket/handlers/index.d.ts +2 -0
  278. package/dist/websocket/handlers/index.js +9 -0
  279. package/dist/websocket/handlers/items.js +2 -2
  280. package/dist/websocket/handlers/subscribe.js +1 -1
  281. package/dist/websocket/types.d.ts +1 -1
  282. package/dist/websocket/utils/items.d.ts +2 -2
  283. package/dist/websocket/utils/message.d.ts +1 -1
  284. package/dist/websocket/utils/message.js +2 -2
  285. package/dist/websocket/utils/wait-for-message.js +1 -1
  286. package/package.json +35 -33
  287. package/dist/controllers/webhooks.js +0 -74
  288. package/dist/services/webhooks.d.ts +0 -14
  289. package/dist/services/webhooks.js +0 -32
  290. package/dist/utils/get-relation-info.d.ts +0 -6
  291. package/dist/utils/get-relation-info.js +0 -43
  292. package/dist/utils/get-relation-type.d.ts +0 -6
  293. package/dist/utils/get-relation-type.js +0 -18
  294. package/dist/utils/is-login-redirect-allowed.d.ts +0 -4
  295. package/dist/utils/versioning/deep-map-with-schema.d.ts +0 -23
  296. package/dist/utils/versioning/deep-map-with-schema.js +0 -81
  297. /package/dist/controllers/{webhooks.d.ts → deployment.d.ts} +0 -0
@@ -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';
@@ -1,12 +1,12 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { processChunk, toBoolean } from '@directus/utils';
2
3
  import { omit } from 'lodash-es';
3
- import { randomUUID } from 'node:crypto';
4
4
  import { useLogger } from '../../logger/index.js';
5
5
  import { fetchPermissions } from '../../permissions/lib/fetch-permissions.js';
6
6
  import { fetchPolicies } from '../../permissions/lib/fetch-policies.js';
7
7
  import { fetchRolesTree } from '../../permissions/lib/fetch-roles-tree.js';
8
- import { getSchema } from '../../utils/get-schema.js';
9
8
  import { mergePermissions } from '../../permissions/utils/merge-permissions.js';
9
+ import { getSchema } from '../../utils/get-schema.js';
10
10
  import { getSchemaInspector } from '../index.js';
11
11
  async function fetchRoleAccess(roles, context) {
12
12
  const roleAccess = {
@@ -1,5 +1,5 @@
1
- import { Action } from '@directus/constants';
2
1
  import { randomUUID } from 'node:crypto';
2
+ import { Action } from '@directus/constants';
3
3
  export async function up(knex) {
4
4
  // remove foreign key constraint for projects already migrated to retentions-p1
5
5
  try {
@@ -1,8 +1,8 @@
1
1
  import { useEnv } from '@directus/env';
2
2
  import { toBoolean } from '@directus/utils';
3
+ import { email } from 'zod';
3
4
  import { SettingsService } from '../../services/settings.js';
4
5
  import { getSchema } from '../../utils/get-schema.js';
5
- import { email } from 'zod';
6
6
  export async function up(knex) {
7
7
  await knex.schema.alterTable('directus_settings', (table) => {
8
8
  table.string('project_owner');
@@ -0,0 +1,3 @@
1
+ import type { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
@@ -0,0 +1,19 @@
1
+ export async function up(knex) {
2
+ await knex.schema.dropTable('directus_webhooks');
3
+ }
4
+ export async function down(knex) {
5
+ await knex.schema.createTable('directus_webhooks', (table) => {
6
+ table.increments('id');
7
+ table.string('name', 255).notNullable();
8
+ table.string('method', 10).notNullable().defaultTo('POST');
9
+ table.text('url').notNullable();
10
+ table.string('status', 10).notNullable().defaultTo('active');
11
+ table.boolean('data').notNullable().defaultTo(true);
12
+ table.string('actions', 100).notNullable();
13
+ table.text('collections').notNullable();
14
+ table.json('headers');
15
+ table.boolean('was_active_before_deprecation').notNullable().defaultTo(false);
16
+ table.uuid('migrated_flow');
17
+ table.foreign('migrated_flow').references('directus_flows.id').onDelete('SET NULL');
18
+ });
19
+ }
@@ -0,0 +1,3 @@
1
+ import type { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
@@ -0,0 +1,35 @@
1
+ const DEFAULT_OPENAI_MODELS = ['gpt-5-nano', 'gpt-5-mini', 'gpt-5'];
2
+ const DEFAULT_ANTHROPIC_MODELS = ['claude-haiku-4-5', 'claude-sonnet-4-5'];
3
+ const DEFAULT_GOOGLE_MODELS = ['gemini-3-pro-preview', 'gemini-3-flash-preview', 'gemini-2.5-pro', 'gemini-2.5-flash'];
4
+ export async function up(knex) {
5
+ await knex.schema.alterTable('directus_settings', (table) => {
6
+ table.text('ai_google_api_key');
7
+ table.text('ai_openai_compatible_api_key');
8
+ table.text('ai_openai_compatible_base_url');
9
+ table.text('ai_openai_compatible_name');
10
+ table.json('ai_openai_compatible_models');
11
+ table.json('ai_openai_compatible_headers');
12
+ table.json('ai_openai_allowed_models');
13
+ table.json('ai_anthropic_allowed_models');
14
+ table.json('ai_google_allowed_models');
15
+ });
16
+ // Set default allowed models for existing installations
17
+ await knex('directus_settings').update({
18
+ ai_openai_allowed_models: JSON.stringify(DEFAULT_OPENAI_MODELS),
19
+ ai_anthropic_allowed_models: JSON.stringify(DEFAULT_ANTHROPIC_MODELS),
20
+ ai_google_allowed_models: JSON.stringify(DEFAULT_GOOGLE_MODELS),
21
+ });
22
+ }
23
+ export async function down(knex) {
24
+ await knex.schema.alterTable('directus_settings', (table) => {
25
+ table.dropColumn('ai_google_api_key');
26
+ table.dropColumn('ai_openai_compatible_api_key');
27
+ table.dropColumn('ai_openai_compatible_base_url');
28
+ table.dropColumn('ai_openai_compatible_name');
29
+ table.dropColumn('ai_openai_compatible_models');
30
+ table.dropColumn('ai_openai_compatible_headers');
31
+ table.dropColumn('ai_openai_allowed_models');
32
+ table.dropColumn('ai_anthropic_allowed_models');
33
+ table.dropColumn('ai_google_allowed_models');
34
+ });
35
+ }
@@ -0,0 +1,3 @@
1
+ import type { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
@@ -0,0 +1,41 @@
1
+ import { FieldsService } from '../../services/fields.js';
2
+ import { getSchema } from '../../utils/get-schema.js';
3
+ import { transaction } from '../../utils/transaction.js';
4
+ import { getHelpers } from '../helpers/index.js';
5
+ import { getDatabaseClient } from '../index.js';
6
+ const RETENTION_INDEXES = [
7
+ // MySQL and MariaDB are ignored because they already have an index on revisions.activity
8
+ { collection: 'directus_revisions', field: 'activity', ignore: ['mysql', 'mariadb'] },
9
+ ];
10
+ export async function up(knex) {
11
+ const client = getDatabaseClient(knex);
12
+ const helpers = getHelpers(knex);
13
+ const schema = await getSchema();
14
+ const service = new FieldsService({ knex, schema });
15
+ for (const { collection, field, ignore } of RETENTION_INDEXES) {
16
+ if (ignore.includes(client))
17
+ continue;
18
+ const existingColumn = await service.columnInfo(collection, field);
19
+ if (!existingColumn.is_indexed) {
20
+ await helpers.schema.createIndex(collection, field, { attemptConcurrentIndex: true });
21
+ }
22
+ }
23
+ }
24
+ export async function down(knex) {
25
+ const client = getDatabaseClient(knex);
26
+ const helpers = getHelpers(knex);
27
+ const schema = await getSchema();
28
+ const service = new FieldsService({ knex, schema });
29
+ for (const { collection, field, ignore } of RETENTION_INDEXES) {
30
+ if (ignore.includes(client))
31
+ continue;
32
+ const existingColumn = await service.columnInfo(collection, field);
33
+ if (existingColumn.is_indexed) {
34
+ await transaction(knex, async (trx) => {
35
+ await trx.schema.alterTable(collection, async (table) => {
36
+ table.dropIndex([field], helpers.schema.generateIndexName('index', collection, field));
37
+ });
38
+ });
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,3 @@
1
+ import type { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
@@ -0,0 +1,10 @@
1
+ export async function up(knex) {
2
+ await knex.schema.alterTable('directus_settings', (table) => {
3
+ table.boolean('collaborative_editing_enabled').defaultTo(false).notNullable();
4
+ });
5
+ }
6
+ export async function down(knex) {
7
+ await knex.schema.alterTable('directus_settings', (table) => {
8
+ table.dropColumn('collaborative_editing_enabled');
9
+ });
10
+ }
@@ -0,0 +1,3 @@
1
+ import type { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
@@ -0,0 +1,32 @@
1
+ export async function up(knex) {
2
+ await knex.schema.createTable('directus_deployments', (table) => {
3
+ table.uuid('id').primary().notNullable();
4
+ table.string('provider').notNullable().unique();
5
+ table.text('credentials');
6
+ table.text('options');
7
+ table.timestamp('date_created').defaultTo(knex.fn.now());
8
+ table.uuid('user_created').references('id').inTable('directus_users').onDelete('SET NULL');
9
+ });
10
+ await knex.schema.createTable('directus_deployment_projects', (table) => {
11
+ table.uuid('id').primary().notNullable();
12
+ table.uuid('deployment').notNullable().references('id').inTable('directus_deployments').onDelete('CASCADE');
13
+ table.string('external_id').notNullable();
14
+ table.string('name').notNullable();
15
+ table.timestamp('date_created').defaultTo(knex.fn.now());
16
+ table.uuid('user_created').references('id').inTable('directus_users').onDelete('SET NULL');
17
+ table.unique(['deployment', 'external_id']);
18
+ });
19
+ await knex.schema.createTable('directus_deployment_runs', (table) => {
20
+ table.uuid('id').primary().notNullable();
21
+ table.uuid('project').notNullable().references('id').inTable('directus_deployment_projects').onDelete('CASCADE');
22
+ table.string('external_id').notNullable();
23
+ table.string('target').notNullable(); // 'production' or 'preview'
24
+ table.timestamp('date_created').defaultTo(knex.fn.now());
25
+ table.uuid('user_created').references('id').inTable('directus_users').onDelete('SET NULL');
26
+ });
27
+ }
28
+ export async function down(knex) {
29
+ await knex.schema.dropTable('directus_deployment_runs');
30
+ await knex.schema.dropTable('directus_deployment_projects');
31
+ await knex.schema.dropTable('directus_deployments');
32
+ }
@@ -1,10 +1,10 @@
1
+ import { dirname } from 'node:path';
2
+ import { fileURLToPath } from 'node:url';
3
+ import path from 'path';
1
4
  import { useEnv } from '@directus/env';
2
5
  import formatTitle from '@directus/format-title';
3
6
  import fse from 'fs-extra';
4
7
  import { orderBy } from 'lodash-es';
5
- import { dirname } from 'node:path';
6
- import { fileURLToPath } from 'node:url';
7
- import path from 'path';
8
8
  import { flushCaches } from '../../cache.js';
9
9
  import { useLogger } from '../../logger/index.js';
10
10
  import getModuleDefault from '../../utils/get-module-default.js';
@@ -1,6 +1,6 @@
1
1
  import { InvalidQueryError } from '@directus/errors';
2
+ import { getRelationInfo } from '@directus/utils';
2
3
  import { clone } from 'lodash-es';
3
- import { getRelationInfo } from '../../../../utils/get-relation-info.js';
4
4
  import { getHelpers } from '../../../helpers/index.js';
5
5
  import { generateJoinAlias } from '../../utils/generate-alias.js';
6
6
  export function addJoin({ path, collection, aliasMap, rootQuery, schema, knex }) {
@@ -1,8 +1,8 @@
1
1
  import type { FieldOverview } from '@directus/types';
2
2
  export declare function getFilterType(fields: Record<string, FieldOverview>, key: string, collection?: string): {
3
- type: "string" | "boolean" | "binary" | "time" | "text" | "integer" | "float" | "alias" | "uuid" | "dateTime" | "timestamp" | "bigInteger" | "date" | "decimal" | "json" | "hash" | "csv" | "geometry" | "geometry.Point" | "geometry.LineString" | "geometry.Polygon" | "geometry.MultiPoint" | "geometry.MultiLineString" | "geometry.MultiPolygon" | "unknown";
3
+ type: "string" | "boolean" | "binary" | "integer" | "unknown" | "date" | "text" | "json" | "float" | "alias" | "uuid" | "time" | "dateTime" | "timestamp" | "bigInteger" | "decimal" | "hash" | "csv" | "geometry" | "geometry.Point" | "geometry.LineString" | "geometry.Polygon" | "geometry.MultiPoint" | "geometry.MultiLineString" | "geometry.MultiPolygon";
4
4
  special?: never;
5
5
  } | {
6
- type: "string" | "boolean" | "binary" | "time" | "text" | "integer" | "float" | "alias" | "uuid" | "dateTime" | "timestamp" | "bigInteger" | "date" | "decimal" | "json" | "hash" | "csv" | "geometry" | "geometry.Point" | "geometry.LineString" | "geometry.Polygon" | "geometry.MultiPoint" | "geometry.MultiLineString" | "geometry.MultiPolygon" | "unknown";
6
+ type: "string" | "boolean" | "binary" | "integer" | "unknown" | "date" | "text" | "json" | "float" | "alias" | "uuid" | "time" | "dateTime" | "timestamp" | "bigInteger" | "decimal" | "hash" | "csv" | "geometry" | "geometry.Point" | "geometry.LineString" | "geometry.Polygon" | "geometry.MultiPoint" | "geometry.MultiLineString" | "geometry.MultiPolygon";
7
7
  special: string[];
8
8
  };
@@ -1,6 +1,6 @@
1
- import { parseFilterKey } from '../../../../../utils/parse-filter-key.js';
2
1
  import { InvalidQueryError } from '@directus/errors';
3
2
  import { getFunctionsForType, getOutputTypeForFunction } from '@directus/utils';
3
+ import { parseFilterKey } from '../../../../../utils/parse-filter-key.js';
4
4
  export function getFilterType(fields, key, collection = 'unknown') {
5
5
  const { fieldName, functionName } = parseFilterKey(key);
6
6
  const field = fields[fieldName];
@@ -1,7 +1,7 @@
1
1
  import { InvalidQueryError } from '@directus/errors';
2
+ import { getRelationInfo } from '@directus/utils';
2
3
  import { getCases } from '../../../../../permissions/modules/process-ast/lib/get-cases.js';
3
4
  import { getColumnPath } from '../../../../../utils/get-column-path.js';
4
- import { getRelationInfo } from '../../../../../utils/get-relation-info.js';
5
5
  import { getHelpers } from '../../../../helpers/index.js';
6
6
  import { addJoin } from '../add-join.js';
7
7
  import { getFilterPath } from '../get-filter-path.js';
@@ -1,6 +1,6 @@
1
- import { getColumn } from '../../../utils/get-column.js';
2
1
  import { getOutputTypeForFunction } from '@directus/utils';
3
2
  import { getHelpers } from '../../../../helpers/index.js';
3
+ import { getColumn } from '../../../utils/get-column.js';
4
4
  export function applyOperator(knex, dbQuery, schema, key, operator, compareValue, logical = 'and', originalCollectionName) {
5
5
  const helpers = getHelpers(knex);
6
6
  const [table, column] = key.split('.');
@@ -1,6 +1,6 @@
1
+ import { getRelationInfo } from '@directus/utils';
1
2
  import { getColumnPath } from '../../../../utils/get-column-path.js';
2
3
  import { getColumn } from '../../utils/get-column.js';
3
- import { getRelationInfo } from '../../../../utils/get-relation-info.js';
4
4
  import { addJoin } from './add-join.js';
5
5
  export function applySort(knex, schema, rootQuery, sort, aggregate, collection, aliasMap, returnRecords = false) {
6
6
  const relations = schema.relations;
@@ -1,8 +1,8 @@
1
- import { joinFilterWithCases } from '../lib/apply-query/join-filter-with-cases.js';
2
- import { getColumn } from './get-column.js';
3
1
  import { parseFilterKey } from '../../../utils/parse-filter-key.js';
4
2
  import { getHelpers } from '../../helpers/index.js';
3
+ import { joinFilterWithCases } from '../lib/apply-query/join-filter-with-cases.js';
5
4
  import { applyCaseWhen } from './apply-case-when.js';
5
+ import { getColumn } from './get-column.js';
6
6
  import { getNodeAlias } from './get-field-alias.js';
7
7
  export function getColumnPreprocessor(knex, schema, table, cases, permissions, aliasMap, permissionsOnly) {
8
8
  const helpers = getHelpers(knex);
@@ -1,7 +1,7 @@
1
1
  import { REGEX_BETWEEN_PARENS } from '@directus/constants';
2
+ import { InvalidQueryError } from '@directus/errors';
2
3
  import { getFunctionsForType } from '@directus/utils';
3
4
  import { getFunctions } from '../../helpers/index.js';
4
- import { InvalidQueryError } from '@directus/errors';
5
5
  import { applyFunctionToColumnName } from './apply-function-to-column-name.js';
6
6
  /**
7
7
  * Return column prefixed by table. If column includes functions (like `year(date_created)`), the
@@ -1,9 +1,9 @@
1
- import fse from 'fs-extra';
2
- import yaml from 'js-yaml';
3
- import { isObject } from 'lodash-es';
4
1
  import { dirname } from 'node:path';
5
2
  import { fileURLToPath } from 'node:url';
6
3
  import path from 'path';
4
+ import fse from 'fs-extra';
5
+ import yaml from 'js-yaml';
6
+ import { isObject } from 'lodash-es';
7
7
  import { getHelpers } from '../helpers/index.js';
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
9
  export default async function runSeed(database) {