Merge pull request #15169 from strapi/deits/strategies-cleanup

This commit is contained in:
Ben Irvin 2022-12-16 16:23:37 +01:00 committed by GitHub
commit 0444bb9929
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 41 additions and 76 deletions

View File

@ -299,9 +299,8 @@ describe('Transfer engine', () => {
} as IDestinationProvider;
const defaultOptions = {
strategy: 'restore',
versionMatching: 'exact',
schemasMatching: 'exact',
versionStrategy: 'exact',
schemaStrategy: 'exact',
exclude: [],
} as ITransferEngineOptions;
@ -416,9 +415,8 @@ describe('Transfer engine', () => {
describe('schema matching', () => {
describe('exact', () => {
const engineOptions = {
strategy: 'restore',
versionMatching: 'exact',
schemasMatching: 'exact',
versionStrategy: 'exact',
schemaStrategy: 'exact',
exclude: [],
} as ITransferEngineOptions;
test('source with source schema missing in destination fails', async () => {
@ -465,7 +463,7 @@ describe('Transfer engine', () => {
const versionsThatFail = ['foo', 'z1.2.3', '1.2.3z'];
const options: ITransferEngineOptions = {
...defaultOptions,
versionMatching: 'exact',
versionStrategy: 'exact',
};
versionsThatFail.forEach((version) => {
@ -487,7 +485,7 @@ describe('Transfer engine', () => {
const versionsThatSucceed = ['1.2.3'];
const options: ITransferEngineOptions = {
...defaultOptions,
versionMatching: 'exact',
versionStrategy: 'exact',
};
versionsThatFail.forEach((version) => {
@ -522,7 +520,7 @@ describe('Transfer engine', () => {
const versionsThatSucceed = ['1.2.3', '1.3.4', '1.4.4-alpha'];
const options: ITransferEngineOptions = {
...defaultOptions,
versionMatching: 'major',
versionStrategy: 'major',
};
await Promise.all(
@ -561,7 +559,7 @@ describe('Transfer engine', () => {
const versionsThatSucceed = ['1.2.3', '1.2.40', '1.2.4-alpha'];
const options: ITransferEngineOptions = {
...defaultOptions,
versionMatching: 'minor',
versionStrategy: 'minor',
};
await Promise.all(
@ -600,7 +598,7 @@ describe('Transfer engine', () => {
const versionsThatSucceed = ['1.2.3'];
const options: ITransferEngineOptions = {
...defaultOptions,
versionMatching: 'patch',
versionStrategy: 'patch',
};
await Promise.all(
@ -638,7 +636,7 @@ describe('Transfer engine', () => {
const versionsThatSucceed = ['1.2.3', '1.3.4', '5.24.44-alpha'];
const options: ITransferEngineOptions = {
...defaultOptions,
versionMatching: 'ignore',
versionStrategy: 'ignore',
};
await Promise.all(

View File

@ -1,5 +1,4 @@
import { PassThrough, Transform, Readable, Writable } from 'stream';
import * as path from 'path';
import { extname } from 'path';
import { isEmpty, uniq } from 'lodash/fp';
import { diff as semverDiff } from 'semver';
@ -24,6 +23,9 @@ import type { Diff } from '../utils/json';
import compareSchemas from '../strategies';
import { filter, map } from '../utils/stream';
export const DEFAULT_VERSION_STRATEGY = 'ignore';
export const DEFAULT_SCHEMA_STRATEGY = 'strict';
type SchemaMap = Record<string, Schema>;
class TransferEngine<
@ -158,7 +160,7 @@ class TransferEngine<
}
#assertStrapiVersionIntegrity(sourceVersion?: string, destinationVersion?: string) {
const strategy = this.options.versionMatching;
const strategy = this.options.versionStrategy || DEFAULT_VERSION_STRATEGY;
if (
!sourceVersion ||
@ -200,7 +202,11 @@ class TransferEngine<
}
#assertSchemasMatching(sourceSchemas: SchemaMap, destinationSchemas: SchemaMap) {
const strategy = this.options.schemasMatching || 'strict';
const strategy = this.options.schemaStrategy || DEFAULT_SCHEMA_STRATEGY;
if (strategy === 'ignore') {
return;
}
const keys = uniq(Object.keys(sourceSchemas).concat(Object.keys(destinationSchemas)));
const diffs: { [key: string]: Diff[] } = {};

View File

@ -6,7 +6,8 @@ import type { IAsset, IDestinationProvider, IMetadata, ProviderType } from '../.
import { restore } from './strategies';
import * as utils from '../../utils';
export const VALID_STRATEGIES = ['restore', 'merge'];
export const VALID_CONFLICT_STRATEGIES = ['restore', 'merge'];
export const DEFAULT_CONFLICT_STRATEGY = 'restore';
interface ILocalStrapiDestinationProviderOptions {
getStrapi(): Strapi.Strapi | Promise<Strapi.Strapi>;
@ -40,7 +41,7 @@ class LocalStrapiDestinationProvider implements IDestinationProvider {
}
#validateOptions() {
if (!VALID_STRATEGIES.includes(this.options.strategy)) {
if (!VALID_CONFLICT_STRATEGIES.includes(this.options.strategy)) {
throw new Error(`Invalid stategy ${this.options.strategy}`);
}
}

View File

@ -112,12 +112,12 @@ export interface ITransferEngineOptions {
* "minor" // both the major and minor version should match. 4.3.9 and 4.3.11 will work, while 4.3.9 and 4.4.1 won't
* "patch" // every part of the version should match. Similar to "exact" but only work on semver.
*/
versionMatching: 'exact' | 'ignore' | 'major' | 'minor' | 'patch';
versionStrategy: 'exact' | 'ignore' | 'major' | 'minor' | 'patch';
/**
* Strategy used to do the schema matching in the integrity checks
*/
schemasMatching: 'exact' | 'strict';
schemaStrategy: 'exact' | 'strict' | 'ignore';
// List of rules to integrate into the final pipelines
transforms?: {

View File

@ -14,11 +14,7 @@ const inquirer = require('inquirer');
const program = new Command();
const packageJSON = require('../package.json');
const {
parseInputList,
promptEncryptionKey,
confirmKeyValue,
} = require('../lib/commands/utils/commander');
const { promptEncryptionKey, confirmMessage } = require('../lib/commands/utils/commander');
const checkCwdIsStrapiApp = (name) => {
const logErrorAndExit = () => {
@ -273,45 +269,15 @@ program
.addOption(
new Option('--key <string>', 'Provide encryption key in command instead of using a prompt')
)
.addOption(
new Option(
'--max-size-jsonl <max MB per internal backup file>',
'split internal jsonl files when exceeding max size in MB'
)
.argParser(parseFloat)
.default(256)
)
.addOption(new Option('-f, --file <file>', 'name to use for exported file (without extensions)'))
.allowExcessArguments(false)
.hook('preAction', promptEncryptionKey)
// validate inputs
.hook('preAction', (thisCommand) => {
const opts = thisCommand.opts();
if (!opts.maxSizeJsonl) {
console.error('Invalid max-size-jsonl provided. Must be a number value.');
process.exit(1);
}
})
.action(getLocalScript('transfer/export'));
// `$ strapi import`
program
.command('import')
.description('Import data from file to Strapi')
.addOption(
new Option('--conflictStrategy <conflictStrategy>', 'Which strategy to use for ID conflicts')
.choices(['restore', 'abort', 'keep', 'replace'])
.default('restore')
)
.addOption(
new Option(
'--schemaComparison <schemaComparison>',
'exact requires every field to match, strict requires Strapi version and content type schema fields do not break, subset requires source schema to exist in destination, bypass skips checks',
parseInputList
)
.choices(['exact', 'strict', 'subset', 'bypass'])
.default('exact')
)
.requiredOption(
'-f, --file <file>',
'path and filename to the Strapi export file you want to import'
@ -344,10 +310,8 @@ program
})
.hook(
'preAction',
confirmKeyValue(
'conflictStrategy',
'restore',
"Using strategy 'restore' will delete all data in your database. Are you sure you want to proceed?"
confirmMessage(
'The import will delete all data in your database. Are you sure you want to proceed?'
)
)
.action(getLocalScript('transfer/import'));

View File

@ -22,7 +22,6 @@ const {
* @typedef ImportCommandOptions Options given to the CLI import command
*
* @property {string} [file] The file path to import
* @property {number} [maxSizeJsonl] Maximum size for each .jsonl file
* @property {boolean} [encrypt] Used to encrypt the final archive
* @property {string} [key] Encryption key, only useful when encryption is enabled
* @property {boolean} [compress] Used to compress the final archive
@ -52,8 +51,8 @@ module.exports = async (opts) => {
const destination = createDestinationProvider(opts);
const engine = createTransferEngine(source, destination, {
strategy: 'restore', // for an export to file, strategy will always be 'restore'
versionMatching: 'ignore', // for an export to file, versionMatching will always be skipped
versionStrategy: 'ignore', // for an export to file, versionStrategy will always be skipped
schemaStrategy: 'ignore', // for an export to file, schemaStrategy will always be skipped
transforms: {
links: [
{

View File

@ -4,6 +4,9 @@ const {
createLocalFileSourceProvider,
createLocalStrapiDestinationProvider,
createTransferEngine,
DEFAULT_VERSION_STRATEGY,
DEFAULT_SCHEMA_STRATEGY,
DEFAULT_CONFLICT_STRATEGY,
// TODO: we need to solve this issue with typescript modules
// eslint-disable-next-line import/no-unresolved, node/no-missing-require
} = require('@strapi/data-transfer');
@ -42,7 +45,7 @@ module.exports = async (opts) => {
async getStrapi() {
return strapiInstance;
},
strategy: opts.conflictStrategy,
strategy: opts.conflictStrategy || DEFAULT_CONFLICT_STRATEGY,
restore: {
entities: { exclude: DEFAULT_IGNORED_CONTENT_TYPES },
},
@ -53,8 +56,8 @@ module.exports = async (opts) => {
* Configure and run the transfer engine
*/
const engineOptions = {
strategy: opts.conflictStrategy,
versionMatching: opts.schemaComparison,
versionStrategy: opts.versionStrategy || DEFAULT_VERSION_STRATEGY,
schemaStrategy: opts.schemaStrategy || DEFAULT_SCHEMA_STRATEGY,
exclude: opts.exclude,
rules: {
links: [

View File

@ -48,25 +48,19 @@ const promptEncryptionKey = async (thisCommand) => {
};
/**
* hook: confirm that key has a value with a provided message
* hook: require a confirmation message to be accepted
*/
const confirmKeyValue = (key, value, message) => {
return async (thisCommand) => {
const opts = thisCommand.opts();
if (!opts[key] || opts[key] !== value) {
console.error(`Could not confirm key ${key}, halting operation.`);
process.exit(1);
}
const confirmMessage = (message) => {
return async () => {
const answers = await inquirer.prompt([
{
type: 'confirm',
message,
name: `confirm_${key}`,
name: `confirm`,
default: false,
},
]);
if (!answers[`confirm_${key}`]) {
if (!answers.confirm) {
process.exit(0);
}
};
@ -75,5 +69,5 @@ const confirmKeyValue = (key, value, message) => {
module.exports = {
parseInputList,
promptEncryptionKey,
confirmKeyValue,
confirmMessage,
};