directus 9.4.0 → 9.5.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/README.md +1 -1
- package/dist/app.js +20 -1
- package/dist/auth/auth.d.ts +2 -1
- package/dist/auth/drivers/ldap.js +2 -1
- package/dist/auth/drivers/local.js +2 -1
- package/dist/auth/drivers/oauth2.js +12 -21
- package/dist/auth/drivers/openid.js +14 -3
- package/dist/cache.js +1 -3
- package/dist/cli/commands/init/questions.d.ts +3 -0
- package/dist/cli/commands/init/questions.js +2 -0
- package/dist/cli/index.js +1 -1
- package/dist/cli/utils/create-db-connection.d.ts +1 -1
- package/dist/cli/utils/create-db-connection.js +11 -1
- package/dist/cli/utils/drivers.d.ts +1 -0
- package/dist/cli/utils/drivers.js +2 -1
- package/dist/controllers/activity.js +2 -1
- package/dist/controllers/auth.js +5 -4
- package/dist/controllers/extensions.js +1 -1
- package/dist/controllers/files.js +1 -1
- package/dist/controllers/shares.js +2 -2
- package/dist/controllers/utils.js +2 -0
- package/dist/database/helpers/date/index.d.ts +1 -0
- package/dist/database/helpers/date/index.js +3 -1
- package/dist/database/helpers/geometry/index.d.ts +1 -0
- package/dist/database/helpers/geometry/index.js +3 -1
- package/dist/database/helpers/index.d.ts +2 -0
- package/dist/database/helpers/index.js +2 -0
- package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +16 -0
- package/dist/database/helpers/schema/dialects/cockroachdb.js +16 -0
- package/dist/database/helpers/schema/dialects/default.d.ts +3 -0
- package/dist/database/helpers/schema/dialects/default.js +7 -0
- package/dist/database/helpers/schema/dialects/oracle.d.ts +12 -0
- package/dist/database/helpers/schema/dialects/oracle.js +13 -0
- package/dist/database/helpers/schema/index.d.ts +7 -0
- package/dist/database/helpers/schema/index.js +17 -0
- package/dist/database/helpers/schema/types.d.ts +25 -0
- package/dist/database/helpers/schema/types.js +89 -0
- package/dist/database/index.d.ts +1 -1
- package/dist/database/index.js +36 -16
- package/dist/database/migrations/20201105B-change-webhook-url-type.js +6 -25
- package/dist/database/migrations/20210312A-webhooks-collections-text.js +6 -25
- package/dist/database/migrations/20210415A-make-filesize-nullable.js +9 -4
- package/dist/database/migrations/20210506A-rename-interfaces.js +1 -1
- package/dist/database/migrations/20210510A-restructure-relations.js +12 -4
- package/dist/database/migrations/20210525A-add-insights.js +2 -2
- package/dist/database/migrations/20210626A-change-filesize-bigint.js +5 -7
- package/dist/database/migrations/20210903A-add-auth-provider.js +11 -2
- package/dist/database/migrations/20210907A-webhooks-collections-not-null.js +6 -20
- package/dist/database/migrations/20210920A-webhooks-url-not-null.js +10 -14
- package/dist/database/migrations/20211211A-add-shares.js +5 -4
- package/dist/database/migrations/20211230A-add-project-descriptor.d.ts +3 -0
- package/dist/database/migrations/20211230A-add-project-descriptor.js +15 -0
- package/dist/database/migrations/run.js +1 -1
- package/dist/database/run-ast.d.ts +1 -1
- package/dist/database/seeds/01-collections.yaml +1 -0
- package/dist/database/seeds/02-roles.yaml +1 -0
- package/dist/database/seeds/03-users.yaml +1 -0
- package/dist/database/system-data/fields/_defaults.yaml +2 -0
- package/dist/database/system-data/fields/settings.yaml +20 -1
- package/dist/database/system-data/fields/shares.yaml +4 -0
- package/dist/database/system-data/relations/index.d.ts +1 -1
- package/dist/emitter.d.ts +3 -4
- package/dist/emitter.js +2 -8
- package/dist/env.js +4 -1
- package/dist/exceptions/database/translate.js +1 -0
- package/dist/exceptions/index.d.ts +1 -0
- package/dist/exceptions/index.js +1 -0
- package/dist/exceptions/unsupported-media-type.d.ts +4 -0
- package/dist/exceptions/unsupported-media-type.js +10 -0
- package/dist/extensions.d.ts +14 -8
- package/dist/extensions.js +136 -69
- package/dist/logger.js +22 -1
- package/dist/middleware/authenticate.js +2 -1
- package/dist/middleware/rate-limiter.js +2 -1
- package/dist/services/assets.js +3 -3
- package/dist/services/authentication.d.ts +2 -2
- package/dist/services/authentication.js +10 -5
- package/dist/services/authorization.d.ts +2 -3
- package/dist/services/collections.d.ts +2 -2
- package/dist/services/collections.js +10 -6
- package/dist/services/fields.d.ts +2 -3
- package/dist/services/fields.js +8 -4
- package/dist/services/graphql.d.ts +3 -2
- package/dist/services/graphql.js +35 -5
- package/dist/services/import.d.ts +2 -2
- package/dist/services/import.js +2 -1
- package/dist/services/items.d.ts +2 -2
- package/dist/services/items.js +22 -18
- package/dist/services/mail/index.d.ts +2 -2
- package/dist/services/meta.d.ts +2 -2
- package/dist/services/payload.d.ts +2 -2
- package/dist/services/relations.d.ts +2 -2
- package/dist/services/server.d.ts +2 -2
- package/dist/services/server.js +1 -0
- package/dist/services/shares.js +2 -2
- package/dist/services/specifications.d.ts +2 -2
- package/dist/services/users.d.ts +2 -3
- package/dist/services/utils.d.ts +2 -2
- package/dist/types/ast.d.ts +1 -2
- package/dist/types/auth.d.ts +1 -3
- package/dist/types/index.d.ts +0 -3
- package/dist/types/index.js +0 -3
- package/dist/types/services.d.ts +1 -3
- package/dist/types/snapshot.d.ts +1 -2
- package/dist/utils/apply-query.d.ts +1 -2
- package/dist/utils/apply-query.js +1 -1
- package/dist/utils/apply-snapshot.d.ts +2 -1
- package/dist/utils/get-ast-from-query.d.ts +2 -3
- package/dist/utils/get-default-value.js +3 -1
- package/dist/utils/get-ip-from-req.d.ts +2 -0
- package/dist/utils/get-ip-from-req.js +24 -0
- package/dist/utils/get-local-type.js +1 -1
- package/dist/utils/get-permissions.d.ts +1 -2
- package/dist/utils/get-relation-type.d.ts +1 -1
- package/dist/utils/get-schema.d.ts +1 -2
- package/dist/utils/get-snapshot.d.ts +2 -1
- package/dist/utils/merge-permissions-for-share.d.ts +1 -2
- package/dist/utils/reduce-schema.d.ts +1 -2
- package/example.env +9 -1
- package/package.json +18 -15
- package/dist/cli/index.test.d.ts +0 -1
- package/dist/cli/index.test.js +0 -58
- package/dist/middleware/cache.test.d.ts +0 -1
- package/dist/middleware/cache.test.js +0 -62
- package/dist/tests/database/migrations/run.test.d.ts +0 -1
- package/dist/tests/database/migrations/run.test.js +0 -29
- package/dist/types/extensions.d.ts +0 -43
- package/dist/types/extensions.js +0 -2
- package/dist/types/relation.d.ts +0 -21
- package/dist/types/relation.js +0 -2
- package/dist/types/schema.d.ts +0 -32
- package/dist/types/schema.js +0 -2
- package/dist/utils/get-cache-key.test.d.ts +0 -1
- package/dist/utils/get-cache-key.test.js +0 -53
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.down = exports.up = void 0;
|
|
4
|
+
async function up(knex) {
|
|
5
|
+
await knex.schema.alterTable('directus_settings', (table) => {
|
|
6
|
+
table.string('project_descriptor', 100).nullable();
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
exports.up = up;
|
|
10
|
+
async function down(knex) {
|
|
11
|
+
await knex.schema.alterTable('directus_settings', (table) => {
|
|
12
|
+
table.dropColumn('project_descriptor');
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
exports.down = down;
|
|
@@ -13,7 +13,7 @@ async function run(database, direction, log = true) {
|
|
|
13
13
|
let migrationFiles = await fs_extra_1.default.readdir(__dirname);
|
|
14
14
|
const customMigrationsPath = path_1.default.resolve(env_1.default.EXTENSIONS_PATH, 'migrations');
|
|
15
15
|
let customMigrationFiles = ((await fs_extra_1.default.pathExists(customMigrationsPath)) && (await fs_extra_1.default.readdir(customMigrationsPath))) || [];
|
|
16
|
-
migrationFiles = migrationFiles.filter((file) =>
|
|
16
|
+
migrationFiles = migrationFiles.filter((file) => /^[0-9]+[A-Z]-[^.]+\.(?:js|ts)$/.test(file));
|
|
17
17
|
customMigrationFiles = customMigrationFiles.filter((file) => file.endsWith('.js'));
|
|
18
18
|
const completedMigrations = await database.select('*').from('directus_migrations').orderBy('version');
|
|
19
19
|
const migrations = [
|
|
@@ -14,6 +14,16 @@ fields:
|
|
|
14
14
|
translations: Name
|
|
15
15
|
width: half
|
|
16
16
|
|
|
17
|
+
- field: project_descriptor
|
|
18
|
+
interface: input
|
|
19
|
+
options:
|
|
20
|
+
iconRight: title
|
|
21
|
+
placeholder: $t:field_options.directus_settings.project_name_placeholder
|
|
22
|
+
translations:
|
|
23
|
+
language: en-US
|
|
24
|
+
translations: Name
|
|
25
|
+
width: half
|
|
26
|
+
|
|
17
27
|
- field: project_url
|
|
18
28
|
interface: input
|
|
19
29
|
options:
|
|
@@ -22,7 +32,7 @@ fields:
|
|
|
22
32
|
translations:
|
|
23
33
|
language: en-US
|
|
24
34
|
translations: Website
|
|
25
|
-
width:
|
|
35
|
+
width: full
|
|
26
36
|
|
|
27
37
|
- field: branding_divider
|
|
28
38
|
interface: presentation-divider
|
|
@@ -343,3 +353,12 @@ fields:
|
|
|
343
353
|
type:
|
|
344
354
|
_neq: 'raster'
|
|
345
355
|
hidden: true
|
|
356
|
+
- field: attribution
|
|
357
|
+
name: $t:fields.directus_settings.attribution
|
|
358
|
+
type: string
|
|
359
|
+
schema:
|
|
360
|
+
is_nullable: true
|
|
361
|
+
meta:
|
|
362
|
+
interface: input
|
|
363
|
+
options:
|
|
364
|
+
placeholder: $t:fields.directus_settings.attribution_placeholder
|
|
@@ -32,15 +32,19 @@ fields:
|
|
|
32
32
|
iconRight: lock
|
|
33
33
|
masked: true
|
|
34
34
|
width: half
|
|
35
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
35
36
|
|
|
36
37
|
- field: date_start
|
|
37
38
|
width: half
|
|
39
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
38
40
|
|
|
39
41
|
- field: date_end
|
|
40
42
|
width: half
|
|
43
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
41
44
|
|
|
42
45
|
- field: max_uses
|
|
43
46
|
width: half
|
|
47
|
+
note: $t:shared_leave_blank_for_unlimited
|
|
44
48
|
|
|
45
49
|
- field: times_used
|
|
46
50
|
width: half
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { RelationMeta } from '
|
|
1
|
+
import { RelationMeta } from '@directus/shared/types';
|
|
2
2
|
export declare const systemRelationRows: RelationMeta[];
|
package/dist/emitter.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { ActionHandler,
|
|
1
|
+
import { ActionHandler, EventContext, FilterHandler, InitHandler } from '@directus/shared/types';
|
|
2
2
|
export declare class Emitter {
|
|
3
3
|
private filterEmitter;
|
|
4
4
|
private actionEmitter;
|
|
5
5
|
private initEmitter;
|
|
6
6
|
constructor();
|
|
7
|
-
emitFilter<T>(event: string, payload: T, meta: Record<string, any>, context:
|
|
8
|
-
emitAction(event: string, meta: Record<string, any>, context:
|
|
7
|
+
emitFilter<T>(event: string | string[], payload: T, meta: Record<string, any>, context: EventContext): Promise<T>;
|
|
8
|
+
emitAction(event: string | string[], meta: Record<string, any>, context: EventContext): void;
|
|
9
9
|
emitInit(event: string, meta: Record<string, any>): Promise<void>;
|
|
10
10
|
onFilter(event: string, handler: FilterHandler): void;
|
|
11
11
|
onAction(event: string, handler: ActionHandler): void;
|
|
@@ -14,7 +14,6 @@ export declare class Emitter {
|
|
|
14
14
|
offAction(event: string, handler: ActionHandler): void;
|
|
15
15
|
offInit(event: string, handler: InitHandler): void;
|
|
16
16
|
offAll(): void;
|
|
17
|
-
private eventsToEmit;
|
|
18
17
|
}
|
|
19
18
|
declare const emitter: Emitter;
|
|
20
19
|
export default emitter;
|
package/dist/emitter.js
CHANGED
|
@@ -20,7 +20,7 @@ class Emitter {
|
|
|
20
20
|
this.initEmitter = new eventemitter2_1.EventEmitter2(emitterOptions);
|
|
21
21
|
}
|
|
22
22
|
async emitFilter(event, payload, meta, context) {
|
|
23
|
-
const events =
|
|
23
|
+
const events = Array.isArray(event) ? event : [event];
|
|
24
24
|
const listeners = events.flatMap((event) => this.filterEmitter.listeners(event));
|
|
25
25
|
let updatedPayload = payload;
|
|
26
26
|
for (const listener of listeners) {
|
|
@@ -32,7 +32,7 @@ class Emitter {
|
|
|
32
32
|
return updatedPayload;
|
|
33
33
|
}
|
|
34
34
|
emitAction(event, meta, context) {
|
|
35
|
-
const events =
|
|
35
|
+
const events = Array.isArray(event) ? event : [event];
|
|
36
36
|
for (const event of events) {
|
|
37
37
|
this.actionEmitter.emitAsync(event, meta, context).catch((err) => {
|
|
38
38
|
logger_1.default.warn(`An error was thrown while executing action "${event}"`);
|
|
@@ -72,12 +72,6 @@ class Emitter {
|
|
|
72
72
|
this.actionEmitter.removeAllListeners();
|
|
73
73
|
this.initEmitter.removeAllListeners();
|
|
74
74
|
}
|
|
75
|
-
eventsToEmit(event, meta) {
|
|
76
|
-
if (event.startsWith('items')) {
|
|
77
|
-
return [event, `${meta.collection}.${event}`];
|
|
78
|
-
}
|
|
79
|
-
return [event];
|
|
80
|
-
}
|
|
81
75
|
}
|
|
82
76
|
exports.Emitter = Emitter;
|
|
83
77
|
const emitter = new Emitter();
|
package/dist/env.js
CHANGED
|
@@ -20,7 +20,7 @@ const defaults = {
|
|
|
20
20
|
PORT: 8055,
|
|
21
21
|
PUBLIC_URL: '/',
|
|
22
22
|
MAX_PAYLOAD_SIZE: '100kb',
|
|
23
|
-
DB_EXCLUDE_TABLES: 'spatial_ref_sys',
|
|
23
|
+
DB_EXCLUDE_TABLES: 'spatial_ref_sys,sysdiagrams',
|
|
24
24
|
STORAGE_LOCATIONS: 'local',
|
|
25
25
|
STORAGE_LOCAL_DRIVER: 'local',
|
|
26
26
|
STORAGE_LOCAL_ROOT: './uploads',
|
|
@@ -52,6 +52,7 @@ const defaults = {
|
|
|
52
52
|
AUTH_PROVIDERS: '',
|
|
53
53
|
AUTH_DISABLE_DEFAULT: false,
|
|
54
54
|
EXTENSIONS_PATH: './extensions',
|
|
55
|
+
EXTENSIONS_AUTO_RELOAD: false,
|
|
55
56
|
EMAIL_FROM: 'no-reply@directus.io',
|
|
56
57
|
EMAIL_TRANSPORT: 'sendmail',
|
|
57
58
|
EMAIL_SENDMAIL_NEW_LINE: 'unix',
|
|
@@ -61,6 +62,8 @@ const defaults = {
|
|
|
61
62
|
ASSETS_TRANSFORM_MAX_CONCURRENT: 1,
|
|
62
63
|
ASSETS_TRANSFORM_IMAGE_MAX_DIMENSION: 6000,
|
|
63
64
|
ASSETS_TRANSFORM_MAX_OPERATIONS: 5,
|
|
65
|
+
IP_TRUST_PROXY: true,
|
|
66
|
+
IP_CUSTOM_HEADER: false,
|
|
64
67
|
SERVE_APP: true,
|
|
65
68
|
};
|
|
66
69
|
// Allows us to force certain environment variable into a type, instead of relying
|
|
@@ -14,5 +14,6 @@ export * from './range-not-satisfiable';
|
|
|
14
14
|
export * from './route-not-found';
|
|
15
15
|
export * from './service-unavailable';
|
|
16
16
|
export * from './unprocessable-entity';
|
|
17
|
+
export * from './unsupported-media-type';
|
|
17
18
|
export * from './user-suspended';
|
|
18
19
|
export * from './unexpected-response';
|
package/dist/exceptions/index.js
CHANGED
|
@@ -26,5 +26,6 @@ __exportStar(require("./range-not-satisfiable"), exports);
|
|
|
26
26
|
__exportStar(require("./route-not-found"), exports);
|
|
27
27
|
__exportStar(require("./service-unavailable"), exports);
|
|
28
28
|
__exportStar(require("./unprocessable-entity"), exports);
|
|
29
|
+
__exportStar(require("./unsupported-media-type"), exports);
|
|
29
30
|
__exportStar(require("./user-suspended"), exports);
|
|
30
31
|
__exportStar(require("./unexpected-response"), exports);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UnsupportedMediaTypeException = void 0;
|
|
4
|
+
const exceptions_1 = require("@directus/shared/exceptions");
|
|
5
|
+
class UnsupportedMediaTypeException extends exceptions_1.BaseException {
|
|
6
|
+
constructor(message, extensions) {
|
|
7
|
+
super(message, 415, 'UNSUPPORTED_MEDIA_TYPE', extensions);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.UnsupportedMediaTypeException = UnsupportedMediaTypeException;
|
package/dist/extensions.d.ts
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
2
|
import { AppExtensionType, ExtensionType } from '@directus/shared/types';
|
|
3
3
|
export declare function getExtensionManager(): ExtensionManager;
|
|
4
|
+
declare type Options = {
|
|
5
|
+
schedule: boolean;
|
|
6
|
+
watch: boolean;
|
|
7
|
+
};
|
|
4
8
|
declare class ExtensionManager {
|
|
5
|
-
private
|
|
9
|
+
private isLoaded;
|
|
10
|
+
private options;
|
|
6
11
|
private extensions;
|
|
7
12
|
private appExtensions;
|
|
8
|
-
private
|
|
9
|
-
private apiEndpoints;
|
|
13
|
+
private apiExtensions;
|
|
10
14
|
private apiEmitter;
|
|
11
15
|
private endpointRouter;
|
|
12
|
-
private
|
|
16
|
+
private watcher;
|
|
13
17
|
constructor();
|
|
14
|
-
initialize(
|
|
15
|
-
schedule: boolean;
|
|
16
|
-
}): Promise<void>;
|
|
18
|
+
initialize(options?: Partial<Options>): Promise<void>;
|
|
17
19
|
reload(): Promise<void>;
|
|
18
|
-
|
|
20
|
+
getExtensionsList(type?: ExtensionType): string[];
|
|
19
21
|
getAppExtensions(type: AppExtensionType): string | undefined;
|
|
20
22
|
getEndpointRouter(): Router;
|
|
23
|
+
private load;
|
|
24
|
+
private unload;
|
|
25
|
+
private initializeWatcher;
|
|
26
|
+
private updateWatchedExtensions;
|
|
21
27
|
private getExtensions;
|
|
22
28
|
private generateExtensionBundles;
|
|
23
29
|
private getSharedDepsMapping;
|
package/dist/extensions.js
CHANGED
|
@@ -45,6 +45,8 @@ const plugin_alias_1 = __importDefault(require("@rollup/plugin-alias"));
|
|
|
45
45
|
const url_1 = require("./utils/url");
|
|
46
46
|
const get_module_default_1 = __importDefault(require("./utils/get-module-default"));
|
|
47
47
|
const lodash_1 = require("lodash");
|
|
48
|
+
const chokidar_1 = __importDefault(require("chokidar"));
|
|
49
|
+
const utils_1 = require("@directus/shared/utils");
|
|
48
50
|
let extensionManager;
|
|
49
51
|
function getExtensionManager() {
|
|
50
52
|
if (extensionManager) {
|
|
@@ -54,21 +56,73 @@ function getExtensionManager() {
|
|
|
54
56
|
return extensionManager;
|
|
55
57
|
}
|
|
56
58
|
exports.getExtensionManager = getExtensionManager;
|
|
59
|
+
const defaultOptions = {
|
|
60
|
+
schedule: true,
|
|
61
|
+
watch: env_1.default.EXTENSIONS_AUTO_RELOAD && env_1.default.NODE_ENV !== 'development',
|
|
62
|
+
};
|
|
57
63
|
class ExtensionManager {
|
|
58
64
|
constructor() {
|
|
59
|
-
this.
|
|
65
|
+
this.isLoaded = false;
|
|
60
66
|
this.extensions = [];
|
|
61
67
|
this.appExtensions = {};
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
64
|
-
this.
|
|
68
|
+
this.apiExtensions = { hooks: [], endpoints: [] };
|
|
69
|
+
this.watcher = null;
|
|
70
|
+
this.options = defaultOptions;
|
|
65
71
|
this.apiEmitter = new emitter_1.Emitter();
|
|
66
72
|
this.endpointRouter = (0, express_1.Router)();
|
|
67
73
|
}
|
|
68
|
-
async initialize(
|
|
69
|
-
this.
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
async initialize(options = {}) {
|
|
75
|
+
this.options = {
|
|
76
|
+
...defaultOptions,
|
|
77
|
+
...options,
|
|
78
|
+
};
|
|
79
|
+
this.initializeWatcher();
|
|
80
|
+
if (!this.isLoaded) {
|
|
81
|
+
await this.load();
|
|
82
|
+
this.updateWatchedExtensions(this.extensions);
|
|
83
|
+
const loadedExtensions = this.getExtensionsList();
|
|
84
|
+
if (loadedExtensions.length > 0) {
|
|
85
|
+
logger_1.default.info(`Loaded extensions: ${loadedExtensions.join(', ')}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async reload() {
|
|
90
|
+
if (this.isLoaded) {
|
|
91
|
+
logger_1.default.info('Reloading extensions');
|
|
92
|
+
const prevExtensions = (0, lodash_1.clone)(this.extensions);
|
|
93
|
+
await this.unload();
|
|
94
|
+
await this.load();
|
|
95
|
+
const added = this.extensions.filter((extension) => !prevExtensions.some((prevExtension) => extension.path === prevExtension.path));
|
|
96
|
+
const removed = prevExtensions.filter((prevExtension) => !this.extensions.some((extension) => prevExtension.path === extension.path));
|
|
97
|
+
this.updateWatchedExtensions(added, removed);
|
|
98
|
+
const addedExtensions = added.map((extension) => extension.name);
|
|
99
|
+
const removedExtensions = removed.map((extension) => extension.name);
|
|
100
|
+
if (addedExtensions.length > 0) {
|
|
101
|
+
logger_1.default.info(`Added extensions: ${addedExtensions.join(', ')}`);
|
|
102
|
+
}
|
|
103
|
+
if (removedExtensions.length > 0) {
|
|
104
|
+
logger_1.default.info(`Removed extensions: ${removedExtensions.join(', ')}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
logger_1.default.warn('Extensions have to be loaded before they can be reloaded');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
getExtensionsList(type) {
|
|
112
|
+
if (type === undefined) {
|
|
113
|
+
return this.extensions.map((extension) => extension.name);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
return this.extensions.filter((extension) => extension.type === type).map((extension) => extension.name);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
getAppExtensions(type) {
|
|
120
|
+
return this.appExtensions[type];
|
|
121
|
+
}
|
|
122
|
+
getEndpointRouter() {
|
|
123
|
+
return this.endpointRouter;
|
|
124
|
+
}
|
|
125
|
+
async load() {
|
|
72
126
|
try {
|
|
73
127
|
await (0, node_1.ensureExtensionDirs)(env_1.default.EXTENSIONS_PATH, env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES);
|
|
74
128
|
this.extensions = await this.getExtensions();
|
|
@@ -82,38 +136,42 @@ class ExtensionManager {
|
|
|
82
136
|
if (env_1.default.SERVE_APP) {
|
|
83
137
|
this.appExtensions = await this.generateExtensionBundles();
|
|
84
138
|
}
|
|
85
|
-
|
|
86
|
-
if (loadedExtensions.length > 0) {
|
|
87
|
-
logger_1.default.info(`Loaded extensions: ${loadedExtensions.join(', ')}`);
|
|
88
|
-
}
|
|
89
|
-
this.isInitialized = true;
|
|
139
|
+
this.isLoaded = true;
|
|
90
140
|
}
|
|
91
|
-
async
|
|
92
|
-
if (!this.isInitialized)
|
|
93
|
-
return;
|
|
94
|
-
logger_1.default.info('Reloading extensions');
|
|
141
|
+
async unload() {
|
|
95
142
|
this.unregisterHooks();
|
|
96
143
|
this.unregisterEndpoints();
|
|
97
144
|
this.apiEmitter.offAll();
|
|
98
145
|
if (env_1.default.SERVE_APP) {
|
|
99
146
|
this.appExtensions = {};
|
|
100
147
|
}
|
|
101
|
-
this.
|
|
102
|
-
await this.initialize();
|
|
148
|
+
this.isLoaded = false;
|
|
103
149
|
}
|
|
104
|
-
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
150
|
+
initializeWatcher() {
|
|
151
|
+
if (this.options.watch && !this.watcher) {
|
|
152
|
+
logger_1.default.info('Watching extensions for changes...');
|
|
153
|
+
const localExtensionPaths = (env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES).map((type) => path_1.default.posix.join(path_1.default.relative('.', env_1.default.EXTENSIONS_PATH).split(path_1.default.sep).join(path_1.default.posix.sep), (0, utils_1.pluralize)(type), '*', 'index.js'));
|
|
154
|
+
this.watcher = chokidar_1.default.watch([path_1.default.resolve('.', 'package.json'), ...localExtensionPaths], {
|
|
155
|
+
ignoreInitial: true,
|
|
156
|
+
});
|
|
157
|
+
this.watcher
|
|
158
|
+
.on('add', () => this.reload())
|
|
159
|
+
.on('change', () => this.reload())
|
|
160
|
+
.on('unlink', () => this.reload());
|
|
110
161
|
}
|
|
111
162
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
163
|
+
updateWatchedExtensions(added, removed = []) {
|
|
164
|
+
if (this.watcher) {
|
|
165
|
+
const toPackageExtensionPaths = (extensions) => extensions
|
|
166
|
+
.filter((extension) => !extension.local)
|
|
167
|
+
.map((extension) => extension.type !== 'pack'
|
|
168
|
+
? path_1.default.resolve(extension.path, extension.entrypoint || '')
|
|
169
|
+
: path_1.default.resolve(extension.path, 'package.json'));
|
|
170
|
+
const addedPackageExtensionPaths = toPackageExtensionPaths(added);
|
|
171
|
+
const removedPackageExtensionPaths = toPackageExtensionPaths(removed);
|
|
172
|
+
this.watcher.add(addedPackageExtensionPaths);
|
|
173
|
+
this.watcher.unwatch(removedPackageExtensionPaths);
|
|
174
|
+
}
|
|
117
175
|
}
|
|
118
176
|
async getExtensions() {
|
|
119
177
|
const packageExtensions = await (0, node_1.getPackageExtensions)('.', env_1.default.SERVE_APP ? constants_1.EXTENSION_PACKAGE_TYPES : constants_1.API_EXTENSION_PACKAGE_TYPES);
|
|
@@ -129,15 +187,21 @@ class ExtensionManager {
|
|
|
129
187
|
const bundles = {};
|
|
130
188
|
for (const extensionType of constants_1.APP_EXTENSION_TYPES) {
|
|
131
189
|
const entry = (0, node_1.generateExtensionsEntry)(extensionType, this.extensions);
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
190
|
+
try {
|
|
191
|
+
const bundle = await (0, rollup_1.rollup)({
|
|
192
|
+
input: 'entry',
|
|
193
|
+
external: Object.values(sharedDepsMapping),
|
|
194
|
+
makeAbsoluteExternalsRelative: false,
|
|
195
|
+
plugins: [(0, plugin_virtual_1.default)({ entry }), (0, plugin_alias_1.default)({ entries: internalImports })],
|
|
196
|
+
});
|
|
197
|
+
const { output } = await bundle.generate({ format: 'es', compact: true });
|
|
198
|
+
bundles[extensionType] = output[0].code;
|
|
199
|
+
await bundle.close();
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
logger_1.default.warn(`Couldn't bundle App extensions`);
|
|
203
|
+
logger_1.default.warn(error);
|
|
204
|
+
}
|
|
141
205
|
}
|
|
142
206
|
return bundles;
|
|
143
207
|
}
|
|
@@ -185,38 +249,39 @@ class ExtensionManager {
|
|
|
185
249
|
const hookPath = path_1.default.resolve(hook.path, hook.entrypoint || '');
|
|
186
250
|
const hookInstance = require(hookPath);
|
|
187
251
|
const register = (0, get_module_default_1.default)(hookInstance);
|
|
252
|
+
const hookHandler = {
|
|
253
|
+
path: hookPath,
|
|
254
|
+
events: [],
|
|
255
|
+
};
|
|
188
256
|
const registerFunctions = {
|
|
189
257
|
filter: (event, handler) => {
|
|
190
258
|
emitter_1.default.onFilter(event, handler);
|
|
191
|
-
|
|
259
|
+
hookHandler.events.push({
|
|
192
260
|
type: 'filter',
|
|
193
|
-
|
|
194
|
-
event,
|
|
261
|
+
name: event,
|
|
195
262
|
handler,
|
|
196
263
|
});
|
|
197
264
|
},
|
|
198
265
|
action: (event, handler) => {
|
|
199
266
|
emitter_1.default.onAction(event, handler);
|
|
200
|
-
|
|
267
|
+
hookHandler.events.push({
|
|
201
268
|
type: 'action',
|
|
202
|
-
|
|
203
|
-
event,
|
|
269
|
+
name: event,
|
|
204
270
|
handler,
|
|
205
271
|
});
|
|
206
272
|
},
|
|
207
273
|
init: (event, handler) => {
|
|
208
274
|
emitter_1.default.onInit(event, handler);
|
|
209
|
-
|
|
275
|
+
hookHandler.events.push({
|
|
210
276
|
type: 'init',
|
|
211
|
-
|
|
212
|
-
event,
|
|
277
|
+
name: event,
|
|
213
278
|
handler,
|
|
214
279
|
});
|
|
215
280
|
},
|
|
216
281
|
schedule: (cron, handler) => {
|
|
217
282
|
if ((0, node_cron_1.validate)(cron)) {
|
|
218
283
|
const task = (0, node_cron_1.schedule)(cron, async () => {
|
|
219
|
-
if (this.
|
|
284
|
+
if (this.options.schedule) {
|
|
220
285
|
try {
|
|
221
286
|
await handler();
|
|
222
287
|
}
|
|
@@ -225,9 +290,8 @@ class ExtensionManager {
|
|
|
225
290
|
}
|
|
226
291
|
}
|
|
227
292
|
});
|
|
228
|
-
|
|
293
|
+
hookHandler.events.push({
|
|
229
294
|
type: 'schedule',
|
|
230
|
-
path: hookPath,
|
|
231
295
|
task,
|
|
232
296
|
});
|
|
233
297
|
}
|
|
@@ -245,6 +309,7 @@ class ExtensionManager {
|
|
|
245
309
|
logger: logger_1.default,
|
|
246
310
|
getSchema: get_schema_1.getSchema,
|
|
247
311
|
});
|
|
312
|
+
this.apiExtensions.hooks.push(hookHandler);
|
|
248
313
|
}
|
|
249
314
|
registerEndpoint(endpoint, router) {
|
|
250
315
|
const endpointPath = path_1.default.resolve(endpoint.path, endpoint.entrypoint || '');
|
|
@@ -263,35 +328,37 @@ class ExtensionManager {
|
|
|
263
328
|
logger: logger_1.default,
|
|
264
329
|
getSchema: get_schema_1.getSchema,
|
|
265
330
|
});
|
|
266
|
-
this.
|
|
331
|
+
this.apiExtensions.endpoints.push({
|
|
267
332
|
path: endpointPath,
|
|
268
333
|
});
|
|
269
334
|
}
|
|
270
335
|
unregisterHooks() {
|
|
271
|
-
for (const hook of this.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
336
|
+
for (const hook of this.apiExtensions.hooks) {
|
|
337
|
+
for (const event of hook.events) {
|
|
338
|
+
switch (event.type) {
|
|
339
|
+
case 'filter':
|
|
340
|
+
emitter_1.default.offFilter(event.name, event.handler);
|
|
341
|
+
break;
|
|
342
|
+
case 'action':
|
|
343
|
+
emitter_1.default.offAction(event.name, event.handler);
|
|
344
|
+
break;
|
|
345
|
+
case 'init':
|
|
346
|
+
emitter_1.default.offInit(event.name, event.handler);
|
|
347
|
+
break;
|
|
348
|
+
case 'schedule':
|
|
349
|
+
event.task.stop();
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
285
352
|
}
|
|
286
353
|
delete require.cache[require.resolve(hook.path)];
|
|
287
354
|
}
|
|
288
|
-
this.
|
|
355
|
+
this.apiExtensions.hooks = [];
|
|
289
356
|
}
|
|
290
357
|
unregisterEndpoints() {
|
|
291
|
-
for (const endpoint of this.
|
|
358
|
+
for (const endpoint of this.apiExtensions.endpoints) {
|
|
292
359
|
delete require.cache[require.resolve(endpoint.path)];
|
|
293
360
|
}
|
|
294
361
|
this.endpointRouter.stack = [];
|
|
295
|
-
this.
|
|
362
|
+
this.apiExtensions.endpoints = [];
|
|
296
363
|
}
|
|
297
364
|
}
|
package/dist/logger.js
CHANGED
|
@@ -25,6 +25,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
25
25
|
exports.expressLogger = void 0;
|
|
26
26
|
const pino_1 = __importDefault(require("pino"));
|
|
27
27
|
const pino_http_1 = __importStar(require("pino-http"));
|
|
28
|
+
const get_config_from_env_1 = require("./utils/get-config-from-env");
|
|
28
29
|
const url_1 = require("url");
|
|
29
30
|
const env_1 = __importDefault(require("./env"));
|
|
30
31
|
const pinoOptions = {
|
|
@@ -38,9 +39,29 @@ if (env_1.default.LOG_STYLE !== 'raw') {
|
|
|
38
39
|
pinoOptions.prettyPrint = true;
|
|
39
40
|
pinoOptions.prettifier = require('pino-colada');
|
|
40
41
|
}
|
|
41
|
-
const
|
|
42
|
+
const loggerEnvConfig = (0, get_config_from_env_1.getConfigFromEnv)('LOGGER_', 'LOGGER_HTTP');
|
|
43
|
+
// Expose custom log levels into formatter function
|
|
44
|
+
if (loggerEnvConfig.levels) {
|
|
45
|
+
const customLogLevels = {};
|
|
46
|
+
for (const el of loggerEnvConfig.levels.split(',')) {
|
|
47
|
+
const key_val = el.split(':');
|
|
48
|
+
customLogLevels[key_val[0].trim()] = key_val[1].trim();
|
|
49
|
+
}
|
|
50
|
+
pinoOptions.formatters = {
|
|
51
|
+
level(label, number) {
|
|
52
|
+
return {
|
|
53
|
+
severity: customLogLevels[label] || 'info',
|
|
54
|
+
level: number,
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
delete loggerEnvConfig.levels;
|
|
59
|
+
}
|
|
60
|
+
const logger = (0, pino_1.default)(Object.assign(pinoOptions, loggerEnvConfig));
|
|
61
|
+
const httpLoggerEnvConfig = (0, get_config_from_env_1.getConfigFromEnv)('LOGGER_HTTP', ['LOGGER_HTTP_LOGGER']);
|
|
42
62
|
exports.expressLogger = (0, pino_http_1.default)({
|
|
43
63
|
logger,
|
|
64
|
+
...httpLoggerEnvConfig,
|
|
44
65
|
}, {
|
|
45
66
|
serializers: {
|
|
46
67
|
req(request) {
|