@directus/api 35.1.0 → 35.2.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.
- package/dist/controllers/assets.js +43 -1
- package/dist/controllers/schema.js +2 -2
- package/dist/extensions/lib/installation/manager.js +3 -3
- package/dist/extensions/lib/sync/sync.js +2 -2
- package/dist/extensions/manager.js +3 -3
- package/dist/flows.js +8 -6
- package/dist/services/collections.js +1 -0
- package/dist/services/schema.js +2 -2
- package/dist/services/versions.js +26 -25
- package/dist/utils/validate-diff.js +7 -3
- package/package.json +21 -22
- package/dist/utils/job-queue.js +0 -24
|
@@ -6,7 +6,9 @@ import { getMilliseconds } from "../utils/get-milliseconds.js";
|
|
|
6
6
|
import { ASSET_TRANSFORM_QUERY_KEYS, SYSTEM_ASSET_ALLOW_LIST } from "../constants.js";
|
|
7
7
|
import { isValidUuid } from "../utils/is-valid-uuid.js";
|
|
8
8
|
import database_default from "../database/index.js";
|
|
9
|
+
import { validateAccess } from "../permissions/modules/validate-access/validate-access.js";
|
|
9
10
|
import { PayloadService } from "../services/payload.js";
|
|
11
|
+
import { FilesService } from "../services/files.js";
|
|
10
12
|
import { AssetsService } from "../services/assets.js";
|
|
11
13
|
import { getCacheControlHeader } from "../utils/get-cache-headers.js";
|
|
12
14
|
import use_collection_default from "../middleware/use-collection.js";
|
|
@@ -170,6 +172,44 @@ router.get("/:pk/:filename?", async_handler_default(async (req, res, next) => {
|
|
|
170
172
|
}
|
|
171
173
|
}
|
|
172
174
|
}
|
|
175
|
+
const revalidate = env["ASSETS_CACHE_REVALIDATE"] === true;
|
|
176
|
+
if (revalidate) {
|
|
177
|
+
const ifNoneMatch = req.headers["if-none-match"];
|
|
178
|
+
const ifModifiedSince = req.headers["if-modified-since"];
|
|
179
|
+
if (ifNoneMatch || ifModifiedSince) {
|
|
180
|
+
if (req.accountability) await validateAccess({
|
|
181
|
+
accountability: req.accountability,
|
|
182
|
+
action: "read",
|
|
183
|
+
collection: "directus_files",
|
|
184
|
+
primaryKeys: [id]
|
|
185
|
+
}, {
|
|
186
|
+
knex: database_default(),
|
|
187
|
+
schema: req.schema
|
|
188
|
+
});
|
|
189
|
+
const fileRecord = await new FilesService({ schema: req.schema }).readOne(id, { fields: ["modified_on"] });
|
|
190
|
+
if (fileRecord?.modified_on) {
|
|
191
|
+
const modifiedOnTime = new Date(fileRecord.modified_on).getTime();
|
|
192
|
+
const etag = `"${Math.floor(modifiedOnTime / 1e3)}"`;
|
|
193
|
+
if (ifNoneMatch === etag) {
|
|
194
|
+
res.setHeader("Cache-Control", "max-age=0, must-revalidate");
|
|
195
|
+
res.setHeader("ETag", etag);
|
|
196
|
+
res.setHeader("Last-Modified", new Date(modifiedOnTime).toUTCString());
|
|
197
|
+
res.status(304);
|
|
198
|
+
return res.end();
|
|
199
|
+
}
|
|
200
|
+
if (ifModifiedSince) {
|
|
201
|
+
const ifModifiedSinceTime = new Date(ifModifiedSince).getTime();
|
|
202
|
+
if (Math.floor(modifiedOnTime / 1e3) <= Math.floor(ifModifiedSinceTime / 1e3)) {
|
|
203
|
+
res.setHeader("Cache-Control", "max-age=0, must-revalidate");
|
|
204
|
+
res.setHeader("ETag", etag);
|
|
205
|
+
res.setHeader("Last-Modified", new Date(modifiedOnTime).toUTCString());
|
|
206
|
+
res.status(304);
|
|
207
|
+
return res.end();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
173
213
|
const { stream, file, stat } = await service.getAsset(id, {
|
|
174
214
|
transformationParams,
|
|
175
215
|
acceptFormat
|
|
@@ -178,12 +218,14 @@ router.get("/:pk/:filename?", async_handler_default(async (req, res, next) => {
|
|
|
178
218
|
res.attachment(filename);
|
|
179
219
|
res.setHeader("Content-Type", file.type);
|
|
180
220
|
res.setHeader("Accept-Ranges", "bytes");
|
|
181
|
-
res.setHeader("Cache-Control",
|
|
221
|
+
if (revalidate) res.setHeader("Cache-Control", "max-age=0, must-revalidate");
|
|
222
|
+
else res.setHeader("Cache-Control", getCacheControlHeader(req, getMilliseconds(env["ASSETS_CACHE_TTL"]), false, true));
|
|
182
223
|
res.setHeader("Vary", vary.join(", "));
|
|
183
224
|
const unixTime = Date.parse(file.modified_on);
|
|
184
225
|
if (!Number.isNaN(unixTime)) {
|
|
185
226
|
const lastModifiedDate = new Date(unixTime);
|
|
186
227
|
res.setHeader("Last-Modified", lastModifiedDate.toUTCString());
|
|
228
|
+
res.setHeader("ETag", `"${Math.floor(unixTime / 1e3)}"`);
|
|
187
229
|
}
|
|
188
230
|
if (range) {
|
|
189
231
|
res.setHeader("Content-Range", `bytes ${range.start}-${range.end || stat.size - 1}/${stat.size}`);
|
|
@@ -4,7 +4,7 @@ import { respond } from "../middleware/respond.js";
|
|
|
4
4
|
import { getVersionedHash } from "../utils/get-versioned-hash.js";
|
|
5
5
|
import { SchemaService } from "../services/schema.js";
|
|
6
6
|
import { InvalidPayloadError, UnsupportedMediaTypeError } from "@directus/errors";
|
|
7
|
-
import { parseJSON } from "@directus/utils";
|
|
7
|
+
import { parseJSON, toBoolean } from "@directus/utils";
|
|
8
8
|
import express from "express";
|
|
9
9
|
import { load } from "js-yaml";
|
|
10
10
|
import Busboy from "busboy";
|
|
@@ -83,7 +83,7 @@ router.post("/diff", async_handler_default(schemaMultipartHandler), async_handle
|
|
|
83
83
|
router.post("/apply", async_handler_default(schemaMultipartHandler), async_handler_default(async (req, res, next) => {
|
|
84
84
|
const service = new SchemaService({ accountability: req.accountability });
|
|
85
85
|
const diff = res.locals["upload"];
|
|
86
|
-
await service.apply(diff);
|
|
86
|
+
await service.apply(diff, { force: toBoolean(req.query["force"]) });
|
|
87
87
|
return next();
|
|
88
88
|
}), respond);
|
|
89
89
|
var schema_default = router;
|
|
@@ -7,10 +7,10 @@ import { useEnv } from "@directus/env";
|
|
|
7
7
|
import { ErrorCode, ServiceUnavailableError, isDirectusError } from "@directus/errors";
|
|
8
8
|
import { move, remove } from "fs-extra";
|
|
9
9
|
import { Readable } from "node:stream";
|
|
10
|
+
import PQueue from "p-queue";
|
|
10
11
|
import { download } from "@directus/extensions-registry";
|
|
11
12
|
import { EXTENSION_PKG_KEY, ExtensionManifest } from "@directus/extensions";
|
|
12
13
|
import DriverLocal from "@directus/storage-driver-local";
|
|
13
|
-
import Queue from "p-queue";
|
|
14
14
|
import { extract } from "tar";
|
|
15
15
|
|
|
16
16
|
//#region src/extensions/lib/installation/manager.ts
|
|
@@ -50,7 +50,7 @@ var InstallationManager = class {
|
|
|
50
50
|
if (!(await ExtensionManifest.parseAsync(packageFile))[EXTENSION_PKG_KEY]?.type) throw new Error(`Extension type not found in package.json`);
|
|
51
51
|
if (env["EXTENSIONS_LOCATION"]) {
|
|
52
52
|
const remoteDisk = (await getStorage()).location(env["EXTENSIONS_LOCATION"]);
|
|
53
|
-
const queue = new
|
|
53
|
+
const queue = new PQueue({ concurrency: 1e3 });
|
|
54
54
|
for await (const filepath of tmpStorage.list(extractedPath)) {
|
|
55
55
|
const readStream = await tmpStorage.read(filepath);
|
|
56
56
|
const remotePath = join(env["EXTENSIONS_PATH"], ".registry", versionId, filepath.substring(7));
|
|
@@ -74,7 +74,7 @@ var InstallationManager = class {
|
|
|
74
74
|
async uninstall(folder) {
|
|
75
75
|
if (env["EXTENSIONS_LOCATION"]) {
|
|
76
76
|
const remoteDisk = (await getStorage()).location(env["EXTENSIONS_LOCATION"]);
|
|
77
|
-
const queue = new
|
|
77
|
+
const queue = new PQueue({ concurrency: 1e3 });
|
|
78
78
|
const prefix = join(env["EXTENSIONS_PATH"], ".registry", folder);
|
|
79
79
|
for await (const filepath of remoteDisk.list(prefix)) queue.add(() => remoteDisk.delete(filepath));
|
|
80
80
|
await queue.onIdle();
|
|
@@ -13,8 +13,8 @@ import { useEnv } from "@directus/env";
|
|
|
13
13
|
import { normalizePath } from "@directus/utils";
|
|
14
14
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
15
15
|
import { pipeline } from "node:stream/promises";
|
|
16
|
+
import PQueue from "p-queue";
|
|
16
17
|
import { createWriteStream } from "node:fs";
|
|
17
|
-
import Queue from "p-queue";
|
|
18
18
|
import mid from "node-machine-id";
|
|
19
19
|
|
|
20
20
|
//#region src/extensions/lib/sync/sync.ts
|
|
@@ -50,7 +50,7 @@ async function syncExtensions(options) {
|
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
-
const queue = new
|
|
53
|
+
const queue = new PQueue({ concurrency: 1e3 });
|
|
54
54
|
const fileTracker = new SyncFileTracker();
|
|
55
55
|
const hasLocalFiles = await fileTracker.readLocalFiles(localExtensionsPath) > 0;
|
|
56
56
|
for await (const filepath of disk.list(remoteExtensionsPath)) {
|
|
@@ -8,7 +8,6 @@ import { getSchema } from "../utils/get-schema.js";
|
|
|
8
8
|
import { deleteFromRequireCache } from "../utils/delete-from-require-cache.js";
|
|
9
9
|
import getModuleDefault from "../utils/get-module-default.js";
|
|
10
10
|
import { importFileUrl } from "../utils/import-file-url.js";
|
|
11
|
-
import { JobQueue } from "../utils/job-queue.js";
|
|
12
11
|
import { scheduleSynchronizedJob, validateCron } from "../utils/schedule.js";
|
|
13
12
|
import { getExtensionsSettings } from "./lib/get-extensions-settings.js";
|
|
14
13
|
import { getExtensions } from "./lib/get-extensions.js";
|
|
@@ -30,6 +29,7 @@ import { pathToRelativeUrl, processId } from "@directus/utils/node";
|
|
|
30
29
|
import { fileURLToPath } from "node:url";
|
|
31
30
|
import { HYBRID_EXTENSION_TYPES } from "@directus/constants";
|
|
32
31
|
import { dirname, join as join$1, relative, resolve, sep } from "node:path";
|
|
32
|
+
import PQueue from "p-queue";
|
|
33
33
|
import os from "node:os";
|
|
34
34
|
import { APP_SHARED_DEPS } from "@directus/extensions";
|
|
35
35
|
import { generateExtensionsEntrypoint } from "@directus/extensions/node";
|
|
@@ -97,7 +97,7 @@ var ExtensionManager = class {
|
|
|
97
97
|
* Used to prevent race conditions when reloading extensions. Forces each reload to happen in
|
|
98
98
|
* sequence.
|
|
99
99
|
*/
|
|
100
|
-
reloadQueue = new
|
|
100
|
+
reloadQueue = new PQueue({ concurrency: 1 });
|
|
101
101
|
/**
|
|
102
102
|
* Used to prevent race condition when reading extension data while reloading extensions
|
|
103
103
|
*/
|
|
@@ -248,7 +248,7 @@ var ExtensionManager = class {
|
|
|
248
248
|
resolve$1 = res;
|
|
249
249
|
reject = rej;
|
|
250
250
|
});
|
|
251
|
-
this.reloadQueue.
|
|
251
|
+
this.reloadQueue.add(async () => {
|
|
252
252
|
if (this.isLoaded) {
|
|
253
253
|
const prevExtensions = clone(this.extensions);
|
|
254
254
|
await this.unload();
|
package/dist/flows.js
CHANGED
|
@@ -8,7 +8,6 @@ import emitter_default from "./emitter.js";
|
|
|
8
8
|
import { getSchema } from "./utils/get-schema.js";
|
|
9
9
|
import { ActivityService } from "./services/activity.js";
|
|
10
10
|
import { getService } from "./utils/get-service.js";
|
|
11
|
-
import { JobQueue } from "./utils/job-queue.js";
|
|
12
11
|
import { scheduleSynchronizedJob, validateCron } from "./utils/schedule.js";
|
|
13
12
|
import { RevisionsService } from "./services/revisions.js";
|
|
14
13
|
import { services_exports } from "./services/index.js";
|
|
@@ -22,6 +21,7 @@ import { pick } from "lodash-es";
|
|
|
22
21
|
import { Action } from "@directus/constants";
|
|
23
22
|
import { isSystemCollection } from "@directus/system-data";
|
|
24
23
|
import { get as get$1 } from "micromustache";
|
|
24
|
+
import PQueue from "p-queue";
|
|
25
25
|
|
|
26
26
|
//#region src/flows.ts
|
|
27
27
|
let flowManager;
|
|
@@ -41,15 +41,15 @@ var FlowManager = class {
|
|
|
41
41
|
triggerHandlers = [];
|
|
42
42
|
operationFlowHandlers = {};
|
|
43
43
|
webhookFlowHandlers = {};
|
|
44
|
-
reloadQueue;
|
|
44
|
+
reloadQueue = new PQueue({ concurrency: 1 });
|
|
45
45
|
envs;
|
|
46
46
|
constructor() {
|
|
47
47
|
const env = useEnv();
|
|
48
|
-
const logger = useLogger();
|
|
49
|
-
this.reloadQueue = new JobQueue();
|
|
50
48
|
this.envs = env["FLOWS_ENV_ALLOW_LIST"] ? pick(env, toArray(env["FLOWS_ENV_ALLOW_LIST"])) : {};
|
|
51
|
-
useBus()
|
|
52
|
-
|
|
49
|
+
const messenger = useBus();
|
|
50
|
+
const logger = useLogger();
|
|
51
|
+
messenger.subscribe("flows", (event) => {
|
|
52
|
+
if (event.type === "reload") this.reloadQueue.add(async () => {
|
|
53
53
|
if (this.isLoaded) {
|
|
54
54
|
await this.unload();
|
|
55
55
|
await this.load();
|
|
@@ -70,6 +70,7 @@ var FlowManager = class {
|
|
|
70
70
|
this.operations.delete(id);
|
|
71
71
|
}
|
|
72
72
|
async runOperationFlow(id, data, context) {
|
|
73
|
+
if (this.reloadQueue.pending > 0) await this.reloadQueue.onIdle();
|
|
73
74
|
const logger = useLogger();
|
|
74
75
|
if (!(id in this.operationFlowHandlers)) {
|
|
75
76
|
logger.warn(`Couldn't find operation triggered flow with id "${id}"`);
|
|
@@ -79,6 +80,7 @@ var FlowManager = class {
|
|
|
79
80
|
return handler(data, context);
|
|
80
81
|
}
|
|
81
82
|
async runWebhookFlow(id, data, context) {
|
|
83
|
+
if (this.reloadQueue.pending > 0) await this.reloadQueue.onIdle();
|
|
82
84
|
const logger = useLogger();
|
|
83
85
|
if (!(id in this.webhookFlowHandlers)) {
|
|
84
86
|
logger.warn(`Couldn't find webhook or manual triggered flow with id "${id}"`);
|
|
@@ -47,6 +47,7 @@ var CollectionsService = class CollectionsService {
|
|
|
47
47
|
if (!("collection" in payload)) throw new InvalidPayloadError({ reason: `"collection" is required` });
|
|
48
48
|
if (typeof payload.collection !== "string" || payload.collection === "") throw new InvalidPayloadError({ reason: `"collection" must be a non-empty string` });
|
|
49
49
|
if (payload.collection.startsWith("directus_")) throw new InvalidPayloadError({ reason: `Collections can't start with "directus_"` });
|
|
50
|
+
if (payload.collection.includes("/")) throw new InvalidPayloadError({ reason: `Collection name can't contain "/"` });
|
|
50
51
|
payload.collection = await this.helpers.schema.parseCollectionName(payload.collection);
|
|
51
52
|
const nestedActionEvents = [];
|
|
52
53
|
try {
|
package/dist/services/schema.js
CHANGED
|
@@ -19,10 +19,10 @@ var SchemaService = class {
|
|
|
19
19
|
if (this.accountability?.admin !== true) throw new ForbiddenError();
|
|
20
20
|
return await getSnapshot({ database: this.knex });
|
|
21
21
|
}
|
|
22
|
-
async apply(payload) {
|
|
22
|
+
async apply(payload, options) {
|
|
23
23
|
if (this.accountability?.admin !== true) throw new ForbiddenError();
|
|
24
24
|
const currentSnapshot = await this.snapshot();
|
|
25
|
-
if (!validateApplyDiff(payload, this.getHashedSnapshot(currentSnapshot))) return;
|
|
25
|
+
if (!validateApplyDiff(payload, this.getHashedSnapshot(currentSnapshot), options?.force)) return;
|
|
26
26
|
await applyDiff(currentSnapshot, payload.diff, { database: this.knex });
|
|
27
27
|
}
|
|
28
28
|
async diff(snapshot, options) {
|
|
@@ -136,34 +136,35 @@ var VersionsService = class VersionsService extends ItemsService {
|
|
|
136
136
|
knex: this.knex,
|
|
137
137
|
schema: this.schema
|
|
138
138
|
});
|
|
139
|
-
const activityService = new ActivityService({
|
|
140
|
-
knex: this.knex,
|
|
141
|
-
schema: this.schema
|
|
142
|
-
});
|
|
143
|
-
const revisionsService = new RevisionsService({
|
|
144
|
-
knex: this.knex,
|
|
145
|
-
schema: this.schema
|
|
146
|
-
});
|
|
147
139
|
const { item, collection, delta: existingDelta } = version;
|
|
148
|
-
const activity = await activityService.createOne({
|
|
149
|
-
action: Action.VERSION_SAVE,
|
|
150
|
-
user: this.accountability?.user ?? null,
|
|
151
|
-
collection,
|
|
152
|
-
ip: this.accountability?.ip ?? null,
|
|
153
|
-
user_agent: this.accountability?.userAgent ?? null,
|
|
154
|
-
origin: this.accountability?.origin ?? null,
|
|
155
|
-
item
|
|
156
|
-
});
|
|
157
140
|
const helpers = getHelpers(this.knex);
|
|
158
141
|
let revisionDelta = await payloadService.prepareDelta(delta);
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
142
|
+
const trackingAccountability = this.schema.collections[collection]?.accountability ?? null;
|
|
143
|
+
if (trackingAccountability !== null) {
|
|
144
|
+
const activity = await new ActivityService({
|
|
145
|
+
knex: this.knex,
|
|
146
|
+
schema: this.schema
|
|
147
|
+
}).createOne({
|
|
148
|
+
action: Action.VERSION_SAVE,
|
|
149
|
+
user: this.accountability?.user ?? null,
|
|
150
|
+
collection,
|
|
151
|
+
ip: this.accountability?.ip ?? null,
|
|
152
|
+
user_agent: this.accountability?.userAgent ?? null,
|
|
153
|
+
origin: this.accountability?.origin ?? null,
|
|
154
|
+
item
|
|
155
|
+
});
|
|
156
|
+
if (trackingAccountability === "all") await new RevisionsService({
|
|
157
|
+
knex: this.knex,
|
|
158
|
+
schema: this.schema
|
|
159
|
+
}).createOne({
|
|
160
|
+
activity,
|
|
161
|
+
version: key,
|
|
162
|
+
collection,
|
|
163
|
+
item,
|
|
164
|
+
data: revisionDelta,
|
|
165
|
+
delta: revisionDelta
|
|
166
|
+
});
|
|
167
|
+
}
|
|
167
168
|
revisionDelta = revisionDelta ? revisionDelta : null;
|
|
168
169
|
const date = new Date(helpers.date.writeTimestamp((/* @__PURE__ */ new Date()).toISOString()));
|
|
169
170
|
deepMapObjects(revisionDelta, (object, path) => {
|
|
@@ -53,13 +53,17 @@ const applyJoiSchema = Joi.object({
|
|
|
53
53
|
/**
|
|
54
54
|
* Validates the diff against the current schema snapshot.
|
|
55
55
|
*
|
|
56
|
+
* @param applyDiff The diff to validate with the expected hash
|
|
57
|
+
* @param currentSnapshotWithHash The current snapshot with hash to validate against
|
|
58
|
+
* @param force When true bypass hash validation. Use with caution as this can lead to unintended consequences, only use when the diff can be applied irrespective of the current schema.
|
|
59
|
+
*
|
|
56
60
|
* @returns True if the diff can be applied (valid & not empty).
|
|
57
61
|
*/
|
|
58
|
-
function validateApplyDiff(applyDiff, currentSnapshotWithHash) {
|
|
62
|
+
function validateApplyDiff(applyDiff, currentSnapshotWithHash, force = false) {
|
|
59
63
|
const { error } = applyJoiSchema.validate(applyDiff);
|
|
60
64
|
if (error) throw new InvalidPayloadError({ reason: error.message });
|
|
61
65
|
if (applyDiff.diff.collections.length === 0 && applyDiff.diff.fields.length === 0 && applyDiff.diff.systemFields.length === 0 && applyDiff.diff.relations.length === 0) return false;
|
|
62
|
-
if (applyDiff.hash === currentSnapshotWithHash.hash) return true;
|
|
66
|
+
if (applyDiff.hash === currentSnapshotWithHash.hash || force) return true;
|
|
63
67
|
for (const diffCollection of applyDiff.diff.collections) {
|
|
64
68
|
const collection = diffCollection.collection;
|
|
65
69
|
if (diffCollection.diff[0]?.kind === DiffKind.NEW) {
|
|
@@ -97,7 +101,7 @@ function validateApplyDiff(applyDiff, currentSnapshotWithHash) {
|
|
|
97
101
|
if (!currentSnapshotWithHash.relations.find((r) => r.collection === diffRelation.collection && r.field === diffRelation.field)) throw new InvalidPayloadError({ reason: `Provided diff is trying to delete relation "${relation}" but it does not exist. Please generate a new diff and try again` });
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
|
-
throw new InvalidPayloadError({ reason: `Provided hash does not match the current instance's schema hash, indicating the schema has changed after this diff was generated. Please generate a new diff and try again` });
|
|
104
|
+
throw new InvalidPayloadError({ reason: `Provided hash does not match the current instance's schema hash, indicating the schema has changed after this diff was generated. Please generate a new diff and try again or use the "force" query parameter to bypass this check` });
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
//#endregion
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@directus/api",
|
|
3
|
-
"version": "35.
|
|
3
|
+
"version": "35.2.0",
|
|
4
4
|
"description": "Directus is a real-time API and App dashboard for managing SQL database content",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"directus",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"keyv": "5.5.3",
|
|
122
122
|
"knex": "3.1.0",
|
|
123
123
|
"ldapts": "8.1.3",
|
|
124
|
-
"liquidjs": "10.25.
|
|
124
|
+
"liquidjs": "10.25.7",
|
|
125
125
|
"lodash-es": "4.18.1",
|
|
126
126
|
"marked": "16.4.1",
|
|
127
127
|
"micromustache": "8.0.3",
|
|
@@ -166,30 +166,29 @@
|
|
|
166
166
|
"zod": "4.1.12",
|
|
167
167
|
"zod-validation-error": "4.0.2",
|
|
168
168
|
"@directus/ai": "1.3.1",
|
|
169
|
-
"@directus/
|
|
169
|
+
"@directus/env": "5.8.0",
|
|
170
|
+
"@directus/app": "15.10.0",
|
|
170
171
|
"@directus/errors": "2.3.1",
|
|
171
|
-
"@directus/extensions": "3.0.
|
|
172
|
-
"@directus/env": "5.7.1",
|
|
172
|
+
"@directus/extensions": "3.0.25",
|
|
173
173
|
"@directus/constants": "14.3.0",
|
|
174
|
-
"@directus/extensions-registry": "3.0.
|
|
174
|
+
"@directus/extensions-registry": "3.0.26",
|
|
175
|
+
"@directus/extensions-sdk": "17.1.4",
|
|
175
176
|
"@directus/format-title": "12.1.2",
|
|
176
|
-
"@directus/
|
|
177
|
-
"@directus/pressure": "3.0.21",
|
|
178
|
-
"@directus/memory": "3.1.7",
|
|
177
|
+
"@directus/memory": "3.1.8",
|
|
179
178
|
"@directus/schema": "13.0.8",
|
|
180
|
-
"@directus/
|
|
181
|
-
"@directus/schema-builder": "0.0.19",
|
|
182
|
-
"@directus/storage-driver-azure": "12.0.21",
|
|
179
|
+
"@directus/pressure": "3.0.22",
|
|
183
180
|
"@directus/storage": "12.0.4",
|
|
184
|
-
"@directus/storage-driver-
|
|
185
|
-
"@directus/storage-driver-
|
|
186
|
-
"@directus/
|
|
187
|
-
"@directus/storage-driver-
|
|
181
|
+
"@directus/storage-driver-cloudinary": "12.0.22",
|
|
182
|
+
"@directus/storage-driver-azure": "12.0.22",
|
|
183
|
+
"@directus/specs": "13.0.0",
|
|
184
|
+
"@directus/storage-driver-gcs": "12.0.22",
|
|
188
185
|
"@directus/storage-driver-local": "12.0.4",
|
|
189
|
-
"@directus/
|
|
190
|
-
"@directus/
|
|
191
|
-
"directus": "
|
|
192
|
-
"@directus/validation": "2.0.
|
|
186
|
+
"@directus/storage-driver-s3": "12.1.8",
|
|
187
|
+
"@directus/storage-driver-supabase": "3.0.22",
|
|
188
|
+
"@directus/utils": "13.4.1",
|
|
189
|
+
"@directus/validation": "2.0.23",
|
|
190
|
+
"directus": "11.17.4",
|
|
191
|
+
"@directus/system-data": "4.4.0"
|
|
193
192
|
},
|
|
194
193
|
"devDependencies": {
|
|
195
194
|
"@directus/tsconfig": "4.0.0",
|
|
@@ -231,8 +230,8 @@
|
|
|
231
230
|
"knex-mock-client": "3.0.2",
|
|
232
231
|
"typescript": "5.9.3",
|
|
233
232
|
"vitest": "3.2.4",
|
|
234
|
-
"@directus/schema-builder": "0.0.
|
|
235
|
-
"@directus/types": "15.0.
|
|
233
|
+
"@directus/schema-builder": "0.0.20",
|
|
234
|
+
"@directus/types": "15.0.3"
|
|
236
235
|
},
|
|
237
236
|
"optionalDependencies": {
|
|
238
237
|
"@keyv/redis": "3.0.1",
|
package/dist/utils/job-queue.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
//#region src/utils/job-queue.ts
|
|
2
|
-
var JobQueue = class {
|
|
3
|
-
running;
|
|
4
|
-
jobs;
|
|
5
|
-
constructor() {
|
|
6
|
-
this.running = false;
|
|
7
|
-
this.jobs = [];
|
|
8
|
-
}
|
|
9
|
-
enqueue(job) {
|
|
10
|
-
this.jobs.push(job);
|
|
11
|
-
if (!this.running) this.run();
|
|
12
|
-
}
|
|
13
|
-
async run() {
|
|
14
|
-
this.running = true;
|
|
15
|
-
while (this.jobs.length > 0) await this.jobs.shift()();
|
|
16
|
-
this.running = false;
|
|
17
|
-
}
|
|
18
|
-
get size() {
|
|
19
|
-
return this.jobs.length;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
//#endregion
|
|
24
|
-
export { JobQueue };
|