Skip to content

Commit

Permalink
Fixed applying of snapshot changes to/from alias fields (#24120)
Browse files Browse the repository at this point in the history
* Fix applying of snapshot changes to/from alias fields

* Add changeset
  • Loading branch information
licitdev authored Dec 2, 2024
1 parent fb41400 commit 92684fc
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/tiny-deers-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@directus/api': patch
---

Fixed applying of snapshot changes to/from alias fields
21 changes: 18 additions & 3 deletions api/src/utils/apply-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export async function applyDiff(
}
}

const fieldsService = new FieldsService({
let fieldsService = new FieldsService({
knex: trx,
schema: await getSchema({ database: trx, bypassCache: true }),
});
Expand All @@ -214,6 +214,12 @@ export async function applyDiff(
if (diff?.[0]?.kind === DiffKind.NEW && !isNestedMetaUpdate(diff?.[0])) {
try {
await fieldsService.createField(collection, (diff[0] as DiffNew<Field>).rhs, undefined, mutationOptions);

// Refresh the schema
fieldsService = new FieldsService({
knex: trx,
schema: await getSchema({ database: trx, bypassCache: true }),
});
} catch (err) {
logger.error(`Failed to create field "${collection}.${field}"`);
throw err;
Expand Down Expand Up @@ -243,15 +249,24 @@ export async function applyDiff(
if (diff?.[0]?.kind === DiffKind.DELETE && !isNestedMetaUpdate(diff?.[0])) {
try {
await fieldsService.deleteField(collection, field, mutationOptions);

// Refresh the schema
fieldsService = new FieldsService({
knex: trx,
schema: await getSchema({ database: trx, bypassCache: true }),
});
} catch (err) {
logger.error(`Failed to delete field "${collection}.${field}"`);
throw err;
}

// Field deletion also cleans up the relationship. We should ignore any relationship
// changes attached to this now non-existing field
// changes attached to this now non-existing field except newly created relationship
snapshotDiff.relations = snapshotDiff.relations.filter(
(relation) => (relation.collection === collection && relation.field === field) === false,
(relation) =>
(relation.collection === collection &&
relation.field === field &&
!relation.diff.some((diff) => diff.kind === DiffKind.NEW)) === false,
);
}
}
Expand Down
27 changes: 26 additions & 1 deletion api/src/utils/get-snapshot-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,22 @@ export function getSnapshotDiff(current: Snapshot, after: Snapshot): SnapshotDif
const isAutoIncrementPrimaryKey =
!!currentField.schema?.is_primary_key && !!currentField.schema?.has_auto_increment;

// Changing to/from alias fields should delete the current field
if (
afterField &&
currentField.type !== afterField.type &&
(currentField.type === 'alias' || afterField.type === 'alias')
) {
return {
collection: currentField.collection,
field: currentField.field,
diff: deepDiff.diff(
sanitizeField(currentField, isAutoIncrementPrimaryKey),
sanitizeField(undefined, isAutoIncrementPrimaryKey),
),
};
}

return {
collection: currentField.collection,
field: currentField.field,
Expand All @@ -49,11 +65,20 @@ export function getSnapshotDiff(current: Snapshot, after: Snapshot): SnapshotDif
}),
...after.fields
.filter((afterField) => {
const currentField = current.fields.find(
let currentField = current.fields.find(
(currentField) =>
currentField.collection === afterField.collection && afterField.field === currentField.field,
);

// Changing to/from alias fields should create the new field
if (
currentField &&
currentField.type !== afterField.type &&
(currentField.type === 'alias' || afterField.type === 'alias')
) {
currentField = undefined;
}

return !!currentField === false;
})
.map((afterField) => ({
Expand Down

0 comments on commit 92684fc

Please sign in to comment.