@directus/api 13.1.1 → 13.2.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 (219) hide show
  1. package/dist/app.js +4 -4
  2. package/dist/auth/drivers/ldap.js +3 -2
  3. package/dist/auth/drivers/local.js +1 -1
  4. package/dist/auth/drivers/oauth2.js +1 -1
  5. package/dist/auth/drivers/openid.js +1 -1
  6. package/dist/auth/drivers/saml.js +1 -1
  7. package/dist/auth.js +1 -1
  8. package/dist/cli/index.js +1 -1
  9. package/dist/controllers/activity.js +1 -1
  10. package/dist/controllers/assets.js +2 -2
  11. package/dist/controllers/auth.js +1 -1
  12. package/dist/controllers/collections.js +1 -1
  13. package/dist/controllers/dashboards.js +1 -1
  14. package/dist/controllers/extensions.js +11 -7
  15. package/dist/controllers/fields.js +1 -1
  16. package/dist/controllers/files.js +1 -1
  17. package/dist/controllers/flows.js +1 -1
  18. package/dist/controllers/folders.js +1 -1
  19. package/dist/controllers/items.js +1 -1
  20. package/dist/controllers/not-found.js +1 -1
  21. package/dist/controllers/notifications.js +1 -1
  22. package/dist/controllers/operations.js +1 -1
  23. package/dist/controllers/panels.js +1 -1
  24. package/dist/controllers/permissions.js +1 -1
  25. package/dist/controllers/presets.js +1 -1
  26. package/dist/controllers/relations.js +1 -1
  27. package/dist/controllers/roles.js +1 -1
  28. package/dist/controllers/schema.js +1 -1
  29. package/dist/controllers/server.js +1 -1
  30. package/dist/controllers/settings.js +1 -1
  31. package/dist/controllers/shares.js +1 -1
  32. package/dist/controllers/translations.js +1 -1
  33. package/dist/controllers/users.js +1 -1
  34. package/dist/controllers/utils.js +37 -18
  35. package/dist/controllers/webhooks.js +1 -1
  36. package/dist/database/errors/dialects/mssql.js +1 -1
  37. package/dist/database/errors/dialects/mysql.js +1 -1
  38. package/dist/database/errors/dialects/oracle.js +1 -1
  39. package/dist/database/errors/dialects/postgres.js +1 -1
  40. package/dist/database/errors/dialects/sqlite.js +1 -1
  41. package/dist/database/helpers/schema/dialects/mysql.js +1 -1
  42. package/dist/database/helpers/sequence/dialects/postgres.d.ts +5 -2
  43. package/dist/database/helpers/sequence/dialects/postgres.js +6 -3
  44. package/dist/database/migrations/20231009A-update-csv-fields-to-text.d.ts +3 -0
  45. package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +44 -0
  46. package/dist/database/run-ast.js +1 -1
  47. package/dist/database/seeds/run.js +1 -1
  48. package/dist/extensions/get-extensions.d.ts +47 -0
  49. package/dist/extensions/get-extensions.js +9 -0
  50. package/dist/extensions/get-shared-deps-mapping.d.ts +1 -0
  51. package/dist/extensions/get-shared-deps-mapping.js +26 -0
  52. package/dist/extensions/index.d.ts +2 -0
  53. package/dist/extensions/index.js +9 -0
  54. package/dist/{extensions.d.ts → extensions/manager.d.ts} +4 -11
  55. package/dist/{extensions.js → extensions/manager.js} +28 -86
  56. package/dist/extensions/normalize-extension-info.d.ts +5 -0
  57. package/dist/extensions/normalize-extension-info.js +30 -0
  58. package/dist/extensions/types.d.ts +23 -0
  59. package/dist/extensions/wrap-embeds.d.ts +4 -0
  60. package/dist/extensions/wrap-embeds.js +8 -0
  61. package/dist/flows.d.ts +1 -1
  62. package/dist/flows.js +1 -1
  63. package/dist/middleware/check-ip.js +1 -1
  64. package/dist/middleware/collection-exists.js +1 -1
  65. package/dist/middleware/error-handler.js +1 -1
  66. package/dist/middleware/graphql.js +1 -1
  67. package/dist/middleware/rate-limiter-global.js +1 -1
  68. package/dist/middleware/rate-limiter-ip.js +1 -1
  69. package/dist/middleware/respond.js +1 -1
  70. package/dist/middleware/validate-batch.js +1 -1
  71. package/dist/operations/condition/index.d.ts +1 -1
  72. package/dist/operations/condition/index.js +2 -1
  73. package/dist/operations/exec/index.d.ts +1 -1
  74. package/dist/operations/exec/index.js +1 -1
  75. package/dist/operations/item-create/index.d.ts +1 -1
  76. package/dist/operations/item-create/index.js +2 -1
  77. package/dist/operations/item-delete/index.d.ts +1 -1
  78. package/dist/operations/item-delete/index.js +2 -1
  79. package/dist/operations/item-read/index.d.ts +1 -1
  80. package/dist/operations/item-read/index.js +2 -1
  81. package/dist/operations/item-update/index.d.ts +1 -1
  82. package/dist/operations/item-update/index.js +2 -1
  83. package/dist/operations/json-web-token/index.d.ts +1 -1
  84. package/dist/operations/json-web-token/index.js +2 -1
  85. package/dist/operations/log/index.d.ts +1 -1
  86. package/dist/operations/log/index.js +2 -1
  87. package/dist/operations/mail/index.d.ts +1 -1
  88. package/dist/operations/mail/index.js +1 -1
  89. package/dist/operations/notification/index.d.ts +1 -1
  90. package/dist/operations/notification/index.js +2 -1
  91. package/dist/operations/request/index.d.ts +1 -1
  92. package/dist/operations/request/index.js +3 -2
  93. package/dist/operations/sleep/index.d.ts +1 -1
  94. package/dist/operations/sleep/index.js +1 -1
  95. package/dist/operations/transform/index.d.ts +1 -1
  96. package/dist/operations/transform/index.js +2 -1
  97. package/dist/operations/trigger/index.d.ts +1 -1
  98. package/dist/operations/trigger/index.js +2 -1
  99. package/dist/services/activity.js +1 -1
  100. package/dist/services/assets.d.ts +1 -1
  101. package/dist/services/assets.js +2 -2
  102. package/dist/services/authentication.js +2 -2
  103. package/dist/services/authorization.js +1 -1
  104. package/dist/services/collections.js +3 -3
  105. package/dist/services/fields.d.ts +2 -2
  106. package/dist/services/fields.js +4 -4
  107. package/dist/services/files.d.ts +4 -1
  108. package/dist/services/files.js +5 -5
  109. package/dist/services/graphql/index.js +2 -2
  110. package/dist/services/graphql/subscription.js +3 -3
  111. package/dist/services/import-export/import-worker.d.ts +9 -0
  112. package/dist/services/import-export/import-worker.js +9 -0
  113. package/dist/services/{import-export.d.ts → import-export/index.d.ts} +2 -2
  114. package/dist/services/{import-export.js → import-export/index.js} +51 -42
  115. package/dist/services/index.d.ts +1 -1
  116. package/dist/services/index.js +1 -1
  117. package/dist/services/items.js +2 -2
  118. package/dist/services/mail/index.js +1 -1
  119. package/dist/services/meta.js +1 -1
  120. package/dist/services/payload.js +1 -1
  121. package/dist/services/permissions.d.ts +2 -2
  122. package/dist/services/permissions.js +1 -1
  123. package/dist/services/relations.js +1 -1
  124. package/dist/services/revisions.js +1 -1
  125. package/dist/services/roles.js +1 -1
  126. package/dist/services/schema.js +1 -1
  127. package/dist/services/shares.js +1 -1
  128. package/dist/services/tfa.js +1 -1
  129. package/dist/services/translations.js +1 -1
  130. package/dist/services/users.js +2 -2
  131. package/dist/services/utils.d.ts +1 -0
  132. package/dist/services/utils.js +8 -2
  133. package/dist/services/websocket.js +11 -1
  134. package/dist/types/index.d.ts +0 -1
  135. package/dist/types/index.js +0 -1
  136. package/dist/utils/apply-query.js +1 -1
  137. package/dist/utils/get-accountability-for-token.js +1 -1
  138. package/dist/utils/get-ast-from-query.js +1 -1
  139. package/dist/utils/get-column-path.js +1 -1
  140. package/dist/utils/get-column.js +1 -1
  141. package/dist/utils/get-default-value.d.ts +1 -2
  142. package/dist/utils/get-permissions.js +1 -1
  143. package/dist/utils/jwt.js +1 -1
  144. package/dist/utils/redact-object.js +9 -3
  145. package/dist/utils/transformations.d.ts +2 -1
  146. package/dist/utils/validate-diff.js +1 -1
  147. package/dist/utils/validate-keys.js +1 -1
  148. package/dist/utils/validate-query.js +1 -1
  149. package/dist/utils/validate-snapshot.js +1 -1
  150. package/dist/websocket/controllers/base.js +1 -1
  151. package/dist/websocket/controllers/index.d.ts +1 -1
  152. package/dist/websocket/controllers/index.js +0 -7
  153. package/dist/websocket/handlers/heartbeat.js +6 -1
  154. package/dist/websocket/handlers/subscribe.js +11 -16
  155. package/dist/websocket/utils/items.d.ts +4 -14
  156. package/dist/websocket/utils/items.js +59 -64
  157. package/dist/worker-pool.d.ts +2 -0
  158. package/dist/worker-pool.js +11 -0
  159. package/package.json +24 -22
  160. package/dist/errors/codes.d.ts +0 -29
  161. package/dist/errors/codes.js +0 -30
  162. package/dist/errors/contains-null-values.d.ts +0 -7
  163. package/dist/errors/contains-null-values.js +0 -4
  164. package/dist/errors/content-too-large.d.ts +0 -1
  165. package/dist/errors/content-too-large.js +0 -3
  166. package/dist/errors/forbidden.d.ts +0 -1
  167. package/dist/errors/forbidden.js +0 -3
  168. package/dist/errors/hit-rate-limit.d.ts +0 -6
  169. package/dist/errors/hit-rate-limit.js +0 -8
  170. package/dist/errors/illegal-asset-transformation.d.ts +0 -4
  171. package/dist/errors/illegal-asset-transformation.js +0 -3
  172. package/dist/errors/index.d.ts +0 -28
  173. package/dist/errors/index.js +0 -28
  174. package/dist/errors/invalid-credentials.d.ts +0 -1
  175. package/dist/errors/invalid-credentials.js +0 -3
  176. package/dist/errors/invalid-foreign-key.d.ts +0 -6
  177. package/dist/errors/invalid-foreign-key.js +0 -14
  178. package/dist/errors/invalid-ip.d.ts +0 -1
  179. package/dist/errors/invalid-ip.js +0 -3
  180. package/dist/errors/invalid-otp.d.ts +0 -1
  181. package/dist/errors/invalid-otp.js +0 -3
  182. package/dist/errors/invalid-payload.d.ts +0 -5
  183. package/dist/errors/invalid-payload.js +0 -4
  184. package/dist/errors/invalid-provider-config.d.ts +0 -5
  185. package/dist/errors/invalid-provider-config.js +0 -3
  186. package/dist/errors/invalid-provider.d.ts +0 -1
  187. package/dist/errors/invalid-provider.js +0 -3
  188. package/dist/errors/invalid-query.d.ts +0 -5
  189. package/dist/errors/invalid-query.js +0 -4
  190. package/dist/errors/invalid-token.d.ts +0 -1
  191. package/dist/errors/invalid-token.js +0 -3
  192. package/dist/errors/method-not-allowed.d.ts +0 -6
  193. package/dist/errors/method-not-allowed.js +0 -6
  194. package/dist/errors/not-null-violation.d.ts +0 -6
  195. package/dist/errors/not-null-violation.js +0 -14
  196. package/dist/errors/range-not-satisfiable.d.ts +0 -7
  197. package/dist/errors/range-not-satisfiable.js +0 -7
  198. package/dist/errors/record-not-unique.d.ts +0 -6
  199. package/dist/errors/record-not-unique.js +0 -14
  200. package/dist/errors/route-not-found.d.ts +0 -5
  201. package/dist/errors/route-not-found.js +0 -4
  202. package/dist/errors/service-unavailable.d.ts +0 -7
  203. package/dist/errors/service-unavailable.js +0 -4
  204. package/dist/errors/token-expired.d.ts +0 -1
  205. package/dist/errors/token-expired.js +0 -3
  206. package/dist/errors/unexpected-response.d.ts +0 -1
  207. package/dist/errors/unexpected-response.js +0 -3
  208. package/dist/errors/unprocessable-content.d.ts +0 -5
  209. package/dist/errors/unprocessable-content.js +0 -4
  210. package/dist/errors/unsupported-media-type.d.ts +0 -6
  211. package/dist/errors/unsupported-media-type.js +0 -4
  212. package/dist/errors/user-suspended.d.ts +0 -1
  213. package/dist/errors/user-suspended.js +0 -3
  214. package/dist/errors/value-out-of-range.d.ts +0 -6
  215. package/dist/errors/value-out-of-range.js +0 -14
  216. package/dist/errors/value-too-long.d.ts +0 -6
  217. package/dist/errors/value-too-long.js +0 -14
  218. package/dist/types/files.d.ts +0 -29
  219. /package/dist/{types/files.js → extensions/types.js} +0 -0
