@directus/api 10.1.0 → 11.0.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 (68) hide show
  1. package/dist/app.js +4 -3
  2. package/dist/auth/drivers/oauth2.js +1 -1
  3. package/dist/auth/drivers/openid.js +1 -1
  4. package/dist/cli/utils/create-env/env-stub.liquid +7 -0
  5. package/dist/constants.d.ts +0 -1
  6. package/dist/constants.js +0 -1
  7. package/dist/controllers/assets.js +6 -10
  8. package/dist/controllers/files.js +19 -1
  9. package/dist/controllers/permissions.js +7 -4
  10. package/dist/controllers/translations.d.ts +2 -0
  11. package/dist/controllers/translations.js +149 -0
  12. package/dist/controllers/users.js +1 -1
  13. package/dist/database/migrations/20230525A-add-preview-settings.d.ts +3 -0
  14. package/dist/database/migrations/20230525A-add-preview-settings.js +10 -0
  15. package/dist/database/migrations/20230526A-migrate-translation-strings.d.ts +3 -0
  16. package/dist/database/migrations/20230526A-migrate-translation-strings.js +54 -0
  17. package/dist/database/run-ast.js +3 -3
  18. package/dist/database/system-data/app-access-permissions/app-access-permissions.yaml +3 -0
  19. package/dist/database/system-data/collections/collections.yaml +23 -0
  20. package/dist/database/system-data/fields/collections.yaml +16 -0
  21. package/dist/database/system-data/fields/settings.yaml +0 -5
  22. package/dist/database/system-data/fields/translations.yaml +27 -0
  23. package/dist/env.js +17 -0
  24. package/dist/exceptions/content-too-large.d.ts +4 -0
  25. package/dist/exceptions/content-too-large.js +6 -0
  26. package/dist/extensions.js +13 -11
  27. package/dist/flows.d.ts +1 -1
  28. package/dist/flows.js +20 -19
  29. package/dist/logger.d.ts +1 -1
  30. package/dist/logger.js +6 -6
  31. package/dist/server.js +0 -11
  32. package/dist/services/assets.d.ts +2 -2
  33. package/dist/services/collections.js +8 -7
  34. package/dist/services/fields.js +7 -5
  35. package/dist/services/files.d.ts +2 -2
  36. package/dist/services/files.js +4 -9
  37. package/dist/services/graphql/index.js +4 -41
  38. package/dist/services/index.d.ts +1 -0
  39. package/dist/services/index.js +1 -0
  40. package/dist/services/items.js +10 -9
  41. package/dist/services/revisions.d.ts +6 -1
  42. package/dist/services/revisions.js +24 -0
  43. package/dist/services/server.js +3 -17
  44. package/dist/services/specifications.d.ts +2 -2
  45. package/dist/services/specifications.js +6 -5
  46. package/dist/services/translations.d.ts +10 -0
  47. package/dist/services/translations.js +36 -0
  48. package/dist/synchronization.d.ts +7 -0
  49. package/dist/synchronization.js +120 -0
  50. package/dist/types/assets.d.ts +6 -1
  51. package/dist/types/events.d.ts +2 -2
  52. package/dist/utils/apply-query.d.ts +9 -2
  53. package/dist/utils/apply-query.js +43 -16
  54. package/dist/utils/md.js +1 -1
  55. package/dist/utils/redact.d.ts +11 -0
  56. package/dist/utils/redact.js +75 -0
  57. package/dist/utils/sanitize-query.js +10 -1
  58. package/dist/utils/schedule.d.ts +5 -0
  59. package/dist/utils/schedule.js +27 -0
  60. package/dist/utils/should-clear-cache.d.ts +10 -0
  61. package/dist/utils/should-clear-cache.js +18 -0
  62. package/dist/utils/should-skip-cache.js +18 -2
  63. package/dist/utils/transformations.d.ts +2 -2
  64. package/dist/utils/transformations.js +27 -10
  65. package/dist/utils/validate-query.js +3 -1
  66. package/package.json +49 -53
  67. package/dist/utils/get-os-info.d.ts +0 -9
  68. package/dist/utils/get-os-info.js +0 -40
