directus 9.22.4 → 9.23.1

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 (112) hide show
  1. package/dist/app.js +5 -4
  2. package/dist/auth/drivers/ldap.d.ts +2 -2
  3. package/dist/auth/drivers/ldap.js +8 -8
  4. package/dist/auth/drivers/oauth2.js +2 -2
  5. package/dist/auth/drivers/openid.js +2 -2
  6. package/dist/cache.js +4 -4
  7. package/dist/cli/commands/schema/apply.js +19 -17
  8. package/dist/cli/utils/create-db-connection.d.ts +2 -1
  9. package/dist/cli/utils/create-env/env-stub.liquid +1 -1
  10. package/dist/cli/utils/drivers.d.ts +3 -9
  11. package/dist/constants.d.ts +2 -8
  12. package/dist/constants.js +3 -7
  13. package/dist/controllers/assets.js +5 -5
  14. package/dist/controllers/extensions.js +7 -7
  15. package/dist/controllers/files.js +1 -1
  16. package/dist/controllers/graphql.js +8 -0
  17. package/dist/controllers/schema.d.ts +2 -0
  18. package/dist/controllers/schema.js +98 -0
  19. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +1 -1
  20. package/dist/database/helpers/schema/dialects/oracle.d.ts +4 -1
  21. package/dist/database/helpers/schema/dialects/oracle.js +25 -0
  22. package/dist/database/helpers/schema/types.d.ts +8 -6
  23. package/dist/database/helpers/schema/types.js +7 -1
  24. package/dist/database/index.d.ts +2 -1
  25. package/dist/database/run-ast.js +2 -2
  26. package/dist/env.js +9 -2
  27. package/dist/extensions.js +1 -1
  28. package/dist/flows.js +17 -8
  29. package/dist/middleware/cache.js +2 -2
  30. package/dist/middleware/respond.js +14 -9
  31. package/dist/operations/request/index.js +2 -1
  32. package/dist/operations/trigger/index.d.ts +2 -0
  33. package/dist/operations/trigger/index.js +26 -9
  34. package/dist/request/index.d.ts +5 -0
  35. package/dist/request/index.js +18 -0
  36. package/dist/request/index.test.d.ts +1 -0
  37. package/dist/request/request-interceptor.d.ts +2 -0
  38. package/dist/request/request-interceptor.js +33 -0
  39. package/dist/request/request-interceptor.test.d.ts +1 -0
  40. package/dist/request/response-interceptor.d.ts +2 -0
  41. package/dist/request/response-interceptor.js +9 -0
  42. package/dist/request/response-interceptor.test.d.ts +1 -0
  43. package/dist/request/validate-ip.d.ts +1 -0
  44. package/dist/request/validate-ip.js +27 -0
  45. package/dist/request/validate-ip.test.d.ts +1 -0
  46. package/dist/services/assets.d.ts +1 -1
  47. package/dist/services/assets.js +11 -2
  48. package/dist/services/authentication.js +5 -5
  49. package/dist/services/fields.js +1 -0
  50. package/dist/services/files.js +44 -88
  51. package/dist/services/graphql/index.js +14 -8
  52. package/dist/services/graphql/utils/process-error.js +22 -9
  53. package/dist/services/import-export.d.ts +4 -2
  54. package/dist/services/import-export.js +17 -3
  55. package/dist/services/import-export.test.d.ts +1 -0
  56. package/dist/services/index.d.ts +1 -0
  57. package/dist/services/index.js +1 -0
  58. package/dist/services/items.js +34 -15
  59. package/dist/services/relations.js +2 -0
  60. package/dist/services/roles.js +32 -11
  61. package/dist/services/schema.d.ts +15 -0
  62. package/dist/services/schema.js +58 -0
  63. package/dist/services/schema.test.d.ts +1 -0
  64. package/dist/services/shares.d.ts +2 -2
  65. package/dist/services/shares.js +9 -9
  66. package/dist/services/users.js +74 -47
  67. package/dist/types/assets.d.ts +1 -1
  68. package/dist/types/database.d.ts +3 -0
  69. package/dist/types/database.js +4 -0
  70. package/dist/types/index.d.ts +1 -0
  71. package/dist/types/index.js +1 -0
  72. package/dist/types/items.d.ts +5 -0
  73. package/dist/types/snapshot.d.ts +22 -0
  74. package/dist/types/snapshot.js +14 -0
  75. package/dist/utils/apply-diff.d.ts +9 -0
  76. package/dist/utils/apply-diff.js +259 -0
  77. package/dist/utils/apply-diff.test.d.ts +1 -0
  78. package/dist/utils/apply-query.js +8 -6
  79. package/dist/utils/apply-snapshot.d.ts +1 -3
  80. package/dist/utils/apply-snapshot.js +4 -234
  81. package/dist/utils/get-cache-headers.d.ts +3 -1
  82. package/dist/utils/get-cache-headers.js +20 -19
  83. package/dist/utils/get-cache-headers.test.d.ts +1 -0
  84. package/dist/utils/get-milliseconds.d.ts +4 -0
  85. package/dist/utils/get-milliseconds.js +15 -0
  86. package/dist/utils/get-milliseconds.test.d.ts +1 -0
  87. package/dist/utils/get-snapshot-diff.js +11 -7
  88. package/dist/utils/get-snapshot.js +29 -6
  89. package/dist/utils/get-versioned-hash.d.ts +1 -0
  90. package/dist/utils/get-versioned-hash.js +12 -0
  91. package/dist/utils/get-versioned-hash.test.d.ts +1 -0
  92. package/dist/utils/map-values-deep.d.ts +1 -0
  93. package/dist/utils/map-values-deep.js +29 -0
  94. package/dist/utils/map-values-deep.test.d.ts +1 -0
  95. package/dist/utils/sanitize-schema.d.ts +30 -0
  96. package/dist/utils/sanitize-schema.js +80 -0
  97. package/dist/utils/sanitize-schema.test.d.ts +1 -0
  98. package/dist/utils/track.js +3 -3
  99. package/dist/utils/url.js +2 -6
  100. package/dist/utils/url.test.d.ts +1 -0
  101. package/dist/utils/validate-diff.d.ts +7 -0
  102. package/dist/utils/validate-diff.js +114 -0
  103. package/dist/utils/validate-diff.test.d.ts +1 -0
  104. package/dist/utils/validate-query.js +1 -1
  105. package/dist/utils/validate-query.test.d.ts +1 -0
  106. package/dist/utils/validate-snapshot.d.ts +5 -0
  107. package/dist/utils/validate-snapshot.js +71 -0
  108. package/dist/utils/validate-snapshot.test.d.ts +1 -0
  109. package/dist/utils/with-timeout.d.ts +1 -0
  110. package/dist/utils/with-timeout.js +16 -0
  111. package/dist/webhooks.js +3 -2
  112. package/package.json +54 -53
