directus 9.21.0 → 9.21.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.
@@ -99,6 +99,7 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
99
99
  code_challenge_method: 'S256',
100
100
  // Some providers require state even with PKCE
101
101
  state: codeChallenge,
102
+ nonce: codeChallenge,
102
103
  });
103
104
  }
104
105
  catch (e) {
@@ -122,7 +123,8 @@ class OpenIDAuthDriver extends local_1.LocalAuthDriver {
122
123
  let userInfo;
123
124
  try {
124
125
  const client = await this.client;
125
- tokenSet = await client.callback(this.redirectUrl, { code: payload.code, state: payload.state }, { code_verifier: payload.codeVerifier, state: openid_client_1.generators.codeChallenge(payload.codeVerifier) });
126
+ const codeChallenge = openid_client_1.generators.codeChallenge(payload.codeVerifier);
127
+ tokenSet = await client.callback(this.redirectUrl, { code: payload.code, state: payload.state }, { code_verifier: payload.codeVerifier, state: codeChallenge, nonce: codeChallenge });
126
128
  userInfo = tokenSet.claims();
127
129
  if (client.issuer.metadata.userinfo_endpoint) {
128
130
  userInfo = {
@@ -33,7 +33,6 @@ const fs_1 = require("fs");
33
33
  const inquirer_1 = __importDefault(require("inquirer"));
34
34
  const js_yaml_1 = require("js-yaml");
35
35
  const path_1 = __importDefault(require("path"));
36
- const cache_1 = require("../../../cache");
37
36
  const database_1 = __importStar(require("../../../database"));
38
37
  const logger_1 = __importDefault(require("../../../logger"));
39
38
  const apply_snapshot_1 = require("../../../utils/apply-snapshot");
@@ -44,7 +43,6 @@ async function apply(snapshotPath, options) {
44
43
  const filename = path_1.default.resolve(process.cwd(), snapshotPath);
45
44
  const database = (0, database_1.default)();
46
45
  await (0, database_1.validateDatabaseConnection)(database);
47
- await (0, cache_1.flushCaches)();
48
46
  if ((await (0, database_1.isInstalled)()) === false) {
49
47
  logger_1.default.error(`Directus isn't installed on this database. Please run "directus bootstrap" first.`);
50
48
  database.destroy();
@@ -11,9 +11,7 @@ const fs_1 = require("fs");
11
11
  const path_1 = __importDefault(require("path"));
12
12
  const inquirer_1 = __importDefault(require("inquirer"));
13
13
  const js_yaml_1 = require("js-yaml");
14
- const cache_1 = require("../../../cache");
15
14
  async function snapshot(snapshotPath, options) {
16
- await (0, cache_1.flushCaches)();
17
15
  const database = (0, database_1.default)();
18
16
  try {
19
17
  const snapshot = await (0, get_snapshot_1.getSnapshot)({ database });
@@ -4,7 +4,7 @@ exports.FnHelperMySQL = void 0;
4
4
  const types_1 = require("../types");
5
5
  const parseLocaltime = (columnType) => {
6
6
  if (columnType === 'timestamp') {
7
- return `CONVERT_TZ(??.??, @@GLOBAL.time_zone, 'UTC')`;
7
+ return `CONVERT_TZ(??.??, @@GLOBAL.time_zone, '+00:00')`;
8
8
  }
9
9
  return '??.??';
10
10
  };
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const async_handler_1 = __importDefault(require("../utils/async-handler"));
7
7
  const get_schema_1 = require("../utils/get-schema");
8
8
  const schema = (0, async_handler_1.default)(async (req, res, next) => {
9
- req.schema = await (0, get_schema_1.getSchema)({ accountability: req.accountability });
9
+ req.schema = await (0, get_schema_1.getSchema)();
10
10
  return next();
11
11
  });
12
12
  exports.default = schema;
@@ -157,7 +157,7 @@ class CollectionsService {
157
157
  await (0, cache_1.clearSystemCache)();
158
158
  }
159
159
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
160
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
160
+ const updatedSchema = await (0, get_schema_1.getSchema)();
161
161
  for (const nestedActionEvent of nestedActionEvents) {
162
162
  nestedActionEvent.context.schema = updatedSchema;
163
163
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -198,7 +198,7 @@ class CollectionsService {
198
198
  await (0, cache_1.clearSystemCache)();
199
199
  }
200
200
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
201
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
201
+ const updatedSchema = await (0, get_schema_1.getSchema)();
202
202
  for (const nestedActionEvent of nestedActionEvents) {
203
203
  nestedActionEvent.context.schema = updatedSchema;
204
204
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -343,7 +343,7 @@ class CollectionsService {
343
343
  await (0, cache_1.clearSystemCache)();
344
344
  }
345
345
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
346
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
346
+ const updatedSchema = await (0, get_schema_1.getSchema)();
347
347
  for (const nestedActionEvent of nestedActionEvents) {
348
348
  nestedActionEvent.context.schema = updatedSchema;
349
349
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -391,7 +391,7 @@ class CollectionsService {
391
391
  await (0, cache_1.clearSystemCache)();
392
392
  }
393
393
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
394
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
394
+ const updatedSchema = await (0, get_schema_1.getSchema)();
395
395
  for (const nestedActionEvent of nestedActionEvents) {
396
396
  nestedActionEvent.context.schema = updatedSchema;
397
397
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -433,7 +433,7 @@ class CollectionsService {
433
433
  await (0, cache_1.clearSystemCache)();
434
434
  }
435
435
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
436
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
436
+ const updatedSchema = await (0, get_schema_1.getSchema)();
437
437
  for (const nestedActionEvent of nestedActionEvents) {
438
438
  nestedActionEvent.context.schema = updatedSchema;
439
439
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -538,7 +538,7 @@ class CollectionsService {
538
538
  await (0, cache_1.clearSystemCache)();
539
539
  }
540
540
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
541
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
541
+ const updatedSchema = await (0, get_schema_1.getSchema)();
542
542
  for (const nestedActionEvent of nestedActionEvents) {
543
543
  nestedActionEvent.context.schema = updatedSchema;
544
544
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -579,7 +579,7 @@ class CollectionsService {
579
579
  await (0, cache_1.clearSystemCache)();
580
580
  }
581
581
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
582
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
582
+ const updatedSchema = await (0, get_schema_1.getSchema)();
583
583
  for (const nestedActionEvent of nestedActionEvents) {
584
584
  nestedActionEvent.context.schema = updatedSchema;
585
585
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -24,8 +24,9 @@ export declare class FieldsService {
24
24
  createField(collection: string, field: Partial<Field> & {
25
25
  field: string;
26
26
  type: Type | null;
27
- }, table?: Knex.CreateTableBuilder): Promise<void>;
28
- updateField(collection: string, field: RawField): Promise<string>;
27
+ }, table?: Knex.CreateTableBuilder, // allows collection creation to
28
+ opts?: MutationOptions): Promise<void>;
29
+ updateField(collection: string, field: RawField, opts?: MutationOptions): Promise<string>;
29
30
  deleteField(collection: string, field: string, opts?: MutationOptions): Promise<void>;
30
31
  addColumnToTable(table: Knex.CreateTableBuilder, field: RawField | Field, alter?: Column | null): void;
31
32
  }
@@ -218,8 +218,8 @@ class FieldsService {
218
218
  };
219
219
  return data;
220
220
  }
221
- async createField(collection, field, table // allows collection creation to
222
- ) {
221
+ async createField(collection, field, table, // allows collection creation to
222
+ opts) {
223
223
  if (this.accountability && this.accountability.admin !== true) {
224
224
  throw new exceptions_1.ForbiddenException();
225
225
  }
@@ -267,7 +267,7 @@ class FieldsService {
267
267
  field: hookAdjustedField.field,
268
268
  }, { emitEvents: false });
269
269
  }
270
- nestedActionEvents.push({
270
+ const actionEvent = {
271
271
  event: 'fields.create',
272
272
  meta: {
273
273
  payload: hookAdjustedField,
@@ -279,25 +279,35 @@ class FieldsService {
279
279
  schema: this.schema,
280
280
  accountability: this.accountability,
281
281
  },
282
- });
282
+ };
283
+ if (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) {
284
+ opts.bypassEmitAction(actionEvent);
285
+ }
286
+ else {
287
+ nestedActionEvents.push(actionEvent);
288
+ }
283
289
  });
284
290
  }
285
291
  finally {
286
292
  if (runPostColumnChange) {
287
293
  await this.helpers.schema.postColumnChange();
288
294
  }
289
- if (this.cache && env_1.default.CACHE_AUTO_PURGE) {
295
+ if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
290
296
  await this.cache.clear();
291
297
  }
292
- await (0, cache_1.clearSystemCache)();
293
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
294
- for (const nestedActionEvent of nestedActionEvents) {
295
- nestedActionEvent.context.schema = updatedSchema;
296
- emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
298
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoPurgeSystemCache) !== false) {
299
+ await (0, cache_1.clearSystemCache)();
300
+ }
301
+ if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
302
+ const updatedSchema = await (0, get_schema_1.getSchema)();
303
+ for (const nestedActionEvent of nestedActionEvents) {
304
+ nestedActionEvent.context.schema = updatedSchema;
305
+ emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
306
+ }
297
307
  }
298
308
  }
299
309
  }
300
- async updateField(collection, field) {
310
+ async updateField(collection, field, opts) {
301
311
  var _a, _b, _c;
302
312
  if (this.accountability && this.accountability.admin !== true) {
303
313
  throw new exceptions_1.ForbiddenException();
@@ -353,7 +363,7 @@ class FieldsService {
353
363
  }, { emitEvents: false });
354
364
  }
355
365
  }
356
- nestedActionEvents.push({
366
+ const actionEvent = {
357
367
  event: 'fields.update',
358
368
  meta: {
359
369
  payload: hookAdjustedField,
@@ -365,21 +375,31 @@ class FieldsService {
365
375
  schema: this.schema,
366
376
  accountability: this.accountability,
367
377
  },
368
- });
378
+ };
379
+ if (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) {
380
+ opts.bypassEmitAction(actionEvent);
381
+ }
382
+ else {
383
+ nestedActionEvents.push(actionEvent);
384
+ }
369
385
  return field.field;
370
386
  }
371
387
  finally {
372
388
  if (runPostColumnChange) {
373
389
  await this.helpers.schema.postColumnChange();
374
390
  }
375
- if (this.cache && env_1.default.CACHE_AUTO_PURGE) {
391
+ if (this.cache && env_1.default.CACHE_AUTO_PURGE && (opts === null || opts === void 0 ? void 0 : opts.autoPurgeCache) !== false) {
376
392
  await this.cache.clear();
377
393
  }
378
- await (0, cache_1.clearSystemCache)();
379
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
380
- for (const nestedActionEvent of nestedActionEvents) {
381
- nestedActionEvent.context.schema = updatedSchema;
382
- emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
394
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoPurgeSystemCache) !== false) {
395
+ await (0, cache_1.clearSystemCache)();
396
+ }
397
+ if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
398
+ const updatedSchema = await (0, get_schema_1.getSchema)();
399
+ for (const nestedActionEvent of nestedActionEvents) {
400
+ nestedActionEvent.context.schema = updatedSchema;
401
+ emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
402
+ }
383
403
  }
384
404
  }
385
405
  }
@@ -507,7 +527,7 @@ class FieldsService {
507
527
  await (0, cache_1.clearSystemCache)();
508
528
  }
509
529
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
510
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
530
+ const updatedSchema = await (0, get_schema_1.getSchema)();
511
531
  for (const nestedActionEvent of nestedActionEvents) {
512
532
  nestedActionEvent.context.schema = updatedSchema;
513
533
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -21,13 +21,13 @@ export declare class RelationsService {
21
21
  /**
22
22
  * Create a new relationship / foreign key constraint
23
23
  */
24
- createOne(relation: Partial<Relation>): Promise<void>;
24
+ createOne(relation: Partial<Relation>, opts?: MutationOptions): Promise<void>;
25
25
  /**
26
26
  * Update an existing foreign key constraint
27
27
  *
28
28
  * Note: You can update anything under meta, but only the `on_delete` trigger under schema
29
29
  */
30
- updateOne(collection: string, field: string, relation: Partial<Relation>): Promise<void>;
30
+ updateOne(collection: string, field: string, relation: Partial<Relation>, opts?: MutationOptions): Promise<void>;
31
31
  /**
32
32
  * Delete an existing relationship
33
33
  */
@@ -127,7 +127,7 @@ class RelationsService {
127
127
  /**
128
128
  * Create a new relationship / foreign key constraint
129
129
  */
130
- async createOne(relation) {
130
+ async createOne(relation, opts) {
131
131
  if (this.accountability && this.accountability.admin !== true) {
132
132
  throw new exceptions_1.ForbiddenException();
133
133
  }
@@ -185,7 +185,7 @@ class RelationsService {
185
185
  // happens in `filterForbidden` down below
186
186
  });
187
187
  await relationsItemService.createOne(metaRow, {
188
- bypassEmitAction: (params) => nestedActionEvents.push(params),
188
+ bypassEmitAction: (params) => (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
189
189
  });
190
190
  });
191
191
  }
@@ -193,11 +193,15 @@ class RelationsService {
193
193
  if (runPostColumnChange) {
194
194
  await this.helpers.schema.postColumnChange();
195
195
  }
196
- await (0, cache_1.clearSystemCache)();
197
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
198
- for (const nestedActionEvent of nestedActionEvents) {
199
- nestedActionEvent.context.schema = updatedSchema;
200
- emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
196
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoPurgeSystemCache) !== false) {
197
+ await (0, cache_1.clearSystemCache)();
198
+ }
199
+ if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
200
+ const updatedSchema = await (0, get_schema_1.getSchema)();
201
+ for (const nestedActionEvent of nestedActionEvents) {
202
+ nestedActionEvent.context.schema = updatedSchema;
203
+ emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
204
+ }
201
205
  }
202
206
  }
203
207
  }
@@ -206,7 +210,7 @@ class RelationsService {
206
210
  *
207
211
  * Note: You can update anything under meta, but only the `on_delete` trigger under schema
208
212
  */
209
- async updateOne(collection, field, relation) {
213
+ async updateOne(collection, field, relation, opts) {
210
214
  if (this.accountability && this.accountability.admin !== true) {
211
215
  throw new exceptions_1.ForbiddenException();
212
216
  }
@@ -254,7 +258,7 @@ class RelationsService {
254
258
  if (relation.meta) {
255
259
  if (existingRelation === null || existingRelation === void 0 ? void 0 : existingRelation.meta) {
256
260
  await relationsItemService.updateOne(existingRelation.meta.id, relation.meta, {
257
- bypassEmitAction: (params) => nestedActionEvents.push(params),
261
+ bypassEmitAction: (params) => (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
258
262
  });
259
263
  }
260
264
  else {
@@ -264,7 +268,7 @@ class RelationsService {
264
268
  many_field: relation.field,
265
269
  one_collection: existingRelation.related_collection || null,
266
270
  }, {
267
- bypassEmitAction: (params) => nestedActionEvents.push(params),
271
+ bypassEmitAction: (params) => (opts === null || opts === void 0 ? void 0 : opts.bypassEmitAction) ? opts.bypassEmitAction(params) : nestedActionEvents.push(params),
268
272
  });
269
273
  }
270
274
  }
@@ -274,11 +278,15 @@ class RelationsService {
274
278
  if (runPostColumnChange) {
275
279
  await this.helpers.schema.postColumnChange();
276
280
  }
277
- await (0, cache_1.clearSystemCache)();
278
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
279
- for (const nestedActionEvent of nestedActionEvents) {
280
- nestedActionEvent.context.schema = updatedSchema;
281
- emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
281
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoPurgeSystemCache) !== false) {
282
+ await (0, cache_1.clearSystemCache)();
283
+ }
284
+ if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
285
+ const updatedSchema = await (0, get_schema_1.getSchema)();
286
+ for (const nestedActionEvent of nestedActionEvents) {
287
+ nestedActionEvent.context.schema = updatedSchema;
288
+ emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
289
+ }
282
290
  }
283
291
  }
284
292
  }
@@ -343,7 +351,7 @@ class RelationsService {
343
351
  await (0, cache_1.clearSystemCache)();
344
352
  }
345
353
  if ((opts === null || opts === void 0 ? void 0 : opts.emitEvents) !== false && nestedActionEvents.length > 0) {
346
- const updatedSchema = await (0, get_schema_1.getSchema)({ accountability: this.accountability || undefined });
354
+ const updatedSchema = await (0, get_schema_1.getSchema)();
347
355
  for (const nestedActionEvent of nestedActionEvents) {
348
356
  nestedActionEvent.context.schema = updatedSchema;
349
357
  emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
@@ -202,11 +202,17 @@ class UsersService extends items_1.ItemsService {
202
202
  if (data.tfa_secret !== undefined) {
203
203
  throw new exceptions_2.InvalidPayloadException(`You can't change the "tfa_secret" value manually.`);
204
204
  }
205
- if (data.provider !== undefined && this.accountability && this.accountability.admin !== true) {
206
- throw new exceptions_2.InvalidPayloadException(`You can't change the "provider" value manually.`);
205
+ if (data.provider !== undefined) {
206
+ if (this.accountability && this.accountability.admin !== true) {
207
+ throw new exceptions_2.InvalidPayloadException(`You can't change the "provider" value manually.`);
208
+ }
209
+ data.auth_data = null;
207
210
  }
208
- if (data.external_identifier !== undefined && this.accountability && this.accountability.admin !== true) {
209
- throw new exceptions_2.InvalidPayloadException(`You can't change the "external_identifier" value manually.`);
211
+ if (data.external_identifier !== undefined) {
212
+ if (this.accountability && this.accountability.admin !== true) {
213
+ throw new exceptions_2.InvalidPayloadException(`You can't change the "external_identifier" value manually.`);
214
+ }
215
+ data.auth_data = null;
210
216
  }
211
217
  return await super.updateMany(keys, data, opts);
212
218
  }
@@ -12,13 +12,19 @@ const get_schema_1 = require("./get-schema");
12
12
  const get_snapshot_1 = require("./get-snapshot");
13
13
  const get_snapshot_diff_1 = require("./get-snapshot-diff");
14
14
  const cache_1 = require("../cache");
15
+ const emitter_1 = __importDefault(require("../emitter"));
15
16
  async function applySnapshot(snapshot, options) {
16
17
  var _a, _b, _c, _d;
17
18
  const database = (_a = options === null || options === void 0 ? void 0 : options.database) !== null && _a !== void 0 ? _a : (0, database_1.default)();
18
- const schema = (_b = options === null || options === void 0 ? void 0 : options.schema) !== null && _b !== void 0 ? _b : (await (0, get_schema_1.getSchema)({ database }));
19
+ const schema = (_b = options === null || options === void 0 ? void 0 : options.schema) !== null && _b !== void 0 ? _b : (await (0, get_schema_1.getSchema)({ database, bypassCache: true }));
19
20
  const { systemCache } = (0, cache_1.getCache)();
20
21
  const current = (_c = options === null || options === void 0 ? void 0 : options.current) !== null && _c !== void 0 ? _c : (await (0, get_snapshot_1.getSnapshot)({ database, schema }));
21
22
  const snapshotDiff = (_d = options === null || options === void 0 ? void 0 : options.diff) !== null && _d !== void 0 ? _d : (0, get_snapshot_diff_1.getSnapshotDiff)(current, snapshot);
23
+ const nestedActionEvents = [];
24
+ const mutationOptions = {
25
+ autoPurgeSystemCache: false,
26
+ bypassEmitAction: (params) => nestedActionEvents.push(params),
27
+ };
22
28
  await database.transaction(async (trx) => {
23
29
  const collectionsService = new services_1.CollectionsService({ knex: trx, schema });
24
30
  const getNestedCollectionsToCreate = (currentLevelCollection) => snapshotDiff.collections.filter(({ diff }) => { var _a, _b; return ((_b = (_a = diff[0].rhs) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.group) === currentLevelCollection; });
@@ -49,7 +55,7 @@ async function applySnapshot(snapshot, options) {
49
55
  await collectionsService.createOne({
50
56
  ...diff[0].rhs,
51
57
  fields,
52
- });
58
+ }, mutationOptions);
53
59
  }
54
60
  catch (err) {
55
61
  logger_1.default.error(`Failed to create collection "${collection}"`);
@@ -69,7 +75,7 @@ async function applySnapshot(snapshot, options) {
69
75
  const relationsService = new services_1.RelationsService({ knex: trx, schema });
70
76
  for (const relation of relations) {
71
77
  try {
72
- await relationsService.deleteOne(relation.collection, relation.field);
78
+ await relationsService.deleteOne(relation.collection, relation.field, mutationOptions);
73
79
  }
74
80
  catch (err) {
75
81
  logger_1.default.error(`Failed to delete collection "${collection}" due to relation "${relation.collection}.${relation.field}"`);
@@ -81,7 +87,7 @@ async function applySnapshot(snapshot, options) {
81
87
  }
82
88
  await deleteCollections(getNestedCollectionsToDelete(collection));
83
89
  try {
84
- await collectionsService.deleteOne(collection);
90
+ await collectionsService.deleteOne(collection, mutationOptions);
85
91
  }
86
92
  catch (err) {
87
93
  logger_1.default.error(`Failed to delete collection "${collection}"`);
@@ -130,7 +136,7 @@ async function applySnapshot(snapshot, options) {
130
136
  });
131
137
  if (newValues) {
132
138
  try {
133
- await collectionsService.updateOne(collection, newValues);
139
+ await collectionsService.updateOne(collection, newValues, mutationOptions);
134
140
  }
135
141
  catch (err) {
136
142
  logger_1.default.error(`Failed to update collection "${collection}"`);
@@ -139,11 +145,14 @@ async function applySnapshot(snapshot, options) {
139
145
  }
140
146
  }
141
147
  }
142
- const fieldsService = new services_1.FieldsService({ knex: trx, schema: await (0, get_schema_1.getSchema)({ database: trx }) });
148
+ const fieldsService = new services_1.FieldsService({
149
+ knex: trx,
150
+ schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
151
+ });
143
152
  for (const { collection, field, diff } of snapshotDiff.fields) {
144
153
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
145
154
  try {
146
- await fieldsService.createField(collection, diff[0].rhs);
155
+ await fieldsService.createField(collection, diff[0].rhs, undefined, mutationOptions);
147
156
  }
148
157
  catch (err) {
149
158
  logger_1.default.error(`Failed to create field "${collection}.${field}"`);
@@ -158,7 +167,7 @@ async function applySnapshot(snapshot, options) {
158
167
  try {
159
168
  await fieldsService.updateField(collection, {
160
169
  ...newValues,
161
- });
170
+ }, mutationOptions);
162
171
  }
163
172
  catch (err) {
164
173
  logger_1.default.error(`Failed to update field "${collection}.${field}"`);
@@ -168,7 +177,7 @@ async function applySnapshot(snapshot, options) {
168
177
  }
169
178
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D' && !isNestedMetaUpdate(diff === null || diff === void 0 ? void 0 : diff[0])) {
170
179
  try {
171
- await fieldsService.deleteField(collection, field);
180
+ await fieldsService.deleteField(collection, field, mutationOptions);
172
181
  }
173
182
  catch (err) {
174
183
  logger_1.default.error(`Failed to delete field "${collection}.${field}"`);
@@ -179,7 +188,10 @@ async function applySnapshot(snapshot, options) {
179
188
  snapshotDiff.relations = snapshotDiff.relations.filter((relation) => (relation.collection === collection && relation.field === field) === false);
180
189
  }
181
190
  }
182
- const relationsService = new services_1.RelationsService({ knex: trx, schema: await (0, get_schema_1.getSchema)({ database: trx }) });
191
+ const relationsService = new services_1.RelationsService({
192
+ knex: trx,
193
+ schema: await (0, get_schema_1.getSchema)({ database: trx, bypassCache: true }),
194
+ });
183
195
  for (const { collection, field, diff } of snapshotDiff.relations) {
184
196
  const structure = {};
185
197
  for (const diffEdit of diff) {
@@ -187,7 +199,7 @@ async function applySnapshot(snapshot, options) {
187
199
  }
188
200
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'N') {
189
201
  try {
190
- await relationsService.createOne(diff[0].rhs);
202
+ await relationsService.createOne(diff[0].rhs, mutationOptions);
191
203
  }
192
204
  catch (err) {
193
205
  logger_1.default.error(`Failed to create relation "${collection}.${field}"`);
@@ -200,7 +212,7 @@ async function applySnapshot(snapshot, options) {
200
212
  });
201
213
  if (newValues) {
202
214
  try {
203
- await relationsService.updateOne(collection, field, newValues);
215
+ await relationsService.updateOne(collection, field, newValues, mutationOptions);
204
216
  }
205
217
  catch (err) {
206
218
  logger_1.default.error(`Failed to update relation "${collection}.${field}"`);
@@ -210,7 +222,7 @@ async function applySnapshot(snapshot, options) {
210
222
  }
211
223
  if ((diff === null || diff === void 0 ? void 0 : diff[0].kind) === 'D') {
212
224
  try {
213
- await relationsService.deleteOne(collection, field);
225
+ await relationsService.deleteOne(collection, field, mutationOptions);
214
226
  }
215
227
  catch (err) {
216
228
  logger_1.default.error(`Failed to delete relation "${collection}.${field}"`);
@@ -220,6 +232,13 @@ async function applySnapshot(snapshot, options) {
220
232
  }
221
233
  });
222
234
  await (systemCache === null || systemCache === void 0 ? void 0 : systemCache.clear());
235
+ if (nestedActionEvents.length > 0) {
236
+ const updatedSchema = await (0, get_schema_1.getSchema)({ database, bypassCache: true });
237
+ for (const nestedActionEvent of nestedActionEvents) {
238
+ nestedActionEvent.context.schema = updatedSchema;
239
+ emitter_1.default.emitAction(nestedActionEvent.event, nestedActionEvent.meta, nestedActionEvent.context);
240
+ }
241
+ }
223
242
  }
224
243
  exports.applySnapshot = applySnapshot;
225
244
  function isNestedMetaUpdate(diff) {
@@ -1,6 +1,10 @@
1
- import { Accountability, SchemaOverview } from '@directus/shared/types';
1
+ import { SchemaOverview } from '@directus/shared/types';
2
2
  import { Knex } from 'knex';
3
3
  export declare function getSchema(options?: {
4
- accountability?: Accountability;
5
4
  database?: Knex;
5
+ /**
6
+ * To bypass any cached schema if bypassCache is enabled.
7
+ * Used to ensure schema snapshot/apply is not using outdated schema
8
+ */
9
+ bypassCache?: boolean;
6
10
  }): Promise<SchemaOverview>;
@@ -21,7 +21,7 @@ async function getSchema(options) {
21
21
  const database = (options === null || options === void 0 ? void 0 : options.database) || (0, database_1.default)();
22
22
  const schemaInspector = (0, schema_1.default)(database);
23
23
  let result;
24
- if (env_1.default.CACHE_SCHEMA !== false) {
24
+ if (!(options === null || options === void 0 ? void 0 : options.bypassCache) && env_1.default.CACHE_SCHEMA !== false) {
25
25
  let cachedSchema;
26
26
  try {
27
27
  cachedSchema = (await (0, cache_1.getSystemCache)('schema'));
@@ -12,7 +12,7 @@ const lodash_1 = require("lodash");
12
12
  async function getSnapshot(options) {
13
13
  var _a, _b;
14
14
  const database = (_a = options === null || options === void 0 ? void 0 : options.database) !== null && _a !== void 0 ? _a : (0, database_1.default)();
15
- const schema = (_b = options === null || options === void 0 ? void 0 : options.schema) !== null && _b !== void 0 ? _b : (await (0, get_schema_1.getSchema)({ database }));
15
+ const schema = (_b = options === null || options === void 0 ? void 0 : options.schema) !== null && _b !== void 0 ? _b : (await (0, get_schema_1.getSchema)({ database, bypassCache: true }));
16
16
  const collectionsService = new services_1.CollectionsService({ knex: database, schema });
17
17
  const fieldsService = new services_1.FieldsService({ knex: database, schema });
18
18
  const relationsService = new services_1.RelationsService({ knex: database, schema });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "directus",
3
- "version": "9.21.0",
3
+ "version": "9.21.2",
4
4
  "description": "Directus is a real-time API and App dashboard for managing SQL database content",
5
5
  "keywords": [
6
6
  "directus",
@@ -66,16 +66,7 @@
66
66
  "dependencies": {
67
67
  "@authenio/samlify-node-xmllint": "2.0.0",
68
68
  "@aws-sdk/client-ses": "3.211.0",
69
- "@directus/app": "9.21.0",
70
- "@directus/drive": "9.21.0",
71
- "@directus/drive-azure": "9.21.0",
72
- "@directus/drive-gcs": "9.21.0",
73
- "@directus/drive-s3": "9.21.0",
74
- "@directus/extensions-sdk": "9.21.0",
75
69
  "@directus/format-title": "9.15.0",
76
- "@directus/schema": "9.21.0",
77
- "@directus/shared": "9.21.0",
78
- "@directus/specs": "9.21.0",
79
70
  "@godaddy/terminus": "4.11.2",
80
71
  "@rollup/plugin-alias": "4.0.2",
81
72
  "@rollup/plugin-virtual": "3.0.1",
@@ -94,7 +85,6 @@
94
85
  "csv-parser": "3.0.0",
95
86
  "date-fns": "2.29.3",
96
87
  "deep-diff": "1.0.2",
97
- "deep-map": "2.0.0",
98
88
  "destroy": "1.2.0",
99
89
  "dotenv": "16.0.3",
100
90
  "encodeurl": "1.0.2",
@@ -140,7 +130,6 @@
140
130
  "pino-http-print": "3.1.0",
141
131
  "qs": "6.11.0",
142
132
  "rate-limiter-flexible": "2.4.1",
143
- "resolve-cwd": "3.0.0",
144
133
  "rollup": "3.3.0",
145
134
  "samlify": "2.8.7",
146
135
  "sanitize-html": "2.7.3",
@@ -153,10 +142,18 @@
153
142
  "uuid": "9.0.0",
154
143
  "uuid-validate": "0.0.3",
155
144
  "vm2": "3.9.11",
156
- "wellknown": "0.5.0"
145
+ "wellknown": "0.5.0",
146
+ "@directus/app": "9.21.2",
147
+ "@directus/drive": "9.21.2",
148
+ "@directus/drive-azure": "9.21.2",
149
+ "@directus/drive-gcs": "9.21.2",
150
+ "@directus/drive-s3": "9.21.2",
151
+ "@directus/extensions-sdk": "9.21.2",
152
+ "@directus/schema": "9.21.2",
153
+ "@directus/shared": "9.21.2",
154
+ "@directus/specs": "9.21.2"
157
155
  },
158
156
  "devDependencies": {
159
- "@otplib/preset-default": "12.0.1",
160
157
  "@types/async": "3.2.15",
161
158
  "@types/busboy": "1.5.0",
162
159
  "@types/bytes": "3.1.1",
@@ -166,9 +163,7 @@
166
163
  "@types/destroy": "1.0.0",
167
164
  "@types/encodeurl": "1.0.0",
168
165
  "@types/express": "4.17.14",
169
- "@types/express-pino-logger": "4.0.3",
170
166
  "@types/express-serve-static-core": "4.17.31",
171
- "@types/express-session": "1.17.5",
172
167
  "@types/fast-redact": "3.0.2",
173
168
  "@types/flat": "5.0.2",
174
169
  "@types/fs-extra": "9.0.13",
@@ -192,7 +187,6 @@
192
187
  "@types/sanitize-html": "2.6.2",
193
188
  "@types/sharp": "0.31.0",
194
189
  "@types/stream-json": "1.7.2",
195
- "@types/supertest": "2.0.12",
196
190
  "@types/uuid": "8.3.4",
197
191
  "@types/uuid-validate": "0.0.1",
198
192
  "@types/wellknown": "0.5.4",
@@ -200,8 +194,6 @@
200
194
  "copyfiles": "2.4.1",
201
195
  "form-data": "4.0.0",
202
196
  "knex-mock-client": "1.8.4",
203
- "rimraf": "3.0.2",
204
- "supertest": "6.3.1",
205
197
  "ts-node": "10.9.1",
206
198
  "ts-node-dev": "2.0.0",
207
199
  "typescript": "4.9.3",
@@ -222,9 +214,7 @@
222
214
  "node": ">=12.20.0"
223
215
  },
224
216
  "scripts": {
225
- "prebuild": "pnpm cleanup",
226
217
  "build": "tsc --build && copyfiles \"src/**/*.{yaml,liquid}\" -u 1 dist",
227
- "cleanup": "rimraf dist",
228
218
  "cli": "NODE_ENV=development SERVE_APP=false ts-node --script-mode --transpile-only src/cli/run.ts",
229
219
  "dev": "NODE_ENV=development SERVE_APP=false ts-node-dev --files --transpile-only --respawn --watch \".env\" --inspect=0 --exit-child -- src/start.ts",
230
220
  "start": "npx directus start",