directus 9.14.5 → 9.16.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 (129) hide show
  1. package/dist/__utils__/items-utils.d.ts +2 -0
  2. package/dist/__utils__/items-utils.js +36 -0
  3. package/dist/__utils__/schemas.d.ts +13 -0
  4. package/dist/__utils__/schemas.js +304 -0
  5. package/dist/__utils__/snapshots.d.ts +5 -0
  6. package/dist/__utils__/snapshots.js +897 -0
  7. package/dist/app.js +2 -1
  8. package/dist/auth/drivers/ldap.js +18 -8
  9. package/dist/auth/drivers/oauth2.js +19 -9
  10. package/dist/auth/drivers/openid.js +19 -9
  11. package/dist/cache.d.ts +3 -0
  12. package/dist/cache.js +21 -2
  13. package/dist/cli/index.test.d.ts +1 -0
  14. package/dist/cli/index.test.js +58 -0
  15. package/dist/cli/utils/create-env/env-stub.liquid +2 -2
  16. package/dist/constants.d.ts +1 -0
  17. package/dist/constants.js +2 -1
  18. package/dist/controllers/assets.js +27 -1
  19. package/dist/controllers/extensions.js +3 -2
  20. package/dist/controllers/files.test.d.ts +1 -0
  21. package/dist/controllers/files.test.js +49 -0
  22. package/dist/controllers/server.js +0 -1
  23. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +3 -14
  24. package/dist/database/helpers/schema/dialects/cockroachdb.js +2 -8
  25. package/dist/database/helpers/schema/dialects/oracle.d.ts +3 -10
  26. package/dist/database/helpers/schema/dialects/oracle.js +2 -5
  27. package/dist/database/helpers/schema/types.d.ts +8 -18
  28. package/dist/database/helpers/schema/types.js +7 -36
  29. package/dist/database/migrations/20201105B-change-webhook-url-type.js +3 -2
  30. package/dist/database/migrations/20210312A-webhooks-collections-text.js +3 -2
  31. package/dist/database/migrations/20210415A-make-filesize-nullable.js +2 -2
  32. package/dist/database/migrations/20210510A-restructure-relations.js +3 -3
  33. package/dist/database/migrations/20210903A-add-auth-provider.js +2 -2
  34. package/dist/database/migrations/20210907A-webhooks-collections-not-null.js +4 -2
  35. package/dist/database/migrations/20210920A-webhooks-url-not-null.js +2 -2
  36. package/dist/database/migrations/20220303A-remove-default-project-color.js +2 -2
  37. package/dist/database/migrations/20220325B-add-default-language.js +2 -2
  38. package/dist/database/migrations/20220402A-remove-default-value-panel-icon.js +2 -2
  39. package/dist/database/migrations/20220801A-update-notifications-timestamp-column.d.ts +3 -0
  40. package/dist/database/migrations/20220801A-update-notifications-timestamp-column.js +19 -0
  41. package/dist/database/migrations/20220802A-add-custom-aspect-ratios.d.ts +3 -0
  42. package/dist/database/migrations/20220802A-add-custom-aspect-ratios.js +15 -0
  43. package/dist/database/migrations/run.test.d.ts +1 -0
  44. package/dist/database/migrations/run.test.js +92 -0
  45. package/dist/database/system-data/fields/settings.yaml +33 -0
  46. package/dist/env.js +8 -0
  47. package/dist/env.test.d.ts +8 -0
  48. package/dist/env.test.js +39 -0
  49. package/dist/extensions.d.ts +2 -2
  50. package/dist/extensions.js +10 -9
  51. package/dist/flows.js +2 -1
  52. package/dist/logger.js +0 -1
  53. package/dist/middleware/authenticate.test.d.ts +1 -0
  54. package/dist/middleware/authenticate.test.js +174 -0
  55. package/dist/middleware/cache.js +3 -3
  56. package/dist/middleware/extract-token.test.d.ts +1 -0
  57. package/dist/middleware/extract-token.test.js +60 -0
  58. package/dist/middleware/respond.js +2 -2
  59. package/dist/operations/exec/index.d.ts +5 -0
  60. package/dist/operations/exec/index.js +26 -0
  61. package/dist/operations/exec/index.test.d.ts +1 -0
  62. package/dist/operations/exec/index.test.js +95 -0
  63. package/dist/operations/item-create/index.js +1 -1
  64. package/dist/operations/item-delete/index.js +2 -2
  65. package/dist/operations/item-read/index.js +2 -2
  66. package/dist/operations/item-update/index.js +3 -3
  67. package/dist/operations/notification/index.js +9 -6
  68. package/dist/operations/request/index.js +22 -3
  69. package/dist/services/assets.d.ts +1 -1
  70. package/dist/services/assets.js +7 -2
  71. package/dist/services/authorization.js +2 -1
  72. package/dist/services/files.js +3 -2
  73. package/dist/services/files.test.d.ts +1 -0
  74. package/dist/services/files.test.js +53 -0
  75. package/dist/services/flows.js +4 -0
  76. package/dist/services/graphql/index.d.ts +2 -2
  77. package/dist/services/graphql/index.js +59 -40
  78. package/dist/services/graphql/types/hash.d.ts +2 -0
  79. package/dist/services/graphql/types/hash.js +9 -0
  80. package/dist/services/items.js +83 -39
  81. package/dist/services/items.test.d.ts +1 -0
  82. package/dist/services/items.test.js +765 -0
  83. package/dist/services/payload.d.ts +7 -4
  84. package/dist/services/payload.js +35 -8
  85. package/dist/services/payload.test.d.ts +1 -0
  86. package/dist/services/payload.test.js +94 -0
  87. package/dist/services/server.js +5 -3
  88. package/dist/services/specifications.js +1 -6
  89. package/dist/services/specifications.test.d.ts +1 -0
  90. package/dist/services/specifications.test.js +96 -0
  91. package/dist/types/items.d.ts +11 -0
  92. package/dist/utils/apply-query.js +15 -0
  93. package/dist/utils/apply-snapshot.js +15 -0
  94. package/dist/utils/apply-snapshot.test.d.ts +1 -0
  95. package/dist/utils/apply-snapshot.test.js +305 -0
  96. package/dist/utils/calculate-field-depth.test.d.ts +1 -0
  97. package/dist/utils/calculate-field-depth.test.js +76 -0
  98. package/dist/utils/compress.d.ts +3 -0
  99. package/dist/utils/compress.js +17 -0
  100. package/dist/utils/filter-items.test.d.ts +1 -0
  101. package/dist/utils/filter-items.test.js +60 -0
  102. package/dist/utils/get-ast-from-query.js +1 -1
  103. package/dist/utils/get-cache-key.test.d.ts +1 -0
  104. package/dist/utils/get-cache-key.test.js +53 -0
  105. package/dist/utils/get-column-path.test.d.ts +1 -0
  106. package/dist/utils/get-column-path.test.js +136 -0
  107. package/dist/utils/get-config-from-env.test.d.ts +1 -0
  108. package/dist/utils/get-config-from-env.test.js +19 -0
  109. package/dist/utils/get-graphql-type.d.ts +1 -1
  110. package/dist/utils/get-graphql-type.js +7 -1
  111. package/dist/utils/get-os-info.d.ts +9 -0
  112. package/dist/utils/get-os-info.js +47 -0
  113. package/dist/utils/get-permissions.js +2 -2
  114. package/dist/utils/get-relation-info.test.d.ts +1 -0
  115. package/dist/utils/get-relation-info.test.js +88 -0
  116. package/dist/utils/get-relation-type.test.d.ts +1 -0
  117. package/dist/utils/get-relation-type.test.js +69 -0
  118. package/dist/utils/get-schema.js +1 -2
  119. package/dist/utils/get-string-byte-size.test.d.ts +1 -0
  120. package/dist/utils/get-string-byte-size.test.js +8 -0
  121. package/dist/utils/is-directus-jwt.test.d.ts +1 -0
  122. package/dist/utils/is-directus-jwt.test.js +26 -0
  123. package/dist/utils/jwt.test.d.ts +1 -0
  124. package/dist/utils/jwt.test.js +36 -0
  125. package/dist/utils/merge-permissions.test.d.ts +1 -0
  126. package/dist/utils/merge-permissions.test.js +80 -0
  127. package/dist/utils/validate-keys.test.d.ts +1 -0
  128. package/dist/utils/validate-keys.test.js +97 -0
  129. package/package.json +12 -11
