@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
@@ -30,7 +30,7 @@ export default async function runSeed(database) {
30
30
  column = tableBuilder.increments();
31
31
  }
32
32
  else if (columnInfo.type === 'csv') {
33
- column = tableBuilder.string(columnName);
33
+ column = tableBuilder.text(columnName);
34
34
  }
35
35
  else if (columnInfo.type === 'hash') {
36
36
  column = tableBuilder.string(columnName, 255);
@@ -0,0 +1,47 @@
1
+ export declare const getExtensions: () => Promise<(({
2
+ path: string;
3
+ name: string;
4
+ version?: string;
5
+ host?: string;
6
+ local: boolean;
7
+ } & {
8
+ type: "interface" | "display" | "layout" | "module" | "panel";
9
+ entrypoint: string;
10
+ }) | ({
11
+ path: string;
12
+ name: string;
13
+ version?: string;
14
+ host?: string;
15
+ local: boolean;
16
+ } & {
17
+ type: "endpoint" | "hook";
18
+ entrypoint: string;
19
+ }) | ({
20
+ path: string;
21
+ name: string;
22
+ version?: string;
23
+ host?: string;
24
+ local: boolean;
25
+ } & {
26
+ type: "operation";
27
+ entrypoint: {
28
+ app: string;
29
+ api: string;
30
+ };
31
+ }) | ({
32
+ path: string;
33
+ name: string;
34
+ version?: string;
35
+ host?: string;
36
+ local: boolean;
37
+ } & {
38
+ type: "bundle";
39
+ entrypoint: {
40
+ app: string;
41
+ api: string;
42
+ };
43
+ entries: {
44
+ type: "operation" | "interface" | "display" | "endpoint" | "layout" | "module" | "panel" | "hook";
45
+ name: string;
46
+ }[];
47
+ }))[]>;
@@ -0,0 +1,9 @@
1
+ import { APP_EXTENSION_TYPES } from '@directus/extensions';
2
+ import { getLocalExtensions, getPackageExtensions, resolvePackageExtensions } from '@directus/extensions/node';
3
+ import env from '../env.js';
4
+ export const getExtensions = async () => {
5
+ const packageExtensions = await getPackageExtensions(env['PACKAGE_FILE_LOCATION']);
6
+ const localPackageExtensions = await resolvePackageExtensions(env['EXTENSIONS_PATH']);
7
+ const localExtensions = await getLocalExtensions(env['EXTENSIONS_PATH']);
8
+ return [...packageExtensions, ...localPackageExtensions, ...localExtensions].filter((extension) => env['SERVE_APP'] || APP_EXTENSION_TYPES.includes(extension.type) === false);
9
+ };
@@ -0,0 +1 @@
1
+ export declare const getSharedDepsMapping: (deps: string[]) => Promise<Record<string, string>>;
@@ -0,0 +1,26 @@
1
+ import { resolvePackage } from '@directus/utils/node';
2
+ import { escapeRegExp } from 'lodash-es';
3
+ import { readdir } from 'node:fs/promises';
4
+ import path from 'path';
5
+ import env from '../env.js';
6
+ import logger from '../logger.js';
7
+ import { Url } from '../utils/url.js';
8
+ import { dirname } from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ const __dirname = dirname(fileURLToPath(import.meta.url));
11
+ export const getSharedDepsMapping = async (deps) => {
12
+ const appDir = await readdir(path.join(resolvePackage('@directus/app', __dirname), 'dist', 'assets'));
13
+ const depsMapping = {};
14
+ for (const dep of deps) {
15
+ const depRegex = new RegExp(`${escapeRegExp(dep.replace(/\//g, '_'))}\\.[0-9a-f]{8}\\.entry\\.js`);
16
+ const depName = appDir.find((file) => depRegex.test(file));
17
+ if (depName) {
18
+ const depUrl = new Url(env['PUBLIC_URL']).addPath('admin', 'assets', depName);
19
+ depsMapping[dep] = depUrl.toString({ rootRelative: true });
20
+ }
21
+ else {
22
+ logger.warn(`Couldn't find shared extension dependency "${dep}"`);
23
+ }
24
+ }
25
+ return depsMapping;
26
+ };
@@ -0,0 +1,2 @@
1
+ import { ExtensionManager } from './manager.js';
2
+ export declare function getExtensionManager(): ExtensionManager;
@@ -0,0 +1,9 @@
1
+ import { ExtensionManager } from './manager.js';
2
+ let extensionManager;
3
+ export function getExtensionManager() {
4
+ if (extensionManager) {
5
+ return extensionManager;
6
+ }
7
+ extensionManager = new ExtensionManager();
8
+ return extensionManager;
9
+ }
@@ -1,11 +1,7 @@
1
- import type { Extension, ExtensionInfo, ExtensionType } from '@directus/types';
1
+ import type { Extension, ExtensionType } from '@directus/extensions';
2
2
  import { Router } from 'express';
3
- export declare function getExtensionManager(): ExtensionManager;
4
- type Options = {
5
- schedule: boolean;
6
- watch: boolean;
7
- };
8
- declare class ExtensionManager {
3
+ import type { Options } from './types.js';
4
+ export declare class ExtensionManager {
9
5
  private isLoaded;
10
6
  private options;
11
7
  private extensions;
@@ -22,7 +18,7 @@ declare class ExtensionManager {
22
18
  constructor();
23
19
  initialize(options?: Partial<Options>): Promise<void>;
24
20
  reload(): void;
25
- getExtensionsList(type?: ExtensionType): ExtensionInfo[];
21
+ getExtensionsList(type?: ExtensionType): import("@directus/extensions").ExtensionInfo[];
26
22
  getExtension(name: string): Extension | undefined;
27
23
  getAppExtensions(): string | null;
28
24
  getAppExtensionChunk(name: string): string | null;
@@ -36,9 +32,7 @@ declare class ExtensionManager {
36
32
  private initializeWatcher;
37
33
  private closeWatcher;
38
34
  private updateWatchedExtensions;
39
- private getExtensions;
40
35
  private generateExtensionBundle;
41
- private getSharedDepsMapping;
42
36
  private registerHooks;
43
37
  private registerEndpoints;
44
38
  private registerOperations;
@@ -48,4 +42,3 @@ declare class ExtensionManager {
48
42
  private registerOperation;
49
43
  private unregisterApiExtensions;
50
44
  }
51
- export {};
@@ -1,48 +1,45 @@
1
- import { APP_EXTENSION_TYPES, APP_SHARED_DEPS, HYBRID_EXTENSION_TYPES, JAVASCRIPT_FILE_EXTS, NESTED_EXTENSION_TYPES, } from '@directus/constants';
1
+ import { JAVASCRIPT_FILE_EXTS } from '@directus/constants';
2
+ import { APP_SHARED_DEPS, HYBRID_EXTENSION_TYPES, NESTED_EXTENSION_TYPES } from '@directus/extensions';
3
+ import { ensureExtensionDirs, generateExtensionsEntrypoint } from '@directus/extensions/node';
2
4
  import { isIn, isTypeIn, pluralize } from '@directus/utils';
3
- import { ensureExtensionDirs, generateExtensionsEntrypoint, getLocalExtensions, getPackageExtensions, pathToRelativeUrl, resolvePackage, resolvePackageExtensions, } from '@directus/utils/node';
5
+ import { pathToRelativeUrl } from '@directus/utils/node';
4
6
  import aliasDefault from '@rollup/plugin-alias';
5
7
  import nodeResolveDefault from '@rollup/plugin-node-resolve';
6
8
  import virtualDefault from '@rollup/plugin-virtual';
7
9
  import chokidar, { FSWatcher } from 'chokidar';
8
10
  import express, { Router } from 'express';
9
- import { clone, escapeRegExp } from 'lodash-es';
11
+ import { clone } from 'lodash-es';
10
12
  import { readdir } from 'node:fs/promises';
11
13
  import { createRequire } from 'node:module';
12
14
  import { dirname } from 'node:path';
13
15
  import { fileURLToPath } from 'node:url';
14
16
  import path from 'path';
15
17
  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';
18
+ import getDatabase from '../database/index.js';
19
+ import emitter, { Emitter } from '../emitter.js';
20
+ import env from '../env.js';
21
+ import { getFlowManager } from '../flows.js';
22
+ import logger from '../logger.js';
23
+ import * as services from '../services/index.js';
24
+ import getModuleDefault from '../utils/get-module-default.js';
25
+ import { getSchema } from '../utils/get-schema.js';
26
+ import { JobQueue } from '../utils/job-queue.js';
27
+ import { scheduleSynchronizedJob, validateCron } from '../utils/schedule.js';
28
+ import { getExtensions } from './get-extensions.js';
29
+ import { getSharedDepsMapping } from './get-shared-deps-mapping.js';
30
+ import { normalizeExtensionInfo } from './normalize-extension-info.js';
31
+ import { wrapEmbeds } from './wrap-embeds.js';
27
32
  // Workaround for https://github.com/rollup/plugins/issues/1329
28
33
  const virtual = virtualDefault;
29
34
  const alias = aliasDefault;
30
35
  const nodeResolve = nodeResolveDefault;
31
36
  const require = createRequire(import.meta.url);
32
37
  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
38
  const defaultOptions = {
42
39
  schedule: true,
43
40
  watch: env['EXTENSIONS_AUTO_RELOAD'] && env['NODE_ENV'] !== 'development',
44
41
  };
45
- class ExtensionManager {
42
+ export class ExtensionManager {
46
43
  isLoaded = false;
47
44
  options;
48
45
  extensions = [];
@@ -111,39 +108,11 @@ class ExtensionManager {
111
108
  });
112
109
  }
113
110
  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
- }
111
+ const extensionInfo = this.extensions.map(normalizeExtensionInfo);
112
+ if (type) {
113
+ return extensionInfo.filter((extension) => extension.type === type);
146
114
  }
115
+ return extensionInfo;
147
116
  }
148
117
  getExtension(name) {
149
118
  return this.extensions.find((extension) => extension.name === name);
@@ -162,16 +131,11 @@ class ExtensionManager {
162
131
  head: wrapEmbeds('Custom Embed Head', this.hookEmbedsHead),
163
132
  body: wrapEmbeds('Custom Embed Body', this.hookEmbedsBody),
164
133
  };
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
134
  }
171
135
  async load() {
172
136
  try {
173
137
  await ensureExtensionDirs(env['EXTENSIONS_PATH'], NESTED_EXTENSION_TYPES);
174
- this.extensions = await this.getExtensions();
138
+ this.extensions = await getExtensions();
175
139
  }
176
140
  catch (err) {
177
141
  logger.warn(`Couldn't load extensions`);
@@ -239,14 +203,8 @@ class ExtensionManager {
239
203
  this.watcher.unwatch(removedPackageExtensionPaths);
240
204
  }
241
205
  }
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
206
  async generateExtensionBundle() {
249
- const sharedDepsMapping = await this.getSharedDepsMapping(APP_SHARED_DEPS);
207
+ const sharedDepsMapping = await getSharedDepsMapping(APP_SHARED_DEPS);
250
208
  const internalImports = Object.entries(sharedDepsMapping).map(([name, path]) => ({
251
209
  find: name,
252
210
  replacement: path,
@@ -274,22 +232,6 @@ class ExtensionManager {
274
232
  }
275
233
  return null;
276
234
  }
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
235
  async registerHooks() {
294
236
  const hooks = this.extensions.filter((extension) => extension.type === 'hook');
295
237
  for (const hook of hooks) {
@@ -323,9 +265,9 @@ class ExtensionManager {
323
265
  }
324
266
  }
325
267
  async registerOperations() {
326
- const internalOperations = await readdir(path.join(__dirname, 'operations'));
268
+ const internalOperations = await readdir(path.join(__dirname, '..', 'operations'));
327
269
  for (const operation of internalOperations) {
328
- const operationInstance = await import(`./operations/${operation}/index.js`);
270
+ const operationInstance = await import(`../operations/${operation}/index.js`);
329
271
  const config = getModuleDefault(operationInstance);
330
272
  this.registerOperation(config);
331
273
  }
@@ -0,0 +1,5 @@
1
+ import type { Extension, ExtensionInfo } from '@directus/extensions';
2
+ /**
3
+ * Creates a standardized extension info object for a given extension
4
+ */
5
+ export declare const normalizeExtensionInfo: (extension: Extension) => ExtensionInfo;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Creates a standardized extension info object for a given extension
3
+ */
4
+ export const normalizeExtensionInfo = (extension) => {
5
+ const extensionInfo = {
6
+ name: extension.name,
7
+ type: extension.type,
8
+ local: extension.local,
9
+ entries: [],
10
+ };
11
+ if (extension.host)
12
+ extensionInfo.host = extension.host;
13
+ if (extension.version)
14
+ extensionInfo.version = extension.version;
15
+ if (extension.type === 'bundle') {
16
+ const bundleExtensionInfo = {
17
+ name: extensionInfo.name,
18
+ type: 'bundle',
19
+ local: extensionInfo.local,
20
+ entries: extension.entries.map((entry) => ({
21
+ name: entry.name,
22
+ type: entry.type,
23
+ })),
24
+ };
25
+ return bundleExtensionInfo;
26
+ }
27
+ else {
28
+ return extensionInfo;
29
+ }
30
+ };
@@ -0,0 +1,23 @@
1
+ import type { EndpointConfig, HookConfig, OperationApiConfig } from '@directus/extensions';
2
+ export type BundleConfig = {
3
+ endpoints: {
4
+ name: string;
5
+ config: EndpointConfig;
6
+ }[];
7
+ hooks: {
8
+ name: string;
9
+ config: HookConfig;
10
+ }[];
11
+ operations: {
12
+ name: string;
13
+ config: OperationApiConfig;
14
+ }[];
15
+ };
16
+ export type AppExtensions = string | null;
17
+ export type ApiExtensions = {
18
+ path: string;
19
+ }[];
20
+ export interface Options {
21
+ schedule: boolean;
22
+ watch: boolean;
23
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Wraps an array of passed strings in a set of HTML comments with the given label
3
+ */
4
+ export declare const wrapEmbeds: (label: string, content: string[]) => string;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Wraps an array of passed strings in a set of HTML comments with the given label
3
+ */
4
+ export const wrapEmbeds = (label, content) => {
5
+ if (content.length === 0)
6
+ return '';
7
+ return `<!-- Start ${label} -->\n${content.join('\n')}\n<!-- End ${label} -->`;
8
+ };
package/dist/flows.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { OperationHandler } from '@directus/types';
1
+ import type { OperationHandler } from '@directus/extensions';
2
2
  export declare function getFlowManager(): FlowManager;
3
3
  declare class FlowManager {
4
4
  private isLoaded;
package/dist/flows.js CHANGED
@@ -5,7 +5,7 @@ import { get } from 'micromustache';
5
5
  import getDatabase from './database/index.js';
6
6
  import emitter from './emitter.js';
7
7
  import env from './env.js';
8
- import { ForbiddenError } from './errors/index.js';
8
+ import { ForbiddenError } from '@directus/errors';
9
9
  import logger from './logger.js';
10
10
  import { getMessenger } from './messenger.js';
11
11
  import { ActivityService } from './services/activity.js';
@@ -1,5 +1,5 @@
1
1
  import getDatabase from '../database/index.js';
2
- import { InvalidIpError } from '../errors/index.js';
2
+ import { InvalidIpError } from '@directus/errors';
3
3
  import asyncHandler from '../utils/async-handler.js';
4
4
  export const checkIP = asyncHandler(async (req, _res, next) => {
5
5
  const database = getDatabase();
@@ -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';
@@ -2,7 +2,7 @@ import { parse as parseBytesConfiguration } from 'bytes';
2
2
  import { getCache, setCacheValue } from '../cache.js';
3
3
  import env from '../env.js';
4
4
  import logger from '../logger.js';
5
- import { ExportService } from '../services/import-export.js';
5
+ import { ExportService } from '../services/import-export/index.js';
6
6
  import asyncHandler from '../utils/async-handler.js';
7
7
  import { getCacheControlHeader } from '../utils/get-cache-headers.js';
8
8
  import { getCacheKey } from '../utils/get-cache-key.js';
@@ -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',