package/dist/app.js CHANGED
@@ -52,6 +52,7 @@ const presets_1 = __importDefault(require("./controllers/presets"));
52
52
  const relations_1 = __importDefault(require("./controllers/relations"));
53
53
  const revisions_1 = __importDefault(require("./controllers/revisions"));
54
54
  const roles_1 = __importDefault(require("./controllers/roles"));
55
+ const schema_1 = __importDefault(require("./controllers/schema"));
55
56
  const server_1 = __importDefault(require("./controllers/server"));
56
57
  const settings_1 = __importDefault(require("./controllers/settings"));
57
58
  const users_1 = __importDefault(require("./controllers/users"));
@@ -74,8 +75,7 @@ const error_handler_1 = __importDefault(require("./middleware/error-handler"));
74
75
  const extract_token_1 = __importDefault(require("./middleware/extract-token"));
75
76
  const rate_limiter_1 = __importDefault(require("./middleware/rate-limiter"));
76
77
  const sanitize_query_1 = __importDefault(require("./middleware/sanitize-query"));
77
- const schema_1 = __importDefault(require("./middleware/schema"));
78
- const constants_1 = require("./constants");
78
+ const schema_2 = __importDefault(require("./middleware/schema"));
79
79
  const track_1 = require("./utils/track");
80
80
  const validate_env_1 = require("./utils/validate-env");
81
81
  const validate_storage_1 = require("./utils/validate-storage");
