@directus/api 9.25.1 → 9.26.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 (51) hide show
  1. package/dist/app.js +0 -2
  2. package/dist/auth/drivers/oauth2.d.ts +1 -1
  3. package/dist/auth/drivers/openid.d.ts +1 -1
  4. package/dist/cli/commands/init/index.js +1 -1
  5. package/dist/cli/commands/schema/apply.js +1 -1
  6. package/dist/controllers/assets.js +11 -5
  7. package/dist/controllers/files.d.ts +1 -1
  8. package/dist/database/helpers/fn/dialects/mssql.d.ts +2 -1
  9. package/dist/database/helpers/fn/dialects/mysql.d.ts +2 -1
  10. package/dist/database/helpers/fn/dialects/oracle.d.ts +2 -1
  11. package/dist/database/helpers/fn/dialects/postgres.d.ts +2 -1
  12. package/dist/database/helpers/fn/dialects/sqlite.d.ts +2 -1
  13. package/dist/database/helpers/geometry/types.d.ts +1 -1
  14. package/dist/database/helpers/schema/dialects/cockroachdb.d.ts +2 -1
  15. package/dist/database/helpers/schema/dialects/oracle.d.ts +2 -1
  16. package/dist/database/migrations/run.js +8 -0
  17. package/dist/extensions.js +40 -40
  18. package/dist/mailer.d.ts +1 -1
  19. package/dist/operations/exec/index.js +1 -1
  20. package/dist/operations/mail/index.d.ts +5 -3
  21. package/dist/operations/mail/index.js +12 -8
  22. package/dist/operations/mail/index.test.d.ts +1 -0
  23. package/dist/rate-limiter.d.ts +1 -1
  24. package/dist/rate-limiter.js +1 -1
  25. package/dist/server.js +2 -2
  26. package/dist/services/collections.d.ts +2 -2
  27. package/dist/services/collections.js +2 -2
  28. package/dist/services/fields.d.ts +1 -1
  29. package/dist/services/fields.js +1 -1
  30. package/dist/services/graphql/index.d.ts +2 -1
  31. package/dist/services/graphql/index.js +3 -4
  32. package/dist/services/graphql/utils/add-path-to-validation-error.js +1 -1
  33. package/dist/services/payload.d.ts +1 -1
  34. package/dist/services/payload.js +2 -2
  35. package/dist/services/permissions.d.ts +2 -1
  36. package/dist/services/relations.d.ts +4 -3
  37. package/dist/services/relations.js +1 -1
  38. package/dist/services/server.js +3 -2
  39. package/dist/services/webhooks.d.ts +1 -1
  40. package/dist/utils/apply-diff.d.ts +1 -1
  41. package/dist/utils/apply-diff.js +2 -2
  42. package/dist/utils/apply-query.d.ts +1 -1
  43. package/dist/utils/apply-query.js +1 -1
  44. package/dist/utils/get-cache-key.js +2 -0
  45. package/dist/utils/get-graphql-type.d.ts +2 -1
  46. package/dist/utils/get-graphql-type.js +1 -1
  47. package/dist/utils/get-snapshot-diff.d.ts +1 -1
  48. package/dist/utils/validate-diff.d.ts +1 -1
  49. package/dist/utils/validate-snapshot.d.ts +1 -1
  50. package/dist/utils/validate-snapshot.js +4 -4
  51. package/package.json +48 -50
package/dist/app.js CHANGED
@@ -6,7 +6,6 @@ import { createRequire } from 'node:module';
6
6
  import path from 'path';
7
7
  import qs from 'qs';
8
8
  import { registerAuthProviders } from './auth.js';
9
- import { flushCaches } from './cache.js';
10
9
  import activityRouter from './controllers/activity.js';
11
10
  import assetsRouter from './controllers/assets.js';
12
11
  import authRouter from './controllers/auth.js';
