@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.
- package/dist/app.js +4 -4
- package/dist/auth/drivers/ldap.js +3 -2
- package/dist/auth/drivers/local.js +1 -1
- package/dist/auth/drivers/oauth2.js +1 -1
- package/dist/auth/drivers/openid.js +1 -1
- package/dist/auth/drivers/saml.js +1 -1
- package/dist/auth.js +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/controllers/activity.js +1 -1
- package/dist/controllers/assets.js +2 -2
- package/dist/controllers/auth.js +1 -1
- package/dist/controllers/collections.js +1 -1
- package/dist/controllers/dashboards.js +1 -1
- package/dist/controllers/extensions.js +11 -7
- package/dist/controllers/fields.js +1 -1
- package/dist/controllers/files.js +1 -1
- package/dist/controllers/flows.js +1 -1
- package/dist/controllers/folders.js +1 -1
- package/dist/controllers/items.js +1 -1
- package/dist/controllers/not-found.js +1 -1
- package/dist/controllers/notifications.js +1 -1
- package/dist/controllers/operations.js +1 -1
- package/dist/controllers/panels.js +1 -1
- package/dist/controllers/permissions.js +1 -1
- package/dist/controllers/presets.js +1 -1
- package/dist/controllers/relations.js +1 -1
- package/dist/controllers/roles.js +1 -1
- package/dist/controllers/schema.js +1 -1
- package/dist/controllers/server.js +1 -1
- package/dist/controllers/settings.js +1 -1
- package/dist/controllers/shares.js +1 -1
- package/dist/controllers/translations.js +1 -1
- package/dist/controllers/users.js +1 -1
- package/dist/controllers/utils.js +37 -18
- package/dist/controllers/webhooks.js +1 -1
- package/dist/database/errors/dialects/mssql.js +1 -1
- package/dist/database/errors/dialects/mysql.js +1 -1
- package/dist/database/errors/dialects/oracle.js +1 -1
- package/dist/database/errors/dialects/postgres.js +1 -1
- package/dist/database/errors/dialects/sqlite.js +1 -1
- package/dist/database/helpers/schema/dialects/mysql.js +1 -1
- package/dist/database/helpers/sequence/dialects/postgres.d.ts +5 -2
- package/dist/database/helpers/sequence/dialects/postgres.js +6 -3
- package/dist/database/migrations/20231009A-update-csv-fields-to-text.d.ts +3 -0
- package/dist/database/migrations/20231009A-update-csv-fields-to-text.js +44 -0
- package/dist/database/run-ast.js +1 -1
- package/dist/database/seeds/run.js +1 -1
- package/dist/extensions/get-extensions.d.ts +47 -0
- package/dist/extensions/get-extensions.js +9 -0
- package/dist/extensions/get-shared-deps-mapping.d.ts +1 -0
- package/dist/extensions/get-shared-deps-mapping.js +26 -0
- package/dist/extensions/index.d.ts +2 -0
- package/dist/extensions/index.js +9 -0
- package/dist/{extensions.d.ts → extensions/manager.d.ts} +4 -11
- package/dist/{extensions.js → extensions/manager.js} +28 -86
- package/dist/extensions/normalize-extension-info.d.ts +5 -0
- package/dist/extensions/normalize-extension-info.js +30 -0
- package/dist/extensions/types.d.ts +23 -0
- package/dist/extensions/wrap-embeds.d.ts +4 -0
- package/dist/extensions/wrap-embeds.js +8 -0
- package/dist/flows.d.ts +1 -1
- package/dist/flows.js +1 -1
- package/dist/middleware/check-ip.js +1 -1
- package/dist/middleware/collection-exists.js +1 -1
- package/dist/middleware/error-handler.js +1 -1
- package/dist/middleware/graphql.js +1 -1
- package/dist/middleware/rate-limiter-global.js +1 -1
- package/dist/middleware/rate-limiter-ip.js +1 -1
- package/dist/middleware/respond.js +1 -1
- package/dist/middleware/validate-batch.js +1 -1
- package/dist/operations/condition/index.d.ts +1 -1
- package/dist/operations/condition/index.js +2 -1
- package/dist/operations/exec/index.d.ts +1 -1
- package/dist/operations/exec/index.js +1 -1
- package/dist/operations/item-create/index.d.ts +1 -1
- package/dist/operations/item-create/index.js +2 -1
- package/dist/operations/item-delete/index.d.ts +1 -1
- package/dist/operations/item-delete/index.js +2 -1
- package/dist/operations/item-read/index.d.ts +1 -1
- package/dist/operations/item-read/index.js +2 -1
- package/dist/operations/item-update/index.d.ts +1 -1
- package/dist/operations/item-update/index.js +2 -1
- package/dist/operations/json-web-token/index.d.ts +1 -1
- package/dist/operations/json-web-token/index.js +2 -1
- package/dist/operations/log/index.d.ts +1 -1
- package/dist/operations/log/index.js +2 -1
- package/dist/operations/mail/index.d.ts +1 -1
- package/dist/operations/mail/index.js +1 -1
- package/dist/operations/notification/index.d.ts +1 -1
- package/dist/operations/notification/index.js +2 -1
- package/dist/operations/request/index.d.ts +1 -1
- package/dist/operations/request/index.js +3 -2
- package/dist/operations/sleep/index.d.ts +1 -1
- package/dist/operations/sleep/index.js +1 -1
- package/dist/operations/transform/index.d.ts +1 -1
- package/dist/operations/transform/index.js +2 -1
- package/dist/operations/trigger/index.d.ts +1 -1
- package/dist/operations/trigger/index.js +2 -1
- package/dist/services/activity.js +1 -1
- package/dist/services/assets.d.ts +1 -1
- package/dist/services/assets.js +2 -2
- package/dist/services/authentication.js +2 -2
- package/dist/services/authorization.js +1 -1
- package/dist/services/collections.js +3 -3
- package/dist/services/fields.d.ts +2 -2
- package/dist/services/fields.js +4 -4
- package/dist/services/files.d.ts +4 -1
- package/dist/services/files.js +5 -5
- package/dist/services/graphql/index.js +2 -2
- package/dist/services/graphql/subscription.js +3 -3
- package/dist/services/import-export/import-worker.d.ts +9 -0
- package/dist/services/import-export/import-worker.js +9 -0
- package/dist/services/{import-export.d.ts → import-export/index.d.ts} +2 -2
- package/dist/services/{import-export.js → import-export/index.js} +51 -42
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/items.js +2 -2
- package/dist/services/mail/index.js +1 -1
- package/dist/services/meta.js +1 -1
- package/dist/services/payload.js +1 -1
- package/dist/services/permissions.d.ts +2 -2
- package/dist/services/permissions.js +1 -1
- package/dist/services/relations.js +1 -1
- package/dist/services/revisions.js +1 -1
- package/dist/services/roles.js +1 -1
- package/dist/services/schema.js +1 -1
- package/dist/services/shares.js +1 -1
- package/dist/services/tfa.js +1 -1
- package/dist/services/translations.js +1 -1
- package/dist/services/users.js +2 -2
- package/dist/services/utils.d.ts +1 -0
- package/dist/services/utils.js +8 -2
- package/dist/services/websocket.js +11 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/index.js +0 -1
- package/dist/utils/apply-query.js +1 -1
- package/dist/utils/get-accountability-for-token.js +1 -1
- package/dist/utils/get-ast-from-query.js +1 -1
- package/dist/utils/get-column-path.js +1 -1
- package/dist/utils/get-column.js +1 -1
- package/dist/utils/get-default-value.d.ts +1 -2
- package/dist/utils/get-permissions.js +1 -1
- package/dist/utils/jwt.js +1 -1
- package/dist/utils/redact-object.js +9 -3
- package/dist/utils/transformations.d.ts +2 -1
- package/dist/utils/validate-diff.js +1 -1
- package/dist/utils/validate-keys.js +1 -1
- package/dist/utils/validate-query.js +1 -1
- package/dist/utils/validate-snapshot.js +1 -1
- package/dist/websocket/controllers/base.js +1 -1
- package/dist/websocket/controllers/index.d.ts +1 -1
- package/dist/websocket/controllers/index.js +0 -7
- package/dist/websocket/handlers/heartbeat.js +6 -1
- package/dist/websocket/handlers/subscribe.js +11 -16
- package/dist/websocket/utils/items.d.ts +4 -14
- package/dist/websocket/utils/items.js +59 -64
- package/dist/worker-pool.d.ts +2 -0
- package/dist/worker-pool.js +11 -0
- package/package.json +24 -22
- package/dist/errors/codes.d.ts +0 -29
- package/dist/errors/codes.js +0 -30
- package/dist/errors/contains-null-values.d.ts +0 -7
- package/dist/errors/contains-null-values.js +0 -4
- package/dist/errors/content-too-large.d.ts +0 -1
- package/dist/errors/content-too-large.js +0 -3
- package/dist/errors/forbidden.d.ts +0 -1
- package/dist/errors/forbidden.js +0 -3
- package/dist/errors/hit-rate-limit.d.ts +0 -6
- package/dist/errors/hit-rate-limit.js +0 -8
- package/dist/errors/illegal-asset-transformation.d.ts +0 -4
- package/dist/errors/illegal-asset-transformation.js +0 -3
- package/dist/errors/index.d.ts +0 -28
- package/dist/errors/index.js +0 -28
- package/dist/errors/invalid-credentials.d.ts +0 -1
- package/dist/errors/invalid-credentials.js +0 -3
- package/dist/errors/invalid-foreign-key.d.ts +0 -6
- package/dist/errors/invalid-foreign-key.js +0 -14
- package/dist/errors/invalid-ip.d.ts +0 -1
- package/dist/errors/invalid-ip.js +0 -3
- package/dist/errors/invalid-otp.d.ts +0 -1
- package/dist/errors/invalid-otp.js +0 -3
- package/dist/errors/invalid-payload.d.ts +0 -5
- package/dist/errors/invalid-payload.js +0 -4
- package/dist/errors/invalid-provider-config.d.ts +0 -5
- package/dist/errors/invalid-provider-config.js +0 -3
- package/dist/errors/invalid-provider.d.ts +0 -1
- package/dist/errors/invalid-provider.js +0 -3
- package/dist/errors/invalid-query.d.ts +0 -5
- package/dist/errors/invalid-query.js +0 -4
- package/dist/errors/invalid-token.d.ts +0 -1
- package/dist/errors/invalid-token.js +0 -3
- package/dist/errors/method-not-allowed.d.ts +0 -6
- package/dist/errors/method-not-allowed.js +0 -6
- package/dist/errors/not-null-violation.d.ts +0 -6
- package/dist/errors/not-null-violation.js +0 -14
- package/dist/errors/range-not-satisfiable.d.ts +0 -7
- package/dist/errors/range-not-satisfiable.js +0 -7
- package/dist/errors/record-not-unique.d.ts +0 -6
- package/dist/errors/record-not-unique.js +0 -14
- package/dist/errors/route-not-found.d.ts +0 -5
- package/dist/errors/route-not-found.js +0 -4
- package/dist/errors/service-unavailable.d.ts +0 -7
- package/dist/errors/service-unavailable.js +0 -4
- package/dist/errors/token-expired.d.ts +0 -1
- package/dist/errors/token-expired.js +0 -3
- package/dist/errors/unexpected-response.d.ts +0 -1
- package/dist/errors/unexpected-response.js +0 -3
- package/dist/errors/unprocessable-content.d.ts +0 -5
- package/dist/errors/unprocessable-content.js +0 -4
- package/dist/errors/unsupported-media-type.d.ts +0 -6
- package/dist/errors/unsupported-media-type.js +0 -4
- package/dist/errors/user-suspended.d.ts +0 -1
- package/dist/errors/user-suspended.js +0 -3
- package/dist/errors/value-out-of-range.d.ts +0 -6
- package/dist/errors/value-out-of-range.js +0 -14
- package/dist/errors/value-too-long.d.ts +0 -6
- package/dist/errors/value-too-long.js +0 -14
- package/dist/types/files.d.ts +0 -29
- /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.
|
|
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
|
+
};
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import type { Extension,
|
|
1
|
+
import type { Extension, ExtensionType } from '@directus/extensions';
|
|
2
2
|
import { Router } from 'express';
|
|
3
|
-
|
|
4
|
-
|
|
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 {
|
|
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 {
|
|
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
|
|
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 '
|
|
17
|
-
import emitter, { Emitter } from '
|
|
18
|
-
import env from '
|
|
19
|
-
import { getFlowManager } from '
|
|
20
|
-
import logger from '
|
|
21
|
-
import * as services from '
|
|
22
|
-
import getModuleDefault from '
|
|
23
|
-
import { getSchema } from '
|
|
24
|
-
import { JobQueue } from '
|
|
25
|
-
import { scheduleSynchronizedJob, validateCron } from '
|
|
26
|
-
import {
|
|
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
|
-
|
|
115
|
-
|
|
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
|
|
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
|
|
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(
|
|
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,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,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
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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 '
|
|
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/
|
|
5
|
+
declare const _default: import("@directus/extensions").OperationApiConfig<Options>;
|
|
6
6
|
export default _default;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
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,4 +1,5 @@
|
|
|
1
|
-
import { defineOperationApi
|
|
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({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineOperationApi
|
|
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';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineOperationApi
|
|
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';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineOperationApi
|
|
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';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { defineOperationApi
|
|
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,4 +1,5 @@
|
|
|
1
|
-
import { defineOperationApi
|
|
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',
|