From 953eb99eb3f322b79624eae2c0dfe1e482d7e246 Mon Sep 17 00:00:00 2001 From: Azri Kahar <42867097+azrikahar@users.noreply.github.com> Date: Sat, 16 Apr 2022 01:27:47 +0800 Subject: [PATCH] Fix schema apply for changes in field meta options & display_options (#12712) * Fix schema apply for changes in field meta options * take display_options into account * check changes in meta in general --- api/src/cli/commands/schema/apply.ts | 10 +++++++--- api/src/utils/apply-snapshot.ts | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/api/src/cli/commands/schema/apply.ts b/api/src/cli/commands/schema/apply.ts index 6d72e9ae7e..f399b7f2bd 100644 --- a/api/src/cli/commands/schema/apply.ts +++ b/api/src/cli/commands/schema/apply.ts @@ -8,7 +8,7 @@ import logger from '../../../logger'; import { Snapshot } from '../../../types'; import { getSnapshot } from '../../../utils/get-snapshot'; import { getSnapshotDiff } from '../../../utils/get-snapshot-diff'; -import { applySnapshot } from '../../../utils/apply-snapshot'; +import { applySnapshot, isNestedMetaUpdate } from '../../../utils/apply-snapshot'; import { flushCaches } from '../../../cache'; export async function apply(snapshotPath: string, options?: { yes: boolean; dryRun: boolean }): Promise { @@ -82,13 +82,17 @@ export async function apply(snapshotPath: string, options?: { yes: boolean; dryR message += '\n\n' + chalk.black.underline.bold('Fields:'); for (const { collection, field, diff } of snapshotDiff.fields) { - if (diff[0]?.kind === 'E') { + if (diff[0]?.kind === 'E' || isNestedMetaUpdate(diff[0])) { message += `\n - ${chalk.blue('Update')} ${collection}.${field}`; for (const change of diff) { + const path = change.path!.slice(1).join('.'); if (change.kind === 'E') { - const path = change.path!.slice(1).join('.'); message += `\n - Set ${path} to ${change.rhs}`; + } else if (change.kind === 'D') { + message += `\n - Remove ${path}`; + } else if (change.kind === 'N') { + message += `\n - Add ${path} and set it to ${change.rhs}`; } } } else if (diff[0]?.kind === 'D') { diff --git a/api/src/utils/apply-snapshot.ts b/api/src/utils/apply-snapshot.ts index c33f6c85cc..a83ea12877 100644 --- a/api/src/utils/apply-snapshot.ts +++ b/api/src/utils/apply-snapshot.ts @@ -1,4 +1,4 @@ -import { Snapshot, SnapshotDiff } from '../types'; +import { Snapshot, SnapshotDiff, SnapshotField } from '../types'; import { getSnapshot } from './get-snapshot'; import { getSnapshotDiff } from './get-snapshot-diff'; import { Knex } from 'knex'; @@ -6,7 +6,7 @@ import getDatabase from '../database'; import { getSchema } from './get-schema'; import { CollectionsService, FieldsService, RelationsService } from '../services'; import { set, merge } from 'lodash'; -import { DiffNew } from 'deep-diff'; +import { Diff, DiffNew } from 'deep-diff'; import { Field, Relation, SchemaOverview } from '@directus/shared/types'; import logger from '../logger'; @@ -96,7 +96,7 @@ export async function applySnapshot( const fieldsService = new FieldsService({ knex: trx, schema: await getSchema({ database: trx }) }); for (const { collection, field, diff } of snapshotDiff.fields) { - if (diff?.[0].kind === 'N') { + if (diff?.[0].kind === 'N' && !isNestedMetaUpdate(diff?.[0])) { try { await fieldsService.createField(collection, (diff[0] as DiffNew).rhs); } catch (err) { @@ -105,7 +105,7 @@ export async function applySnapshot( } } - if (diff?.[0].kind === 'E' || diff?.[0].kind === 'A') { + if (diff?.[0].kind === 'E' || diff?.[0].kind === 'A' || isNestedMetaUpdate(diff?.[0])) { const newValues = snapshot.fields.find((snapshotField) => { return snapshotField.collection === collection && snapshotField.field === field; }); @@ -122,7 +122,7 @@ export async function applySnapshot( } } - if (diff?.[0].kind === 'D') { + if (diff?.[0].kind === 'D' && !isNestedMetaUpdate(diff?.[0])) { try { await fieldsService.deleteField(collection, field); } catch (err) { @@ -182,3 +182,10 @@ export async function applySnapshot( } }); } + +export function isNestedMetaUpdate(diff: Diff): boolean { + if (!diff) return false; + if (diff.kind !== 'N' && diff.kind !== 'D') return false; + if (!diff.path || diff.path.length < 2 || diff.path[0] !== 'meta') return false; + return true; +}