@directus/api 9.25.1 → 9.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +0 -2
- package/dist/controllers/assets.js +11 -5
- package/dist/database/migrations/run.js +8 -0
- package/dist/extensions.js +37 -38
- package/dist/utils/get-cache-key.js +2 -0
- package/package.json +16 -17
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();
|
|
@@ -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'
|
|
112
|
-
let format
|
|
113
|
-
if (req.headers.accept
|
|
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
|
|
117
|
-
format = '
|
|
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);
|
|
@@ -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
|
}
|
package/dist/extensions.js
CHANGED
|
@@ -7,7 +7,6 @@ import nodeResolveDefault from '@rollup/plugin-node-resolve';
|
|
|
7
7
|
import virtualDefault from '@rollup/plugin-virtual';
|
|
8
8
|
import chokidar 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
|
-
|
|
73
|
+
const wasWatcherInitialized = this.watcher !== null;
|
|
74
|
+
if (this.options.watch && !wasWatcherInitialized) {
|
|
76
75
|
this.initializeWatcher();
|
|
77
76
|
}
|
|
78
|
-
else if (
|
|
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 (
|
|
87
|
+
if (this.options.watch && !wasWatcherInitialized) {
|
|
89
88
|
this.updateWatchedExtensions(this.extensions);
|
|
90
89
|
}
|
|
91
90
|
}
|
|
@@ -198,29 +197,32 @@ class ExtensionManager {
|
|
|
198
197
|
this.isLoaded = false;
|
|
199
198
|
}
|
|
200
199
|
initializeWatcher() {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
200
|
+
logger.info('Watching extensions for changes...');
|
|
201
|
+
const localExtensionPaths = NESTED_EXTENSION_TYPES.flatMap((type) => {
|
|
202
|
+
const typeDir = path.posix.join(pathToRelativeUrl(env['EXTENSIONS_PATH']), pluralize(type));
|
|
203
|
+
const fileExts = ['js', 'mjs', 'cjs'];
|
|
204
|
+
if (isIn(type, HYBRID_EXTENSION_TYPES)) {
|
|
205
|
+
return [
|
|
206
|
+
path.posix.join(typeDir, '*', `app.{${fileExts.join()}}`),
|
|
207
|
+
path.posix.join(typeDir, '*', `api.{${fileExts.join()}}`),
|
|
208
|
+
];
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
return path.posix.join(typeDir, '*', `index.{${fileExts.join()}}`);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
this.watcher = chokidar.watch([path.resolve('package.json'), ...localExtensionPaths], {
|
|
215
|
+
ignoreInitial: true,
|
|
216
|
+
});
|
|
217
|
+
this.watcher
|
|
218
|
+
.on('add', () => this.reload())
|
|
219
|
+
.on('change', () => this.reload())
|
|
220
|
+
.on('unlink', () => this.reload());
|
|
220
221
|
}
|
|
221
222
|
async closeWatcher() {
|
|
222
223
|
if (this.watcher) {
|
|
223
224
|
await this.watcher.close();
|
|
225
|
+
this.watcher = null;
|
|
224
226
|
}
|
|
225
227
|
}
|
|
226
228
|
updateWatchedExtensions(added, removed = []) {
|
|
@@ -295,7 +297,7 @@ class ExtensionManager {
|
|
|
295
297
|
for (const hook of hooks) {
|
|
296
298
|
try {
|
|
297
299
|
const hookPath = path.resolve(hook.path, hook.entrypoint);
|
|
298
|
-
const hookInstance = await import(
|
|
300
|
+
const hookInstance = await import(`./${pathToRelativeUrl(hookPath, __dirname)}?t=${Date.now()}`);
|
|
299
301
|
const config = getModuleDefault(hookInstance);
|
|
300
302
|
this.registerHook(config);
|
|
301
303
|
this.apiExtensions.push({ path: hookPath });
|
|
@@ -311,7 +313,7 @@ class ExtensionManager {
|
|
|
311
313
|
for (const endpoint of endpoints) {
|
|
312
314
|
try {
|
|
313
315
|
const endpointPath = path.resolve(endpoint.path, endpoint.entrypoint);
|
|
314
|
-
const endpointInstance = await import(
|
|
316
|
+
const endpointInstance = await import(`./${pathToRelativeUrl(endpointPath, __dirname)}?t=${Date.now()}`);
|
|
315
317
|
const config = getModuleDefault(endpointInstance);
|
|
316
318
|
this.registerEndpoint(config, endpoint.name);
|
|
317
319
|
this.apiExtensions.push({ path: endpointPath });
|
|
@@ -323,20 +325,17 @@ class ExtensionManager {
|
|
|
323
325
|
}
|
|
324
326
|
}
|
|
325
327
|
async registerOperations() {
|
|
326
|
-
const
|
|
327
|
-
const
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
entrypoint: { api: dirs[dirs.length - 1] },
|
|
333
|
-
};
|
|
334
|
-
});
|
|
328
|
+
const internalOperations = await readdir(path.join(__dirname, 'operations'));
|
|
329
|
+
for (const operation of internalOperations) {
|
|
330
|
+
const operationInstance = await import(`./operations/${operation}/index.js`);
|
|
331
|
+
const config = getModuleDefault(operationInstance);
|
|
332
|
+
this.registerOperation(config);
|
|
333
|
+
}
|
|
335
334
|
const operations = this.extensions.filter((extension) => extension.type === 'operation');
|
|
336
|
-
for (const operation of
|
|
335
|
+
for (const operation of operations) {
|
|
337
336
|
try {
|
|
338
337
|
const operationPath = path.resolve(operation.path, operation.entrypoint.api);
|
|
339
|
-
const operationInstance = await import(
|
|
338
|
+
const operationInstance = await import(`./${pathToRelativeUrl(operationPath, __dirname)}?t=${Date.now()}`);
|
|
340
339
|
const config = getModuleDefault(operationInstance);
|
|
341
340
|
this.registerOperation(config);
|
|
342
341
|
this.apiExtensions.push({ path: operationPath });
|
|
@@ -352,7 +351,7 @@ class ExtensionManager {
|
|
|
352
351
|
for (const bundle of bundles) {
|
|
353
352
|
try {
|
|
354
353
|
const bundlePath = path.resolve(bundle.path, bundle.entrypoint.api);
|
|
355
|
-
const bundleInstances = await import(
|
|
354
|
+
const bundleInstances = await import(`./${pathToRelativeUrl(bundlePath, __dirname)}?t=${Date.now()}`);
|
|
356
355
|
const configs = getModuleDefault(bundleInstances);
|
|
357
356
|
for (const { config } of configs.hooks) {
|
|
358
357
|
this.registerHook(config);
|
|
@@ -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,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/api",
|
|
3
|
-
"version": "9.25.
|
|
3
|
+
"version": "9.25.2",
|
|
4
4
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -95,7 +95,6 @@
|
|
|
95
95
|
"fast-redact": "3.1.2",
|
|
96
96
|
"flat": "5.0.2",
|
|
97
97
|
"fs-extra": "11.1.0",
|
|
98
|
-
"globby": "11.1.0",
|
|
99
98
|
"graphql": "16.6.0",
|
|
100
99
|
"graphql-compose": "9.0.10",
|
|
101
100
|
"helmet": "6.0.1",
|
|
@@ -144,20 +143,20 @@
|
|
|
144
143
|
"uuid-validate": "0.0.3",
|
|
145
144
|
"vm2": "3.9.16",
|
|
146
145
|
"wellknown": "0.5.0",
|
|
147
|
-
"@directus/app": "9.25.
|
|
148
|
-
"@directus/constants": "9.25.
|
|
149
|
-
"@directus/exceptions": "9.25.
|
|
150
|
-
"@directus/extensions-sdk": "9.25.
|
|
151
|
-
"@directus/schema": "9.25.
|
|
152
|
-
"@directus/specs": "9.25.
|
|
153
|
-
"@directus/storage": "9.25.
|
|
154
|
-
"@directus/storage-driver-azure": "9.25.
|
|
155
|
-
"@directus/storage-driver-cloudinary": "9.25.
|
|
156
|
-
"@directus/storage-driver-gcs": "9.25.
|
|
157
|
-
"@directus/storage-driver-local": "9.25.
|
|
158
|
-
"@directus/storage-driver-s3": "9.25.
|
|
159
|
-
"@directus/update-check": "9.25.
|
|
160
|
-
"@directus/utils": "9.25.
|
|
146
|
+
"@directus/app": "9.25.2",
|
|
147
|
+
"@directus/constants": "9.25.2",
|
|
148
|
+
"@directus/exceptions": "9.25.2",
|
|
149
|
+
"@directus/extensions-sdk": "9.25.2",
|
|
150
|
+
"@directus/schema": "9.25.2",
|
|
151
|
+
"@directus/specs": "9.25.2",
|
|
152
|
+
"@directus/storage": "9.25.2",
|
|
153
|
+
"@directus/storage-driver-azure": "9.25.2",
|
|
154
|
+
"@directus/storage-driver-cloudinary": "9.25.2",
|
|
155
|
+
"@directus/storage-driver-gcs": "9.25.2",
|
|
156
|
+
"@directus/storage-driver-local": "9.25.2",
|
|
157
|
+
"@directus/storage-driver-s3": "9.25.2",
|
|
158
|
+
"@directus/update-check": "9.25.2",
|
|
159
|
+
"@directus/utils": "9.25.2"
|
|
161
160
|
},
|
|
162
161
|
"devDependencies": {
|
|
163
162
|
"@directus/tsconfig": "0.0.6",
|
|
@@ -206,7 +205,7 @@
|
|
|
206
205
|
"supertest": "6.3.3",
|
|
207
206
|
"typescript": "4.9.5",
|
|
208
207
|
"vitest": "0.29.3",
|
|
209
|
-
"@directus/types": "9.25.
|
|
208
|
+
"@directus/types": "9.25.2"
|
|
210
209
|
},
|
|
211
210
|
"optionalDependencies": {
|
|
212
211
|
"@keyv/redis": "2.5.7",
|