@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
@@ -1,487 +0,0 @@
1
- import { APP_EXTENSION_TYPES, APP_SHARED_DEPS, HYBRID_EXTENSION_TYPES, JAVASCRIPT_FILE_EXTS, NESTED_EXTENSION_TYPES, } from '@directus/constants';
2
- import { isIn, isTypeIn, pluralize } from '@directus/utils';
3
- import { ensureExtensionDirs, generateExtensionsEntrypoint, getLocalExtensions, getPackageExtensions, pathToRelativeUrl, resolvePackage, resolvePackageExtensions, } from '@directus/utils/node';
4
- import aliasDefault from '@rollup/plugin-alias';
5
- import nodeResolveDefault from '@rollup/plugin-node-resolve';
6
- import virtualDefault from '@rollup/plugin-virtual';
7
- import chokidar, { FSWatcher } from 'chokidar';
8
- import express, { Router } from 'express';
9
- import { clone, escapeRegExp } from 'lodash-es';
10
- import { readdir } from 'node:fs/promises';
11
- import { createRequire } from 'node:module';
12
- import { dirname } from 'node:path';
13
- import { fileURLToPath } from 'node:url';
14
- import path from 'path';
15
- import { rollup } from 'rollup';
16
- import getDatabase from './database/index.js';
17
- import emitter, { Emitter } from './emitter.js';
18
- import env from './env.js';
19
- import { getFlowManager } from './flows.js';
20
- import logger from './logger.js';
21
- import * as services from './services/index.js';
22
- import getModuleDefault from './utils/get-module-default.js';
23
- import { getSchema } from './utils/get-schema.js';
24
- import { JobQueue } from './utils/job-queue.js';
25
- import { scheduleSynchronizedJob, validateCron } from './utils/schedule.js';
26
- import { Url } from './utils/url.js';
27
- // Workaround for https://github.com/rollup/plugins/issues/1329
28
- const virtual = virtualDefault;
29
- const alias = aliasDefault;
30
- const nodeResolve = nodeResolveDefault;
31
- const require = createRequire(import.meta.url);
32
- const __dirname = dirname(fileURLToPath(import.meta.url));
33
- let extensionManager;
34
- export function getExtensionManager() {
35
- if (extensionManager) {
36
- return extensionManager;
37
- }
38
- extensionManager = new ExtensionManager();
39
- return extensionManager;
40
- }
41
- const defaultOptions = {
42
- schedule: true,
43
- watch: env['EXTENSIONS_AUTO_RELOAD'] && env['NODE_ENV'] !== 'development',
44
- };
45
- class ExtensionManager {
46
- isLoaded = false;
47
- options;
48
- extensions = [];
49
- appExtensions = null;
50
- appExtensionChunks;
51
- apiExtensions = [];
52
- apiEmitter;
53
- hookEvents = [];
54
- endpointRouter;
55
- hookEmbedsHead = [];
56
- hookEmbedsBody = [];
57
- reloadQueue;
58
- watcher = null;
59
- constructor() {
60
- this.options = defaultOptions;
61
- this.apiEmitter = new Emitter();
62
- this.endpointRouter = Router();
63
- this.reloadQueue = new JobQueue();
64
- this.appExtensionChunks = new Map();
65
- }
66
- async initialize(options = {}) {
67
- this.options = {
68
- ...defaultOptions,
69
- ...options,
70
- };
71
- const wasWatcherInitialized = this.watcher !== null;
72
- if (this.options.watch && !wasWatcherInitialized) {
73
- this.initializeWatcher();
74
- }
75
- else if (!this.options.watch && wasWatcherInitialized) {
76
- await this.closeWatcher();
77
- }
78
- if (!this.isLoaded) {
79
- await this.load();
80
- const loadedExtensions = this.getExtensionsList();
81
- if (loadedExtensions.length > 0) {
82
- logger.info(`Loaded extensions: ${loadedExtensions.map((ext) => ext.name).join(', ')}`);
83
- }
84
- }
85
- if (this.options.watch && !wasWatcherInitialized) {
86
- this.updateWatchedExtensions(this.extensions);
87
- }
88
- }
89
- reload() {
90
- this.reloadQueue.enqueue(async () => {
91
- if (this.isLoaded) {
92
- logger.info('Reloading extensions');
93
- const prevExtensions = clone(this.extensions);
94
- await this.unload();
95
- await this.load();
96
- const added = this.extensions.filter((extension) => !prevExtensions.some((prevExtension) => extension.path === prevExtension.path));
97
- const removed = prevExtensions.filter((prevExtension) => !this.extensions.some((extension) => prevExtension.path === extension.path));
98
- this.updateWatchedExtensions(added, removed);
99
- const addedExtensions = added.map((extension) => extension.name);
100
- const removedExtensions = removed.map((extension) => extension.name);
101
- if (addedExtensions.length > 0) {
102
- logger.info(`Added extensions: ${addedExtensions.join(', ')}`);
103
- }
104
- if (removedExtensions.length > 0) {
105
- logger.info(`Removed extensions: ${removedExtensions.join(', ')}`);
106
- }
107
- }
108
- else {
109
- logger.warn('Extensions have to be loaded before they can be reloaded');
110
- }
111
- });
112
- }
113
- getExtensionsList(type) {
114
- if (type === undefined) {
115
- return this.extensions.map(mapInfo);
116
- }
117
- else {
118
- return this.extensions.map(mapInfo).filter((extension) => extension.type === type);
119
- }
120
- function mapInfo(extension) {
121
- const extensionInfo = {
122
- name: extension.name,
123
- type: extension.type,
124
- local: extension.local,
125
- entries: [],
126
- };
127
- if (extension.host)
128
- extensionInfo.host = extension.host;
129
- if (extension.version)
130
- extensionInfo.version = extension.version;
131
- if (extension.type === 'bundle') {
132
- const bundleExtensionInfo = {
133
- name: extensionInfo.name,
134
- type: 'bundle',
135
- local: extensionInfo.local,
136
- entries: extension.entries.map((entry) => ({
137
- name: entry.name,
138
- type: entry.type,
139
- })),
140
- };
141
- return bundleExtensionInfo;
142
- }
143
- else {
144
- return extensionInfo;
145
- }
146
- }
147
- }
148
- getExtension(name) {
149
- return this.extensions.find((extension) => extension.name === name);
150
- }
151
- getAppExtensions() {
152
- return this.appExtensions;
153
- }
154
- getAppExtensionChunk(name) {
155
- return this.appExtensionChunks.get(name) ?? null;
156
- }
157
- getEndpointRouter() {
158
- return this.endpointRouter;
159
- }
160
- getEmbeds() {
161
- return {
162
- head: wrapEmbeds('Custom Embed Head', this.hookEmbedsHead),
163
- body: wrapEmbeds('Custom Embed Body', this.hookEmbedsBody),
164
- };
165
- function wrapEmbeds(label, content) {
166
- if (content.length === 0)
167
- return '';
168
- return `<!-- Start ${label} -->\n${content.join('\n')}\n<!-- End ${label} -->`;
169
- }
170
- }
171
- async load() {
172
- try {
173
- await ensureExtensionDirs(env['EXTENSIONS_PATH'], NESTED_EXTENSION_TYPES);
174
- this.extensions = await this.getExtensions();
175
- }
176
- catch (err) {
177
- logger.warn(`Couldn't load extensions`);
178
- logger.warn(err);
179
- }
180
- await this.registerHooks();
181
- await this.registerEndpoints();
182
- await this.registerOperations();
183
- await this.registerBundles();
184
- if (env['SERVE_APP']) {
185
- this.appExtensions = await this.generateExtensionBundle();
186
- }
187
- this.isLoaded = true;
188
- }
189
- async unload() {
190
- await this.unregisterApiExtensions();
191
- this.apiEmitter.offAll();
192
- if (env['SERVE_APP']) {
193
- this.appExtensions = null;
194
- }
195
- this.isLoaded = false;
196
- }
197
- initializeWatcher() {
198
- logger.info('Watching extensions for changes...');
199
- const extensionDirUrl = pathToRelativeUrl(env['EXTENSIONS_PATH']);
200
- const localExtensionUrls = NESTED_EXTENSION_TYPES.flatMap((type) => {
201
- const typeDir = path.posix.join(extensionDirUrl, pluralize(type));
202
- if (isIn(type, HYBRID_EXTENSION_TYPES)) {
203
- return [
204
- path.posix.join(typeDir, '*', `app.{${JAVASCRIPT_FILE_EXTS.join()}}`),
205
- path.posix.join(typeDir, '*', `api.{${JAVASCRIPT_FILE_EXTS.join()}}`),
206
- ];
207
- }
208
- else {
209
- return path.posix.join(typeDir, '*', `index.{${JAVASCRIPT_FILE_EXTS.join()}}`);
210
- }
211
- });
212
- this.watcher = chokidar.watch([path.resolve('package.json'), path.posix.join(extensionDirUrl, '*', 'package.json'), ...localExtensionUrls], {
213
- ignoreInitial: true,
214
- });
215
- this.watcher
216
- .on('add', () => this.reload())
217
- .on('change', () => this.reload())
218
- .on('unlink', () => this.reload());
219
- }
220
- async closeWatcher() {
221
- if (this.watcher) {
222
- await this.watcher.close();
223
- this.watcher = null;
224
- }
225
- }
226
- updateWatchedExtensions(added, removed = []) {
227
- if (this.watcher) {
228
- const toPackageExtensionPaths = (extensions) => extensions
229
- .filter((extension) => !extension.local || extension.type === 'bundle')
230
- .flatMap((extension) => isTypeIn(extension, HYBRID_EXTENSION_TYPES) || extension.type === 'bundle'
231
- ? [
232
- path.resolve(extension.path, extension.entrypoint.app),
233
- path.resolve(extension.path, extension.entrypoint.api),
234
- ]
235
- : path.resolve(extension.path, extension.entrypoint));
236
- const addedPackageExtensionPaths = toPackageExtensionPaths(added);
237
- const removedPackageExtensionPaths = toPackageExtensionPaths(removed);
238
- this.watcher.add(addedPackageExtensionPaths);
239
- this.watcher.unwatch(removedPackageExtensionPaths);
240
- }
241
- }
242
- async getExtensions() {
243
- const packageExtensions = await getPackageExtensions(env['PACKAGE_FILE_LOCATION']);
244
- const localPackageExtensions = await resolvePackageExtensions(env['EXTENSIONS_PATH']);
245
- const localExtensions = await getLocalExtensions(env['EXTENSIONS_PATH']);
246
- return [...packageExtensions, ...localPackageExtensions, ...localExtensions].filter((extension) => env['SERVE_APP'] || APP_EXTENSION_TYPES.includes(extension.type) === false);
247
- }
248
- async generateExtensionBundle() {
249
- const sharedDepsMapping = await this.getSharedDepsMapping(APP_SHARED_DEPS);
250
- const internalImports = Object.entries(sharedDepsMapping).map(([name, path]) => ({
251
- find: name,
252
- replacement: path,
253
- }));
254
- const entrypoint = generateExtensionsEntrypoint(this.extensions);
255
- try {
256
- const bundle = await rollup({
257
- input: 'entry',
258
- external: Object.values(sharedDepsMapping),
259
- makeAbsoluteExternalsRelative: false,
260
- plugins: [virtual({ entry: entrypoint }), alias({ entries: internalImports }), nodeResolve({ browser: true })],
261
- });
262
- const { output } = await bundle.generate({ format: 'es', compact: true });
263
- for (const out of output) {
264
- if (out.type === 'chunk') {
265
- this.appExtensionChunks.set(out.fileName, out.code);
266
- }
267
- }
268
- await bundle.close();
269
- return output[0].code;
270
- }
271
- catch (error) {
272
- logger.warn(`Couldn't bundle App extensions`);
273
- logger.warn(error);
274
- }
275
- return null;
276
- }
277
- async getSharedDepsMapping(deps) {
278
- const appDir = await readdir(path.join(resolvePackage('@directus/app', __dirname), 'dist', 'assets'));
279
- const depsMapping = {};
280
- for (const dep of deps) {
281
- const depRegex = new RegExp(`${escapeRegExp(dep.replace(/\//g, '_'))}\\.[0-9a-f]{8}\\.entry\\.js`);
282
- const depName = appDir.find((file) => depRegex.test(file));
283
- if (depName) {
284
- const depUrl = new Url(env['PUBLIC_URL']).addPath('admin', 'assets', depName);
285
- depsMapping[dep] = depUrl.toString({ rootRelative: true });
286
- }
287
- else {
288
- logger.warn(`Couldn't find shared extension dependency "${dep}"`);
289
- }
290
- }
291
- return depsMapping;
292
- }
293
- async registerHooks() {
294
- const hooks = this.extensions.filter((extension) => extension.type === 'hook');
295
- for (const hook of hooks) {
296
- try {
297
- const hookPath = path.resolve(hook.path, hook.entrypoint);
298
- const hookInstance = await import(`./${pathToRelativeUrl(hookPath, __dirname)}?t=${Date.now()}`);
299
- const config = getModuleDefault(hookInstance);
300
- this.registerHook(config, hook.name);
301
- this.apiExtensions.push({ path: hookPath });
302
- }
303
- catch (error) {
304
- logger.warn(`Couldn't register hook "${hook.name}"`);
305
- logger.warn(error);
306
- }
307
- }
308
- }
309
- async registerEndpoints() {
310
- const endpoints = this.extensions.filter((extension) => extension.type === 'endpoint');
311
- for (const endpoint of endpoints) {
312
- try {
313
- const endpointPath = path.resolve(endpoint.path, endpoint.entrypoint);
314
- const endpointInstance = await import(`./${pathToRelativeUrl(endpointPath, __dirname)}?t=${Date.now()}`);
315
- const config = getModuleDefault(endpointInstance);
316
- this.registerEndpoint(config, endpoint.name);
317
- this.apiExtensions.push({ path: endpointPath });
318
- }
319
- catch (error) {
320
- logger.warn(`Couldn't register endpoint "${endpoint.name}"`);
321
- logger.warn(error);
322
- }
323
- }
324
- }
325
- async registerOperations() {
326
- const internalOperations = await readdir(path.join(__dirname, 'operations'));
327
- for (const operation of internalOperations) {
328
- const operationInstance = await import(`./operations/${operation}/index.js`);
329
- const config = getModuleDefault(operationInstance);
330
- this.registerOperation(config);
331
- }
332
- const operations = this.extensions.filter((extension) => extension.type === 'operation');
333
- for (const operation of operations) {
334
- try {
335
- const operationPath = path.resolve(operation.path, operation.entrypoint.api);
336
- const operationInstance = await import(`./${pathToRelativeUrl(operationPath, __dirname)}?t=${Date.now()}`);
337
- const config = getModuleDefault(operationInstance);
338
- this.registerOperation(config);
339
- this.apiExtensions.push({ path: operationPath });
340
- }
341
- catch (error) {
342
- logger.warn(`Couldn't register operation "${operation.name}"`);
343
- logger.warn(error);
344
- }
345
- }
346
- }
347
- async registerBundles() {
348
- const bundles = this.extensions.filter((extension) => extension.type === 'bundle');
349
- for (const bundle of bundles) {
350
- try {
351
- const bundlePath = path.resolve(bundle.path, bundle.entrypoint.api);
352
- const bundleInstances = await import(`./${pathToRelativeUrl(bundlePath, __dirname)}?t=${Date.now()}`);
353
- const configs = getModuleDefault(bundleInstances);
354
- for (const { config, name } of configs.hooks) {
355
- this.registerHook(config, name);
356
- }
357
- for (const { config, name } of configs.endpoints) {
358
- this.registerEndpoint(config, name);
359
- }
360
- for (const { config } of configs.operations) {
361
- this.registerOperation(config);
362
- }
363
- this.apiExtensions.push({ path: bundlePath });
364
- }
365
- catch (error) {
366
- logger.warn(`Couldn't register bundle "${bundle.name}"`);
367
- logger.warn(error);
368
- }
369
- }
370
- }
371
- registerHook(register, name) {
372
- let scheduleIndex = 0;
373
- const registerFunctions = {
374
- filter: (event, handler) => {
375
- emitter.onFilter(event, handler);
376
- this.hookEvents.push({
377
- type: 'filter',
378
- name: event,
379
- handler,
380
- });
381
- },
382
- action: (event, handler) => {
383
- emitter.onAction(event, handler);
384
- this.hookEvents.push({
385
- type: 'action',
386
- name: event,
387
- handler,
388
- });
389
- },
390
- init: (event, handler) => {
391
- emitter.onInit(event, handler);
392
- this.hookEvents.push({
393
- type: 'init',
394
- name: event,
395
- handler,
396
- });
397
- },
398
- schedule: (cron, handler) => {
399
- if (validateCron(cron)) {
400
- const job = scheduleSynchronizedJob(`${name}:${scheduleIndex}`, cron, async () => {
401
- if (this.options.schedule) {
402
- try {
403
- await handler();
404
- }
405
- catch (error) {
406
- logger.error(error);
407
- }
408
- }
409
- });
410
- scheduleIndex++;
411
- this.hookEvents.push({
412
- type: 'schedule',
413
- job,
414
- });
415
- }
416
- else {
417
- logger.warn(`Couldn't register cron hook. Provided cron is invalid: ${cron}`);
418
- }
419
- },
420
- embed: (position, code) => {
421
- const content = typeof code === 'function' ? code() : code;
422
- if (content.trim().length === 0) {
423
- logger.warn(`Couldn't register embed hook. Provided code is empty!`);
424
- return;
425
- }
426
- if (position === 'head') {
427
- this.hookEmbedsHead.push(content);
428
- }
429
- if (position === 'body') {
430
- this.hookEmbedsBody.push(content);
431
- }
432
- },
433
- };
434
- register(registerFunctions, {
435
- services,
436
- env,
437
- database: getDatabase(),
438
- emitter: this.apiEmitter,
439
- logger,
440
- getSchema,
441
- });
442
- }
443
- registerEndpoint(config, name) {
444
- const register = typeof config === 'function' ? config : config.handler;
445
- const routeName = typeof config === 'function' ? name : config.id;
446
- const scopedRouter = express.Router();
447
- this.endpointRouter.use(`/${routeName}`, scopedRouter);
448
- register(scopedRouter, {
449
- services,
450
- env,
451
- database: getDatabase(),
452
- emitter: this.apiEmitter,
453
- logger,
454
- getSchema,
455
- });
456
- }
457
- registerOperation(config) {
458
- const flowManager = getFlowManager();
459
- flowManager.addOperation(config.id, config.handler);
460
- }
461
- async unregisterApiExtensions() {
462
- for (const event of this.hookEvents) {
463
- switch (event.type) {
464
- case 'filter':
465
- emitter.offFilter(event.name, event.handler);
466
- break;
467
- case 'action':
468
- emitter.offAction(event.name, event.handler);
469
- break;
470
- case 'init':
471
- emitter.offInit(event.name, event.handler);
472
- break;
473
- case 'schedule':
474
- await event.job.stop();
475
- break;
476
- }
477
- }
478
- this.hookEvents = [];
479
- this.endpointRouter.stack = [];
480
- const flowManager = getFlowManager();
481
- flowManager.clearOperations();
482
- for (const apiExtension of this.apiExtensions) {
483
- delete require.cache[require.resolve(apiExtension.path)];
484
- }
485
- this.apiExtensions = [];
486
- }
487
- }
@@ -1,29 +0,0 @@
1
- export type File = {
2
- id: string;
3
- storage: string;
4
- filename_disk: string;
5
- filename_download: string;
6
- title: string | null;
7
- type: string | null;
8
- folder: string | null;
9
- uploaded_by: string | null;
10
- uploaded_on: Date;
11
- charset: string | null;
12
- filesize: number;
13
- width: number | null;
14
- height: number | null;
15
- duration: number | null;
16
- embed: string | null;
17
- description: string | null;
18
- location: string | null;
19
- tags: string | null;
20
- metadata: Record<string, any> | null;
21
- };
22
- export type Metadata = {
23
- height?: number | undefined;
24
- width?: number | undefined;
25
- description?: string | undefined;
26
- title?: string | undefined;
27
- tags?: any | undefined;
28
- metadata?: any | undefined;
29
- };
File without changes