@@ -0,0 +1,11 @@
1
+ import type { UnknownObject } from '@directus/types';
2
+ type Paths = string[][];
3
+ /**
4
+ * Redact values at certain paths in an object.
5
+ * @param input Input object in which values should be redacted.
6
+ * @param paths Nested array of object paths to be redacted (supports `*` for shallow matching, `**` for deep matching).
7
+ * @param replacement Replacement the values are redacted by.
8
+ * @returns Redacted object.
9
+ */
10
+ export declare function redact(input: UnknownObject, paths: Paths, replacement: string): UnknownObject;
11
+ export {};
@@ -0,0 +1,75 @@
1
+ import { isObject } from '@directus/utils';
2
+ /**
3
+ * Redact values at certain paths in an object.
4
+ * @param input Input object in which values should be redacted.
5
+ * @param paths Nested array of object paths to be redacted (supports `*` for shallow matching, `**` for deep matching).
6
+ * @param replacement Replacement the values are redacted by.
7
+ * @returns Redacted object.
8
+ */
9
+ export function redact(input, paths, replacement) {
10
+ const wildcardChars = ['*', '**'];
11
+ const clone = structuredClone(input);
12
+ const visited = new WeakSet();
13
+ traverse(clone, paths);
14
+ return clone;
15
+ function traverse(object, checkPaths) {
16
+ if (checkPaths.length === 0) {
17
+ return;
18
+ }
19
+ visited.add(object);
20
+ const globalCheckPaths = [];
21
+ for (const key of Object.keys(object)) {
22
+ const localCheckPaths = [];
23
+ for (const [index, path] of [...checkPaths].entries()) {
24
+ const [current, ...remaining] = path;
25
+ const escapedKey = wildcardChars.includes(key) ? `\\${key}` : key;
26
+ switch (current) {
27
+ case escapedKey:
28
+ if (remaining.length > 0) {
29
+ localCheckPaths.push(remaining);
30
+ }
31
+ else {
32
+ object[key] = replacement;
33
+ checkPaths.splice(index, 1);
34
+ }
35
+ break;
36
+ case '*':
37
+ if (remaining.length > 0) {
38
+ globalCheckPaths.push(remaining);
39
+ checkPaths.splice(index, 1);
40
+ }
41
+ else {
42
+ object[key] = replacement;
43
+ }
44
+ break;
45
+ case '**':
46
+ if (remaining.length > 0) {
47
+ const [next, ...nextRemaining] = remaining;
48
+ if (next === escapedKey) {
49
+ if (nextRemaining.length === 0) {
50
+ object[key] = replacement;
51
+ }
52
+ else {
53
+ localCheckPaths.push(nextRemaining);
54
+ }
55
+ }
56
+ else if (next !== undefined && wildcardChars.includes(next)) {
57
+ localCheckPaths.push(remaining);
58
+ }
59
+ else {
60
+ localCheckPaths.push(path);
61
+ }
62
+ }
63
+ else {
64
+ object[key] = replacement;
65
+ }
66
+ break;
67
+ }
68
+ }
69
+ const value = object[key];
70
+ if (isObject(value) && !visited.has(value)) {
71
+ traverse(value, [...globalCheckPaths, ...localCheckPaths]);
72
+ }
73
+ }
74
+ }
75
+ }
@@ -1,15 +1,24 @@
1
1
  import { parseFilter, parseJSON } from '@directus/utils';
2
2
  import { flatten, get, isPlainObject, merge, set } from 'lodash-es';
3
+ import { getEnv } from '../env.js';
3
4
  import logger from '../logger.js';
4
5
  import { Meta } from '../types/index.js';