@@ -4,7 +4,7 @@ exports.down = exports.up = void 0;
4
4
  const helpers_1 = require("../helpers");
5
5
  async function up(knex) {
6
6
  const helper = (0, helpers_1.getHelpers)(knex).schema;
7
- await helper.changeToInteger('directus_files', 'filesize', {
7
+ await helper.changeToType('directus_files', 'filesize', 'integer', {
8
8
  nullable: true,
9
9
  default: null,
10
10
  });
@@ -12,7 +12,7 @@ async function up(knex) {
12
12
  exports.up = up;
13
13
  async function down(knex) {
14
14
  const helper = (0, helpers_1.getHelpers)(knex).schema;
15
- await helper.changeToInteger('directus_files', 'filesize', {
15
+ await helper.changeToType('directus_files', 'filesize', 'integer', {
16
16
  nullable: false,
17
17
  default: 0,
18
18
  });
@@ -9,10 +9,10 @@ async function up(knex) {
9
9
  table.string('one_deselect_action').defaultTo('nullify');
10
10
  });
11
11
  await knex('directus_relations').update({ one_deselect_action: 'nullify' });
12
- await helper.changeToString('directus_relations', 'sort_field', {
12
+ await helper.changeToType('directus_relations', 'sort_field', 'string', {
13
13
  length: 64,
14
14
  });
15
- await helper.changeToString('directus_relations', 'one_deselect_action', {
15
+ await helper.changeToType('directus_relations', 'one_deselect_action', 'string', {
16
16
  nullable: false,
17
17
  default: 'nullify',
18
18
  });
@@ -20,7 +20,7 @@ async function up(knex) {
20
20
  exports.up = up;
21
21
  async function down(knex) {
22
22
  const helper = (0, helpers_1.getHelpers)(knex).schema;
23
- await helper.changeToString('directus_relations', 'sort_field', {
23
+ await helper.changeToType('directus_relations', 'sort_field', 'string', {
24
24
  length: 255,
25
25
  });
26
26
  await knex.schema.alterTable('directus_relations', (table) => {
@@ -11,7 +11,7 @@ async function up(knex) {
11
11
  table.string('provider', 128).notNullable().defaultTo('default');
12
12
  table.string('external_identifier').unique();
13
13
  });
14
- await helper.changeToString('directus_users', 'email', {
14
+ await helper.changeToType('directus_users', 'email', 'string', {
15
15
  nullable: true,
16
16
  length: 128,
17
17
  });
@@ -29,7 +29,7 @@ async function down(knex) {
29
29
  table.dropColumn('provider');
30
30
  table.dropColumn('external_identifier');
31
31
  });
32
- await helper.changeToString('directus_users', 'email', {
32
+ await helper.changeToType('directus_users', 'email', 'string', {
33
33
  nullable: false,
34
34
  length: 128,
35
35
  });
@@ -4,13 +4,15 @@ exports.down = exports.up = void 0;
4
4
  const helpers_1 = require("../helpers");
5
5
  async function up(knex) {
6
6
  const helper = (0, helpers_1.getHelpers)(knex).schema;
7
- await helper.changeToText('directus_webhooks', 'collections', {
7
+ const type = helper.isOneOfClients(['oracle', 'cockroachdb']) ? 'text' : 'string';
8
+ await helper.changeToType('directus_webhooks', 'collections', type, {
8
9
  nullable: false,
9
10
  });
10
11
  }
11
12
  exports.up = up;
12
13
  async function down(knex) {
13
14
  const helper = (0, helpers_1.getHelpers)(knex).schema;
14
- await helper.changeToText('directus_webhooks', 'collections');
15
+ const type = helper.isOneOfClients(['oracle', 'cockroachdb']) ? 'text' : 'string';
16
+ await helper.changeToType('directus_webhooks', 'collections', type);
15
17
  }
16
18
  exports.down = down;
@@ -9,7 +9,7 @@ async function up(knex) {
9
9
  // "20201105B-change-webhook-url-type.ts"
10
10
  return;
11
11
  }
12
- await helper.changeToText('directus_webhooks', 'url', {
12
+ await helper.changeToType('directus_webhooks', 'url', 'string', {
13
13
  nullable: false,
14
14
  });
15
15
  }
@@ -21,6 +21,6 @@ async function down(knex) {
21
21
  // "20201105B-change-webhook-url-type.ts"
22
22
  return;
23
23
  }
24
- await helper.changeToText('directus_webhooks', 'url');
24
+ await helper.changeToType('directus_webhooks', 'url', 'string');
25
25
  }
26
26
  exports.down = down;
@@ -4,7 +4,7 @@ exports.down = exports.up = void 0;
4
4
  const helpers_1 = require("../helpers");
5
5
  async function up(knex) {
6
6
  const helper = (0, helpers_1.getHelpers)(knex).schema;
7
- await helper.changeToString('directus_settings', 'project_color', {
7
+ await helper.changeToType('directus_settings', 'project_color', 'string', {
8
8
  nullable: true,
9
9
  default: null,
10
10
  length: 50,
@@ -13,7 +13,7 @@ async function up(knex) {
13
13
  exports.up = up;
14
14
  async function down(knex) {
15
15
  const helper = (0, helpers_1.getHelpers)(knex).schema;
16
- await helper.changeToString('directus_settings', 'project_color', {
16
+ await helper.changeToType('directus_settings', 'project_color', 'string', {
17
17
  nullable: true,
18
18
  default: '#00C897',
19
19
  length: 10,
@@ -7,7 +7,7 @@ async function up(knex) {
7
7
  await knex.schema.alterTable('directus_settings', (table) => {
8
8
  table.string('default_language').notNullable().defaultTo('en-US');
9
9
  });
10
- await helper.changeToString('directus_users', 'language', {
10
+ await helper.changeToType('directus_users', 'language', 'string', {
11
11
  nullable: true,
12
12
  default: null,
13
13
  length: 255,
@@ -19,7 +19,7 @@ async function down(knex) {
19
19
  await knex.schema.alterTable('directus_settings', (table) => {
20
20
  table.dropColumn('default_language');
21
21
  });
22
- await helper.changeToString('directus_users', 'language', {
22
+ await helper.changeToType('directus_users', 'language', 'string', {
23
23
  nullable: true,
24
24
  default: 'en-US',
25
25
  length: 255,
@@ -4,7 +4,7 @@ exports.down = exports.up = void 0;
4
4
  const helpers_1 = require("../helpers");
5
5
  async function up(knex) {
6
6
  const helper = (0, helpers_1.getHelpers)(knex).schema;
7
- await helper.changeToString('directus_panels', 'icon', {
7
+ await helper.changeToType('directus_panels', 'icon', 'string', {
8
8
  nullable: true,
9
9
  default: null,
10
10
  length: 30,
@@ -13,7 +13,7 @@ async function up(knex) {
13
13
  exports.up = up;
14
14
  async function down(knex) {
15
15
  const helper = (0, helpers_1.getHelpers)(knex).schema;
16
- await helper.changeToString('directus_panels', 'icon', {
16
+ await helper.changeToType('directus_panels', 'icon', 'string', {
17
17
  nullable: true,
18
18
  default: 'insert_chart',
19
19
  length: 30,
@@ -0,0 +1,3 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.down = exports.up = void 0;
4
+ const helpers_1 = require("../helpers");
5
+ async function up(knex) {
6
+ const helper = (0, helpers_1.getHelpers)(knex).schema;
7
+ await helper.changeToType('directus_notifications', 'timestamp', 'timestamp', {
8
+ nullable: true,
9
+ default: knex.fn.now(),
10
+ });
11
+ }
12
+ exports.up = up;
13
+ async function down(knex) {
14
+ const helper = (0, helpers_1.getHelpers)(knex).schema;
15
+ await helper.changeToType('directus_notifications', 'timestamp', 'timestamp', {
16
+ nullable: false,
17
+ });
18
+ }
19
+ exports.down = down;
@@ -0,0 +1,3 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
@@ -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.json('custom_aspect_ratios');
7
+ });
8
+ }
9
+ exports.up = up;
10
+ async function down(knex) {
11
+ await knex.schema.alterTable('directus_settings', (table) => {
12
+ table.dropColumn('custom_aspect_ratios');
13
+ });
14
+ }
15
+ exports.down = down;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const knex_1 = __importDefault(require("knex"));
7
+ const knex_mock_client_1 = require("knex-mock-client");
8
+ const run_1 = __importDefault(require("./run"));
9
+ describe('run', () => {
10
+ let db;
11
+ let tracker;
12
+ beforeAll(() => {
13
+ db = (0, knex_1.default)({ client: knex_mock_client_1.MockClient });
14
+ tracker = (0, knex_mock_client_1.getTracker)();
15
+ });
16
+ afterEach(() => {
17
+ tracker.reset();
18
+ });
19
+ describe('when passed the argument up', () => {
20
+ it('returns "Nothing To Upgrade" if no directus_migrations', async () => {
21
+ tracker.on.select('directus_migrations').response(['Empty']);
22
+ await (0, run_1.default)(db, 'up').catch((e) => {
23
+ expect(e).toBeInstanceOf(Error);
24
+ expect(e.message).toBe('Nothing to upgrade');
25
+ });
26
+ });
27
+ it('returns "Method implemented in the dialect driver" if no directus_migrations', async () => {
28
+ tracker.on.select('directus_migrations').response([]);
29
+ await (0, run_1.default)(db, 'up').catch((e) => {
30
+ expect(e).toBeInstanceOf(Error);
31
+ expect(e.message).toBe('Method implemented in the dialect driver');
32
+ });
33
+ });
34
+ it('returns undefined if the migration is successful', async () => {
35
+ tracker.on.select('directus_migrations').response([
36
+ {
37
+ version: '20201028A',
38
+ name: 'Remove Collection Foreign Keys',
39
+ timestamp: '2021-11-27 11:36:56.471595-05',
40
+ },
41
+ ]);
42
+ tracker.on.delete('directus_relations').response([]);
43
+ tracker.on.insert('directus_migrations').response(['Remove System Relations', '20201029A']);
44
+ expect(await (0, run_1.default)(db, 'up')).toBe(undefined);
45
+ });
46
+ });
47
+ describe('when passed the argument down', () => {
48
+ it('returns "Nothing To downgrade" if no valid directus_migrations', async () => {
49
+ tracker.on.select('directus_migrations').response(['Empty']);
50
+ await (0, run_1.default)(db, 'down').catch((e) => {
51
+ expect(e).toBeInstanceOf(Error);
52
+ expect(e.message).toBe(`Couldn't find migration`);
53
+ });
54
+ });
55
+ it('returns "Method implemented in the dialect driver" if no directus_migrations', async () => {
56
+ tracker.on.select('directus_migrations').response([]);
57
+ await (0, run_1.default)(db, 'down').catch((e) => {
58
+ expect(e).toBeInstanceOf(Error);
59
+ expect(e.message).toBe('Nothing to downgrade');
60
+ });
61
+ });
62
+ it(`returns "Couldn't find migration" if an invalid migration object is supplied`, async () => {
63
+ tracker.on.select('directus_migrations').response([
64
+ {
65
+ version: '202018129A',
66
+ name: 'Fake Migration',
67
+ timestamp: '2020-00-32 11:36:56.471595-05',
68
+ },
69
+ ]);
70
+ await (0, run_1.default)(db, 'down').catch((e) => {
71
+ expect(e).toBeInstanceOf(Error);
72
+ expect(e.message).toBe(`Couldn't find migration`);
73
+ });
74
+ });
75
+ });
76
+ describe('when passed the argument latest', () => {
77
+ it('returns "Nothing To downgrade" if no valid directus_migrations', async () => {
78
+ tracker.on.select('directus_migrations').response(['Empty']);
79
+ await (0, run_1.default)(db, 'latest').catch((e) => {
80
+ expect(e).toBeInstanceOf(Error);
81
+ expect(e.message).toBe(`Method implemented in the dialect driver`);
82
+ });
83
+ });
84
+ it('returns "Method implemented in the dialect driver" if no directus_migrations', async () => {
85
+ tracker.on.select('directus_migrations').response([]);
86
+ await (0, run_1.default)(db, 'latest').catch((e) => {
87
+ expect(e).toBeInstanceOf(Error);
88
+ expect(e.message).toBe('Method implemented in the dialect driver');
89
+ });
90
+ });
91
+ });
92
+ });
@@ -392,3 +392,36 @@ fields:
392
392
  - field: translation_strings
393
393
  special: cast-json
394
394
  hidden: true
395
+
396
+ - field: image_editor
397
+ interface: presentation-divider
398
+ options:
399
+ icon: image
400
+ title: $t:fields.directus_settings.image_editor
401
+ special:
402
+ - alias
403
+ - no-data
404
+ width: full
405
+
406
+ - field: custom_aspect_ratios
407
+ interface: list
408
+ special: cast-json
409
+ options:
410
+ template: '{{text}}'
411
+ fields:
412
+ - field: text
413
+ name: $t:text
414
+ type: string
415
+ meta:
416
+ interface: text-input
417
+ width: half
418
+ options:
419
+ placeholder: $t:text
420
+ - field: value
421
+ name: $t:value
422
+ type: float
423
+ meta:
424
+ interface: input
425
+ width: half
426
+ options:
427
+ placeholder: $t:value
package/dist/env.js CHANGED
@@ -138,6 +138,13 @@ const allowedEnvironmentVars = [
138
138
  // extensions
139
139
  'EXTENSIONS_PATH',
140
140
  'EXTENSIONS_AUTO_RELOAD',
141
+ // messenger
142
+ 'MESSENGER_STORE',
143
+ 'MESSENGER_NAMESPACE',
144
+ 'MESSENGER_REDIS',
145
+ 'MESSENGER_REDIS_HOST',
146
+ 'MESSENGER_REDIS_PORT',
147
+ 'MESSENGER_REDIS_PASSWORD',
141
148
  // emails
142
149
  'EMAIL_FROM',
143
150
  'EMAIL_TRANSPORT',
@@ -226,6 +233,7 @@ const defaults = {
226
233
  EXPORT_BATCH_SIZE: 5000,
227
234
  FILE_METADATA_ALLOW_LIST: 'ifd0.Make,ifd0.Model,exif.FNumber,exif.ExposureTime,exif.FocalLength,exif.ISO',
228
235
  GRAPHQL_INTROSPECTION: true,
236
+ FLOWS_EXEC_ALLOWED_MODULES: false,
229
237
  };
230
238
  // Allows us to force certain environment variable into a type, instead of relying
231
239
  // on the auto-parsed type in processValues. ref #3705
@@ -0,0 +1,8 @@
1
+ declare const testEnv: {
2
+ NUMBER: string;
3
+ NUMBER_CAST_AS_STRING: string;
4
+ REGEX: string;
5
+ CSV: string;
6
+ CSV_CAST_AS_STRING: string;
7
+ MULTIPLE: string;
8
+ };
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ const testEnv = {
3
+ NUMBER: '1234',
4
+ NUMBER_CAST_AS_STRING: 'string:1234',
5
+ REGEX: 'regex:\\.example\\.com$',
6
+ CSV: 'one,two,three,four',
7
+ CSV_CAST_AS_STRING: 'string:one,two,three,four',
8
+ MULTIPLE: 'array:string:https://example.com,regex:\\.example2\\.com$',
9
+ };
10
+ describe('env processed values', () => {
11
+ const originalEnv = process.env;
12
+ let env;
13
+ beforeEach(() => {
14
+ jest.resetModules();
15
+ process.env = { ...testEnv };
16
+ env = jest.requireActual('../src/env').default;
17
+ });
18
+ afterEach(() => {
19
+ process.env = originalEnv;
20
+ });
21
+ test('Number value should be a number', () => {
22
+ expect(env.NUMBER).toStrictEqual(1234);
23
+ });
24
+ test('Number value casted as string should be a string', () => {
25
+ expect(env.NUMBER_CAST_AS_STRING).toStrictEqual('1234');
26
+ });
27
+ test('Value casted as regex', () => {
28
+ expect(env.REGEX).toBeInstanceOf(RegExp);
29
+ });
30
+ test('CSV value should be an array', () => {
31
+ expect(env.CSV).toStrictEqual(['one', 'two', 'three', 'four']);
32
+ });
33
+ test('CSV value casted as string should be a string', () => {
34
+ expect(env.CSV_CAST_AS_STRING).toStrictEqual('one,two,three,four');
35
+ });
36
+ test('Multiple type cast', () => {
37
+ expect(env.MULTIPLE).toStrictEqual(['https://example.com', /\.example2\.com$/]);
38
+ });
39
+ });
@@ -1,5 +1,5 @@
1
1
  import { Router } from 'express';
2
- import { AppExtensionType, ExtensionType } from '@directus/shared/types';
2
+ import { AppExtensionType, ExtensionType, HybridExtensionType } from '@directus/shared/types';
3
3
  export declare function getExtensionManager(): ExtensionManager;
4
4
  declare type Options = {
5
5
  schedule: boolean;
@@ -19,7 +19,7 @@ declare class ExtensionManager {
19
19
  initialize(options?: Partial<Options>): Promise<void>;
20
20
  reload(): void;
21
21
  getExtensionsList(type?: ExtensionType): string[];
22
- getAppExtensions(type: AppExtensionType): string | undefined;
22
+ getAppExtensions(type: AppExtensionType | HybridExtensionType): string | undefined;
23
23
  getEndpointRouter(): Router;
24
24
  private load;
25
25
  private unload;
@@ -132,7 +132,7 @@ class ExtensionManager {
132
132
  }
133
133
  async load() {
134
134
  try {
135
- await (0, node_1.ensureExtensionDirs)(env_1.default.EXTENSIONS_PATH, env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES);
135
+ await (0, node_1.ensureExtensionDirs)(env_1.default.EXTENSIONS_PATH, env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_OR_HYBRID_EXTENSION_TYPES);
136
136
  this.extensions = await this.getExtensions();
137
137
  }
138
138
  catch (err) {
@@ -160,9 +160,9 @@ class ExtensionManager {
160
160
  initializeWatcher() {
161
161
  if (this.options.watch && !this.watcher) {
162
162
  logger_1.default.info('Watching extensions for changes...');
163
- const localExtensionPaths = (env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES).flatMap((type) => {
163
+ const localExtensionPaths = (env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_OR_HYBRID_EXTENSION_TYPES).flatMap((type) => {
164
164
  const typeDir = 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));
165
- return (0, utils_1.isHybridExtension)(type)
165
+ return (0, utils_1.isIn)(type, constants_1.HYBRID_EXTENSION_TYPES)
166
166
  ? [path_1.default.posix.join(typeDir, '*', 'app.js'), path_1.default.posix.join(typeDir, '*', 'api.js')]
167
167
  : path_1.default.posix.join(typeDir, '*', 'index.js');
168
168
  });
@@ -179,9 +179,9 @@ class ExtensionManager {
179
179
  if (this.watcher) {
180
180
  const toPackageExtensionPaths = (extensions) => extensions
181
181
  .filter((extension) => !extension.local)
182
- .flatMap((extension) => extension.type === constants_1.PACK_EXTENSION_TYPE
182
+ .flatMap((extension) => (0, utils_1.isTypeIn)(extension, constants_1.PACKAGE_EXTENSION_TYPES)
183
183
  ? path_1.default.resolve(extension.path, 'package.json')
184
- : (0, utils_1.isExtensionObject)(extension, constants_1.HYBRID_EXTENSION_TYPES)
184
+ : (0, utils_1.isTypeIn)(extension, constants_1.HYBRID_EXTENSION_TYPES)
185
185
  ? [
186
186
  path_1.default.resolve(extension.path, extension.entrypoint.app),
187
187
  path_1.default.resolve(extension.path, extension.entrypoint.api),
@@ -194,8 +194,8 @@ class ExtensionManager {
194
194
  }
195
195
  }
196
196
  async getExtensions() {
197
- const packageExtensions = await (0, node_1.getPackageExtensions)('.', env_1.default.SERVE_APP ? constants_1.EXTENSION_PACKAGE_TYPES : constants_1.API_EXTENSION_PACKAGE_TYPES);
198
- const localExtensions = await (0, node_1.getLocalExtensions)(env_1.default.EXTENSIONS_PATH, env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_EXTENSION_TYPES);
197
+ const packageExtensions = await (0, node_1.getPackageExtensions)('.', env_1.default.SERVE_APP ? constants_1.EXTENSION_PACKAGE_TYPES : constants_1.API_OR_HYBRID_EXTENSION_PACKAGE_TYPES);
198
+ const localExtensions = await (0, node_1.getLocalExtensions)(env_1.default.EXTENSIONS_PATH, env_1.default.SERVE_APP ? constants_1.EXTENSION_TYPES : constants_1.API_OR_HYBRID_EXTENSION_TYPES);
199
199
  return [...packageExtensions, ...localExtensions];
200
200
  }
201
201
  async generateExtensionBundles() {
@@ -205,7 +205,7 @@ class ExtensionManager {
205
205
  replacement: path,
206
206
  }));
207
207
  const bundles = {};
208
- for (const extensionType of constants_1.APP_EXTENSION_TYPES) {
208
+ for (const extensionType of constants_1.APP_OR_HYBRID_EXTENSION_TYPES) {
209
209
  const entry = (0, node_1.generateExtensionsEntry)(extensionType, this.extensions);
210
210
  try {
211
211
  const bundle = await (0, rollup_1.rollup)({
@@ -226,7 +226,8 @@ class ExtensionManager {
226
226
  return bundles;
227
227
  }
228
228
  async getSharedDepsMapping(deps) {
229
- const appDir = await fs_extra_1.default.readdir(path_1.default.join((0, node_1.resolvePackage)('@directus/app'), 'dist', 'assets'));
229
+ var _a;
230
+ const appDir = await fs_extra_1.default.readdir(path_1.default.join((0, node_1.resolvePackage)('@directus/app', (_a = require.main) === null || _a === void 0 ? void 0 : _a.filename), 'dist', 'assets'));
230
231
  const depsMapping = {};
231
232
  for (const dep of deps) {
232
233
  const depRegex = new RegExp(`${(0, lodash_1.escapeRegExp)(dep.replace(/\//g, '_'))}\\.[0-9a-f]{8}\\.entry\\.js`);
package/dist/flows.js CHANGED
@@ -124,11 +124,12 @@ class FlowManager {
124
124
  const flows = await flowsService.readByQuery({
125
125
  filter: { status: { _eq: 'active' } },
126
126
  fields: ['*', 'operations.*'],
127
+ limit: -1,
127
128
  });
128
129
  const flowTrees = flows.map((flow) => (0, construct_flow_tree_1.constructFlowTree)(flow));
129
130
  for (const flow of flowTrees) {
130
131
  if (flow.trigger === 'event') {
131
- const events = (_d = (_c = (_b = (_a = flow.options) === null || _a === void 0 ? void 0 : _a.scope) === null || _b === void 0 ? void 0 : _b.map((scope) => {
132
+ const events = (_d = (_c = (_b = (0, utils_1.toArray)((_a = flow.options) === null || _a === void 0 ? void 0 : _a.scope)) === null || _b === void 0 ? void 0 : _b.map((scope) => {
132
133
  var _a, _b, _c;
133
134
  if (['items.create', 'items.update', 'items.delete'].includes(scope)) {
134
135
  return ((_c = (_b = (_a = flow.options) === null || _a === void 0 ? void 0 : _a.collections) === null || _b === void 0 ? void 0 : _b.map((collection) => {
package/dist/logger.js CHANGED
@@ -67,7 +67,6 @@ const httpLoggerEnvConfig = (0, get_config_from_env_1.getConfigFromEnv)('LOGGER_
67
67
  exports.expressLogger = (0, pino_http_1.default)({
68
68
  logger,
69
69
  ...httpLoggerEnvConfig,
70
- }, {
71
70
  serializers: {
72
71
  req(request) {
73
72
  const output = pino_http_1.stdSerializers.req(request);
@@ -0,0 +1 @@
1
+ import '../../src/types/express.d.ts';