@directus/api 13.1.1 → 14.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 (292) hide show
  1. package/dist/__utils__/snapshots.js +9 -0
  2. package/dist/app.js +6 -4
  3. package/dist/auth/drivers/ldap.js +3 -2
  4. package/dist/auth/drivers/local.js +1 -1
  5. package/dist/auth/drivers/oauth2.js +1 -1
  6. package/dist/auth/drivers/openid.js +1 -1
  7. package/dist/auth/drivers/saml.js +1 -1
  8. package/dist/auth.js +1 -1
  9. package/dist/cli/index.js +7 -4
  10. package/dist/controllers/activity.js +1 -1
  11. package/dist/controllers/assets.js +2 -2
  12. package/dist/controllers/auth.js +1 -1
  13. package/dist/controllers/collections.js +1 -1
  14. package/dist/controllers/dashboards.js +1 -1
  15. package/dist/controllers/extensions.js +29 -16
  16. package/dist/controllers/fields.js +1 -1
  17. package/dist/controllers/files.js +1 -1
  18. package/dist/controllers/flows.js +1 -1
  19. package/dist/controllers/folders.js +1 -1
  20. package/dist/controllers/items.js +1 -1
  21. package/dist/controllers/not-found.js +1 -1
  22. package/dist/controllers/notifications.js +1 -1
  23. package/dist/controllers/operations.js +1 -1
  24. package/dist/controllers/panels.js +1 -1
  25. package/dist/controllers/permissions.js +1 -1
  26. package/dist/controllers/presets.js +1 -1
  27. package/dist/controllers/relations.js +1 -1
  28. package/dist/controllers/roles.js +1 -1
  29. package/dist/controllers/schema.js +1 -1
  30. package/dist/controllers/server.js +1 -1
  31. package/dist/controllers/settings.js +1 -1
  32. package/dist/controllers/shares.js +1 -1
  33. package/dist/controllers/translations.js +1 -1
  34. package/dist/controllers/users.js +1 -1
  35. package/dist/controllers/utils.js +37 -18
  36. package/dist/controllers/versions.d.ts +2 -0
  37. package/dist/controllers/versions.js +188 -0
  38. package/dist/controllers/webhooks.js +1 -1
  39. package/dist/database/errors/dialects/mssql.js +1 -1
  40. package/dist/database/errors/dialects/mysql.js +1 -1
  41. package/dist/database/errors/dialects/oracle.js +1 -1
  42. package/dist/database/errors/dialects/postgres.js +1 -1
  43. package/dist/database/errors/dialects/sqlite.js +1 -1
  44. package/dist/database/helpers/schema/dialects/mysql.js +1 -1
  45. package/dist/database/helpers/sequence/dialects/postgres.d.ts +5 -2
  46. package/dist/database/helpers/sequence/dialects/postgres.js +6 -3
  47. package/dist/database/migrations/20230823A-add-content-versioning.d.ts +3 -0
  48. package/dist/database/migrations/20230823A-add-content-versioning.js +36 -0
  49. package/dist/database/migrations/20230927A-themes.d.ts +3 -0
  50. package/dist/database/migrations/20230927A-themes.js +49 -0
  51. package/dist/database/migrations/20231009A-update-csv-fields-to-text.d.ts +3 -0
  52. package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +44 -0
  53. package/dist/database/migrations/20231009B-update-panel-options.d.ts +3 -0
  54. package/dist/database/migrations/20231009B-update-panel-options.js +77 -0
  55. package/dist/database/migrations/20231010A-add-extensions.d.ts +3 -0
  56. package/dist/database/migrations/20231010A-add-extensions.js +9 -0
  57. package/dist/database/run-ast.js +2 -2
  58. package/dist/database/seeds/run.js +1 -1
  59. package/dist/database/system-data/collections/collections.yaml +6 -0
  60. package/dist/database/system-data/fields/activity.yaml +4 -4
  61. package/dist/database/system-data/fields/collections.yaml +19 -0
  62. package/dist/database/system-data/fields/extensions.yaml +10 -0
  63. package/dist/database/system-data/fields/revisions.yaml +3 -0
  64. package/dist/database/system-data/fields/settings.yaml +73 -17
  65. package/dist/database/system-data/fields/users.yaml +48 -12
  66. package/dist/database/system-data/fields/versions.yaml +38 -0
  67. package/dist/database/system-data/fields/webhooks.yaml +9 -9
  68. package/dist/database/system-data/relations/relations.yaml +88 -20
  69. package/dist/env.js +4 -0
  70. package/dist/extensions/index.d.ts +2 -0
  71. package/dist/extensions/index.js +9 -0
  72. package/dist/extensions/lib/get-extensions-settings.d.ts +7 -0
  73. package/dist/extensions/lib/get-extensions-settings.js +39 -0
  74. package/dist/extensions/lib/get-extensions.d.ts +1 -0
  75. package/dist/extensions/lib/get-extensions.js +11 -0
  76. package/dist/extensions/lib/get-shared-deps-mapping.d.ts +1 -0
  77. package/dist/extensions/lib/get-shared-deps-mapping.js +26 -0
  78. package/dist/extensions/lib/sandbox/generate-api-extensions-sandbox-entrypoint.d.ts +31 -0
  79. package/dist/extensions/lib/sandbox/generate-api-extensions-sandbox-entrypoint.js +80 -0
  80. package/dist/extensions/lib/sandbox/generate-host-function-reference.d.ts +11 -0
  81. package/dist/extensions/lib/sandbox/generate-host-function-reference.js +28 -0
  82. package/dist/extensions/lib/sandbox/register/action.d.ts +6 -0
  83. package/dist/extensions/lib/sandbox/register/action.js +18 -0
  84. package/dist/extensions/lib/sandbox/register/call-reference.d.ts +5 -0
  85. package/dist/extensions/lib/sandbox/register/call-reference.js +20 -0
  86. package/dist/extensions/lib/sandbox/register/filter.d.ts +6 -0
  87. package/dist/extensions/lib/sandbox/register/filter.js +21 -0
  88. package/dist/extensions/lib/sandbox/register/index.d.ts +5 -0
  89. package/dist/extensions/lib/sandbox/register/index.js +5 -0
  90. package/dist/extensions/lib/sandbox/register/operation.d.ts +6 -0
  91. package/dist/extensions/lib/sandbox/register/operation.js +19 -0
  92. package/dist/extensions/lib/sandbox/register/route.d.ts +17 -0
  93. package/dist/extensions/lib/sandbox/register/route.js +44 -0
  94. package/dist/extensions/lib/sandbox/sdk/generators/index.d.ts +3 -0
  95. package/dist/extensions/lib/sandbox/sdk/generators/index.js +3 -0
  96. package/dist/extensions/lib/sandbox/sdk/generators/log.d.ts +3 -0
  97. package/dist/extensions/lib/sandbox/sdk/generators/log.js +11 -0
  98. package/dist/extensions/lib/sandbox/sdk/generators/request.d.ts +12 -0
  99. package/dist/extensions/lib/sandbox/sdk/generators/request.js +49 -0
  100. package/dist/extensions/lib/sandbox/sdk/generators/sleep.d.ts +3 -0
  101. package/dist/extensions/lib/sandbox/sdk/generators/sleep.js +11 -0
  102. package/dist/extensions/lib/sandbox/sdk/index.d.ts +2 -0
  103. package/dist/extensions/lib/sandbox/sdk/index.js +2 -0
  104. package/dist/extensions/lib/sandbox/sdk/instantiate.d.ts +11 -0
  105. package/dist/extensions/lib/sandbox/sdk/instantiate.js +28 -0
  106. package/dist/extensions/lib/sandbox/sdk/sdk.d.ts +20 -0
  107. package/dist/extensions/lib/sandbox/sdk/sdk.js +11 -0
  108. package/dist/extensions/lib/sandbox/sdk/utils/index.d.ts +1 -0
  109. package/dist/extensions/lib/sandbox/sdk/utils/index.js +1 -0
  110. package/dist/extensions/lib/sandbox/sdk/utils/wrap.d.ts +11 -0
  111. package/dist/extensions/lib/sandbox/sdk/utils/wrap.js +17 -0
  112. package/dist/extensions/lib/wrap-embeds.d.ts +4 -0
  113. package/dist/extensions/lib/wrap-embeds.js +8 -0
  114. package/dist/extensions/manager.d.ts +158 -0
  115. package/dist/extensions/manager.js +604 -0
  116. package/dist/extensions/types.d.ts +19 -0
  117. package/dist/flows.d.ts +2 -2
  118. package/dist/flows.js +7 -7
  119. package/dist/middleware/check-ip.js +1 -1
  120. package/dist/middleware/collection-exists.js +1 -1
  121. package/dist/middleware/error-handler.js +1 -1
  122. package/dist/middleware/graphql.js +1 -1
  123. package/dist/middleware/rate-limiter-global.js +1 -1
  124. package/dist/middleware/rate-limiter-ip.js +1 -1
  125. package/dist/middleware/respond.js +13 -1
  126. package/dist/middleware/validate-batch.js +1 -1
  127. package/dist/operations/condition/index.d.ts +1 -1
  128. package/dist/operations/condition/index.js +2 -1
  129. package/dist/operations/exec/index.d.ts +1 -1
  130. package/dist/operations/exec/index.js +1 -1
  131. package/dist/operations/item-create/index.d.ts +1 -1
  132. package/dist/operations/item-create/index.js +2 -1
  133. package/dist/operations/item-delete/index.d.ts +1 -1
  134. package/dist/operations/item-delete/index.js +2 -1
  135. package/dist/operations/item-read/index.d.ts +1 -1
  136. package/dist/operations/item-read/index.js +2 -1
  137. package/dist/operations/item-update/index.d.ts +1 -1
  138. package/dist/operations/item-update/index.js +2 -1
  139. package/dist/operations/json-web-token/index.d.ts +1 -1
  140. package/dist/operations/json-web-token/index.js +2 -1
  141. package/dist/operations/log/index.d.ts +1 -1
  142. package/dist/operations/log/index.js +2 -1
  143. package/dist/operations/mail/index.d.ts +1 -1
  144. package/dist/operations/mail/index.js +1 -1
  145. package/dist/operations/notification/index.d.ts +1 -1
  146. package/dist/operations/notification/index.js +2 -1
  147. package/dist/operations/request/index.d.ts +1 -1
  148. package/dist/operations/request/index.js +3 -2
  149. package/dist/operations/sleep/index.d.ts +1 -1
  150. package/dist/operations/sleep/index.js +1 -1
  151. package/dist/operations/transform/index.d.ts +1 -1
  152. package/dist/operations/transform/index.js +2 -1
  153. package/dist/operations/trigger/index.d.ts +1 -1
  154. package/dist/operations/trigger/index.js +2 -1
  155. package/dist/services/activity.js +1 -1
  156. package/dist/services/assets.d.ts +1 -1
  157. package/dist/services/assets.js +3 -3
  158. package/dist/services/authentication.js +2 -2
  159. package/dist/services/authorization.js +1 -1
  160. package/dist/services/collections.js +3 -3
  161. package/dist/services/extensions.d.ts +31 -0
  162. package/dist/services/extensions.js +121 -0
  163. package/dist/services/fields.d.ts +2 -2
  164. package/dist/services/fields.js +4 -4
  165. package/dist/services/files.d.ts +4 -1
  166. package/dist/services/files.js +5 -5
  167. package/dist/services/graphql/index.d.ts +1 -1
  168. package/dist/services/graphql/index.js +87 -24
  169. package/dist/services/graphql/subscription.js +3 -3
  170. package/dist/services/import-export/import-worker.d.ts +9 -0
  171. package/dist/services/import-export/import-worker.js +9 -0
  172. package/dist/services/{import-export.d.ts → import-export/index.d.ts} +2 -2
  173. package/dist/services/{import-export.js → import-export/index.js} +51 -42
  174. package/dist/services/index.d.ts +3 -1
  175. package/dist/services/index.js +3 -1
  176. package/dist/services/items.js +2 -2
  177. package/dist/services/mail/index.js +1 -1
  178. package/dist/services/meta.js +1 -1
  179. package/dist/services/payload.js +1 -1
  180. package/dist/services/permissions.d.ts +2 -2
  181. package/dist/services/permissions.js +1 -1
  182. package/dist/services/relations.js +1 -1
  183. package/dist/services/revisions.js +1 -1
  184. package/dist/services/roles.js +1 -1
  185. package/dist/services/schema.js +1 -1
  186. package/dist/services/server.js +3 -1
  187. package/dist/services/shares.js +1 -1
  188. package/dist/services/tfa.js +1 -1
  189. package/dist/services/translations.js +1 -1
  190. package/dist/services/users.js +4 -2
  191. package/dist/services/utils.d.ts +1 -0
  192. package/dist/services/utils.js +8 -2
  193. package/dist/services/versions.d.ts +21 -0
  194. package/dist/services/versions.js +232 -0
  195. package/dist/services/websocket.js +11 -1
  196. package/dist/types/collection.d.ts +1 -0
  197. package/dist/types/index.d.ts +0 -1
  198. package/dist/types/index.js +0 -1
  199. package/dist/utils/apply-query.d.ts +1 -1
  200. package/dist/utils/apply-query.js +31 -3
  201. package/dist/utils/delete-from-require-cache.d.ts +1 -0
  202. package/dist/utils/delete-from-require-cache.js +5 -0
  203. package/dist/utils/get-accountability-for-token.js +1 -1
  204. package/dist/utils/get-ast-from-query.js +1 -1
  205. package/dist/utils/get-column-path.js +1 -1
  206. package/dist/utils/get-column.js +1 -1
  207. package/dist/utils/get-default-value.d.ts +1 -2
  208. package/dist/utils/get-permissions.js +1 -1
  209. package/dist/utils/get-service.js +3 -1
  210. package/dist/utils/import-file-url.d.ts +5 -0
  211. package/dist/utils/import-file-url.js +6 -0
  212. package/dist/utils/job-queue.d.ts +2 -3
  213. package/dist/utils/jwt.js +1 -1
  214. package/dist/utils/redact-object.js +9 -3
  215. package/dist/utils/sanitize-query.js +3 -0
  216. package/dist/utils/transformations.d.ts +2 -1
  217. package/dist/utils/validate-diff.js +1 -1
  218. package/dist/utils/validate-keys.js +1 -1
  219. package/dist/utils/validate-query.js +2 -1
  220. package/dist/utils/validate-snapshot.js +1 -1
  221. package/dist/websocket/controllers/base.js +1 -1
  222. package/dist/websocket/controllers/index.d.ts +1 -1
  223. package/dist/websocket/controllers/index.js +0 -7
  224. package/dist/websocket/handlers/heartbeat.js +6 -1
  225. package/dist/websocket/handlers/subscribe.js +11 -16
  226. package/dist/websocket/utils/items.d.ts +4 -14
  227. package/dist/websocket/utils/items.js +59 -64
  228. package/dist/worker-pool.d.ts +2 -0
  229. package/dist/worker-pool.js +11 -0
  230. package/package.json +34 -31
  231. package/dist/errors/codes.d.ts +0 -29
  232. package/dist/errors/codes.js +0 -30
  233. package/dist/errors/contains-null-values.d.ts +0 -7
  234. package/dist/errors/contains-null-values.js +0 -4
  235. package/dist/errors/content-too-large.d.ts +0 -1
  236. package/dist/errors/content-too-large.js +0 -3
  237. package/dist/errors/forbidden.d.ts +0 -1
  238. package/dist/errors/forbidden.js +0 -3
  239. package/dist/errors/hit-rate-limit.d.ts +0 -6
  240. package/dist/errors/hit-rate-limit.js +0 -8
  241. package/dist/errors/illegal-asset-transformation.d.ts +0 -4
  242. package/dist/errors/illegal-asset-transformation.js +0 -3
  243. package/dist/errors/index.d.ts +0 -28
  244. package/dist/errors/index.js +0 -28
  245. package/dist/errors/invalid-credentials.d.ts +0 -1
  246. package/dist/errors/invalid-credentials.js +0 -3
  247. package/dist/errors/invalid-foreign-key.d.ts +0 -6
  248. package/dist/errors/invalid-foreign-key.js +0 -14
  249. package/dist/errors/invalid-ip.d.ts +0 -1
  250. package/dist/errors/invalid-ip.js +0 -3
  251. package/dist/errors/invalid-otp.d.ts +0 -1
  252. package/dist/errors/invalid-otp.js +0 -3
  253. package/dist/errors/invalid-payload.d.ts +0 -5
  254. package/dist/errors/invalid-payload.js +0 -4
  255. package/dist/errors/invalid-provider-config.d.ts +0 -5
  256. package/dist/errors/invalid-provider-config.js +0 -3
  257. package/dist/errors/invalid-provider.d.ts +0 -1
  258. package/dist/errors/invalid-provider.js +0 -3
  259. package/dist/errors/invalid-query.d.ts +0 -5
  260. package/dist/errors/invalid-query.js +0 -4
  261. package/dist/errors/invalid-token.d.ts +0 -1
  262. package/dist/errors/invalid-token.js +0 -3
  263. package/dist/errors/method-not-allowed.d.ts +0 -6
  264. package/dist/errors/method-not-allowed.js +0 -6
  265. package/dist/errors/not-null-violation.d.ts +0 -6
  266. package/dist/errors/not-null-violation.js +0 -14
  267. package/dist/errors/range-not-satisfiable.d.ts +0 -7
  268. package/dist/errors/range-not-satisfiable.js +0 -7
  269. package/dist/errors/record-not-unique.d.ts +0 -6
  270. package/dist/errors/record-not-unique.js +0 -14
  271. package/dist/errors/route-not-found.d.ts +0 -5
  272. package/dist/errors/route-not-found.js +0 -4
  273. package/dist/errors/service-unavailable.d.ts +0 -7
  274. package/dist/errors/service-unavailable.js +0 -4
  275. package/dist/errors/token-expired.d.ts +0 -1
  276. package/dist/errors/token-expired.js +0 -3
  277. package/dist/errors/unexpected-response.d.ts +0 -1
  278. package/dist/errors/unexpected-response.js +0 -3
  279. package/dist/errors/unprocessable-content.d.ts +0 -5
  280. package/dist/errors/unprocessable-content.js +0 -4
  281. package/dist/errors/unsupported-media-type.d.ts +0 -6
  282. package/dist/errors/unsupported-media-type.js +0 -4
  283. package/dist/errors/user-suspended.d.ts +0 -1
  284. package/dist/errors/user-suspended.js +0 -3
  285. package/dist/errors/value-out-of-range.d.ts +0 -6
  286. package/dist/errors/value-out-of-range.js +0 -14
  287. package/dist/errors/value-too-long.d.ts +0 -6
  288. package/dist/errors/value-too-long.js +0 -14
  289. package/dist/extensions.d.ts +0 -51
  290. package/dist/extensions.js +0 -487
  291. package/dist/types/files.d.ts +0 -29
  292. /package/dist/{types/files.js → extensions/types.js} +0 -0