@@ -76,7 +75,6 @@ export default async function createApp() {
76
75
  if ((await validateMigrations()) === false) {
77
76
  logger.warn(`Database migrations have not all been run`);
78
77
  }
79
- await flushCaches();
80
78
  await registerAuthProviders();
81
79
  const extensionManager = getExtensionManager();
82
80
  const flowManager = getFlowManager();
@@ -1,5 +1,5 @@
1
1
  import { Router } from 'express';
2
- import { Client } from 'openid-client';
2
+ import type { Client } from 'openid-client';
3
3
  import { UsersService } from '../../services/users.js';
4
4
  import type { AuthDriverOptions, User } from '../../types/index.js';
5
5
  import { LocalAuthDriver } from './local.js';
@@ -1,5 +1,5 @@
1
1
  import { Router } from 'express';
2
- import { Client } from 'openid-client';
2
+ import type { Client } from 'openid-client';
3
3
  import { UsersService } from '../../services/users.js';
4
4
  import type { AuthDriverOptions, User } from '../../types/index.js';
5
5
  import { LocalAuthDriver } from './local.js';
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import execa from 'execa';
2
+ import { execa } from 'execa';
3
3
  import inquirer from 'inquirer';
4
4
  import Joi from 'joi';
5
5
  import ora from 'ora';
@@ -9,8 +9,8 @@ import logger from '../../../logger.js';
9
9
  import { DiffKind } from '../../../types/index.js';
10
10
  import { isNestedMetaUpdate } from '../../../utils/apply-diff.js';
11
11
  import { applySnapshot } from '../../../utils/apply-snapshot.js';
12
- import { getSnapshot } from '../../../utils/get-snapshot.js';
13
12
  import { getSnapshotDiff } from '../../../utils/get-snapshot-diff.js';
13
+ import { getSnapshot } from '../../../utils/get-snapshot.js';
14
14
  export async function apply(snapshotPath, options) {
15
15
  const filename = path.resolve(process.cwd(), snapshotPath);
16
16
  const database = getDatabase();
@@ -105,18 +105,23 @@ asyncHandler(async (req, res) => {
105
105
  accountability: req.accountability,
106
106
  schema: req.schema,
107
107
  });
108
+ const vary = ['Origin', 'Cache-Control'];
108
109
  const transformation = res.locals['transformation'].key
109
110
  ? res.locals['shortcuts'].find((transformation) => transformation['key'] === res.locals['transformation'].key)
110
111
  : res.locals['transformation'];
111
- if (transformation.format === 'auto' && req.headers.accept) {
112
- let format = 'jpg';
113
- if (req.headers.accept.includes('image/webp')) {
112
+ if (transformation.format === 'auto') {
113
+ let format;
114
+ if (req.headers.accept?.includes('image/avif')) {
115
+ format = 'avif';
116
+ }
117
+ else if (req.headers.accept?.includes('image/webp')) {
114
118
  format = 'webp';
115
119
  }
116
- else if (req.headers.accept.includes('image/avif')) {
117
- format = 'avif';
120
+ else {
121
+ format = 'jpg';
118
122
  }
119
123
  transformation.format = format;
124
+ vary.push('Accept');
120
125
  }
121
126
  let range = undefined;
122
127
  if (req.headers.range) {
@@ -141,6 +146,7 @@ asyncHandler(async (req, res) => {
141
146
  res.setHeader('Content-Type', file.type);
142
147
  res.setHeader('Accept-Ranges', 'bytes');
143
148
  res.setHeader('Cache-Control', getCacheControlHeader(req, getMilliseconds(env['ASSETS_CACHE_TTL']), false, true));
149
+ res.setHeader('Vary', vary.join(', '));
144
150
  const unixTime = Date.parse(file.modified_on);
145
151
  if (!Number.isNaN(unixTime)) {
146
152
  const lastModifiedDate = new Date(unixTime);
@@ -1,4 +1,4 @@
1
- import { RequestHandler } from 'express';
1
+ import type { RequestHandler } from 'express';
2
2
  declare const router: import("express-serve-static-core").Router;
3
3
  export declare const multipartHandler: RequestHandler;
4
4
  export default router;
@@ -1,5 +1,6 @@
1
1
  import type { Knex } from 'knex';
2
- import { FnHelper, FnHelperOptions } from '../types.js';
2
+ import type { FnHelperOptions } from '../types.js';
3
+ import { FnHelper } from '../types.js';
3
4
  export declare class FnHelperMSSQL extends FnHelper {
4
5
  year(table: string, column: string, options: FnHelperOptions): Knex.Raw;
5
6
  month(table: string, column: string, options: FnHelperOptions): Knex.Raw;
@@ -1,5 +1,6 @@
1
1
  import type { Knex } from 'knex';
2
- import { FnHelper, FnHelperOptions } from '../types.js';
2
+ import type { FnHelperOptions } from '../types.js';
3
+ import { FnHelper } from '../types.js';
3
4
  export declare class FnHelperMySQL extends FnHelper {
4
5
  year(table: string, column: string): Knex.Raw;
5
6
  month(table: string, column: string): Knex.Raw;
@@ -1,5 +1,6 @@
1
1
  import type { Knex } from 'knex';
2
- import { FnHelper, FnHelperOptions } from '../types.js';
2
+ import type { FnHelperOptions } from '../types.js';
3
+ import { FnHelper } from '../types.js';
3
4
  export declare class FnHelperOracle extends FnHelper {
4
5
  year(table: string, column: string, options: FnHelperOptions): Knex.Raw;
5
6
  month(table: string, column: string, options: FnHelperOptions): Knex.Raw;
@@ -1,5 +1,6 @@
1
1
  import type { Knex } from 'knex';
2
- import { FnHelper, FnHelperOptions } from '../types.js';
2
+ import type { FnHelperOptions } from '../types.js';
3
+ import { FnHelper } from '../types.js';
3
4
  export declare class FnHelperPostgres extends FnHelper {
4
5
  year(table: string, column: string, options: FnHelperOptions): Knex.Raw;
5
6
  month(table: string, column: string, options: FnHelperOptions): Knex.Raw;
@@ -1,5 +1,6 @@
1
1
  import type { Knex } from 'knex';
2
- import { FnHelper, FnHelperOptions } from '../types.js';
2
+ import type { FnHelperOptions } from '../types.js';
3
+ import { FnHelper } from '../types.js';
3
4
  export declare class FnHelperSQLite extends FnHelper {
4
5
  year(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
5
6
  month(table: string, column: string, options?: FnHelperOptions): Knex.Raw;
@@ -1,6 +1,6 @@
1
1
  import type { Field, RawField } from '@directus/types';
2
2
  import type { Knex } from 'knex';
3
- import { GeoJSONGeometry } from 'wellknown';
3
+ import type { GeoJSONGeometry } from 'wellknown';
4
4
  import { DatabaseHelper } from '../types.js';
5
5
  export declare abstract class GeometryHelper extends DatabaseHelper {
6
6
  supported(): boolean | Promise<boolean>;
@@ -1,5 +1,6 @@
1
1
  import type { KNEX_TYPES } from '@directus/constants';
2
- import { Options, SchemaHelper } from '../types.js';
2
+ import type { Options } from '../types.js';
3
+ import { SchemaHelper } from '../types.js';
3
4
  export declare class SchemaHelperCockroachDb extends SchemaHelper {
4
5
  changeToType(table: string, column: string, type: (typeof KNEX_TYPES)[number], options?: Options): Promise<void>;
5
6
  constraintName(existingName: string): string;
@@ -1,6 +1,7 @@
1
1
  import type { KNEX_TYPES } from '@directus/constants';
2
2
  import type { Field, Relation, Type } from '@directus/types';
3
- import { Options, SchemaHelper } from '../types.js';
3
+ import type { Options } from '../types.js';
4
+ import { SchemaHelper } from '../types.js';
4
5
  export declare class SchemaHelperOracle extends SchemaHelper {
5
6
  changeToType(table: string, column: string, type: (typeof KNEX_TYPES)[number], options?: Options): Promise<void>;
6
7
  castA2oPrimaryKey(): string;
@@ -4,6 +4,7 @@ import { orderBy } from 'lodash-es';
4
4
  import { dirname } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import path from 'path';
7
+ import { flushCaches } from '../../cache.js';
7
8
  import env from '../../env.js';
8
9
  import logger from '../../logger.js';
9
10
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -59,6 +60,7 @@ export default async function run(database, direction, log = true) {
59
60
  }
60
61
  await up(database);
61
62
  await database.insert({ version: nextVersion.version, name: nextVersion.name }).into('directus_migrations');
63
+ await flushCaches(true);
62
64
  }
63
65
  async function down() {
64
66
  const lastAppliedMigration = orderBy(completedMigrations, ['timestamp', 'version'], ['desc', 'desc'])[0];
@@ -75,10 +77,13 @@ export default async function run(database, direction, log = true) {
75
77
  }
76
78
  await down(database);
77
79
  await database('directus_migrations').delete().where({ version: migration.version });
80
+ await flushCaches(true);
78
81
  }
79
82
  async function latest() {
83
+ let needsCacheFlush = false;
80
84
  for (const migration of migrations) {
81
85
  if (migration.completed === false) {
86
+ needsCacheFlush = true;
82
87
  const { up } = await import(`file://${migration.file}`);
83
88
  if (log) {
84
89
  logger.info(`Applying ${migration.name}...`);
@@ -87,5 +92,8 @@ export default async function run(database, direction, log = true) {
87
92
  await database.insert({ version: migration.version, name: migration.name }).into('directus_migrations');
88
93
  }
89
94
  }
95
+ if (needsCacheFlush) {
96
+ await flushCaches(true);
97
+ }
90
98
  }
91
99
  }
@@ -5,9 +5,8 @@ import { ensureExtensionDirs, generateExtensionsEntrypoint, getLocalExtensions,
5
5
  import aliasDefault from '@rollup/plugin-alias';
6
6
  import nodeResolveDefault from '@rollup/plugin-node-resolve';
7
7
  import virtualDefault from '@rollup/plugin-virtual';
8
- import chokidar from 'chokidar';
8
+ import chokidar, { FSWatcher } from 'chokidar';
9
9
  import express, { Router } from 'express';
10
- import globby from 'globby';
11
10
  import { clone, escapeRegExp } from 'lodash-es';
12
11
  import { schedule, validate } from 'node-cron';
13
12
  import { readdir } from 'node:fs/promises';
@@ -67,15 +66,15 @@ class ExtensionManager {
67
66
  this.appExtensionChunks = new Map();
68
67
  }
69
68
  async initialize(options = {}) {
70
- const prevOptions = this.options;
71
69
  this.options = {
72
70
  ...defaultOptions,
73
71
  ...options,
74
72
  };
75
- if (!prevOptions.watch && this.options.watch) {
73
+ const wasWatcherInitialized = this.watcher !== null;
74
+ if (this.options.watch && !wasWatcherInitialized) {
76
75
  this.initializeWatcher();
77
76
  }
78
- else if (prevOptions.watch && !this.options.watch) {
77
+ else if (!this.options.watch && wasWatcherInitialized) {
79
78
  await this.closeWatcher();
80
79
  }
81
80
  if (!this.isLoaded) {
@@ -85,7 +84,7 @@ class ExtensionManager {
85
84
  logger.info(`Loaded extensions: ${loadedExtensions.map((ext) => ext.name).join(', ')}`);
86
85
  }
87
86
  }
88
- if (!prevOptions.watch && this.options.watch) {
87
+ if (this.options.watch && !wasWatcherInitialized) {
89
88
  this.updateWatchedExtensions(this.extensions);
90
89
  }
91
90
  }
@@ -198,35 +197,39 @@ class ExtensionManager {
198
197
  this.isLoaded = false;
199
198
  }
200
199
  initializeWatcher() {
201
- if (!this.watcher) {
202
- logger.info('Watching extensions for changes...');
203
- const localExtensionPaths = NESTED_EXTENSION_TYPES.flatMap((type) => {
204
- const typeDir = path.posix.join(pathToRelativeUrl(env['EXTENSIONS_PATH']), pluralize(type));
205
- if (isIn(type, HYBRID_EXTENSION_TYPES)) {
206
- return [path.posix.join(typeDir, '*', 'app.js'), path.posix.join(typeDir, '*', 'api.js')];
207
- }
208
- else {
209
- return path.posix.join(typeDir, '*', 'index.js');
210
- }
211
- });
212
- this.watcher = chokidar.watch([path.resolve('package.json'), ...localExtensionPaths], {
213
- ignoreInitial: true,
214
- });
215
- this.watcher
216
- .on('add', () => this.reload())
217
- .on('change', () => this.reload())
218
- .on('unlink', () => this.reload());
219
- }
200
+ logger.info('Watching extensions for changes...');
201
+ const extensionDirUrl = pathToRelativeUrl(env['EXTENSIONS_PATH']);
202
+ const localExtensionUrls = NESTED_EXTENSION_TYPES.flatMap((type) => {
203
+ const typeDir = path.posix.join(extensionDirUrl, pluralize(type));
204
+ const fileExts = ['js', 'mjs', 'cjs'];
205
+ if (isIn(type, HYBRID_EXTENSION_TYPES)) {
206
+ return [
207
+ path.posix.join(typeDir, '*', `app.{${fileExts.join()}}`),
208
+ path.posix.join(typeDir, '*', `api.{${fileExts.join()}}`),
209
+ ];
210
+ }
211
+ else {
212
+ return path.posix.join(typeDir, '*', `index.{${fileExts.join()}}`);
213
+ }
214
+ });
215
+ this.watcher = chokidar.watch([path.resolve('package.json'), path.posix.join(extensionDirUrl, '*', 'package.json'), ...localExtensionUrls], {
216
+ ignoreInitial: true,
217
+ });
218
+ this.watcher
219
+ .on('add', () => this.reload())
220
+ .on('change', () => this.reload())
221
+ .on('unlink', () => this.reload());
220
222
  }
221
223
  async closeWatcher() {
222
224
  if (this.watcher) {
223
225
  await this.watcher.close();
226
+ this.watcher = null;
224
227
  }
225
228
  }
226
229
  updateWatchedExtensions(added, removed = []) {
227
230
  if (this.watcher) {
228
231
  const toPackageExtensionPaths = (extensions) => extensions
229
- .filter((extension) => !extension.local)
232
+ .filter((extension) => !extension.local || extension.type === 'bundle')
230
233
  .flatMap((extension) => isTypeIn(extension, HYBRID_EXTENSION_TYPES) || extension.type === 'bundle'
231
234
  ? [
232
235
  path.resolve(extension.path, extension.entrypoint.app),
@@ -295,7 +298,7 @@ class ExtensionManager {
295
298
  for (const hook of hooks) {
296
299
  try {
297
300
  const hookPath = path.resolve(hook.path, hook.entrypoint);
298
- const hookInstance = await import(`file://${hookPath}`);
301
+ const hookInstance = await import(`./${pathToRelativeUrl(hookPath, __dirname)}?t=${Date.now()}`);
299
302
  const config = getModuleDefault(hookInstance);
300
303
  this.registerHook(config);
301
304
  this.apiExtensions.push({ path: hookPath });
@@ -311,7 +314,7 @@ class ExtensionManager {
311
314
  for (const endpoint of endpoints) {
312
315
  try {
313
316
  const endpointPath = path.resolve(endpoint.path, endpoint.entrypoint);
314
- const endpointInstance = await import(`file://${endpointPath}`);
317
+ const endpointInstance = await import(`./${pathToRelativeUrl(endpointPath, __dirname)}?t=${Date.now()}`);
315
318
  const config = getModuleDefault(endpointInstance);
316
319
  this.registerEndpoint(config, endpoint.name);
317
320
  this.apiExtensions.push({ path: endpointPath });
@@ -323,20 +326,17 @@ class ExtensionManager {
323
326
  }
324
327
  }
325
328
  async registerOperations() {
326
- const internalPaths = await globby(path.posix.join(pathToRelativeUrl(__dirname), 'operations/*/index.(js|ts)'));
327
- const internalOperations = internalPaths.map((internalPath) => {
328
- const dirs = internalPath.split(path.sep);
329
- return {
330
- name: dirs[dirs.length - 2],
331
- path: dirs.slice(0, -1).join(path.sep),
332
- entrypoint: { api: dirs[dirs.length - 1] },
333
- };
334
- });
329
+ const internalOperations = await readdir(path.join(__dirname, 'operations'));
330
+ for (const operation of internalOperations) {
331
+ const operationInstance = await import(`./operations/${operation}/index.js`);
332
+ const config = getModuleDefault(operationInstance);
333
+ this.registerOperation(config);
334
+ }
335
335
  const operations = this.extensions.filter((extension) => extension.type === 'operation');
336
- for (const operation of [...internalOperations, ...operations]) {
336
+ for (const operation of operations) {
337
337
  try {
338
338
  const operationPath = path.resolve(operation.path, operation.entrypoint.api);
339
- const operationInstance = await import(`file://${operationPath}`);
339
+ const operationInstance = await import(`./${pathToRelativeUrl(operationPath, __dirname)}?t=${Date.now()}`);
340
340
  const config = getModuleDefault(operationInstance);
341
341
  this.registerOperation(config);
342
342
  this.apiExtensions.push({ path: operationPath });
@@ -352,7 +352,7 @@ class ExtensionManager {
352
352
  for (const bundle of bundles) {
353
353
  try {
354
354
  const bundlePath = path.resolve(bundle.path, bundle.entrypoint.api);
355
- const bundleInstances = await import(`file://${bundlePath}`);
355
+ const bundleInstances = await import(`./${pathToRelativeUrl(bundlePath, __dirname)}?t=${Date.now()}`);
356
356
  const configs = getModuleDefault(bundleInstances);
357
357
  for (const { config } of configs.hooks) {
358
358
  this.registerHook(config);
package/dist/mailer.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { Transporter } from 'nodemailer';
1
+ import type { Transporter } from 'nodemailer';
2
2
  export default function getMailer(): Transporter;
@@ -1,6 +1,6 @@
1
1
  import { defineOperationApi, toArray } from '@directus/utils';
2
- import { NodeVM, VMScript } from 'vm2';
3
2
  import { isBuiltin } from 'node:module';
3
+ import { NodeVM, VMScript } from 'vm2';
4
4
  export default defineOperationApi({
5
5
  id: 'exec',
6
6
  handler: async ({ code }, { data, env }) => {
@@ -1,7 +1,9 @@
1
- type Options = {
2
- body: string;
1
+ export type Options = {
2
+ body?: string;
3
+ template?: string;
4
+ data?: Record<string, any>;
3
5
  to: string;
4
- type: 'wysiwyg' | 'markdown';
6
+ type: 'wysiwyg' | 'markdown' | 'template';
5
7
  subject: string;
6
8
  };
7
9
  declare const _default: import("@directus/types").OperationApiConfig<Options>;
@@ -3,15 +3,19 @@ import { MailService } from '../../services/mail/index.js';
3
3
  import { md } from '../../utils/md.js';
4
4
  export default defineOperationApi({
5
5
  id: 'mail',
6
- handler: async ({ body, to, type, subject }, { accountability, database, getSchema }) => {
6
+ handler: async ({ body, template, data, to, type, subject }, { accountability, database, getSchema }) => {
7
7
  const mailService = new MailService({ schema: await getSchema({ database }), accountability, knex: database });
8
- // If 'body' is of type object/undefined (happens when body consists solely of a placeholder)
9
- // convert it to JSON string
8
+ const mailObject = { to, subject };
10
9
  const safeBody = typeof body !== 'string' ? JSON.stringify(body) : body;
11
- await mailService.send({
12
- html: type === 'wysiwyg' ? safeBody : md(safeBody),
13
- to,
14
- subject,
15
- });
10
+ if (type === 'template') {
11
+ mailObject.template = {
12
+ name: template || 'base',
13
+ data: data || {},
14
+ };
15
+ }
16
+ else {
17
+ mailObject.html = type === 'wysiwyg' ? safeBody : md(safeBody);
18
+ }
19
+ await mailService.send(mailObject);
16
20
  },
17
21
  });
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { IRateLimiterOptions, IRateLimiterStoreOptions, RateLimiterAbstract } from 'rate-limiter-flexible';
1
+ import type { IRateLimiterOptions, IRateLimiterStoreOptions, RateLimiterAbstract } from 'rate-limiter-flexible';
2
2
  type IRateLimiterOptionsOverrides = Partial<IRateLimiterOptions> | Partial<IRateLimiterStoreOptions>;
3
3
  export declare function createRateLimiter(configPrefix?: string, configOverrides?: IRateLimiterOptionsOverrides): RateLimiterAbstract;
4
4
  export {};
@@ -1,5 +1,5 @@
1
1
  import { merge } from 'lodash-es';
2
- import { RateLimiterMemcache, RateLimiterMemory, RateLimiterRedis, } from 'rate-limiter-flexible';
2
+ import { RateLimiterMemcache, RateLimiterMemory, RateLimiterRedis } from 'rate-limiter-flexible';
3
3
  import env from './env.js';
4
4
  import { getConfigFromEnv } from './utils/get-config-from-env.js';
5
5
  import { createRequire } from 'node:module';
package/dist/server.js CHANGED
@@ -1,17 +1,17 @@
1
+ import { isUpToDate } from '@directus/update-check';
1
2
  import { createTerminus } from '@godaddy/terminus';
2
3
  import * as http from 'http';
3
4
  import * as https from 'https';
4
5
  import { once } from 'lodash-es';
5
6
  import qs from 'qs';
6
- import { isUpToDate } from '@directus/update-check';
7
7
  import url from 'url';
8
- import * as pkg from './utils/package.js';
9
8
  import createApp from './app.js';
10
9
  import getDatabase from './database/index.js';
11
10
  import emitter from './emitter.js';
12
11
  import env from './env.js';
13
12
  import logger from './logger.js';
14
13
  import { getConfigFromEnv } from './utils/get-config-from-env.js';
14
+ import * as pkg from './utils/package.js';
15
15
  export let SERVER_ONLINE = true;
16
16
  export async function createServer() {
17
17
  const server = http.createServer(await createApp());
@@ -1,8 +1,8 @@
1
+ import type { SchemaInspector, Table } from '@directus/schema';
1
2
  import type { Accountability, RawField, SchemaOverview } from '@directus/types';
2
3
  import type Keyv from 'keyv';
3
4
  import type { Knex } from 'knex';
4
- import type { Table, SchemaInspector } from '@directus/schema';
5
- import { Helpers } from '../database/helpers/index.js';
5
+ import type { Helpers } from '../database/helpers/index.js';
6
6
  import type { AbstractServiceOptions, Collection, CollectionMeta, MutationOptions } from '../types/index.js';
7
7
  export type RawCollection = {
8
8
  collection: string;
@@ -1,10 +1,10 @@
1
1
  import { createInspector } from '@directus/schema';
2
2
  import { addFieldFlag } from '@directus/utils';
3
- import { omit, chunk } from 'lodash-es';
3
+ import { chunk, omit } from 'lodash-es';
4
4
  import { clearSystemCache, getCache } from '../cache.js';
5
5
  import { ALIAS_TYPES } from '../constants.js';
6
- import getDatabase, { getSchemaInspector } from '../database/index.js';
7
6
  import { getHelpers } from '../database/helpers/index.js';
7
+ import getDatabase, { getSchemaInspector } from '../database/index.js';
8
8
  import { systemCollectionRows } from '../database/system-data/collections/index.js';
9
9
  import emitter from '../emitter.js';
10
10
  import env from '../env.js';
@@ -2,7 +2,7 @@ import type { Column, SchemaInspector } from '@directus/schema';
2
2
  import type { Accountability, Field, RawField, SchemaOverview, Type } from '@directus/types';
3
3
  import type Keyv from 'keyv';
4
4
  import type { Knex } from 'knex';
5
- import { Helpers } from '../database/helpers/index.js';
5
+ import type { Helpers } from '../database/helpers/index.js';
6
6
  import { ItemsService } from '../services/items.js';
7
7
  import { PayloadService } from '../services/payload.js';
8
8
  import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
@@ -1,5 +1,5 @@
1
- import { createInspector } from '@directus/schema';
2
1
  import { KNEX_TYPES, REGEX_BETWEEN_PARENS } from '@directus/constants';
2
+ import { createInspector } from '@directus/schema';
3
3
  import { addFieldFlag, toArray } from '@directus/utils';
4
4
  import { isEqual, isNil } from 'lodash-es';
5
5
  import { clearSystemCache, getCache } from '../cache.js';
@@ -1,6 +1,7 @@
1
1
  import type { BaseException } from '@directus/exceptions';
2
2
  import type { Accountability, Filter, Query, SchemaOverview } from '@directus/types';
3
- import { ArgumentNode, FormattedExecutionResult, FragmentDefinitionNode, GraphQLError, GraphQLResolveInfo, GraphQLSchema, SelectionNode } from 'graphql';
3
+ import type { ArgumentNode, FormattedExecutionResult, FragmentDefinitionNode, GraphQLResolveInfo, SelectionNode } from 'graphql';
4
+ import { GraphQLError, GraphQLSchema } from 'graphql';
4
5
  import { ObjectTypeComposer, SchemaComposer } from 'graphql-compose';
5
6
  import type { Knex } from 'knex';
6
7
  import type { AbstractServiceOptions, GraphQLParams, Item } from '../../types/index.js';
@@ -1,9 +1,8 @@
1
- import { FUNCTIONS } from '@directus/constants';
2
- import { Action } from '@directus/constants';
1
+ import { Action, FUNCTIONS } from '@directus/constants';
3
2
  import { parseFilterFunctionPath } from '@directus/utils';
4
3
  import argon2 from 'argon2';
5
- import { execute, GraphQLBoolean, GraphQLEnumType, GraphQLError, GraphQLFloat, GraphQLID, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLString, GraphQLUnionType, NoSchemaIntrospectionCustomRule, specifiedRules, validate, } from 'graphql';
6
- import { GraphQLJSON, SchemaComposer, toInputObjectType, } from 'graphql-compose';
4
+ import { GraphQLBoolean, GraphQLEnumType, GraphQLError, GraphQLFloat, GraphQLID, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, GraphQLSchema, GraphQLString, GraphQLUnionType, NoSchemaIntrospectionCustomRule, execute, specifiedRules, validate, } from 'graphql';
5
+ import { GraphQLJSON, InputTypeComposer, ObjectTypeComposer, SchemaComposer, toInputObjectType } from 'graphql-compose';
7
6
  import { flatten, get, mapKeys, merge, omit, pick, set, transform, uniq } from 'lodash-es';
8
7
  import { clearSystemCache, getCache } from '../../cache.js';
9
8
  import { DEFAULT_AUTH_PROVIDER, GENERATE_SPECIAL } from '../../constants.js';
@@ -1,4 +1,4 @@
1
- import { locatedError } from 'graphql';
1
+ import { GraphQLError, Token, locatedError } from 'graphql';
2
2
  export function addPathToValidationError(validationError) {
3
3
  const token = validationError.nodes?.[0]?.loc?.startToken;
4
4
  if (!token)
@@ -1,6 +1,6 @@
1
1
  import type { Accountability, SchemaOverview } from '@directus/types';
2
2
  import type { Knex } from 'knex';
3
- import { Helpers } from '../database/helpers/index.js';
3
+ import type { Helpers } from '../database/helpers/index.js';
4
4
  import type { AbstractServiceOptions, ActionEventParams, Item, MutationOptions, PrimaryKey } from '../types/index.js';
5
5
  type Action = 'create' | 'read' | 'update';
6
6
  type Transformers = {
@@ -1,12 +1,12 @@
1
- import { format, parseISO, isValid } from 'date-fns';
2
1
  import { parseJSON, toArray } from '@directus/utils';
2
+ import { format, isValid, parseISO } from 'date-fns';
3
3
  import flat from 'flat';
4
4
  import Joi from 'joi';
5
5
  import { clone, cloneDeep, isNil, isObject, isPlainObject, omit, pick } from 'lodash-es';
6
6
  import { v4 as uuid } from 'uuid';
7
7
  import { parse as wktToGeoJSON } from 'wellknown';
8
- import getDatabase from '../database/index.js';
9
8
  import { getHelpers } from '../database/helpers/index.js';
9
+ import getDatabase from '../database/index.js';
10
10
  import { ForbiddenException, InvalidPayloadException } from '../exceptions/index.js';
11
11
  import { generateHash } from '../utils/generate-hash.js';
12
12
  import { ItemsService } from './items.js';
@@ -1,6 +1,7 @@
1
1
  import type { PermissionsAction, Query } from '@directus/types';
2
2
  import type Keyv from 'keyv';
3
- import { ItemsService, QueryOptions } from '../services/items.js';
3
+ import type { QueryOptions } from '../services/items.js';
4
+ import { ItemsService } from '../services/items.js';
4
5
  import type { AbstractServiceOptions, Item, MutationOptions, PrimaryKey } from '../types/index.js';
5
6
  export declare class PermissionsService extends ItemsService {
6
7
  systemCache: Keyv<any>;
@@ -1,10 +1,11 @@
1
+ import type { SchemaInspector } from '@directus/schema';
1
2
  import type { Accountability, Relation, RelationMeta, SchemaOverview } from '@directus/types';
2
3
  import type Keyv from 'keyv';
3
4
  import type { Knex } from 'knex';
4
- import type { SchemaInspector } from '@directus/schema';
5
- import { Helpers } from '../database/helpers/index.js';
5
+ import type { Helpers } from '../database/helpers/index.js';
6
6
  import type { AbstractServiceOptions, MutationOptions } from '../types/index.js';
7
- import { ItemsService, QueryOptions } from './items.js';
7
+ import type { QueryOptions } from './items.js';
8
+ import { ItemsService } from './items.js';
8
9
  import { PermissionsService } from './permissions.js';
9
10
  export declare class RelationsService {
10
11
  knex: Knex;
@@ -1,8 +1,8 @@
1
1
  import { createInspector } from '@directus/schema';
2
2
  import { toArray } from '@directus/utils';
3
3
  import { clearSystemCache, getCache } from '../cache.js';
4
- import getDatabase, { getSchemaInspector } from '../database/index.js';
5
4
  import { getHelpers } from '../database/helpers/index.js';
5
+ import getDatabase, { getSchemaInspector } from '../database/index.js';
6
6
  import { systemRelationRows } from '../database/system-data/relations/index.js';
7
7
  import emitter from '../emitter.js';
8
8
  import { ForbiddenException, InvalidPayloadException } from '../exceptions/index.js';
@@ -150,7 +150,8 @@ export class ServerService {
150
150
  }
151
151
  const endTime = performance.now();
152
152
  checks[`${client}:responseTime`][0].observedValue = +(endTime - startTime).toFixed(3);
153
- if (checks[`${client}:responseTime`][0].observedValue > checks[`${client}:responseTime`][0].threshold &&
153
+ if (Number(checks[`${client}:responseTime`][0].observedValue) >
154
+ checks[`${client}:responseTime`][0].threshold &&
154
155
  checks[`${client}:responseTime`][0].status !== 'error') {
155
156
  checks[`${client}:responseTime`][0].status = 'warn';
156
157
  }
@@ -307,7 +308,7 @@ export class ServerService {
307
308
  finally {
308
309
  const endTime = performance.now();
309
310
  checks[`storage:${location}:responseTime`][0].observedValue = +(endTime - startTime).toFixed(3);
310
- if (checks[`storage:${location}:responseTime`][0].observedValue >
311
+ if (Number(checks[`storage:${location}:responseTime`][0].observedValue) >
311
312
  checks[`storage:${location}:responseTime`][0].threshold &&
312
313
  checks[`storage:${location}:responseTime`][0].status !== 'error') {
313
314
  checks[`storage:${location}:responseTime`][0].status = 'warn';
@@ -1,4 +1,4 @@
1
- import { Messenger } from '../messenger.js';
1
+ import type { Messenger } from '../messenger.js';
2
2
  import type { AbstractServiceOptions, Item, MutationOptions, PrimaryKey, Webhook } from '../types/index.js';
3
3
  import { ItemsService } from './items.js';
4
4
  export declare class WebhooksService extends ItemsService<Webhook> {
@@ -1,7 +1,7 @@
1
1
  import type { SchemaOverview } from '@directus/types';
2
2
  import type { Diff } from 'deep-diff';
3
3
  import type { Knex } from 'knex';
4
- import { Snapshot, SnapshotDiff, SnapshotField } from '../types/index.js';
4
+ import type { Snapshot, SnapshotDiff, SnapshotField } from '../types/index.js';
5
5
  export declare function applyDiff(currentSnapshot: Snapshot, snapshotDiff: SnapshotDiff, options?: {
6
6
  database?: Knex;
7
7
  schema?: SchemaOverview;
@@ -1,15 +1,15 @@
1
1
  import deepDiff from 'deep-diff';
2
2
  import { cloneDeep, merge, set } from 'lodash-es';
3
3
  import { clearSystemCache } from '../cache.js';
4
+ import { getHelpers } from '../database/helpers/index.js';
4
5
  import getDatabase from '../database/index.js';
5
6
  import emitter from '../emitter.js';
6
7
  import logger from '../logger.js';
7
8
  import { CollectionsService } from '../services/collections.js';
8
9
  import { FieldsService } from '../services/fields.js';
9
10
  import { RelationsService } from '../services/relations.js';
10
- import { DiffKind, } from '../types/index.js';
11
+ import { DiffKind } from '../types/index.js';
11
12
  import { getSchema } from './get-schema.js';
12
- import { getHelpers } from '../database/helpers/index.js';
13
13
  export async function applyDiff(currentSnapshot, snapshotDiff, options) {
14
14
  const database = options?.database ?? getDatabase();
15
15
  const helpers = getHelpers(database);
@@ -1,6 +1,6 @@
1
1
  import type { Aggregate, Filter, Query, SchemaOverview } from '@directus/types';
2
2
  import type { Knex } from 'knex';
3
- import { AliasMap } from './get-column-path.js';
3
+ import type { AliasMap } from './get-column-path.js';
4
4
  export declare const generateAlias: (size?: number | undefined) => string;
5
5
  /**
6
6
  * Apply the Query to a given Knex query builder instance
@@ -3,8 +3,8 @@ import { clone, isPlainObject } from 'lodash-es';
3
3
  import validate from 'uuid-validate';
4
4
  import { getHelpers } from '../database/helpers/index.js';
5
5
  import { InvalidQueryException } from '../exceptions/invalid-query.js';
6
- import { getColumn } from './get-column.js';
7
6
  import { getColumnPath } from './get-column-path.js';
7
+ import { getColumn } from './get-column.js';
8
8
  import { getRelationInfo } from './get-relation-info.js';
9
9
  import { stripFunction } from './strip-function.js';
10
10
  // @ts-ignore
@@ -1,10 +1,12 @@
1
1
  import hash from 'object-hash';
2
2
  import url from 'url';
3
3
  import { getGraphqlQueryAndVariables } from './get-graphql-query-and-variables.js';
4
+ import { version } from './package.js';
4
5
  export function getCacheKey(req) {
5
6
  const path = url.parse(req.originalUrl).pathname;
6
7
  const isGraphQl = path?.startsWith('/graphql');
7
8
  const info = {
9
+ version,
8
10
  user: req.accountability?.user || null,
9
11
  path,
10
12
  query: isGraphQl ? getGraphqlQueryAndVariables(req) : req.sanitizedQuery,
@@ -1,3 +1,4 @@
1
1
  import type { Type } from '@directus/types';
2
- import { GraphQLList, GraphQLScalarType, GraphQLType } from 'graphql';
2
+ import type { GraphQLType } from 'graphql';
3
+ import { GraphQLList, GraphQLScalarType } from 'graphql';
3
4
  export declare function getGraphQLType(localType: Type | 'alias' | 'unknown', special: string[]): GraphQLScalarType | GraphQLList<GraphQLType>;
@@ -1,4 +1,4 @@
1
- import { GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLList, GraphQLString, } from 'graphql';
1
+ import { GraphQLBoolean, GraphQLFloat, GraphQLInt, GraphQLList, GraphQLScalarType, GraphQLString } from 'graphql';
2
2
  import { GraphQLJSON } from 'graphql-compose';
3
3
  import { GraphQLBigInt } from '../services/graphql/types/bigint.js';
4
4
  import { GraphQLDate } from '../services/graphql/types/date.js';
@@ -1,2 +1,2 @@
1
- import { Snapshot, SnapshotDiff } from '../types/index.js';
1
+ import type { Snapshot, SnapshotDiff } from '../types/index.js';
2
2
  export declare function getSnapshotDiff(current: Snapshot, after: Snapshot): SnapshotDiff;
@@ -1,4 +1,4 @@
1
- import { SnapshotDiffWithHash, SnapshotWithHash } from '../types/snapshot.js';
1
+ import type { SnapshotDiffWithHash, SnapshotWithHash } from '../types/snapshot.js';
2
2
  /**
3
3
  * Validates the diff against the current schema snapshot.
4
4
  *
@@ -1,4 +1,4 @@
1
- import { Snapshot } from '../types/index.js';
1
+ import type { Snapshot } from '../types/index.js';
2
2
  /**
3
3
  * Validates the snapshot against the current instance.
4
4
  **/
@@ -1,10 +1,10 @@
1
- import { version as currentDirectusVersion } from './package.js';
2
- import { InvalidPayloadException } from '../exceptions/invalid-payload.js';
3
- import { getDatabaseClient } from '../database/index.js';
4
- import Joi from 'joi';
5
1
  import { TYPES } from '@directus/constants';
2
+ import Joi from 'joi';
6
3
  import { ALIAS_TYPES } from '../constants.js';
4
+ import { getDatabaseClient } from '../database/index.js';
5
+ import { InvalidPayloadException } from '../exceptions/invalid-payload.js';
7
6
  import { DatabaseClients } from '../types/index.js';
7
+ import { version as currentDirectusVersion } from './package.js';
8
8
  const snapshotJoiSchema = Joi.object({
9
9
  version: Joi.number().valid(1).required(),
10
10
  directus: Joi.string().required(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@directus/api",
3
- "version": "9.25.1",
3
+ "version": "9.26.0",
4
4
  "description": "Directus is a real-time API and App dashboard for managing SQL database content",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -64,21 +64,21 @@
64
64
  ],
65
65
  "dependencies": {
66
66
  "@authenio/samlify-node-xmllint": "2.0.0",
67
- "@aws-sdk/client-ses": "3.292.0",
67
+ "@aws-sdk/client-ses": "3.316.0",
68
68
  "@directus/format-title": "10.0.0",
69
- "@godaddy/terminus": "4.11.2",
70
- "@rollup/plugin-alias": "4.0.3",
71
- "@rollup/plugin-node-resolve": "15.0.1",
69
+ "@godaddy/terminus": "4.12.0",
70
+ "@rollup/plugin-alias": "5.0.0",
71
+ "@rollup/plugin-node-resolve": "15.0.2",
72
72
  "@rollup/plugin-virtual": "3.0.1",
73
73
  "argon2": "0.30.3",
74
74
  "async": "3.2.4",
75
- "axios": "1.3.4",
75
+ "axios": "1.3.6",
76
76
  "busboy": "1.6.0",
77
77
  "bytes": "3.1.2",
78
- "camelcase": "6.3.0",
79
- "chalk": "4.1.2",
78
+ "camelcase": "7.0.1",
79
+ "chalk": "5.2.0",
80
80
  "chokidar": "3.5.3",
81
- "commander": "9.5.0",
81
+ "commander": "10.0.1",
82
82
  "content-disposition": "0.5.4",
83
83
  "cookie-parser": "1.4.6",
84
84
  "cors": "2.8.5",
@@ -89,20 +89,19 @@
89
89
  "dotenv": "16.0.3",
90
90
  "encodeurl": "1.0.2",
91
91
  "eventemitter2": "6.4.9",
92
- "execa": "5.1.1",
92
+ "execa": "7.1.1",
93
93
  "exif-reader": "1.2.0",
94
94
  "express": "4.18.2",
95
95
  "fast-redact": "3.1.2",
96
96
  "flat": "5.0.2",
97
- "fs-extra": "11.1.0",
98
- "globby": "11.1.0",
97
+ "fs-extra": "11.1.1",
99
98
  "graphql": "16.6.0",
100
99
  "graphql-compose": "9.0.10",
101
- "helmet": "6.0.1",
102
- "icc": "2.0.0",
103
- "inquirer": "8.2.5",
104
- "ioredis": "5.3.1",
105
- "joi": "17.8.4",
100
+ "helmet": "6.1.5",
101
+ "icc": "3.0.0",
102
+ "inquirer": "9.1.5",
103
+ "ioredis": "5.3.2",
104
+ "joi": "17.9.1",
106
105
  "js-yaml": "4.1.0",
107
106
  "js2xmlparser": "5.0.0",
108
107
  "json2csv": "5.0.7",
@@ -110,20 +109,20 @@
110
109
  "keyv": "4.5.2",
111
110
  "knex": "2.4.2",
112
111
  "ldapjs": "2.3.3",
113
- "liquidjs": "10.6.1",
112
+ "liquidjs": "10.7.0",
114
113
  "lodash-es": "4.17.21",
115
- "marked": "4.2.12",
114
+ "marked": "4.3.0",
116
115
  "micromustache": "8.0.3",
117
116
  "mime-types": "2.1.35",
118
117
  "ms": "2.1.3",
119
- "nanoid": "3.3.4",
118
+ "nanoid": "4.0.2",
120
119
  "node-cron": "3.0.2",
121
120
  "node-machine-id": "1.1.12",
122
121
  "nodemailer": "6.9.1",
123
122
  "object-hash": "3.0.0",
124
123
  "openapi3-ts": "3.2.0",
125
124
  "openid-client": "5.4.0",
126
- "ora": "5.4.1",
125
+ "ora": "6.3.0",
127
126
  "otplib": "12.0.1",
128
127
  "pino": "8.11.0",
129
128
  "pino-http": "8.3.3",
@@ -131,38 +130,38 @@
131
130
  "pino-pretty": "10.0.0",
132
131
  "qs": "6.11.1",
133
132
  "rate-limiter-flexible": "2.4.1",
134
- "rollup": "3.19.1",
133
+ "rollup": "3.20.7",
135
134
  "samlify": "2.8.10",
136
135
  "sanitize-html": "2.10.0",
137
- "sharp": "0.31.3",
136
+ "sharp": "0.32.0",
138
137
  "snappy": "7.2.2",
139
138
  "stream-json": "1.7.5",
140
- "strip-bom-stream": "4.0.0",
139
+ "strip-bom-stream": "5.0.0",
141
140
  "tmp-promise": "3.0.3",
142
141
  "tsx": "3.12.6",
143
142
  "uuid": "9.0.0",
144
143
  "uuid-validate": "0.0.3",
145
- "vm2": "3.9.16",
144
+ "vm2": "3.9.17",
146
145
  "wellknown": "0.5.0",
147
- "@directus/app": "9.25.1",
148
- "@directus/constants": "9.25.1",
149
- "@directus/exceptions": "9.25.1",
150
- "@directus/extensions-sdk": "9.25.1",
151
- "@directus/schema": "9.25.1",
152
- "@directus/specs": "9.25.1",
153
- "@directus/storage": "9.25.1",
154
- "@directus/storage-driver-azure": "9.25.1",
155
- "@directus/storage-driver-cloudinary": "9.25.1",
156
- "@directus/storage-driver-gcs": "9.25.1",
157
- "@directus/storage-driver-local": "9.25.1",
158
- "@directus/storage-driver-s3": "9.25.1",
159
- "@directus/update-check": "9.25.1",
160
- "@directus/utils": "9.25.1"
146
+ "@directus/app": "9.26.0",
147
+ "@directus/constants": "9.26.0",
148
+ "@directus/exceptions": "9.26.0",
149
+ "@directus/extensions-sdk": "9.26.0",
150
+ "@directus/schema": "9.26.0",
151
+ "@directus/specs": "9.26.0",
152
+ "@directus/storage": "9.26.0",
153
+ "@directus/storage-driver-azure": "9.26.0",
154
+ "@directus/storage-driver-cloudinary": "9.26.0",
155
+ "@directus/storage-driver-gcs": "9.26.0",
156
+ "@directus/storage-driver-local": "9.26.0",
157
+ "@directus/storage-driver-s3": "9.26.0",
158
+ "@directus/update-check": "9.26.0",
159
+ "@directus/utils": "9.26.0"
161
160
  },
162
161
  "devDependencies": {
163
- "@directus/tsconfig": "0.0.6",
162
+ "@directus/tsconfig": "0.0.7",
164
163
  "@ngneat/falso": "6.4.0",
165
- "@types/async": "3.2.18",
164
+ "@types/async": "3.2.19",
166
165
  "@types/busboy": "1.5.0",
167
166
  "@types/bytes": "3.1.1",
168
167
  "@types/content-disposition": "0.5.5",
@@ -177,36 +176,35 @@
177
176
  "@types/fast-redact": "3.0.2",
178
177
  "@types/flat": "5.0.2",
179
178
  "@types/fs-extra": "11.0.1",
180
- "@types/inquirer": "8.2.6",
179
+ "@types/inquirer": "9.0.3",
181
180
  "@types/js-yaml": "4.0.5",
182
181
  "@types/json2csv": "5.0.3",
183
182
  "@types/jsonwebtoken": "9.0.1",
184
- "@types/keyv": "3.1.4",
183
+ "@types/keyv": "4.2.0",
185
184
  "@types/ldapjs": "2.2.5",
186
185
  "@types/lodash-es": "4.17.7",
187
186
  "@types/marked": "4.0.8",
188
187
  "@types/mime-types": "2.1.1",
189
188
  "@types/ms": "0.7.31",
190
- "@types/node": "18.15.3",
189
+ "@types/node": "18.15.13",
191
190
  "@types/node-cron": "3.0.7",
192
191
  "@types/nodemailer": "6.4.7",
193
192
  "@types/object-hash": "3.0.2",
194
193
  "@types/qs": "6.9.7",
195
194
  "@types/sanitize-html": "2.9.0",
196
- "@types/sharp": "0.31.1",
197
195
  "@types/stream-json": "1.7.3",
198
196
  "@types/supertest": "2.0.12",
199
197
  "@types/uuid": "9.0.1",
200
198
  "@types/uuid-validate": "0.0.1",
201
199
  "@types/wellknown": "0.5.4",
202
- "@vitest/coverage-c8": "0.29.3",
200
+ "@vitest/coverage-c8": "0.30.1",
203
201
  "copyfiles": "2.4.1",
204
202
  "form-data": "4.0.0",
205
203
  "knex-mock-client": "2.0.0",
206
204
  "supertest": "6.3.3",
207
- "typescript": "4.9.5",
208
- "vitest": "0.29.3",
209
- "@directus/types": "9.25.1"
205
+ "typescript": "5.0.4",
206
+ "vitest": "0.30.1",
207
+ "@directus/types": "9.26.0"
210
208
  },
211
209
  "optionalDependencies": {
212
210
  "@keyv/redis": "2.5.7",
@@ -217,7 +215,7 @@
217
215
  "nodemailer-sendgrid": "1.0.3",
218
216
  "pg": "8.10.0",
219
217
  "sqlite3": "5.1.6",
220
- "tedious": "15.1.3"
218
+ "tedious": "16.0.0"
221
219
  },
222
220
  "engines": {
223
221
  "node": ">=18.0.0"