@@ -165,7 +165,7 @@ async function createApp() {
165
165
  app.get('/robots.txt', (_, res) => {
166
166
  res.set('Content-Type', 'text/plain');
167
167
  res.status(200);
168
- res.send(constants_1.ROBOTSTXT);
168
+ res.send(env_1.default.ROBOTS_TXT);
169
169
  });
170
170
  if (env_1.default.SERVE_APP) {
171
171
  const adminPath = require.resolve('@directus/app');
@@ -199,7 +199,7 @@ async function createApp() {
199
199
  app.use(check_ip_1.checkIP);
200
200
  app.use(sanitize_query_1.default);
201
201
  app.use(cache_1.default);
202
- app.use(schema_1.default);
202
+ app.use(schema_2.default);
203
203
  app.use(get_permissions_1.default);
204
204
  await emitter_1.default.emitInit('middlewares.after', { app });
205
205
  await emitter_1.default.emitInit('routes.before', { app });
@@ -223,6 +223,7 @@ async function createApp() {
223
223
  app.use('/relations', relations_1.default);
224
224
  app.use('/revisions', revisions_1.default);
225
225
  app.use('/roles', roles_1.default);
226
+ app.use('/schema', schema_1.default);
226
227
  app.use('/server', server_1.default);
227
228
  app.use('/settings', settings_1.default);
228
229
  app.use('/shares', shares_1.default);
@@ -1,8 +1,8 @@
1
1
  import { Router } from 'express';
2
2
  import { Client } from 'ldapjs';
3
- import { AuthDriver } from '../auth';
4
- import { AuthDriverOptions, User } from '../../types';
5
3
  import { UsersService } from '../../services';
4
+ import { AuthDriverOptions, User } from '../../types';
5
+ import { AuthDriver } from '../auth';
6
6
  export declare class LDAPAuthDriver extends AuthDriver {
7
7
  bindClient: Client;
8
8
  usersService: UsersService;
@@ -28,18 +28,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.createLDAPAuthRouter = exports.LDAPAuthDriver = void 0;
30
30
  const express_1 = require("express");
31
- const ldapjs_1 = __importStar(require("ldapjs"));
32
- const ms_1 = __importDefault(require("ms"));
33
- const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
34
31
  const joi_1 = __importDefault(require("joi"));
35
- const auth_1 = require("../auth");
32
+ const ldapjs_1 = __importStar(require("ldapjs"));
33
+ const env_1 = __importDefault(require("../../env"));
36
34
  const exceptions_1 = require("../../exceptions");
37
35
  const record_not_unique_1 = require("../../exceptions/database/record-not-unique");
36
+ const logger_1 = __importDefault(require("../../logger"));
37
+ const respond_1 = require("../../middleware/respond");
38
38
  const services_1 = require("../../services");
39
39
  const async_handler_1 = __importDefault(require("../../utils/async-handler"));
40
- const env_1 = __importDefault(require("../../env"));
41
- const respond_1 = require("../../middleware/respond");
42
- const logger_1 = __importDefault(require("../../logger"));
40
+ const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
41
+ const get_milliseconds_1 = require("../../utils/get-milliseconds");
42
+ const auth_1 = require("../auth");
43
43
  // 0x2: ACCOUNTDISABLE
44
44
  // 0x10: LOCKOUT
45
45
  // 0x800000: PASSWORD_EXPIRED
@@ -325,7 +325,7 @@ function createLDAPAuthRouter(provider) {
325
325
  res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
326
326
  httpOnly: true,
327
327
  domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
328
- maxAge: (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL),
328
+ maxAge: (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL),
329
329
  secure: (_b = env_1.default.REFRESH_TOKEN_COOKIE_SECURE) !== null && _b !== void 0 ? _b : false,
330
330
  sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
331
331
  });
@@ -32,7 +32,6 @@ const utils_1 = require("@directus/shared/utils");
32
32
  const express_1 = __importStar(require("express"));
33
33
  const flat_1 = __importDefault(require("flat"));
34
34
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
35
- const ms_1 = __importDefault(require("ms"));
36
35
  const openid_client_1 = require("openid-client");
37
36
  const auth_1 = require("../../auth");
38
37
  const env_1 = __importDefault(require("../../env"));
@@ -44,6 +43,7 @@ const services_1 = require("../../services");
44
43
  const async_handler_1 = __importDefault(require("../../utils/async-handler"));
45
44
  const get_config_from_env_1 = require("../../utils/get-config-from-env");
46
45
  const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
46
+ const get_milliseconds_1 = require("../../utils/get-milliseconds");
47
47
  const url_1 = require("../../utils/url");
48
48
  const local_1 = require("./local");
49
49
  class OAuth2AuthDriver extends local_1.LocalAuthDriver {
@@ -285,7 +285,7 @@ function createOAuth2AuthRouter(providerName) {
285
285
  res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
286
286
  httpOnly: true,
287
287
  domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
288
- maxAge: (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL),
288
+ maxAge: (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL),
289
289
  secure: (_a = env_1.default.REFRESH_TOKEN_COOKIE_SECURE) !== null && _a !== void 0 ? _a : false,
290
290
  sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
291
291
  });
@@ -32,7 +32,6 @@ const utils_1 = require("@directus/shared/utils");
32
32
  const express_1 = __importStar(require("express"));
33
33
  const flat_1 = __importDefault(require("flat"));
34
34
  const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
35
- const ms_1 = __importDefault(require("ms"));
36
35
  const openid_client_1 = require("openid-client");
37
36
  const auth_1 = require("../../auth");
38
37
  const env_1 = __importDefault(require("../../env"));
@@ -44,6 +43,7 @@ const services_1 = require("../../services");
44
43
  const async_handler_1 = __importDefault(require("../../utils/async-handler"));
45
44
  const get_config_from_env_1 = require("../../utils/get-config-from-env");
46
45
  const get_ip_from_req_1 = require("../../utils/get-ip-from-req");
46
+ const get_milliseconds_1 = require("../../utils/get-milliseconds");
47
47
  const url_1 = require("../../utils/url");
48
48
  const local_1 = require("./local");
49
49
  class OpenIDAuthDriver extends local_1.LocalAuthDriver {
@@ -307,7 +307,7 @@ function createOpenIDAuthRouter(providerName) {
307
307
  res.cookie(env_1.default.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
308
308
  httpOnly: true,
309
309
  domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
310
- maxAge: (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL),
310
+ maxAge: (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL),
311
311
  secure: (_a = env_1.default.REFRESH_TOKEN_COOKIE_SECURE) !== null && _a !== void 0 ? _a : false,
312
312
  sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
313
313
  });
package/dist/cache.js CHANGED
@@ -5,23 +5,23 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getCacheValue = exports.setCacheValue = exports.getSystemCache = exports.setSystemCache = exports.clearSystemCache = exports.flushCaches = exports.getCache = void 0;
7
7
  const keyv_1 = __importDefault(require("keyv"));
8
- const ms_1 = __importDefault(require("ms"));
9
8
  const env_1 = __importDefault(require("./env"));
10
9
  const logger_1 = __importDefault(require("./logger"));
10
+ const compress_1 = require("./utils/compress");
11
11
  const get_config_from_env_1 = require("./utils/get-config-from-env");
12
+ const get_milliseconds_1 = require("./utils/get-milliseconds");
12
13
  const validate_env_1 = require("./utils/validate-env");
13
- const compress_1 = require("./utils/compress");
14
14
  let cache = null;
15
15
  let systemCache = null;
16
16
  let lockCache = null;
17
17
  function getCache() {
18
18
  if (env_1.default.CACHE_ENABLED === true && cache === null) {
19
19
  (0, validate_env_1.validateEnv)(['CACHE_NAMESPACE', 'CACHE_TTL', 'CACHE_STORE']);
20
- cache = getKeyvInstance(env_1.default.CACHE_TTL ? (0, ms_1.default)(env_1.default.CACHE_TTL) : undefined);
20
+ cache = getKeyvInstance((0, get_milliseconds_1.getMilliseconds)(env_1.default.CACHE_TTL));
21
21
  cache.on('error', (err) => logger_1.default.warn(err, `[cache] ${err}`));
22
22
  }
23
23
  if (systemCache === null) {
24
- systemCache = getKeyvInstance(env_1.default.CACHE_SYSTEM_TTL ? (0, ms_1.default)(env_1.default.CACHE_SYSTEM_TTL) : undefined, '_system');
24
+ systemCache = getKeyvInstance((0, get_milliseconds_1.getMilliseconds)(env_1.default.CACHE_SYSTEM_TTL), '_system');
25
25
  systemCache.on('error', (err) => logger_1.default.warn(err, `[cache] ${err}`));
26
26
  }
27
27
  if (lockCache === null) {
@@ -35,6 +35,8 @@ const js_yaml_1 = require("js-yaml");
35
35
  const path_1 = __importDefault(require("path"));
36
36
  const database_1 = __importStar(require("../../../database"));
37
37
  const logger_1 = __importDefault(require("../../../logger"));
38
+ const types_1 = require("../../../types");
39
+ const apply_diff_1 = require("../../../utils/apply-diff");
38
40
  const apply_snapshot_1 = require("../../../utils/apply-snapshot");
39
41
  const get_snapshot_1 = require("../../../utils/get-snapshot");
40
42
  const get_snapshot_diff_1 = require("../../../utils/get-snapshot-diff");
@@ -73,22 +75,22 @@ async function apply(snapshotPath, options) {
73
75
  if (snapshotDiff.collections.length > 0) {
74
76
  message += chalk_1.default.black.underline.bold('Collections:');
75
77
  for (const { collection, diff } of snapshotDiff.collections) {
76
- if (((_a = diff[0]) === null || _a === void 0 ? void 0 : _a.kind) === 'E') {
78
+ if (((_a = diff[0]) === null || _a === void 0 ? void 0 : _a.kind) === types_1.DiffKind.EDIT) {
77
79
  message += `\n - ${chalk_1.default.blue('Update')} ${collection}`;
78
80
  for (const change of diff) {
79
- if (change.kind === 'E') {
81
+ if (change.kind === types_1.DiffKind.EDIT) {
80
82
  const path = change.path.slice(1).join('.');
81
83
  message += `\n - Set ${path} to ${change.rhs}`;
82
84
  }
83
85
  }
84
86
  }
85
- else if (((_b = diff[0]) === null || _b === void 0 ? void 0 : _b.kind) === 'D') {
87
+ else if (((_b = diff[0]) === null || _b === void 0 ? void 0 : _b.kind) === types_1.DiffKind.DELETE) {
86
88
  message += `\n - ${chalk_1.default.red('Delete')} ${collection}`;
87
89
  }
88
- else if (((_c = diff[0]) === null || _c === void 0 ? void 0 : _c.kind) === 'N') {
90
+ else if (((_c = diff[0]) === null || _c === void 0 ? void 0 : _c.kind) === types_1.DiffKind.NEW) {
89
91
  message += `\n - ${chalk_1.default.green('Create')} ${collection}`;
90
92
  }
91
- else if (((_d = diff[0]) === null || _d === void 0 ? void 0 : _d.kind) === 'A') {
93
+ else if (((_d = diff[0]) === null || _d === void 0 ? void 0 : _d.kind) === types_1.DiffKind.ARRAY) {
92
94
  message += `\n - ${chalk_1.default.blue('Update')} ${collection}`;
93
95
  }
94
96
  }
@@ -96,28 +98,28 @@ async function apply(snapshotPath, options) {
96
98
  if (snapshotDiff.fields.length > 0) {
97
99
  message += '\n\n' + chalk_1.default.black.underline.bold('Fields:');
98
100
  for (const { collection, field, diff } of snapshotDiff.fields) {
99
- if (((_e = diff[0]) === null || _e === void 0 ? void 0 : _e.kind) === 'E' || (0, apply_snapshot_1.isNestedMetaUpdate)(diff[0])) {
101
+ if (((_e = diff[0]) === null || _e === void 0 ? void 0 : _e.kind) === types_1.DiffKind.EDIT || (0, apply_diff_1.isNestedMetaUpdate)(diff[0])) {
100
102
  message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
101
103
  for (const change of diff) {
102
104
  const path = change.path.slice(1).join('.');
103
- if (change.kind === 'E') {
105
+ if (change.kind === types_1.DiffKind.EDIT) {
104
106
  message += `\n - Set ${path} to ${change.rhs}`;
105
107
  }
106
- else if (change.kind === 'D') {
108
+ else if (change.kind === types_1.DiffKind.DELETE) {
107
109
  message += `\n - Remove ${path}`;
108
110
  }
109
- else if (change.kind === 'N') {
111
+ else if (change.kind === types_1.DiffKind.NEW) {
110
112
  message += `\n - Add ${path} and set it to ${change.rhs}`;
111
113
  }
112
114
  }
113
115
  }
114
- else if (((_f = diff[0]) === null || _f === void 0 ? void 0 : _f.kind) === 'D') {
116
+ else if (((_f = diff[0]) === null || _f === void 0 ? void 0 : _f.kind) === types_1.DiffKind.DELETE) {
115
117
  message += `\n - ${chalk_1.default.red('Delete')} ${collection}.${field}`;
116
118
  }
117
- else if (((_g = diff[0]) === null || _g === void 0 ? void 0 : _g.kind) === 'N') {
119
+ else if (((_g = diff[0]) === null || _g === void 0 ? void 0 : _g.kind) === types_1.DiffKind.NEW) {
118
120
  message += `\n - ${chalk_1.default.green('Create')} ${collection}.${field}`;
119
121
  }
120
- else if (((_h = diff[0]) === null || _h === void 0 ? void 0 : _h.kind) === 'A') {
122
+ else if (((_h = diff[0]) === null || _h === void 0 ? void 0 : _h.kind) === types_1.DiffKind.ARRAY) {
121
123
  message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
122
124
  }
123
125
  }
@@ -125,22 +127,22 @@ async function apply(snapshotPath, options) {
125
127
  if (snapshotDiff.relations.length > 0) {
126
128
  message += '\n\n' + chalk_1.default.black.underline.bold('Relations:');
127
129
  for (const { collection, field, related_collection, diff } of snapshotDiff.relations) {
128
- if (((_j = diff[0]) === null || _j === void 0 ? void 0 : _j.kind) === 'E') {
130
+ if (((_j = diff[0]) === null || _j === void 0 ? void 0 : _j.kind) === types_1.DiffKind.EDIT) {
129
131
  message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
130
132
  for (const change of diff) {
131
- if (change.kind === 'E') {
133
+ if (change.kind === types_1.DiffKind.EDIT) {
132
134
  const path = change.path.slice(1).join('.');
133
135
  message += `\n - Set ${path} to ${change.rhs}`;
134
136
  }
135
137
  }
136
138
  }
137
- else if (((_k = diff[0]) === null || _k === void 0 ? void 0 : _k.kind) === 'D') {
139
+ else if (((_k = diff[0]) === null || _k === void 0 ? void 0 : _k.kind) === types_1.DiffKind.DELETE) {
138
140
  message += `\n - ${chalk_1.default.red('Delete')} ${collection}.${field}`;
139
141
  }
140
- else if (((_l = diff[0]) === null || _l === void 0 ? void 0 : _l.kind) === 'N') {
142
+ else if (((_l = diff[0]) === null || _l === void 0 ? void 0 : _l.kind) === types_1.DiffKind.NEW) {
141
143
  message += `\n - ${chalk_1.default.green('Create')} ${collection}.${field}`;
142
144
  }
143
- else if (((_m = diff[0]) === null || _m === void 0 ? void 0 : _m.kind) === 'A') {
145
+ else if (((_m = diff[0]) === null || _m === void 0 ? void 0 : _m.kind) === types_1.DiffKind.ARRAY) {
144
146
  message += `\n - ${chalk_1.default.blue('Update')} ${collection}.${field}`;
145
147
  }
146
148
  else {
@@ -1,4 +1,5 @@
1
1
  import { Knex } from 'knex';
2
+ import { Driver } from '../../types';
2
3
  export type Credentials = {
3
4
  filename?: string;
4
5
  host?: string;
@@ -9,4 +10,4 @@ export type Credentials = {
9
10
  ssl?: boolean;
10
11
  options__encrypt?: boolean;
11
12
  };
12
- export default function createDBConnection(client: 'sqlite3' | 'mysql' | 'pg' | 'oracledb' | 'mssql' | 'cockroachdb', credentials: Credentials): Knex<any, unknown[]>;
13
+ export default function createDBConnection(client: Driver, credentials: Credentials): Knex<any, unknown[]>;
@@ -167,7 +167,7 @@ STORAGE_LOCAL_ROOT="./uploads"
167
167
  # STORAGE_DIGITALOCEAN_DRIVER="s3"
168
168
  # STORAGE_DIGITALOCEAN_KEY="abcdef"
169
169
  # STORAGE_DIGITALOCEAN_SECRET="ghijkl"
170
- # STORAGE_DIGITALOCEAN_ENDPOINT="ams3.digitaloceanspaces.com"
170
+ # STORAGE_DIGITALOCEAN_ENDPOINT="https://ams3.digitaloceanspaces.com"
171
171
  # STORAGE_DIGITALOCEAN_BUCKET="my-files"
172
172
  # STORAGE_DIGITALOCEAN_REGION="ams3"
173
173
 
@@ -1,9 +1,3 @@
1
- export declare const drivers: {
2
- pg: string;
3
- cockroachdb: string;
4
- mysql: string;
5
- sqlite3: string;
6
- mssql: string;
7
- oracledb: string;
8
- };
9
- export declare function getDriverForClient(client: string): keyof typeof drivers | null;
1
+ import { Driver } from '../../types';
2
+ export declare const drivers: Record<Driver, string>;
3
+ export declare function getDriverForClient(client: string): Driver | null;
@@ -1,3 +1,4 @@
1
+ import { CookieOptions } from 'express';
1
2
  import { TransformationParams } from './types';
2
3
  export declare const SYSTEM_ASSET_ALLOW_LIST: TransformationParams[];
3
4
  export declare const ASSET_TRANSFORM_QUERY_KEYS: string[];
@@ -7,12 +8,5 @@ export declare const DEFAULT_AUTH_PROVIDER = "default";
7
8
  export declare const COLUMN_TRANSFORMS: string[];
8
9
  export declare const GENERATE_SPECIAL: string[];
9
10
  export declare const UUID_REGEX = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
10
- export declare const COOKIE_OPTIONS: {
11
- httpOnly: boolean;
12
- domain: any;
13
- maxAge: number;
14
- secure: any;
15
- sameSite: "lax" | "strict" | "none";
16
- };
17
- export declare const ROBOTSTXT: string;
11
+ export declare const COOKIE_OPTIONS: CookieOptions;
18
12
  export declare const OAS_REQUIRED_SCHEMAS: string[];
package/dist/constants.js CHANGED
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  var _a;
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.OAS_REQUIRED_SCHEMAS = exports.ROBOTSTXT = exports.COOKIE_OPTIONS = exports.UUID_REGEX = exports.GENERATE_SPECIAL = exports.COLUMN_TRANSFORMS = exports.DEFAULT_AUTH_PROVIDER = exports.ALIAS_TYPES = exports.FILTER_VARIABLES = exports.ASSET_TRANSFORM_QUERY_KEYS = exports.SYSTEM_ASSET_ALLOW_LIST = void 0;
7
+ exports.OAS_REQUIRED_SCHEMAS = exports.COOKIE_OPTIONS = exports.UUID_REGEX = exports.GENERATE_SPECIAL = exports.COLUMN_TRANSFORMS = exports.DEFAULT_AUTH_PROVIDER = exports.ALIAS_TYPES = exports.FILTER_VARIABLES = exports.ASSET_TRANSFORM_QUERY_KEYS = exports.SYSTEM_ASSET_ALLOW_LIST = void 0;
8
8
  const env_1 = __importDefault(require("./env"));
9
- const ms_1 = __importDefault(require("ms"));
9
+ const get_milliseconds_1 = require("./utils/get-milliseconds");
10
10
  exports.SYSTEM_ASSET_ALLOW_LIST = [
11
11
  {
12
12
  key: 'system-small-cover',
@@ -52,12 +52,8 @@ exports.UUID_REGEX = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{1
52
52
  exports.COOKIE_OPTIONS = {
53
53
  httpOnly: true,
54
54
  domain: env_1.default.REFRESH_TOKEN_COOKIE_DOMAIN,
55
- maxAge: (0, ms_1.default)(env_1.default.REFRESH_TOKEN_TTL),
55
+ maxAge: (0, get_milliseconds_1.getMilliseconds)(env_1.default.REFRESH_TOKEN_TTL),
56
56
  secure: (_a = env_1.default.REFRESH_TOKEN_COOKIE_SECURE) !== null && _a !== void 0 ? _a : false,
57
57
  sameSite: env_1.default.REFRESH_TOKEN_COOKIE_SAME_SITE || 'strict',
58
58
  };
59
- exports.ROBOTSTXT = `
60
- User-agent: *
61
- Disallow: /
62
- `.trim();
63
59
  exports.OAS_REQUIRED_SCHEMAS = ['Query', 'x-metadata'];
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const utils_1 = require("@directus/shared/utils");
7
7
  const express_1 = require("express");
8
8
  const lodash_1 = require("lodash");
9
- const ms_1 = __importDefault(require("ms"));
10
9
  const constants_1 = require("../constants");
11
10
  const database_1 = __importDefault(require("../database"));
12
11
  const env_1 = __importDefault(require("../env"));
@@ -16,7 +15,9 @@ const use_collection_1 = __importDefault(require("../middleware/use-collection")
16
15
  const services_1 = require("../services");
17
16
  const assets_1 = require("../types/assets");
18
17
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
18
+ const get_cache_headers_1 = require("../utils/get-cache-headers");
19
19
  const get_config_from_env_1 = require("../utils/get-config-from-env");
20
+ const get_milliseconds_1 = require("../utils/get-milliseconds");
20
21
  const router = (0, express_1.Router)();
21
22
  router.use((0, use_collection_1.default)('directus_files'));
22
23
  router.get('/:pk/:filename?',
@@ -102,7 +103,7 @@ router.get('/:pk/:filename?',
102
103
  }),
103
104
  // Return file
104
105
  (0, async_handler_1.default)(async (req, res) => {
105
- var _a, _b, _c;
106
+ var _a, _b;
106
107
  const id = (_a = req.params.pk) === null || _a === void 0 ? void 0 : _a.substring(0, 36);
107
108
  const service = new services_1.AssetsService({
108
109
  accountability: req.accountability,
@@ -123,11 +124,10 @@ router.get('/:pk/:filename?',
123
124
  }
124
125
  }
125
126
  const { stream, file, stat } = await service.getAsset(id, transformation, range);
126
- const access = ((_b = req.accountability) === null || _b === void 0 ? void 0 : _b.role) ? 'private' : 'public';
127
- res.attachment((_c = req.params.filename) !== null && _c !== void 0 ? _c : file.filename_download);
127
+ res.attachment((_b = req.params.filename) !== null && _b !== void 0 ? _b : file.filename_download);
128
128
  res.setHeader('Content-Type', file.type);
129
129
  res.setHeader('Accept-Ranges', 'bytes');
130
- res.setHeader('Cache-Control', `${access}, max-age=${(0, ms_1.default)(env_1.default.ASSETS_CACHE_TTL) / 1000}`);
130
+ res.setHeader('Cache-Control', (0, get_cache_headers_1.getCacheControlHeader)(req, (0, get_milliseconds_1.getMilliseconds)(env_1.default.ASSETS_CACHE_TTL), false, true));
131
131
  const unixTime = Date.parse(file.modified_on);
132
132
  if (!Number.isNaN(unixTime)) {
133
133
  const lastModifiedDate = new Date(unixTime);
@@ -3,16 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const constants_1 = require("@directus/shared/constants");
7
+ const utils_1 = require("@directus/shared/utils");
6
8
  const express_1 = require("express");
7
- const async_handler_1 = __importDefault(require("../utils/async-handler"));
9
+ const env_1 = __importDefault(require("../env"));
8
10
  const exceptions_1 = require("../exceptions");
9
11
  const extensions_1 = require("../extensions");
10
- const ms_1 = __importDefault(require("ms"));
11
- const env_1 = __importDefault(require("../env"));
12
- const get_cache_headers_1 = require("../utils/get-cache-headers");
13
12
  const respond_1 = require("../middleware/respond");
14
- const utils_1 = require("@directus/shared/utils");
15
- const constants_1 = require("@directus/shared/constants");
13
+ const async_handler_1 = __importDefault(require("../utils/async-handler"));
14
+ const get_cache_headers_1 = require("../utils/get-cache-headers");
15
+ const get_milliseconds_1 = require("../utils/get-milliseconds");
16
16
  const router = (0, express_1.Router)();
17
17
  router.get('/:type', (0, async_handler_1.default)(async (req, res, next) => {
18
18
  const type = (0, utils_1.depluralize)(req.params.type);
@@ -33,7 +33,7 @@ router.get('/sources/index.js', (0, async_handler_1.default)(async (req, res) =>
33
33
  throw new exceptions_1.RouteNotFoundException(req.path);
34
34
  }
35
35
  res.setHeader('Content-Type', 'application/javascript; charset=UTF-8');
36
- res.setHeader('Cache-Control', env_1.default.EXTENSIONS_CACHE_TTL ? (0, get_cache_headers_1.getCacheControlHeader)(req, (0, ms_1.default)(env_1.default.EXTENSIONS_CACHE_TTL)) : 'no-store');
36
+ res.setHeader('Cache-Control', (0, get_cache_headers_1.getCacheControlHeader)(req, (0, get_milliseconds_1.getMilliseconds)(env_1.default.EXTENSIONS_CACHE_TTL), false, false));
37
37
  res.setHeader('Vary', 'Origin, Cache-Control');
38
38
  res.end(extensionSource);
39
39
  }));
@@ -93,7 +93,7 @@ const multipartHandler = (req, res, next) => {
93
93
  function tryDone() {
94
94
  if (savedFiles.length === fileCount) {
95
95
  if (fileCount === 0) {
96
- return next(new exceptions_1.InvalidPayloadException(`No files where included in the body`));
96
+ return next(new exceptions_1.InvalidPayloadException(`No files were included in the body`));
97
97
  }
98
98
  res.locals.savedFiles = savedFiles;
99
99
  return next();
@@ -10,21 +10,29 @@ const services_1 = require("../services");
10
10
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
11
11
  const router = (0, express_1.Router)();
12
12
  router.use('/system', graphql_1.parseGraphQL, (0, async_handler_1.default)(async (req, res, next) => {
13
+ var _a, _b;
13
14
  const service = new services_1.GraphQLService({
14
15
  accountability: req.accountability,
15
16
  schema: req.schema,
16
17
  scope: 'system',
17
18
  });
18
19
  res.locals.payload = await service.execute(res.locals.graphqlParams);
20
+ if (((_b = (_a = res.locals.payload) === null || _a === void 0 ? void 0 : _a.errors) === null || _b === void 0 ? void 0 : _b.length) > 0) {
21
+ res.locals.cache = false;
22
+ }
19
23
  return next();
20
24
  }), respond_1.respond);
21
25
  router.use('/', graphql_1.parseGraphQL, (0, async_handler_1.default)(async (req, res, next) => {
26
+ var _a, _b;
22
27
  const service = new services_1.GraphQLService({
23
28
  accountability: req.accountability,
24
29
  schema: req.schema,
25
30
  scope: 'items',
26
31
  });
27
32
  res.locals.payload = await service.execute(res.locals.graphqlParams);
33
+ if (((_b = (_a = res.locals.payload) === null || _a === void 0 ? void 0 : _a.errors) === null || _b === void 0 ? void 0 : _b.length) > 0) {
34
+ res.locals.cache = false;
35
+ }
28
36
  return next();
29
37
  }), respond_1.respond);
30
38
  exports.default = router;
@@ -0,0 +1,2 @@
1
+ declare const router: import("express-serve-static-core").Router;
2
+ export default router;
@@ -0,0 +1,98 @@
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 utils_1 = require("@directus/shared/utils");
7
+ const busboy_1 = __importDefault(require("busboy"));
8
+ const express_1 = __importDefault(require("express"));
9
+ const js_yaml_1 = require("js-yaml");
10
+ const exceptions_1 = require("../exceptions");
11
+ const logger_1 = __importDefault(require("../logger"));
12
+ const respond_1 = require("../middleware/respond");
13
+ const schema_1 = require("../services/schema");
14
+ const async_handler_1 = __importDefault(require("../utils/async-handler"));
15
+ const get_versioned_hash_1 = require("../utils/get-versioned-hash");
16
+ const router = express_1.default.Router();
17
+ router.get('/snapshot', (0, async_handler_1.default)(async (req, res, next) => {
18
+ const service = new schema_1.SchemaService({ accountability: req.accountability });
19
+ const currentSnapshot = await service.snapshot();
20
+ res.locals.payload = { data: currentSnapshot };
21
+ return next();
22
+ }), respond_1.respond);
23
+ router.post('/apply', (0, async_handler_1.default)(async (req, _res, next) => {
24
+ const service = new schema_1.SchemaService({ accountability: req.accountability });
25
+ await service.apply(req.body);
26
+ return next();
27
+ }), respond_1.respond);
28
+ const schemaMultipartHandler = (req, res, next) => {
29
+ if (req.is('application/json')) {
30
+ if (Object.keys(req.body).length === 0)
31
+ throw new exceptions_1.InvalidPayloadException(`No data was included in the body`);
32
+ res.locals.uploadedSnapshot = req.body;
33
+ return next();
34
+ }
35
+ if (!req.is('multipart/form-data'))
36
+ throw new exceptions_1.UnsupportedMediaTypeException(`Unsupported Content-Type header`);
37
+ const headers = req.headers['content-type']
38
+ ? req.headers
39
+ : {
40
+ ...req.headers,
41
+ 'content-type': 'application/octet-stream',
42
+ };
43
+ const busboy = (0, busboy_1.default)({ headers });
44
+ let isFileIncluded = false;
45
+ let uploadedSnapshot = null;
46
+ busboy.on('file', async (_, fileStream, { mimeType }) => {
47
+ if (isFileIncluded)
48
+ return next(new exceptions_1.InvalidPayloadException(`More than one file was included in the body`));
49
+ isFileIncluded = true;
50
+ const { readableStreamToString } = await import('@directus/utils/node');
51
+ try {
52
+ const uploadedString = await readableStreamToString(fileStream);
53
+ if (mimeType === 'application/json') {
54
+ try {
55
+ uploadedSnapshot = (0, utils_1.parseJSON)(uploadedString);
56
+ }
57
+ catch (err) {
58
+ logger_1.default.warn(err);
59
+ throw new exceptions_1.InvalidPayloadException('Invalid JSON schema snapshot');
60
+ }
61
+ }
62
+ else {
63
+ try {
64
+ uploadedSnapshot = (await (0, js_yaml_1.load)(uploadedString));
65
+ }
66
+ catch (err) {
67
+ logger_1.default.warn(err);
68
+ throw new exceptions_1.InvalidPayloadException('Invalid YAML schema snapshot');
69
+ }
70
+ }
71
+ if (!uploadedSnapshot)
72
+ throw new exceptions_1.InvalidPayloadException(`No file was included in the body`);
73
+ res.locals.uploadedSnapshot = uploadedSnapshot;
74
+ return next();
75
+ }
76
+ catch (error) {
77
+ busboy.emit('error', error);
78
+ }
79
+ });
80
+ busboy.on('error', (error) => next(error));
81
+ busboy.on('close', () => {
82
+ if (!isFileIncluded)
83
+ return next(new exceptions_1.InvalidPayloadException(`No file was included in the body`));
84
+ });
85
+ req.pipe(busboy);
86
+ };
87
+ router.post('/diff', (0, async_handler_1.default)(schemaMultipartHandler), (0, async_handler_1.default)(async (req, res, next) => {
88
+ const service = new schema_1.SchemaService({ accountability: req.accountability });
89
+ const snapshot = res.locals.uploadedSnapshot;
90
+ const currentSnapshot = await service.snapshot();
91
+ const snapshotDiff = await service.diff(snapshot, { currentSnapshot, force: 'force' in req.query });
92
+ if (!snapshotDiff)
93
+ return next();
94
+ const currentSnapshotHash = (0, get_versioned_hash_1.getVersionedHash)(currentSnapshot);
95
+ res.locals.payload = { data: { hash: currentSnapshotHash, diff: snapshotDiff } };
96
+ return next();
97
+ }), respond_1.respond);
98
+ exports.default = router;
@@ -1,6 +1,6 @@
1
1
  import { KNEX_TYPES } from '@directus/shared/constants';
2
2
  import { Options, SchemaHelper } from '../types';
3
3
  export declare class SchemaHelperCockroachDb extends SchemaHelper {
4
- changeToType(table: string, column: string, type: typeof KNEX_TYPES[number], options?: Options): Promise<void>;
4
+ changeToType(table: string, column: string, type: (typeof KNEX_TYPES)[number], options?: Options): Promise<void>;
5
5
  constraintName(existingName: string): string;
6
6
  }
@@ -1,6 +1,9 @@
1
1
  import { KNEX_TYPES } from '@directus/shared/constants';
2
+ import { Field, Relation, Type } from '@directus/shared/types';
2
3
  import { Options, SchemaHelper } from '../types';
3
4
  export declare class SchemaHelperOracle extends SchemaHelper {
4
- changeToType(table: string, column: string, type: typeof KNEX_TYPES[number], options?: Options): Promise<void>;
5
+ changeToType(table: string, column: string, type: (typeof KNEX_TYPES)[number], options?: Options): Promise<void>;
5
6
  castA2oPrimaryKey(): string;
7
+ preRelationChange(relation: Partial<Relation>): void;
8
+ processFieldType(field: Field): Type;
6
9
  }
@@ -9,5 +9,30 @@ class SchemaHelperOracle extends types_1.SchemaHelper {
9
9
  castA2oPrimaryKey() {
10
10
  return 'CAST(?? AS VARCHAR2(255))';
11
11
  }
12
+ preRelationChange(relation) {
13
+ var _a;
14
+ if (relation.collection === relation.related_collection) {
15
+ // Constraints are not allowed on self referencing relationships
16
+ // Setting NO ACTION throws - ORA-00905: missing keyword
17
+ if ((_a = relation.schema) === null || _a === void 0 ? void 0 : _a.on_delete) {
18
+ relation.schema.on_delete = null;
19
+ }
20
+ }
21
+ }
22
+ processFieldType(field) {
23
+ var _a, _b, _c, _d;
24
+ if (field.type === 'integer') {
25
+ if (((_a = field.schema) === null || _a === void 0 ? void 0 : _a.numeric_precision) === 20) {
26
+ return 'bigInteger';
27
+ }
28
+ else if (((_b = field.schema) === null || _b === void 0 ? void 0 : _b.numeric_precision) === 1) {
29
+ return 'boolean';
30
+ }
31
+ else if (((_c = field.schema) === null || _c === void 0 ? void 0 : _c.numeric_precision) || ((_d = field.schema) === null || _d === void 0 ? void 0 : _d.numeric_scale)) {
32
+ return 'decimal';
33
+ }
34
+ }
35
+ return field.type;
36
+ }
12
37
  }
13
38
  exports.SchemaHelperOracle = SchemaHelperOracle;