@@ -2,7 +2,7 @@
2
2
  * Check if requested collection exists, and save it to req.collection
3
3
  */
4
4
  import { systemCollectionRows } from '../database/system-data/collections/index.js';
5
- import { ForbiddenError } from '../errors/index.js';
5
+ import { ForbiddenError } from '@directus/errors';
6
6
  import asyncHandler from '../utils/async-handler.js';
7
7
  const collectionExists = asyncHandler(async (req, _res, next) => {
8
8
  if (!req.params['collection'])
@@ -3,7 +3,7 @@ import { toArray } from '@directus/utils';
3
3
  import getDatabase from '../database/index.js';
4
4
  import emitter from '../emitter.js';
5
5
  import env from '../env.js';
6
- import { ErrorCode, MethodNotAllowedError } from '../errors/index.js';
6
+ import { ErrorCode, MethodNotAllowedError } from '@directus/errors';
7
7
  import logger from '../logger.js';
8
8
  // Note: keep all 4 parameters here. That's how Express recognizes it's the error handler, even if
9
9
  // we don't use next
@@ -1,6 +1,6 @@
1
1
  import { parseJSON } from '@directus/utils';
2
2
  import { getOperationAST, parse, Source } from 'graphql';
3
- import { InvalidPayloadError, InvalidQueryError, MethodNotAllowedError } from '../errors/index.js';
3
+ import { InvalidPayloadError, InvalidQueryError, MethodNotAllowedError } from '@directus/errors';
4
4
  import { GraphQLValidationError } from '../services/graphql/errors/validation.js';
5
5
  import asyncHandler from '../utils/async-handler.js';
6
6
  export const parseGraphQL = asyncHandler(async (req, res, next) => {
@@ -1,5 +1,5 @@
1
1
  import env from '../env.js';
2
- import { HitRateLimitError } from '../errors/index.js';
2
+ import { HitRateLimitError } from '@directus/errors';
3
3
  import logger from '../logger.js';
4
4
  import { createRateLimiter } from '../rate-limiter.js';
5
5
  import asyncHandler from '../utils/async-handler.js';
@@ -1,5 +1,5 @@
1
1
  import env from '../env.js';
2
- import { HitRateLimitError } from '../errors/index.js';
2
+ import { HitRateLimitError } from '@directus/errors';
3
3
  import { createRateLimiter } from '../rate-limiter.js';
4
4
  import asyncHandler from '../utils/async-handler.js';
5
5
  import { getIPFromReq } from '../utils/get-ip-from-req.js';
@@ -1,8 +1,10 @@
1
1
  import { parse as parseBytesConfiguration } from 'bytes';
2
+ import { assign } from 'lodash-es';
2
3
  import { getCache, setCacheValue } from '../cache.js';
3
4
  import env from '../env.js';
4
5
  import logger from '../logger.js';
5
- import { ExportService } from '../services/import-export.js';
6
+ import { ExportService } from '../services/import-export/index.js';
7
+ import { VersionsService } from '../services/versions.js';
6
8
  import asyncHandler from '../utils/async-handler.js';
7
9
  import { getCacheControlHeader } from '../utils/get-cache-headers.js';
8
10
  import { getCacheKey } from '../utils/get-cache-key.js';
@@ -39,6 +41,16 @@ export const respond = asyncHandler(async (req, res) => {
39
41
  res.setHeader('Cache-Control', 'no-cache');
40
42
  res.setHeader('Vary', 'Origin, Cache-Control');
41
43
  }
44
+ if (req.sanitizedQuery.version &&
45
+ req.collection &&
46
+ (req.singleton || req.params['pk']) &&
47
+ 'data' in res.locals['payload']) {
48
+ const versionsService = new VersionsService({ accountability: req.accountability ?? null, schema: req.schema });
49
+ const saves = await versionsService.getVersionSaves(req.sanitizedQuery.version, req.collection, req.params['pk']);
50
+ if (saves) {
51
+ assign(res.locals['payload'].data, ...saves);
52
+ }
53
+ }
42
54
  if (req.sanitizedQuery.export) {
43
55
  const exportService = new ExportService({ accountability: req.accountability ?? null, schema: req.schema });
44
56
  let filename = '';
@@ -1,5 +1,5 @@
1
1
  import Joi from 'joi';
2
- import { InvalidPayloadError } from '../errors/index.js';
2
+ import { InvalidPayloadError } from '@directus/errors';
3
3
  import asyncHandler from '../utils/async-handler.js';
4
4
  import { sanitizeQuery } from '../utils/sanitize-query.js';
5
5
  export const validateBatch = (scope) => asyncHandler(async (req, _res, next) => {
@@ -2,5 +2,5 @@ import type { Filter } from '@directus/types';
2
2
  type Options = {
3
3
  filter: Filter;
4
4
  };
5
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
5
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
6
6
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, validatePayload } from '@directus/utils';
1
+ import { validatePayload } from '@directus/utils';
2
+ import { defineOperationApi } from '@directus/extensions';
2
3
  export default defineOperationApi({
3
4
  id: 'condition',
4
5
  handler: ({ filter }, { data }) => {
@@ -1,5 +1,5 @@
1
1
  type Options = {
2
2
  code: string;
3
3
  };
4
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
4
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
5
5
  export default _default;
@@ -1,4 +1,4 @@
1
- import { defineOperationApi } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
2
  import { createRequire } from 'node:module';
3
3
  const require = createRequire(import.meta.url);
4
4
  const ivm = require('isolated-vm');
@@ -4,5 +4,5 @@ type Options = {
4
4
  emitEvents: boolean;
5
5
  permissions: string;
6
6
  };
7
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
7
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
8
8
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToObject, toArray } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToObject, toArray } from '@directus/utils';
2
3
  import { ItemsService } from '../../services/items.js';
3
4
  import { getAccountabilityForRole } from '../../utils/get-accountability-for-role.js';
4
5
  export default defineOperationApi({
@@ -6,5 +6,5 @@ type Options = {
6
6
  emitEvents: boolean;
7
7
  permissions: string;
8
8
  };
9
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
9
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
10
10
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToObject, toArray } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToObject, toArray } from '@directus/utils';
2
3
  import { ItemsService } from '../../services/items.js';
3
4
  import { getAccountabilityForRole } from '../../utils/get-accountability-for-role.js';
4
5
  import { sanitizeQuery } from '../../utils/sanitize-query.js';
@@ -6,5 +6,5 @@ type Options = {
6
6
  emitEvents: boolean;
7
7
  permissions: string;
8
8
  };
9
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
9
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
10
10
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToObject, toArray } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToObject, toArray } from '@directus/utils';
2
3
  import { ItemsService } from '../../services/items.js';
3
4
  import { getAccountabilityForRole } from '../../utils/get-accountability-for-role.js';
4
5
  import { sanitizeQuery } from '../../utils/sanitize-query.js';
@@ -7,5 +7,5 @@ type Options = {
7
7
  emitEvents: boolean;
8
8
  permissions: string;
9
9
  };
10
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
10
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
11
11
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToObject, toArray } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToObject, toArray } from '@directus/utils';
2
3
  import { ItemsService } from '../../services/items.js';
3
4
  import { getAccountabilityForRole } from '../../utils/get-accountability-for-role.js';
4
5
  import { sanitizeQuery } from '../../utils/sanitize-query.js';
@@ -6,5 +6,5 @@ type Options = {
6
6
  secret?: jwt.Secret;
7
7
  options?: any;
8
8
  };
9
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
9
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
10
10
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToObject, optionToString } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToObject, optionToString } from '@directus/utils';
2
3
  import jwt from 'jsonwebtoken';
3
4
  export default defineOperationApi({
4
5
  id: 'json-web-token',
@@ -1,5 +1,5 @@
1
1
  type Options = {
2
2
  message: unknown;
3
3
  };
4
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
4
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
5
5
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToString } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToString } from '@directus/utils';
2
3
  import logger from '../../logger.js';
3
4
  export default defineOperationApi({
4
5
  id: 'log',
@@ -6,5 +6,5 @@ export type Options = {
6
6
  type: 'wysiwyg' | 'markdown' | 'template';
7
7
  subject: string;
8
8
  };
9
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
9
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
10
10
  export default _default;
@@ -1,4 +1,4 @@
1
- import { defineOperationApi } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
2
  import { MailService } from '../../services/mail/index.js';
3
3
  import { md } from '../../utils/md.js';
4
4
  export default defineOperationApi({
@@ -6,5 +6,5 @@ type Options = {
6
6
  collection?: string;
7
7
  item?: string;
8
8
  };
9
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
9
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
10
10
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToString, toArray } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToString, toArray } from '@directus/utils';
2
3
  import { NotificationsService } from '../../services/notifications.js';
3
4
  import { getAccountabilityForRole } from '../../utils/get-accountability-for-role.js';
4
5
  export default defineOperationApi({
@@ -7,5 +7,5 @@ type Options = {
7
7
  value: string;
8
8
  }[] | null;
9
9
  };
10
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
10
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
11
11
  export default _default;
@@ -1,7 +1,8 @@
1
- import { defineOperationApi, isValidJSON } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { isValidJSON } from '@directus/utils';
3
+ import { isAxiosError } from 'axios';
2
4
  import encodeUrl from 'encodeurl';
3
5
  import { getAxios } from '../../request/index.js';
4
- import { isAxiosError } from 'axios';
5
6
  export default defineOperationApi({
6
7
  id: 'request',
7
8
  handler: async ({ url, method, body, headers }) => {
@@ -1,5 +1,5 @@
1
1
  type Options = {
2
2
  milliseconds: string | number;
3
3
  };
4
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
4
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
5
5
  export default _default;
@@ -1,4 +1,4 @@
1
- import { defineOperationApi } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
2
  export default defineOperationApi({
3
3
  id: 'sleep',
4
4
  handler: async ({ milliseconds }) => {
@@ -1,5 +1,5 @@
1
1
  type Options = {
2
2
  json: string | Record<string, any>;
3
3
  };
4
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
4
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
5
5
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToObject } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToObject } from '@directus/utils';
2
3
  export default defineOperationApi({
3
4
  id: 'transform',
4
5
  handler: ({ json }) => {
@@ -4,5 +4,5 @@ type Options = {
4
4
  iterationMode?: 'serial' | 'batch' | 'parallel';
5
5
  batchSize?: number;
6
6
  };
7
- declare const _default: import("@directus/types").OperationApiConfig<Options>;
7
+ declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
8
8
  export default _default;
@@ -1,4 +1,5 @@
1
- import { defineOperationApi, optionToObject } from '@directus/utils';
1
+ import { defineOperationApi } from '@directus/extensions';
2
+ import { optionToObject } from '@directus/utils';
2
3
  import { omit } from 'lodash-es';
3
4
  import { getFlowManager } from '../../flows.js';
4
5
  export default defineOperationApi({
@@ -3,7 +3,7 @@ import { isDirectusError } from '@directus/errors';
3
3
  import { uniq } from 'lodash-es';
4
4
  import validateUUID from 'uuid-validate';
5
5
  import env from '../env.js';
6
- import { ErrorCode } from '../errors/index.js';
6
+ import { ErrorCode } from '@directus/errors';
7
7
  import logger from '../logger.js';
8
8
  import { getPermissions } from '../utils/get-permissions.js';
9
9
  import { Url } from '../utils/url.js';
@@ -10,7 +10,7 @@ export declare class AssetsService {
10
10
  accountability: Accountability | null;
11
11
  authorizationService: AuthorizationService;
12
12
  constructor(options: AbstractServiceOptions);
13
- getAsset(id: string, transformation: TransformationSet, range?: Range): Promise<{
13
+ getAsset(id: string, transformation?: TransformationSet, range?: Range): Promise<{
14
14
  stream: Readable;
15
15
  file: any;
16
16
  stat: Stat;
@@ -7,7 +7,7 @@ import validateUUID from 'uuid-validate';
7
7
  import { SUPPORTED_IMAGE_TRANSFORM_FORMATS } from '../constants.js';
8
8
  import getDatabase from '../database/index.js';
9
9
  import env from '../env.js';
10
- import { ForbiddenError, IllegalAssetTransformationError, RangeNotSatisfiableError, ServiceUnavailableError, } from '../errors/index.js';
10
+ import { ForbiddenError, IllegalAssetTransformationError, RangeNotSatisfiableError, ServiceUnavailableError, } from '@directus/errors';
11
11
  import logger from '../logger.js';
12
12
  import { getStorage } from '../storage/index.js';
13
13
  import { getMilliseconds } from '../utils/get-milliseconds.js';
@@ -25,7 +25,7 @@ export class AssetsService {
25
25
  async getAsset(id, transformation, range) {
26
26
  const storage = await getStorage();
27
27
  const publicSettings = await this.knex
28
- .select('project_logo', 'public_background', 'public_foreground')
28
+ .select('project_logo', 'public_background', 'public_foreground', 'public_favicon')
29
29
  .from('directus_settings')
30
30
  .first();
31
31
  const systemPublicKeys = Object.values(publicSettings || {});
@@ -78,7 +78,7 @@ export class AssetsService {
78
78
  }
79
79
  }
80
80
  const type = file.type;
81
- const transforms = TransformationUtils.resolvePreset(transformation, file);
81
+ const transforms = transformation ? TransformationUtils.resolvePreset(transformation, file) : [];
82
82
  if (type && transforms.length > 0 && SUPPORTED_IMAGE_TRANSFORM_FORMATS.includes(type)) {
83
83
  const maybeNewFormat = TransformationUtils.maybeExtractFormat(transforms);
84
84
  const assetFilename = path.basename(file.filename_disk, path.extname(file.filename_disk)) +
@@ -7,8 +7,8 @@ import { DEFAULT_AUTH_PROVIDER } 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 { InvalidCredentialsError, InvalidProviderError, UserSuspendedError } from '../errors/index.js';
11
- import { InvalidOtpError } from '../errors/index.js';
10
+ import { InvalidCredentialsError, InvalidProviderError, UserSuspendedError } from '@directus/errors';
11
+ import { InvalidOtpError } from '@directus/errors';
12
12
  import { createRateLimiter } from '../rate-limiter.js';
13
13
  import { getMilliseconds } from '../utils/get-milliseconds.js';
14
14
  import { stall } from '../utils/stall.js';
@@ -3,7 +3,7 @@ import { FailedValidationError, joiValidationErrorItemToErrorExtensions } from '
3
3
  import { cloneDeep, flatten, isArray, isNil, merge, reduce, uniq, uniqWith } from 'lodash-es';
4
4
  import { GENERATE_SPECIAL } from '../constants.js';
5
5
  import getDatabase from '../database/index.js';
6
- import { ForbiddenError } from '../errors/forbidden.js';
6
+ import { ForbiddenError } from '@directus/errors';
7
7
  import { getRelationInfo } from '../utils/get-relation-info.js';
8
8
  import { stripFunction } from '../utils/strip-function.js';
9
9
  import { ItemsService } from './items.js';
@@ -8,9 +8,9 @@ import getDatabase, { getSchemaInspector } from '../database/index.js';
8
8
  import { systemCollectionRows } from '../database/system-data/collections/index.js';
9
9
  import emitter from '../emitter.js';
10
10
  import env from '../env.js';
11
- import { ForbiddenError, InvalidPayloadError } from '../errors/index.js';
12
- import { FieldsService } from '../services/fields.js';
13
- import { ItemsService } from '../services/items.js';
11
+ import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
12
+ import { FieldsService } from './fields.js';
13
+ import { ItemsService } from './items.js';
14
14
  import { getSchema } from '../utils/get-schema.js';
15
15
  import { shouldClearCache } from '../utils/should-clear-cache.js';
16
16
  export class CollectionsService {
@@ -0,0 +1,31 @@
1
+ import type { ApiOutput, ExtensionSettings } from '@directus/extensions';
2
+ import type { SchemaInspector } from '@directus/schema';
3
+ import type { Accountability, DeepPartial, SchemaOverview } from '@directus/types';
4
+ import type Keyv from 'keyv';
5
+ import type { Knex } from 'knex';
6
+ import type { Helpers } from '../database/helpers/index.js';
7
+ import type { ExtensionManager } from '../extensions/manager.js';
8
+ import type { AbstractServiceOptions } from '../types/index.js';
9
+ import { ItemsService } from './items.js';
10
+ import { PermissionsService } from './permissions.js';
11
+ export declare class ExtensionsService {
12
+ knex: Knex;
13
+ permissionsService: PermissionsService;
14
+ schemaInspector: SchemaInspector;
15
+ accountability: Accountability | null;
16
+ schema: SchemaOverview;
17
+ extensionsItemService: ItemsService<ExtensionSettings>;
18
+ systemCache: Keyv<any>;
19
+ helpers: Helpers;
20
+ extensionsManager: ExtensionManager;
21
+ constructor(options: AbstractServiceOptions);
22
+ readAll(): Promise<ApiOutput[]>;
23
+ readOne(bundle: string | null, name: string): Promise<ApiOutput>;
24
+ updateOne(bundle: string | null, name: string, data: DeepPartial<ApiOutput>): Promise<void>;
25
+ private getKey;
26
+ /**
27
+ * Combine the settings stored in the database with the information available from the installed
28
+ * extensions into the standardized extensions api output
29
+ */
30
+ private stitch;
31
+ }
@@ -0,0 +1,121 @@
1
+ import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
2
+ import { createInspector } from '@directus/schema';
3
+ import Joi from 'joi';
4
+ import { omit, pick } from 'lodash-es';
5
+ import { getCache } from '../cache.js';
6
+ import { getHelpers } from '../database/helpers/index.js';
7
+ import getDatabase, { getSchemaInspector } from '../database/index.js';
8
+ import { getExtensionManager } from '../extensions/index.js';
9
+ import { ItemsService } from './items.js';
10
+ import { PermissionsService } from './permissions.js';
11
+ export class ExtensionsService {
12
+ knex;
13
+ permissionsService;
14
+ schemaInspector;
15
+ accountability;
16
+ schema;
17
+ extensionsItemService;
18
+ systemCache;
19
+ helpers;
20
+ extensionsManager;
21
+ constructor(options) {
22
+ this.knex = options.knex || getDatabase();
23
+ this.permissionsService = new PermissionsService(options);
24
+ this.schemaInspector = options.knex ? createInspector(options.knex) : getSchemaInspector();
25
+ this.schema = options.schema;
26
+ this.accountability = options.accountability || null;
27
+ this.extensionsManager = getExtensionManager();
28
+ this.extensionsItemService = new ItemsService('directus_extensions', {
29
+ knex: this.knex,
30
+ schema: this.schema,
31
+ // No accountability here, as every other method is hardcoded to be admin only
32
+ });
33
+ this.systemCache = getCache().systemCache;
34
+ this.helpers = getHelpers(this.knex);
35
+ }
36
+ async readAll() {
37
+ if (this.accountability?.admin !== true) {
38
+ throw new ForbiddenError();
39
+ }
40
+ const installedExtensions = this.extensionsManager.getExtensions();
41
+ const configuredExtensions = await this.extensionsItemService.readByQuery({ limit: -1 });
42
+ return this.stitch(installedExtensions, configuredExtensions);
43
+ }
44
+ async readOne(bundle, name) {
45
+ if (this.accountability?.admin !== true) {
46
+ throw new ForbiddenError();
47
+ }
48
+ const key = this.getKey(bundle, name);
49
+ const schema = this.extensionsManager.getExtensions().find((extension) => extension.name === bundle ?? name);
50
+ const meta = await this.extensionsItemService.readOne(key);
51
+ const stitched = this.stitch(schema ? [schema] : [], [meta])[0];
52
+ if (stitched)
53
+ return stitched;
54
+ throw new ForbiddenError();
55
+ }
56
+ async updateOne(bundle, name, data) {
57
+ if (this.accountability?.admin !== true) {
58
+ throw new ForbiddenError();
59
+ }
60
+ const key = this.getKey(bundle, name);
61
+ const updateExtensionSchema = Joi.object({
62
+ meta: Joi.object({
63
+ enabled: Joi.boolean(),
64
+ }),
65
+ });
66
+ const { error } = updateExtensionSchema.validate(data);
67
+ if (error) {
68
+ throw new InvalidPayloadError({ reason: error.message });
69
+ }
70
+ if ('meta' in data && 'enabled' in data.meta) {
71
+ await this.knex('directus_extensions').update({ enabled: data.meta.enabled }).where({ name: key });
72
+ this.extensionsManager.reload();
73
+ }
74
+ }
75
+ getKey(bundle, name) {
76
+ return bundle ? `${bundle}/${name}` : name;
77
+ }
78
+ /**
79
+ * Combine the settings stored in the database with the information available from the installed
80
+ * extensions into the standardized extensions api output
81
+ */
82
+ stitch(installed, configured) {
83
+ /**
84
+ * On startup, the extensions manager will automatically create the rows for installed
85
+ * extensions that don't have configured settings yet, so there should always be equal or more
86
+ * settings rows than installed extensions.
87
+ */
88
+ return configured.map((meta) => {
89
+ let bundleName = null;
90
+ let name = meta.name;
91
+ if (name.includes('/')) {
92
+ [bundleName, name] = name.split('/');
93
+ }
94
+ let schema;
95
+ if (bundleName) {
96
+ const bundle = installed.find((extension) => extension.name === bundleName);
97
+ if (bundle && 'entries' in bundle) {
98
+ const entry = bundle.entries.find((entry) => entry.name === name) ?? null;
99
+ if (entry) {
100
+ schema = {
101
+ type: entry.type,
102
+ local: bundle.local,
103
+ };
104
+ }
105
+ }
106
+ else {
107
+ schema = null;
108
+ }
109
+ }
110
+ else {
111
+ schema = installed.find((extension) => extension.name === name) ?? null;
112
+ }
113
+ return {
114
+ name,
115
+ bundle: bundleName,
116
+ schema: schema ? pick(schema, 'type', 'local') : null,
117
+ meta: omit(meta, 'name'),
118
+ };
119
+ });
120
+ }
121
+ }
@@ -3,8 +3,8 @@ import type { Accountability, Field, RawField, SchemaOverview, Type } from '@dir
3
3
  import type Keyv from 'keyv';
4
4
  import type { Knex } from 'knex';
5
5
  import type { Helpers } from '../database/helpers/index.js';
6
- import { ItemsService } from '../services/items.js';
7
- import { PayloadService } from '../services/payload.js';
6
+ import { ItemsService } from './items.js';
7
+ import { PayloadService } from './payload.js';
8
8
  import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
9
9
  export declare class FieldsService {
10
10
  knex: Knex;
@@ -9,9 +9,9 @@ import { getHelpers } from '../database/helpers/index.js';
9
9
  import getDatabase, { getSchemaInspector } from '../database/index.js';
10
10
  import { systemFieldRows } from '../database/system-data/fields/index.js';
11
11
  import emitter from '../emitter.js';
12
- import { ForbiddenError, InvalidPayloadError } from '../errors/index.js';
13
- import { ItemsService } from '../services/items.js';
14
- import { PayloadService } from '../services/payload.js';
12
+ import { ForbiddenError, InvalidPayloadError } from '@directus/errors';
13
+ import { ItemsService } from './items.js';
14
+ import { PayloadService } from './payload.js';
15
15
  import getDefaultValue from '../utils/get-default-value.js';
16
16
  import getLocalType from '../utils/get-local-type.js';
17
17
  import { getSchema } from '../utils/get-schema.js';
@@ -541,7 +541,7 @@ export class FieldsService {
541
541
  column = table[type](field.field, field.schema?.numeric_precision ?? 10, field.schema?.numeric_scale ?? 5);
542
542
  }
543
543
  else if (field.type === 'csv') {
544
- column = table.string(field.field);
544
+ column = table.text(field.field);
545
545
  }
546
546
  else if (field.type === 'hash') {
547
547
  column = table.string(field.field, 255);
@@ -1,7 +1,9 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
+ import type { File } from '@directus/types';
2
3
  import type { Readable } from 'node:stream';
3
- import type { AbstractServiceOptions, File, Metadata, MutationOptions, PrimaryKey } from '../types/index.js';
4
+ import type { AbstractServiceOptions, MutationOptions, PrimaryKey } from '../types/index.js';
4
5
  import { ItemsService } from './items.js';
6
+ type Metadata = Partial<Pick<File, 'height' | 'width' | 'description' | 'title' | 'tags' | 'metadata'>>;
5
7
  export declare class FilesService extends ItemsService {
6
8
  constructor(options: AbstractServiceOptions);
7
9
  /**
@@ -32,3 +34,4 @@ export declare class FilesService extends ItemsService {
32
34
  */
33
35
  deleteMany(keys: PrimaryKey[]): Promise<PrimaryKey[]>;
34
36
  }
37
+ export {};