mirror of
https://github.com/strapi/strapi.git
synced 2025-12-28 15:44:59 +00:00
add middleware for schema diff handling
This commit is contained in:
parent
b012dc6e78
commit
9cbdad0a70
@ -27,7 +27,11 @@ import type { Diff } from '../utils/json';
|
||||
import { compareSchemas, validateProvider } from './validation';
|
||||
import { filter, map } from '../utils/stream';
|
||||
|
||||
import { TransferEngineError, TransferEngineValidationError } from './errors';
|
||||
import {
|
||||
TransferEngineError,
|
||||
TransferEngineInitializationError,
|
||||
TransferEngineValidationError,
|
||||
} from './errors';
|
||||
import {
|
||||
createDiagnosticReporter,
|
||||
IDiagnosticReporter,
|
||||
@ -76,6 +80,27 @@ export const DEFAULT_SCHEMA_STRATEGY = 'strict';
|
||||
|
||||
type SchemaMap = Record<string, Schema>;
|
||||
|
||||
type SchemaDiffHandlerContext = {
|
||||
diffs: Record<string, Diff[]>;
|
||||
source: ISourceProvider;
|
||||
destination: IDestinationProvider;
|
||||
};
|
||||
type SchemaDiffHandler = (data: SchemaDiffHandlerContext, next: SchemaDiffHandler) => void;
|
||||
|
||||
// TODO: clean this up
|
||||
type Next = (context: any) => void | Promise<void>;
|
||||
type Middleware<T> = (context: T, next: Next) => Promise<void> | void;
|
||||
async function runMiddleware<T>(context: T, middlewares: Middleware<T>[]): Promise<void> {
|
||||
if (!middlewares.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cb = middlewares[0];
|
||||
await cb(context, async (newContext) => {
|
||||
await runMiddleware(newContext, middlewares.slice(1));
|
||||
});
|
||||
}
|
||||
|
||||
class TransferEngine<
|
||||
S extends ISourceProvider = ISourceProvider,
|
||||
D extends IDestinationProvider = IDestinationProvider
|
||||
@ -99,6 +124,16 @@ class TransferEngine<
|
||||
|
||||
diagnostics: IDiagnosticReporter;
|
||||
|
||||
#handlers: {
|
||||
schemaDiff: SchemaDiffHandler[];
|
||||
} = {
|
||||
schemaDiff: [],
|
||||
};
|
||||
|
||||
onSchemaDiff(handler: SchemaDiffHandler) {
|
||||
this.#handlers?.schemaDiff?.push(handler);
|
||||
}
|
||||
|
||||
// Save the currently open stream so that we can access it at any time
|
||||
#currentStream?: Writable;
|
||||
|
||||
@ -616,15 +651,24 @@ class TransferEngine<
|
||||
if (error instanceof TransferEngineValidationError) {
|
||||
this.#schemaDiffs = error.details?.details?.diffs as Record<string, Diff[]>;
|
||||
|
||||
// TODO: implement a confirmation callback to confirm or reject the error
|
||||
Object.entries(this.#schemaDiffs).forEach(([uid, diffs]) => {
|
||||
for (const diff of diffs) {
|
||||
this.#reportWarning(`${diff.path.join('.')} for ${uid}`, 'Schema Integrity Check');
|
||||
// await new Promise((resolve, reject) => {
|
||||
// this.confirm('Continue with diffs ?', resolve, reject);
|
||||
// });
|
||||
}
|
||||
});
|
||||
const context = {
|
||||
diffs: this.#schemaDiffs,
|
||||
source: this.sourceProvider,
|
||||
destination: this.destinationProvider,
|
||||
};
|
||||
await runMiddleware(context, this.#handlers.schemaDiff);
|
||||
|
||||
if (Object.keys(context.diffs).length) {
|
||||
console.log('DIFFS REMAINING', context.diffs);
|
||||
Object.entries(context.diffs).forEach(([uid, diffs]) => {
|
||||
for (const diff of diffs) {
|
||||
this.#reportWarning(`${diff.path.join('.')} for ${uid}`, 'Schema Integrity Check');
|
||||
this.#panic(
|
||||
new TransferEngineInitializationError('Unresolved differences in schema')
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
|
||||
@ -11,6 +11,7 @@ const {
|
||||
} = require('@strapi/data-transfer');
|
||||
|
||||
const { isObject } = require('lodash/fp');
|
||||
const inquirer = require('inquirer');
|
||||
|
||||
const {
|
||||
buildTransferTable,
|
||||
@ -111,6 +112,24 @@ module.exports = async (opts) => {
|
||||
|
||||
const { updateLoader } = loadersFactory();
|
||||
|
||||
engine.onSchemaDiff(async (context, next) => {
|
||||
// TODO: work with "force"
|
||||
// TODO: yes/no prompt should look like commander prompt
|
||||
const answers = await inquirer.prompt([
|
||||
{
|
||||
type: 'confirm',
|
||||
message: 'Are you sure you want to continue?',
|
||||
name: 'confirmSchemaDiff',
|
||||
},
|
||||
]);
|
||||
if (answers.confirmSchemaDiff) {
|
||||
// diffs have been resolved by user
|
||||
context.diffs = [];
|
||||
}
|
||||
|
||||
return next(context);
|
||||
});
|
||||
|
||||
progress.on(`stage::start`, ({ stage, data }) => {
|
||||
updateLoader(stage, data).start();
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user