package/dist/app.js CHANGED
@@ -39,8 +39,8 @@ import webhooksRouter from './controllers/webhooks.js';
39
39
  import { isInstalled, validateDatabaseConnection, validateDatabaseExtensions, validateMigrations, } from './database/index.js';
40
40
  import emitter from './emitter.js';
41
41
  import env from './env.js';
42
- import { InvalidPayloadError, ServiceUnavailableError } from './errors/index.js';
43
- import { getExtensionManager } from './extensions.js';
42
+ import { InvalidPayloadError, ServiceUnavailableError } from '@directus/errors';
43
+ import { getExtensionManager } from './extensions/index.js';
44
44
  import { getFlowManager } from './flows.js';
45
45
  import logger, { expressLogger } from './logger.js';
46
46
  import authenticate from './middleware/authenticate.js';
@@ -164,8 +164,8 @@ export default async function createApp() {
164
164
  const html = await readFile(adminPath, 'utf8');
165
165
  const htmlWithVars = html
166
166
  .replace(/<base \/>/, `<base href="${adminUrl.toString({ rootRelative: true })}/" />`)
167
- .replace(/<embed-head \/>/, embeds.head)
168
- .replace(/<embed-body \/>/, embeds.body);
167
+ .replace('<!-- directus-embed-head -->', embeds.head)
168
+ .replace('<!-- directus-embed-body -->', embeds.body);
169
169
  const sendHtml = (_req, res) => {
170
170
  res.setHeader('Cache-Control', 'no-cache');
171
171
  res.setHeader('Vary', 'Origin, Cache-Control');
@@ -5,7 +5,7 @@ import ldap from 'ldapjs';
5
5
  import getDatabase from '../../database/index.js';
6
6
  import emitter from '../../emitter.js';
7
7
  import env from '../../env.js';
8
- import { ErrorCode, InvalidCredentialsError, InvalidPayloadError, InvalidProviderError, InvalidProviderConfigError, ServiceUnavailableError, UnexpectedResponseError, } from '../../errors/index.js';
8
+ import { ErrorCode, InvalidCredentialsError, InvalidPayloadError, InvalidProviderError, InvalidProviderConfigError, ServiceUnavailableError, UnexpectedResponseError, } from '@directus/errors';
9
9
  import logger from '../../logger.js';
10
10
  import { respond } from '../../middleware/respond.js';
11
11
  import { AuthenticationService } from '../../services/authentication.js';
@@ -73,7 +73,8 @@ export class LDAPAuthDriver extends AuthDriver {
73
73
  });
74
74
  res.on('end', (result) => {
75
75
  // Handle edge case where authenticated bind user cannot read their own DN
76
- if (result?.status === 0) {
76
+ // Status `0` is success
77
+ if (result?.status !== 0) {
77
78
  logger.warn('[LDAP] Failed to find bind user record');
78
79
  reject(new UnexpectedResponseError());
79
80
  }
@@ -4,7 +4,7 @@ import Joi from 'joi';
4
4
  import { performance } from 'perf_hooks';
5
5
  import { COOKIE_OPTIONS } from '../../constants.js';
6
6
  import env from '../../env.js';
7
- import { InvalidCredentialsError, InvalidPayloadError } from '../../errors/index.js';
7
+ import { InvalidCredentialsError, InvalidPayloadError } from '@directus/errors';
8
8
  import { respond } from '../../middleware/respond.js';
9
9
  import { AuthenticationService } from '../../services/authentication.js';
10
10
  import asyncHandler from '../../utils/async-handler.js';
@@ -8,7 +8,7 @@ import { getAuthProvider } from '../../auth.js';
8
8
  import getDatabase from '../../database/index.js';
9
9
  import emitter from '../../emitter.js';
10
10
  import env from '../../env.js';
11
- import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '../../errors/index.js';
11
+ import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '@directus/errors';
12
12
  import logger from '../../logger.js';
13
13
  import { respond } from '../../middleware/respond.js';
14
14
  import { AuthenticationService } from '../../services/authentication.js';
@@ -8,7 +8,7 @@ import { getAuthProvider } from '../../auth.js';
8
8
  import getDatabase from '../../database/index.js';
9
9
  import emitter from '../../emitter.js';
10
10
  import env from '../../env.js';
11
- import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '../../errors/index.js';
11
+ import { ErrorCode, InvalidCredentialsError, InvalidProviderError, InvalidProviderConfigError, InvalidTokenError, ServiceUnavailableError, } from '@directus/errors';
12
12
  import logger from '../../logger.js';
13
13
  import { respond } from '../../middleware/respond.js';
14
14
  import { AuthenticationService } from '../../services/authentication.js';
@@ -7,7 +7,7 @@ import { COOKIE_OPTIONS } from '../../constants.js';
7
7
  import getDatabase from '../../database/index.js';
8
8
  import emitter from '../../emitter.js';
9
9
  import env from '../../env.js';
10
- import { ErrorCode, InvalidCredentialsError, InvalidProviderError } from '../../errors/index.js';
10
+ import { ErrorCode, InvalidCredentialsError, InvalidProviderError } from '@directus/errors';
11
11
  import logger from '../../logger.js';
12
12
  import { respond } from '../../middleware/respond.js';
13
13
  import { AuthenticationService } from '../../services/authentication.js';
package/dist/auth.js CHANGED
@@ -3,7 +3,7 @@ import { LDAPAuthDriver, LocalAuthDriver, OAuth2AuthDriver, OpenIDAuthDriver, SA
3
3
  import { DEFAULT_AUTH_PROVIDER } from './constants.js';
4
4
  import getDatabase from './database/index.js';
5
5
  import env from './env.js';
6
- import { InvalidProviderConfigError } from './errors/index.js';
6
+ import { InvalidProviderConfigError } from '@directus/errors';
7
7
  import logger from './logger.js';
8
8
  import { getConfigFromEnv } from './utils/get-config-from-env.js';
9
9
  import { getSchema } from './utils/get-schema.js';
package/dist/cli/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Command, Option } from 'commander';
2
2
  import emitter from '../emitter.js';
3
- import { getExtensionManager } from '../extensions.js';
3
+ import { getExtensionManager } from '../extensions/index.js';
4
4
  import { startServer } from '../server.js';
5
5
  import bootstrap from './commands/bootstrap/index.js';
6
6
  import count from './commands/count/index.js';
@@ -2,7 +2,7 @@ import { Action } from '@directus/constants';
2
2
  import { isDirectusError } from '@directus/errors';
3
3
  import express from 'express';
4
4
  import Joi from 'joi';
5
- import { ErrorCode, ForbiddenError, InvalidPayloadError } from '../errors/index.js';
5
+ import { ErrorCode, ForbiddenError, InvalidPayloadError } from '@directus/errors';
6
6
  import { respond } from '../middleware/respond.js';
7
7
  import useCollection from '../middleware/use-collection.js';
8
8
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -5,7 +5,7 @@ import { merge, pick } from 'lodash-es';
5
5
  import { ASSET_TRANSFORM_QUERY_KEYS, SYSTEM_ASSET_ALLOW_LIST } from '../constants.js';
6
6
  import getDatabase from '../database/index.js';
7
7
  import env from '../env.js';
8
- import { InvalidQueryError, RangeNotSatisfiableError } from '../errors/index.js';
8
+ import { InvalidQueryError, RangeNotSatisfiableError } from '@directus/errors';
9
9
  import logger from '../logger.js';
10
10
  import useCollection from '../middleware/use-collection.js';
11
11
  import { AssetsService } from '../services/assets.js';
@@ -130,7 +130,7 @@ asyncHandler(async (req, res) => {
130
130
  vary.push('Accept');
131
131
  }
132
132
  let range = undefined;
133
- if (req.headers.range) {
133
+ if (req.headers.range && Object.keys(transformationParams).length === 0) {
134
134
  const rangeParts = /bytes=([0-9]*)-([0-9]*)/.exec(req.headers.range);
135
135
  if (rangeParts && rangeParts.length > 1) {
136
136
  range = {
@@ -3,7 +3,7 @@ import { Router } from 'express';
3
3
  import { createLDAPAuthRouter, createLocalAuthRouter, createOAuth2AuthRouter, createOpenIDAuthRouter, createSAMLAuthRouter, } from '../auth/drivers/index.js';
4
4
  import { COOKIE_OPTIONS, DEFAULT_AUTH_PROVIDER } from '../constants.js';
5
5
  import env from '../env.js';
6
- import { ErrorCode, InvalidPayloadError } from '../errors/index.js';
6
+ import { ErrorCode, InvalidPayloadError } from '@directus/errors';
7
7
  import logger from '../logger.js';
8
8
  import { respond } from '../middleware/respond.js';
9
9
  import { AuthenticationService } from '../services/authentication.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import { Router } from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import { validateBatch } from '../middleware/validate-batch.js';
6
6
  import { CollectionsService } from '../services/collections.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,18 +1,22 @@
1
- import { EXTENSION_TYPES } from '@directus/constants';
1
+ import { EXTENSION_TYPES } from '@directus/extensions';
2
2
  import { depluralize, isIn } from '@directus/utils';
3
3
  import { Router } from 'express';
4
4
  import env from '../env.js';
5
- import { RouteNotFoundError } from '../errors/index.js';
6
- import { getExtensionManager } from '../extensions.js';
5
+ import { RouteNotFoundError } from '@directus/errors';
6
+ import { getExtensionManager } from '../extensions/index.js';
7
7
  import { respond } from '../middleware/respond.js';
8
8
  import asyncHandler from '../utils/async-handler.js';
9
9
  import { getCacheControlHeader } from '../utils/get-cache-headers.js';
10
10
  import { getMilliseconds } from '../utils/get-milliseconds.js';
11
11
  const router = Router();
12
- router.get('/:type', asyncHandler(async (req, res, next) => {
13
- const type = depluralize(req.params['type']);
14
- if (!isIn(type, EXTENSION_TYPES)) {
15
- throw new RouteNotFoundError({ path: req.path });
12
+ router.get('/:type?', asyncHandler(async (req, res, next) => {
13
+ let type = undefined;
14
+ if (req.params['type']) {
15
+ const singularType = depluralize(req.params['type']);
16
+ if (!isIn(singularType, EXTENSION_TYPES)) {
17
+ throw new RouteNotFoundError({ path: req.path });
18
+ }
19
+ type = singularType;
16
20
  }
17
21
  const extensionManager = getExtensionManager();
18
22
  const extensions = extensionManager.getExtensionsList(type);
@@ -3,7 +3,7 @@ import { isDirectusError } from '@directus/errors';
3
3
  import { Router } from 'express';
4
4
  import Joi from 'joi';
5
5
  import { ALIAS_TYPES } from '../constants.js';
6
- import { ErrorCode, InvalidPayloadError } from '../errors/index.js';
6
+ import { ErrorCode, InvalidPayloadError } from '@directus/errors';
7
7
  import validateCollection from '../middleware/collection-exists.js';
8
8
  import { respond } from '../middleware/respond.js';
9
9
  import useCollection from '../middleware/use-collection.js';
@@ -8,7 +8,7 @@ import Joi from 'joi';
8
8
  import { minimatch } from 'minimatch';
9
9
  import path from 'path';
10
10
  import env from '../env.js';
11
- import { ContentTooLargeError, ErrorCode, InvalidPayloadError } from '../errors/index.js';
11
+ import { ContentTooLargeError, ErrorCode, InvalidPayloadError } from '@directus/errors';
12
12
  import { respond } from '../middleware/respond.js';
13
13
  import useCollection from '../middleware/use-collection.js';
14
14
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,7 +1,7 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
3
  import { UUID_REGEX } from '../constants.js';
4
- import { ErrorCode } from '../errors/index.js';
4
+ import { ErrorCode } from '@directus/errors';
5
5
  import { getFlowManager } from '../flows.js';
6
6
  import { respond } from '../middleware/respond.js';
7
7
  import useCollection from '../middleware/use-collection.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode, ForbiddenError, RouteNotFoundError } from '../errors/index.js';
3
+ import { ErrorCode, ForbiddenError, RouteNotFoundError } from '@directus/errors';
4
4
  import collectionExists from '../middleware/collection-exists.js';
5
5
  import { respond } from '../middleware/respond.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,6 +1,6 @@
1
1
  import getDatabase from '../database/index.js';
2
2
  import emitter from '../emitter.js';
3
- import { RouteNotFoundError } from '../errors/index.js';
3
+ import { RouteNotFoundError } from '@directus/errors';
4
4
  /**
5
5
  * Handles not found routes.
6
6
  *
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,6 +1,6 @@
1
1
  import express from 'express';
2
2
  import { isDirectusError } from '@directus/errors';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,7 +1,7 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
3
  import Joi from 'joi';
4
- import { ErrorCode, InvalidPayloadError } from '../errors/index.js';
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,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -2,7 +2,7 @@ import { parseJSON } from '@directus/utils';
2
2
  import Busboy from 'busboy';
3
3
  import express from 'express';
4
4
  import { load as loadYaml } from 'js-yaml';
5
- import { InvalidPayloadError, UnsupportedMediaTypeError } from '../errors/index.js';
5
+ import { InvalidPayloadError, UnsupportedMediaTypeError } from '@directus/errors';
6
6
  import logger from '../logger.js';
7
7
  import { respond } from '../middleware/respond.js';
8
8
  import { SchemaService } from '../services/schema.js';
@@ -1,6 +1,6 @@
1
1
  import { format } from 'date-fns';
2
2
  import { Router } from 'express';
3
- import { RouteNotFoundError } from '../errors/index.js';
3
+ import { RouteNotFoundError } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import { ServerService } from '../services/server.js';
6
6
  import { SpecificationService } from '../services/specifications.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { SettingsService } from '../services/settings.js';
@@ -3,7 +3,7 @@ import express from 'express';
3
3
  import Joi from 'joi';
4
4
  import { COOKIE_OPTIONS, UUID_REGEX } from '../constants.js';
5
5
  import env from '../env.js';
6
- import { ErrorCode, InvalidPayloadError } from '../errors/index.js';
6
+ import { ErrorCode, InvalidPayloadError } from '@directus/errors';
7
7
  import { respond } from '../middleware/respond.js';
8
8
  import useCollection from '../middleware/use-collection.js';
9
9
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,7 +1,7 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
3
  import Joi from 'joi';
4
- import { ErrorCode, ForbiddenError, InvalidCredentialsError, InvalidPayloadError } from '../errors/index.js';
4
+ import { ErrorCode, ForbiddenError, InvalidCredentialsError, InvalidPayloadError } from '@directus/errors';
5
5
  import { respond } from '../middleware/respond.js';
6
6
  import useCollection from '../middleware/use-collection.js';
7
7
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -2,11 +2,12 @@ import argon2 from 'argon2';
2
2
  import Busboy from 'busboy';
3
3
  import { Router } from 'express';
4
4
  import Joi from 'joi';
5
- import { flushCaches } from '../cache.js';
6
- import { ForbiddenError, InvalidPayloadError, InvalidQueryError, UnsupportedMediaTypeError } from '../errors/index.js';
5
+ import fs from 'node:fs';
6
+ import { createRequire } from 'node:module';
7
+ import { InvalidPayloadError, InvalidQueryError, UnsupportedMediaTypeError } from '@directus/errors';
7
8
  import collectionExists from '../middleware/collection-exists.js';
8
9
  import { respond } from '../middleware/respond.js';
9
- import { ExportService, ImportService } from '../services/import-export.js';
10
+ import { ExportService } from '../services/import-export/index.js';
10
11
  import { RevisionsService } from '../services/revisions.js';
11
12
  import { UtilsService } from '../services/utils.js';
12
13
  import asyncHandler from '../utils/async-handler.js';
@@ -65,10 +66,6 @@ router.post('/import/:collection', collectionExists, asyncHandler(async (req, re
65
66
  if (req.is('multipart/form-data') === false) {
66
67
  throw new UnsupportedMediaTypeError({ mediaType: req.headers['content-type'], where: 'Content-Type header' });
67
68
  }
68
- const service = new ImportService({
69
- accountability: req.accountability,
70
- schema: req.schema,
71
- });
72
69
  let headers;
73
70
  if (req.headers['content-type']) {
74
71
  headers = req.headers;
@@ -81,13 +78,34 @@ router.post('/import/:collection', collectionExists, asyncHandler(async (req, re
81
78
  }
82
79
  const busboy = Busboy({ headers });
83
80
  busboy.on('file', async (_fieldname, fileStream, { mimeType }) => {
84
- try {
85
- await service.import(req.params['collection'], mimeType, fileStream);
86
- }
87
- catch (err) {
88
- return next(err);
89
- }
90
- return res.status(200).end();
81
+ const { createTmpFile } = await import('@directus/utils/node');
82
+ const { getWorkerPool } = await import('../worker-pool.js');
83
+ const tmpFile = await createTmpFile().catch(() => null);
84
+ if (!tmpFile)
85
+ throw new Error('Failed to create temporary file for import');
86
+ fileStream.pipe(fs.createWriteStream(tmpFile.path));
87
+ fileStream.on('end', async () => {
88
+ const workerPool = getWorkerPool();
89
+ const require = createRequire(import.meta.url);
90
+ const filename = require.resolve('../services/import-export/import-worker');
91
+ const workerData = {
92
+ collection: req.params['collection'],
93
+ mimeType,
94
+ filePath: tmpFile.path,
95
+ accountability: req.accountability,
96
+ schema: req.schema,
97
+ };
98
+ try {
99
+ await workerPool.run(workerData, { filename });
100
+ res.status(200).end();
101
+ }
102
+ catch (error) {
103
+ next(error);
104
+ }
105
+ finally {
106
+ await tmpFile.cleanup();
107
+ }
108
+ });
91
109
  });
92
110
  busboy.on('error', (err) => next(err));
93
111
  req.pipe(busboy);
@@ -111,10 +129,11 @@ router.post('/export/:collection', collectionExists, asyncHandler(async (req, _r
111
129
  return next();
112
130
  }), respond);
113
131
  router.post('/cache/clear', asyncHandler(async (req, res) => {
114
- if (req.accountability?.admin !== true) {
115
- throw new ForbiddenError();
116
- }
117
- await flushCaches(true);
132
+ const service = new UtilsService({
133
+ accountability: req.accountability,
134
+ schema: req.schema,
135
+ });
136
+ await service.clearCache();
118
137
  res.status(200).end();
119
138
  }));
120
139
  export default router;
@@ -1,6 +1,6 @@
1
1
  import { isDirectusError } from '@directus/errors';
2
2
  import express from 'express';
3
- import { ErrorCode } from '../errors/index.js';
3
+ import { ErrorCode } from '@directus/errors';
4
4
  import { respond } from '../middleware/respond.js';
5
5
  import useCollection from '../middleware/use-collection.js';
6
6
  import { validateBatch } from '../middleware/validate-batch.js';
@@ -1,4 +1,4 @@
1
- import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, ValueOutOfRangeError, ValueTooLongError, } from '../../../errors/index.js';
1
+ import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, ValueOutOfRangeError, ValueTooLongError, } from '@directus/errors';
2
2
  import getDatabase from '../../index.js';
3
3
  var MSSQLErrorCodes;
4
4
  (function (MSSQLErrorCodes) {
@@ -1,4 +1,4 @@
1
- import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, ValueOutOfRangeError, ValueTooLongError, } from '../../../errors/index.js';
1
+ import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, ValueOutOfRangeError, ValueTooLongError, } from '@directus/errors';
2
2
  var MySQLErrorCodes;
3
3
  (function (MySQLErrorCodes) {
4
4
  MySQLErrorCodes["UNIQUE_VIOLATION"] = "ER_DUP_ENTRY";
@@ -1,4 +1,4 @@
1
- import { ContainsNullValuesError } from '../../../errors/index.js';
1
+ import { ContainsNullValuesError } from '@directus/errors';
2
2
  var OracleErrorCodes;
3
3
  (function (OracleErrorCodes) {
4
4
  OracleErrorCodes[OracleErrorCodes["CONTAINS_NULL_VALUES"] = 2296] = "CONTAINS_NULL_VALUES";
@@ -1,4 +1,4 @@
1
- import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, ValueOutOfRangeError, ValueTooLongError, } from '../../../errors/index.js';
1
+ import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, ValueOutOfRangeError, ValueTooLongError, } from '@directus/errors';
2
2
  var PostgresErrorCodes;
3
3
  (function (PostgresErrorCodes) {
4
4
  PostgresErrorCodes["FOREIGN_KEY_VIOLATION"] = "23503";
@@ -1,4 +1,4 @@
1
- import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, } from '../../../errors/index.js';
1
+ import { ContainsNullValuesError, InvalidForeignKeyError, NotNullViolationError, RecordNotUniqueError, } from '@directus/errors';
2
2
  // NOTE:
3
3
  // - Sqlite doesn't have varchar with length support, so no ValueTooLongError
4
4
  // - Sqlite doesn't have a max range for numbers, so no ValueOutOfRangeError
@@ -1,4 +1,4 @@
1
- import { getDatabaseVersion } from '../../../../database/index.js';
1
+ import { getDatabaseVersion } from '../../../index.js';
2
2
  import { SchemaHelper } from '../types.js';
3
3
  export class SchemaHelperMySQL extends SchemaHelper {
4
4
  applyMultiRelationalSort(knex, dbQuery, table, primaryKey, orderByString, orderByFields) {
@@ -2,8 +2,11 @@ import type { Knex } from 'knex';
2
2
  import { AutoSequenceHelper } from '../types.js';
3
3
  export declare class AutoIncrementHelperPostgres extends AutoSequenceHelper {
4
4
  /**
5
- * Resets the auto increment sequence for a table based on the max value of the PK column.
6
- * The sequence name of determined using a sub query.
5
+ * Resets the auto increment sequence based on the max value of the PK column.
6
+ * The sequence name is determined using a sub query.
7
+ *
8
+ * The table name value for getting the sequence name needs to be escaped explicitly,
9
+ * otherwise PostgreSQL would throw an error for capitalized table names saying "relation x does not exist".
7
10
  */
8
11
  resetAutoIncrementSequence(table: string, column: string): Promise<Knex.Raw | void>;
9
12
  }
@@ -1,10 +1,13 @@
1
1
  import { AutoSequenceHelper } from '../types.js';
2
2
  export class AutoIncrementHelperPostgres extends AutoSequenceHelper {
3
3
  /**
4
- * Resets the auto increment sequence for a table based on the max value of the PK column.
5
- * The sequence name of determined using a sub query.
4
+ * Resets the auto increment sequence based on the max value of the PK column.
5
+ * The sequence name is determined using a sub query.
6
+ *
7
+ * The table name value for getting the sequence name needs to be escaped explicitly,
8
+ * otherwise PostgreSQL would throw an error for capitalized table names saying "relation x does not exist".
6
9
  */
7
10
  async resetAutoIncrementSequence(table, column) {
8
- return await this.knex.raw(`WITH sequence_infos AS (SELECT pg_get_serial_sequence('${table}', '${column}') AS seq_name, MAX(${column}) as max_val FROM ${table}) SELECT SETVAL(seq_name, max_val) FROM sequence_infos;`);
11
+ return await this.knex.raw(`WITH sequence_infos AS (SELECT pg_get_serial_sequence(?, ?) AS seq_name, MAX(??) as max_val FROM ??) SELECT SETVAL(seq_name, max_val) FROM sequence_infos;`, [`"${table}"`, column, column, table]);
9
12
  }
10
13
  }
@@ -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,44 @@
1
+ import { getHelpers } from '../helpers/index.js';
2
+ import { createInspector } from '@directus/schema';
3
+ export async function up(knex) {
4
+ const inspector = createInspector(knex);
5
+ const helper = getHelpers(knex).schema;
6
+ const csvFields = await knex.select('collection', 'field').from('directus_fields').where('special', '=', 'cast-csv');
7
+ const updates = [];
8
+ for (const { collection, field } of csvFields) {
9
+ updates.push(inspector.columnInfo(collection, field).then((column) => {
10
+ if (column.data_type === 'text')
11
+ return;
12
+ return helper.changeToType(collection, field, 'text', {
13
+ default: column.default_value,
14
+ nullable: column.is_nullable,
15
+ });
16
+ }));
17
+ }
18
+ return checkPromises(updates);
19
+ }
20
+ export async function down(knex) {
21
+ const inspector = createInspector(knex);
22
+ const helper = getHelpers(knex).schema;
23
+ const csvFields = await knex.select('collection', 'field').from('directus_fields').where('special', '=', 'cast-csv');
24
+ const updates = [];
25
+ for (const { collection, field } of csvFields) {
26
+ updates.push(inspector.columnInfo(collection, field).then((column) => {
27
+ return helper.changeToType(collection, field, 'string', {
28
+ default: column.default_value,
29
+ nullable: column.is_nullable,
30
+ });
31
+ }));
32
+ }
33
+ return checkPromises(updates);
34
+ }
35
+ async function checkPromises(promises) {
36
+ const result = await Promise.allSettled(promises);
37
+ const errors = result.filter(isRejectedPromise).map((promise) => promise.reason);
38
+ if (errors.length > 0) {
39
+ throw new Error(errors.toString());
40
+ }
41
+ }
42
+ function isRejectedPromise(promise) {
43
+ return promise.status === 'rejected';
44
+ }
@@ -1,6 +1,6 @@
1
1
  import { toArray } from '@directus/utils';
2
2
  import { clone, cloneDeep, isNil, merge, pick, uniq } from 'lodash-es';
3
- import { getHelpers } from '../database/helpers/index.js';
3
+ import { getHelpers } from './helpers/index.js';
4
4
  import env from '../env.js';
5
5
  import { PayloadService } from '../services/payload.js';
6
6
  import { applyFunctionToColumnName } from '../utils/apply-function-to-column-name.js';