5
6
  export function sanitizeQuery(rawQuery, accountability) {
6
7
  const query = {};
8
+ const env = getEnv();
9
+ const hasMaxLimit = 'QUERY_LIMIT_MAX' in env &&
10
+ Number(env['QUERY_LIMIT_MAX']) >= 0 &&
11
+ !Number.isNaN(Number(env['QUERY_LIMIT_MAX'])) &&
12
+ Number.isFinite(Number(env['QUERY_LIMIT_MAX']));
7
13
  if (rawQuery['limit'] !== undefined) {
8
14
  const limit = sanitizeLimit(rawQuery['limit']);
9
15
  if (typeof limit === 'number') {
10
- query.limit = limit;
16
+ query.limit = limit === -1 && hasMaxLimit ? Number(env['QUERY_LIMIT_MAX']) : limit;
11
17
  }
12
18
  }
19
+ else if (hasMaxLimit) {
20
+ query.limit = Math.min(Number(env['QUERY_LIMIT_DEFAULT']), Number(env['QUERY_LIMIT_MAX']));
21
+ }
13
22
  if (rawQuery['fields']) {
14
23
  query.fields = sanitizeFields(rawQuery['fields']);
15
24
  }
@@ -0,0 +1,5 @@
1
+ export interface ScheduledJob {
2
+ stop(): Promise<void>;
3
+ }
4
+ export declare function validateCron(rule: string): boolean;
5
+ export declare function scheduleSynchronizedJob(id: string, rule: string, cb: (fireDate: Date) => void | Promise<void>): ScheduledJob;
@@ -0,0 +1,27 @@
1
+ import cron from 'cron-parser';
2
+ import schedule from 'node-schedule';
3
+ import { SynchronizedClock } from '../synchronization.js';
4
+ export function validateCron(rule) {
5
+ try {
6
+ cron.parseExpression(rule);
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ return true;
12
+ }
13
+ export function scheduleSynchronizedJob(id, rule, cb) {
14
+ const clock = new SynchronizedClock(`${id}:${rule}`);
15
+ const job = schedule.scheduleJob(rule, async (fireDate) => {
16
+ const nextTimestamp = job.nextInvocation().getTime();
17
+ const wasSet = await clock.set(nextTimestamp);
18
+ if (wasSet) {
19
+ await cb(fireDate);
20
+ }
21
+ });
22
+ const stop = async () => {
23
+ job.cancel();
24
+ await clock.reset();
25
+ };
26
+ return { stop };
27
+ }
@@ -0,0 +1,10 @@
1
+ import type Keyv from 'keyv';
2
+ import type { MutationOptions } from '../types/items.js';
3
+ /**
4
+ * Check whether cache should be cleared
5
+ *
6
+ * @param cache Cache instance
7
+ * @param opts Mutation options
8
+ * @param collection Collection name to check if cache purging should be ignored
9
+ */
10
+ export declare function shouldClearCache(cache: Keyv<any> | null, opts?: MutationOptions, collection?: string): cache is Keyv<any>;
@@ -0,0 +1,18 @@
1
+ import { getEnv } from '../env.js';
2
+ /**
3
+ * Check whether cache should be cleared
4
+ *
5
+ * @param cache Cache instance
6
+ * @param opts Mutation options
7
+ * @param collection Collection name to check if cache purging should be ignored
8
+ */
9
+ export function shouldClearCache(cache, opts, collection) {
10
+ const env = getEnv();
11
+ if (collection && env['CACHE_AUTO_PURGE_IGNORE_LIST'].includes(collection)) {
12
+ return false;
13
+ }
14
+ if (cache && env['CACHE_AUTO_PURGE'] && opts?.autoPurgeCache !== false) {
15
+ return true;
16
+ }
17
+ return false;
18
+ }
@@ -1,5 +1,7 @@
1
1
  import { getEnv } from '../env.js';
2
2
  import { Url } from './url.js';
3
+ import url from 'url';
4
+ import { getEndpoint } from '@directus/utils';
3
5
  /**
4
6
  * Whether to skip caching for the current request
5
7
  *
@@ -13,14 +15,28 @@ export function shouldSkipCache(req) {
13
15
  const adminUrl = new Url(env['PUBLIC_URL']).addPath('admin');
14
16
  if (adminUrl.isRootRelative()) {
15
17
  const refererUrl = new Url(referer);
16
- if (refererUrl.path.join('/').startsWith(adminUrl.path.join('/')))
18
+ if (refererUrl.path.join('/').startsWith(adminUrl.path.join('/')) && checkAutoPurge())
17
19
  return true;
18
20
  }
19
- else if (referer.startsWith(adminUrl.toString())) {
21
+ else if (referer.startsWith(adminUrl.toString()) && checkAutoPurge()) {
20
22
  return true;
21
23
  }
22
24
  }
23
25
  if (env['CACHE_SKIP_ALLOWED'] && req.get('cache-control')?.includes('no-store'))
24
26
  return true;
25
27
  return false;
28
+ function checkAutoPurge() {
29
+ if (env['CACHE_AUTO_PURGE'] === false)
30
+ return true;
31
+ const path = url.parse(req.originalUrl).pathname;
32
+ if (!path)
33
+ return false;
34
+ for (const collection of env['CACHE_AUTO_PURGE_IGNORE_LIST']) {
35
+ const ignoredPath = getEndpoint(collection);
36
+ if (path.startsWith(ignoredPath)) {
37
+ return true;
38
+ }
39
+ }
40
+ return false;
41
+ }
26
42
  }
@@ -1,5 +1,5 @@
1
- import type { File, Transformation, TransformationParams } from '../types/index.js';
2
- export declare function resolvePreset(input: TransformationParams, file: File): Transformation[];
1
+ import type { File, Transformation, TransformationSet } from '../types/index.js';
2
+ export declare function resolvePreset({ transformationParams, acceptFormat }: TransformationSet, file: File): Transformation[];
3
3
  /**
4
4
  * Try to extract a file format from an array of `Transformation`'s.
5
5
  */
@@ -1,27 +1,44 @@
1
- export function resolvePreset(input, file) {
2
- const transforms = input.transforms ? [...input.transforms] : [];
3
- if (input.format || input.quality) {
1
+ export function resolvePreset({ transformationParams, acceptFormat }, file) {
2
+ const transforms = transformationParams.transforms ? [...transformationParams.transforms] : [];
3
+ if (transformationParams.format || transformationParams.quality) {
4
4
  transforms.push([
5
5
  'toFormat',
6
- input.format || file.type.split('/')[1],
6
+ getFormat(file, transformationParams.format, acceptFormat),
7
7
  {
8
- quality: input.quality ? Number(input.quality) : undefined,
8
+ quality: transformationParams.quality ? Number(transformationParams.quality) : undefined,
9
9
  },
10
10
  ]);
11
11
  }
12
- if (input.width || input.height) {
12
+ if (transformationParams.width || transformationParams.height) {
13
13
  transforms.push([
14
14
  'resize',
15
15
  {
16
- width: input.width ? Number(input.width) : undefined,
17
- height: input.height ? Number(input.height) : undefined,
18
- fit: input.fit,
19
- withoutEnlargement: input.withoutEnlargement ? Boolean(input.withoutEnlargement) : undefined,
16
+ width: transformationParams.width ? Number(transformationParams.width) : undefined,
17
+ height: transformationParams.height ? Number(transformationParams.height) : undefined,
18
+ fit: transformationParams.fit,
19
+ withoutEnlargement: transformationParams.withoutEnlargement
20
+ ? Boolean(transformationParams.withoutEnlargement)
21
+ : undefined,
20
22
  },
21
23
  ]);
22
24
  }
23
25
  return transforms;
24
26
  }
27
+ function getFormat(file, format, acceptFormat) {
28
+ const fileType = file.type?.split('/')[1];
29
+ if (format) {
30
+ if (format !== 'auto') {
31
+ return format;
32
+ }
33
+ if (acceptFormat) {
34
+ return acceptFormat;
35
+ }
36
+ if (fileType && ['avif', 'webp', 'tiff'].includes(fileType)) {
37
+ return 'png';
38
+ }
39
+ }
40
+ return fileType || 'jpg';
41
+ }
25
42
  /**
26
43
  * Try to extract a file format from an array of `Transformation`'s.
27
44
  */
@@ -9,7 +9,9 @@ const querySchema = Joi.object({
9
9
  group: Joi.array().items(Joi.string()),
10
10
  sort: Joi.array().items(Joi.string()),
11
11
  filter: Joi.object({}).unknown(),
12
- limit: Joi.number().integer().min(-1),
12
+ limit: 'QUERY_LIMIT_MAX' in env && env['QUERY_LIMIT_MAX'] !== -1
13
+ ? Joi.number().integer().min(-1).max(env['QUERY_LIMIT_MAX']) // min should be 0
14
+ : Joi.number().integer().min(-1),
13
15
  offset: Joi.number().integer().min(0),
14
16
  page: Joi.number().integer().min(0),
15
17
  meta: Joi.array().items(Joi.string().valid('total_count', 'filter_count')),
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@directus/api",
3
- "version": "10.1.0",
3
+ "version": "11.0.0",
4
4
  "description": "Directus is a real-time API and App dashboard for managing SQL database content",
5
- "type": "module",
6
5
  "keywords": [
7
6
  "directus",
8
7
  "realtime",
@@ -23,9 +22,6 @@
23
22
  "vue"
24
23
  ],
25
24
  "homepage": "https://directus.io",
26
- "bugs": {
27
- "url": "https://github.com/directus/directus/issues"
28
- },
29
25
  "repository": {
30
26
  "type": "git",
31
27
  "url": "https://github.com/directus/directus.git",
@@ -50,6 +46,7 @@
50
46
  "url": "https://github.com/benhaynes"
51
47
  }
52
48
  ],
49
+ "type": "module",
53
50
  "exports": {
54
51
  ".": "./dist/index.js",
55
52
  "./*": "./dist/*.js",
@@ -62,7 +59,7 @@
62
59
  ],
63
60
  "dependencies": {
64
61
  "@authenio/samlify-node-xmllint": "2.0.0",
65
- "@aws-sdk/client-ses": "3.316.0",
62
+ "@aws-sdk/client-ses": "3.332.0",
66
63
  "@directus/format-title": "10.0.0",
67
64
  "@godaddy/terminus": "4.12.0",
68
65
  "@rollup/plugin-alias": "5.0.0",
@@ -70,7 +67,7 @@
70
67
  "@rollup/plugin-virtual": "3.0.1",
71
68
  "argon2": "0.30.3",
72
69
  "async": "3.2.4",
73
- "axios": "1.3.6",
70
+ "axios": "1.4.0",
74
71
  "busboy": "1.6.0",
75
72
  "bytes": "3.1.2",
76
73
  "camelcase": "7.0.1",
@@ -80,8 +77,9 @@
80
77
  "content-disposition": "0.5.4",
81
78
  "cookie-parser": "1.4.6",
82
79
  "cors": "2.8.5",
80
+ "cron-parser": "4.8.1",
83
81
  "csv-parser": "3.0.0",
84
- "date-fns": "2.29.3",
82
+ "date-fns": "2.30.0",
85
83
  "deep-diff": "1.0.2",
86
84
  "destroy": "1.2.0",
87
85
  "dotenv": "16.0.3",
@@ -90,16 +88,15 @@
90
88
  "execa": "7.1.1",
91
89
  "exif-reader": "1.2.0",
92
90
  "express": "4.18.2",
93
- "fast-redact": "3.1.2",
94
91
  "flat": "5.0.2",
95
92
  "fs-extra": "11.1.1",
96
93
  "graphql": "16.6.0",
97
94
  "graphql-compose": "9.0.10",
98
- "helmet": "6.1.5",
95
+ "helmet": "7.0.0",
99
96
  "icc": "3.0.0",
100
- "inquirer": "9.1.5",
97
+ "inquirer": "9.2.4",
101
98
  "ioredis": "5.3.2",
102
- "joi": "17.9.1",
99
+ "joi": "17.9.2",
103
100
  "js-yaml": "4.1.0",
104
101
  "js2xmlparser": "5.0.0",
105
102
  "json2csv": "5.0.7",
@@ -107,60 +104,59 @@
107
104
  "keyv": "4.5.2",
108
105
  "knex": "2.4.2",
109
106
  "ldapjs": "2.3.3",
110
- "liquidjs": "10.7.0",
107
+ "liquidjs": "10.7.1",
111
108
  "lodash-es": "4.17.21",
112
- "marked": "4.3.0",
109
+ "marked": "5.0.2",
113
110
  "micromustache": "8.0.3",
114
111
  "mime-types": "2.1.35",
112
+ "minimatch": "9.0.1",
115
113
  "ms": "2.1.3",
116
114
  "nanoid": "4.0.2",
117
- "node-cron": "3.0.2",
118
115
  "node-machine-id": "1.1.12",
119
- "nodemailer": "6.9.1",
116
+ "node-schedule": "2.1.1",
117
+ "nodemailer": "6.9.2",
120
118
  "object-hash": "3.0.0",
121
- "openapi3-ts": "3.2.0",
122
- "openid-client": "5.4.0",
123
- "ora": "6.3.0",
119
+ "openapi3-ts": "4.1.2",
120
+ "openid-client": "5.4.2",
121
+ "ora": "6.3.1",
124
122
  "otplib": "12.0.1",
125
- "pino": "8.11.0",
123
+ "pino": "8.14.1",
126
124
  "pino-http": "8.3.3",
127
125
  "pino-http-print": "3.1.0",
128
126
  "pino-pretty": "10.0.0",
129
- "qs": "6.11.1",
127
+ "qs": "6.11.2",
130
128
  "rate-limiter-flexible": "2.4.1",
131
- "rollup": "3.20.7",
129
+ "rollup": "3.22.0",
132
130
  "samlify": "2.8.10",
133
131
  "sanitize-html": "2.10.0",
134
- "sharp": "0.32.0",
132
+ "sharp": "0.32.1",
135
133
  "snappy": "7.2.2",
136
134
  "stream-json": "1.7.5",
137
135
  "strip-bom-stream": "5.0.0",
138
136
  "tmp-promise": "3.0.3",
139
- "tsx": "3.12.6",
137
+ "tsx": "3.12.7",
140
138
  "uuid": "9.0.0",
141
139
  "uuid-validate": "0.0.3",
142
- "vm2": "3.9.17",
140
+ "vm2": "3.9.19",
143
141
  "wellknown": "0.5.0",
144
- "@directus/app": "10.1.0",
142
+ "@directus/app": "10.3.0",
145
143
  "@directus/constants": "10.1.0",
146
- "@directus/exceptions": "10.0.1",
147
- "@directus/extensions-sdk": "10.1.0",
148
- "@directus/pressure": "1.0.0",
149
- "@directus/schema": "10.0.0",
150
- "@directus/specs": "10.1.0",
151
- "@directus/storage": "10.0.1",
152
- "@directus/storage-driver-azure": "10.0.1",
153
- "@directus/storage-driver-cloudinary": "10.0.1",
154
- "@directus/storage-driver-gcs": "10.0.1",
155
- "@directus/storage-driver-local": "10.0.1",
156
- "@directus/storage-driver-s3": "10.0.1",
157
- "@directus/update-check": "10.0.1",
158
- "@directus/utils": "10.0.1"
144
+ "@directus/exceptions": "10.0.2",
145
+ "@directus/extensions-sdk": "10.1.2",
146
+ "@directus/pressure": "1.0.2",
147
+ "@directus/schema": "10.0.1",
148
+ "@directus/specs": "10.1.1",
149
+ "@directus/storage": "10.0.2",
150
+ "@directus/storage-driver-azure": "10.0.3",
151
+ "@directus/storage-driver-cloudinary": "10.0.3",
152
+ "@directus/storage-driver-gcs": "10.0.3",
153
+ "@directus/storage-driver-local": "10.0.3",
154
+ "@directus/storage-driver-s3": "10.0.3",
155
+ "@directus/utils": "10.0.3"
159
156
  },
160
157
  "devDependencies": {
161
- "@directus/tsconfig": "0.0.7",
162
158
  "@ngneat/falso": "6.4.0",
163
- "@types/async": "3.2.19",
159
+ "@types/async": "3.2.20",
164
160
  "@types/busboy": "1.5.0",
165
161
  "@types/bytes": "3.1.1",
166
162
  "@types/content-disposition": "0.5.5",
@@ -171,22 +167,21 @@
171
167
  "@types/encodeurl": "1.0.0",
172
168
  "@types/exif-reader": "1.0.0",
173
169
  "@types/express": "4.17.17",
174
- "@types/express-serve-static-core": "4.17.33",
175
- "@types/fast-redact": "3.0.2",
170
+ "@types/express-serve-static-core": "4.17.35",
176
171
  "@types/flat": "5.0.2",
177
172
  "@types/fs-extra": "11.0.1",
178
173
  "@types/inquirer": "9.0.3",
179
174
  "@types/js-yaml": "4.0.5",
180
175
  "@types/json2csv": "5.0.3",
181
- "@types/jsonwebtoken": "9.0.1",
176
+ "@types/jsonwebtoken": "9.0.2",
182
177
  "@types/keyv": "4.2.0",
183
178
  "@types/ldapjs": "2.2.5",
184
179
  "@types/lodash-es": "4.17.7",
185
- "@types/marked": "4.0.8",
180
+ "@types/marked": "4.3.0",
186
181
  "@types/mime-types": "2.1.1",
187
182
  "@types/ms": "0.7.31",
188
- "@types/node": "18.15.13",
189
- "@types/node-cron": "3.0.7",
183
+ "@types/node": "18.16.12",
184
+ "@types/node-schedule": "2.1.0",
190
185
  "@types/nodemailer": "6.4.7",
191
186
  "@types/object-hash": "3.0.2",
192
187
  "@types/qs": "6.9.7",
@@ -196,25 +191,26 @@
196
191
  "@types/uuid": "9.0.1",
197
192
  "@types/uuid-validate": "0.0.1",
198
193
  "@types/wellknown": "0.5.4",
199
- "@vitest/coverage-c8": "0.31.0",
194
+ "@vitest/coverage-c8": "0.31.1",
200
195
  "copyfiles": "2.4.1",
201
196
  "form-data": "4.0.0",
202
197
  "knex-mock-client": "2.0.0",
203
198
  "supertest": "6.3.3",
204
199
  "typescript": "5.0.4",
205
- "vitest": "0.31.0",
206
- "@directus/types": "10.0.0"
200
+ "vitest": "0.31.1",
201
+ "@directus/tsconfig": "0.0.7",
202
+ "@directus/types": "10.1.0"
207
203
  },
208
204
  "optionalDependencies": {
209
- "@keyv/redis": "2.5.7",
205
+ "@keyv/redis": "2.5.8",
210
206
  "keyv-memcache": "1.3.3",
211
207
  "memcached": "2.2.2",
212
208
  "mysql": "2.18.1",
213
209
  "nodemailer-mailgun-transport": "2.1.5",
214
210
  "nodemailer-sendgrid": "1.0.3",
215
- "pg": "8.10.0",
211
+ "pg": "8.11.0",
216
212
  "sqlite3": "5.1.6",
217
- "tedious": "16.0.0"
213
+ "tedious": "16.1.0"
218
214
  },
219
215
  "engines": {
220
216
  "node": ">=18.0.0"
@@ -1,9 +0,0 @@
1
- /**
2
- * Get current host OS information
3
- *
4
- * @returns Object of OS type and version
5
- */
6
- export declare function getOSInfo(): {
7
- osType: string;
8
- osVersion: string;
9
- };
@@ -1,40 +0,0 @@
1
- import os from 'os';
2
- /**
3
- * Get current host OS information
4
- *
5
- * @returns Object of OS type and version
6
- */
7
- export function getOSInfo() {
8
- const osType = os.type() === 'Darwin' ? 'macOS' : os.type();
9
- const osVersion = osType === 'macOS' ? macosRelease() : os.release();
10
- return { osType, osVersion };
11
- }
12
- /**
13
- * Get the name and version of a macOS release from the Darwin version.
14
- * Lifted from `macos-release`.
15
- */
16
- function macosRelease() {
17
- const release = Number(os.release().split('.')[0]);
18
- const nameMap = new Map([
19
- [22, ['Ventura', '13']],
20
- [21, ['Monterey', '12']],
21
- [20, ['Big Sur', '11']],
22
- [19, ['Catalina', '10.15']],
23
- [18, ['Mojave', '10.14']],
24
- [17, ['High Sierra', '10.13']],
25
- [16, ['Sierra', '10.12']],
26
- [15, ['El Capitan', '10.11']],
27
- [14, ['Yosemite', '10.10']],
28
- [13, ['Mavericks', '10.9']],
29
- [12, ['Mountain Lion', '10.8']],
30
- [11, ['Lion', '10.7']],
31
- [10, ['Snow Leopard', '10.6']],
32
- [9, ['Leopard', '10.5']],
33
- [8, ['Tiger', '10.4']],
34
- [7, ['Panther', '10.3']],
35
- [6, ['Jaguar', '10.2']],
36
- [5, ['Puma', '10.1']],
37
- ]);
38
- const current = nameMap.get(release);
39
- return current ? `${current[0]} (${current[1]})` : 'Unknown';
40
- }