@strapi/strapi 4.10.0-beta.0 → 4.10.0
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.
- package/.eslintignore +2 -0
- package/.eslintrc.js +4 -0
- package/bin/strapi.js +2 -455
- package/ee/LICENSE.txt +21 -0
- package/ee/index.js +42 -5
- package/ee/license.js +11 -8
- package/lib/Strapi.js +14 -7
- package/lib/commands/{admin-create.js → actions/admin/create-user/action.js} +2 -2
- package/lib/commands/actions/admin/create-user/command.js +19 -0
- package/lib/commands/{admin-reset.js → actions/admin/reset-user-password/action.js} +2 -2
- package/lib/commands/actions/admin/reset-user-password/command.js +17 -0
- package/lib/commands/{configurationDump.js → actions/configuration/dump/action.js} +1 -1
- package/lib/commands/actions/configuration/dump/command.js +17 -0
- package/lib/commands/{configurationRestore.js → actions/configuration/restore/action.js} +1 -1
- package/lib/commands/actions/configuration/restore/command.js +17 -0
- package/lib/commands/{console.js → actions/console/action.js} +2 -2
- package/lib/commands/actions/console/command.js +14 -0
- package/lib/commands/{content-types/list.js → actions/content-types/list/action.js} +2 -2
- package/lib/commands/actions/content-types/list/command.js +14 -0
- package/lib/commands/{controllers/list.js → actions/controllers/list/action.js} +2 -2
- package/lib/commands/actions/controllers/list/command.js +14 -0
- package/lib/commands/{develop.js → actions/develop/action.js} +3 -3
- package/lib/commands/actions/develop/command.js +19 -0
- package/lib/commands/{transfer/export.js → actions/export/action.js} +27 -19
- package/lib/commands/actions/export/command.js +45 -0
- package/lib/commands/actions/generate/command.js +18 -0
- package/lib/commands/{hooks/list.js → actions/hooks/list/action.js} +2 -2
- package/lib/commands/actions/hooks/list/command.js +14 -0
- package/lib/commands/{transfer/import.js → actions/import/action.js} +39 -18
- package/lib/commands/actions/import/command.js +97 -0
- package/lib/commands/{install.js → actions/install/action.js} +1 -1
- package/lib/commands/actions/install/command.js +14 -0
- package/lib/commands/{middlewares/list.js → actions/middlewares/list/action.js} +2 -2
- package/lib/commands/actions/middlewares/list/command.js +14 -0
- package/lib/commands/{new.js → actions/new/action.js} +1 -1
- package/lib/commands/actions/new/command.js +35 -0
- package/lib/commands/{policies/list.js → actions/policies/list/action.js} +2 -2
- package/lib/commands/actions/policies/list/command.js +14 -0
- package/lib/commands/actions/report/action.js +35 -0
- package/lib/commands/actions/report/command.js +17 -0
- package/lib/commands/{routes/list.js → actions/routes/list/action.js} +2 -2
- package/lib/commands/actions/routes/list/command.js +14 -0
- package/lib/commands/{services/list.js → actions/services/list/action.js} +2 -2
- package/lib/commands/actions/services/list/command.js +14 -0
- package/lib/commands/{start.js → actions/start/action.js} +1 -1
- package/lib/commands/actions/start/command.js +14 -0
- package/lib/commands/{opt-out-telemetry.js → actions/telemetry/disable/action.js} +1 -1
- package/lib/commands/actions/telemetry/disable/command.js +14 -0
- package/lib/commands/{opt-in-telemetry.js → actions/telemetry/enable/action.js} +1 -1
- package/lib/commands/actions/telemetry/enable/command.js +14 -0
- package/lib/commands/actions/templates/generate/command.js +14 -0
- package/lib/commands/{transfer/transfer.js → actions/transfer/action.js} +61 -14
- package/lib/commands/actions/transfer/command.js +115 -0
- package/lib/commands/{ts/generate-types.js → actions/ts/generate-types/action.js} +2 -2
- package/lib/commands/actions/ts/generate-types/command.js +21 -0
- package/lib/commands/{uninstall.js → actions/uninstall/action.js} +1 -1
- package/lib/commands/actions/uninstall/command.js +15 -0
- package/lib/commands/actions/version/command.js +19 -0
- package/lib/commands/{watchAdmin.js → actions/watch-admin/action.js} +4 -4
- package/lib/commands/actions/watch-admin/command.js +15 -0
- package/lib/commands/index.js +66 -0
- package/lib/commands/utils/commander.js +14 -0
- package/lib/commands/{transfer/utils.js → utils/data-transfer.js} +54 -5
- package/lib/commands/utils/helpers.js +54 -3
- package/lib/core/domain/content-type/validator.js +1 -1
- package/lib/core/loaders/plugins/index.js +7 -2
- package/lib/core/registries/custom-fields.js +19 -2
- package/lib/core/registries/policies.d.ts +3 -3
- package/lib/core-api/controller/collection-type.js +0 -1
- package/lib/core-api/controller/index.js +1 -1
- package/lib/factories.js +3 -4
- package/lib/middlewares/logger.js +1 -17
- package/lib/middlewares/security.js +1 -1
- package/lib/services/event-hub.js +6 -1
- package/lib/services/metrics/index.js +1 -0
- package/lib/services/metrics/sender.js +1 -14
- package/lib/services/server/index.js +2 -2
- package/lib/services/server/register-routes.js +1 -1
- package/lib/services/utils/dynamic-zones.js +13 -0
- package/lib/services/webhook-runner.js +4 -4
- package/lib/types/core/commands/index.d.ts +6 -0
- package/lib/utils/fetch.js +23 -0
- package/package.json +22 -21
- package/lib/commands/build.js +0 -18
- /package/lib/commands/{generate-template.js → actions/templates/generate/action.js} +0 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const { Option } = require('commander');
|
|
5
|
+
const { confirmMessage, forceOption, parseURL } = require('../../utils/commander');
|
|
6
|
+
const {
|
|
7
|
+
getLocalScript,
|
|
8
|
+
exitWith,
|
|
9
|
+
assertUrlHasProtocol,
|
|
10
|
+
ifOptions,
|
|
11
|
+
} = require('../../utils/helpers');
|
|
12
|
+
const {
|
|
13
|
+
excludeOption,
|
|
14
|
+
onlyOption,
|
|
15
|
+
throttleOption,
|
|
16
|
+
validateExcludeOnly,
|
|
17
|
+
} = require('../../utils/data-transfer');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* `$ strapi transfer`
|
|
21
|
+
* @param {import('../../../types/core/commands').AddCommandOptions} options
|
|
22
|
+
*/
|
|
23
|
+
module.exports = ({ command }) => {
|
|
24
|
+
command
|
|
25
|
+
.command('transfer')
|
|
26
|
+
.description('Transfer data from one source to another')
|
|
27
|
+
.allowExcessArguments(false)
|
|
28
|
+
.addOption(
|
|
29
|
+
new Option(
|
|
30
|
+
'--from <sourceURL>',
|
|
31
|
+
`URL of the remote Strapi instance to get data from`
|
|
32
|
+
).argParser(parseURL)
|
|
33
|
+
)
|
|
34
|
+
.addOption(new Option('--from-token <token>', `Transfer token for the remote Strapi source`))
|
|
35
|
+
.addOption(
|
|
36
|
+
new Option(
|
|
37
|
+
'--to <destinationURL>',
|
|
38
|
+
`URL of the remote Strapi instance to send data to`
|
|
39
|
+
).argParser(parseURL)
|
|
40
|
+
)
|
|
41
|
+
.addOption(new Option('--to-token <token>', `Transfer token for the remote Strapi destination`))
|
|
42
|
+
.addOption(forceOption)
|
|
43
|
+
.addOption(excludeOption)
|
|
44
|
+
.addOption(onlyOption)
|
|
45
|
+
.addOption(throttleOption)
|
|
46
|
+
.hook('preAction', validateExcludeOnly)
|
|
47
|
+
.hook(
|
|
48
|
+
'preAction',
|
|
49
|
+
ifOptions(
|
|
50
|
+
(opts) => !(opts.from || opts.to) || (opts.from && opts.to),
|
|
51
|
+
() =>
|
|
52
|
+
exitWith(
|
|
53
|
+
1,
|
|
54
|
+
'Exactly one remote source (from) or destination (to) option must be provided'
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
// If --from is used, validate the URL and token
|
|
59
|
+
.hook(
|
|
60
|
+
'preAction',
|
|
61
|
+
ifOptions(
|
|
62
|
+
(opts) => opts.from,
|
|
63
|
+
async (thisCommand) => {
|
|
64
|
+
assertUrlHasProtocol(thisCommand.opts().from, ['https:', 'http:']);
|
|
65
|
+
if (!thisCommand.opts().fromToken) {
|
|
66
|
+
const answers = await inquirer.prompt([
|
|
67
|
+
{
|
|
68
|
+
type: 'password',
|
|
69
|
+
message: 'Please enter your transfer token for the remote Strapi source',
|
|
70
|
+
name: 'fromToken',
|
|
71
|
+
},
|
|
72
|
+
]);
|
|
73
|
+
if (!answers.fromToken?.length) {
|
|
74
|
+
exitWith(1, 'No token provided for remote source, aborting transfer.');
|
|
75
|
+
}
|
|
76
|
+
thisCommand.opts().fromToken = answers.fromToken;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await confirmMessage(
|
|
80
|
+
'The transfer will delete all the local Strapi assets and its database. Are you sure you want to proceed?',
|
|
81
|
+
{ failMessage: 'Transfer process aborted' }
|
|
82
|
+
)(thisCommand);
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
// If --to is used, validate the URL, token, and confirm restore
|
|
87
|
+
.hook(
|
|
88
|
+
'preAction',
|
|
89
|
+
ifOptions(
|
|
90
|
+
(opts) => opts.to,
|
|
91
|
+
async (thisCommand) => {
|
|
92
|
+
assertUrlHasProtocol(thisCommand.opts().to, ['https:', 'http:']);
|
|
93
|
+
if (!thisCommand.opts().toToken) {
|
|
94
|
+
const answers = await inquirer.prompt([
|
|
95
|
+
{
|
|
96
|
+
type: 'password',
|
|
97
|
+
message: 'Please enter your transfer token for the remote Strapi destination',
|
|
98
|
+
name: 'toToken',
|
|
99
|
+
},
|
|
100
|
+
]);
|
|
101
|
+
if (!answers.toToken?.length) {
|
|
102
|
+
exitWith(1, 'No token provided for remote destination, aborting transfer.');
|
|
103
|
+
}
|
|
104
|
+
thisCommand.opts().toToken = answers.toToken;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
await confirmMessage(
|
|
108
|
+
'The transfer will delete all the remote Strapi assets and its database. Are you sure you want to proceed?',
|
|
109
|
+
{ failMessage: 'Transfer process aborted' }
|
|
110
|
+
)(thisCommand);
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
.action(getLocalScript('transfer'));
|
|
115
|
+
};
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const tsUtils = require('@strapi/typescript-utils');
|
|
4
4
|
|
|
5
|
-
const strapi = require('
|
|
5
|
+
const strapi = require('../../../../index');
|
|
6
6
|
|
|
7
|
-
module.exports = async
|
|
7
|
+
module.exports = async ({ outDir, file, verbose, silent }) => {
|
|
8
8
|
if (verbose && silent) {
|
|
9
9
|
console.error('You cannot enable verbose and silent flags at the same time, exiting...');
|
|
10
10
|
process.exit(1);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getLocalScript } = require('../../../utils/helpers');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `$ strapi ts:generate-types`
|
|
7
|
+
* @param {import('../../../../types/core/commands').AddCommandOptions} options
|
|
8
|
+
*/
|
|
9
|
+
module.exports = ({ command }) => {
|
|
10
|
+
command
|
|
11
|
+
.command('ts:generate-types')
|
|
12
|
+
.description(`Generate TypeScript typings for your schemas`)
|
|
13
|
+
.option(
|
|
14
|
+
'-o, --out-dir <outDir>',
|
|
15
|
+
'Specify a relative directory in which the schemas definitions will be generated'
|
|
16
|
+
)
|
|
17
|
+
.option('-f, --file <file>', 'Specify a filename to store the schemas definitions')
|
|
18
|
+
.option('--verbose', `Display more information about the types generation`, false)
|
|
19
|
+
.option('-s, --silent', `Run the generation silently, without any output`, false)
|
|
20
|
+
.action(getLocalScript('ts/generate-types'));
|
|
21
|
+
};
|
|
@@ -5,7 +5,7 @@ const { existsSync, removeSync } = require('fs-extra');
|
|
|
5
5
|
const ora = require('ora');
|
|
6
6
|
const execa = require('execa');
|
|
7
7
|
const inquirer = require('inquirer');
|
|
8
|
-
const findPackagePath = require('
|
|
8
|
+
const findPackagePath = require('../../../load/package-path');
|
|
9
9
|
|
|
10
10
|
module.exports = async (plugins, { deleteFiles }) => {
|
|
11
11
|
const answers = await inquirer.prompt([
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getLocalScript } = require('../../utils/helpers');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `$ strapi uninstall`
|
|
7
|
+
* @param {import('../../../types/core/commands').AddCommandOptions} options
|
|
8
|
+
*/
|
|
9
|
+
module.exports = ({ command }) => {
|
|
10
|
+
command
|
|
11
|
+
.command('uninstall [plugins...]')
|
|
12
|
+
.description('Uninstall a Strapi plugin')
|
|
13
|
+
.option('-d, --delete-files', 'Delete files', false)
|
|
14
|
+
.action(getLocalScript('uninstall'));
|
|
15
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `$ strapi version`
|
|
5
|
+
* @param {import('../../../types/core/commands').AddCommandOptions} options
|
|
6
|
+
*/
|
|
7
|
+
module.exports = ({ command }) => {
|
|
8
|
+
// load the Strapi package.json to get version and other information
|
|
9
|
+
const packageJSON = require('../../../../package.json');
|
|
10
|
+
|
|
11
|
+
command.version(packageJSON.version, '-v, --version', 'Output the version number');
|
|
12
|
+
command
|
|
13
|
+
.command('version')
|
|
14
|
+
.description('Output the version of Strapi')
|
|
15
|
+
.action(() => {
|
|
16
|
+
process.stdout.write(`${packageJSON.version}\n`);
|
|
17
|
+
process.exit(0);
|
|
18
|
+
});
|
|
19
|
+
};
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
const strapiAdmin = require('@strapi/admin');
|
|
4
4
|
const { getConfigUrls, getAbsoluteServerUrl } = require('@strapi/utils');
|
|
5
5
|
|
|
6
|
-
const getEnabledPlugins = require('
|
|
7
|
-
const addSlash = require('
|
|
8
|
-
const strapi = require('
|
|
6
|
+
const getEnabledPlugins = require('../../../core/loaders/plugins/get-enabled-plugins');
|
|
7
|
+
const addSlash = require('../../../utils/addSlash');
|
|
8
|
+
const strapi = require('../../../index');
|
|
9
9
|
|
|
10
|
-
module.exports = async
|
|
10
|
+
module.exports = async ({ browser }) => {
|
|
11
11
|
const appContext = await strapi.compile();
|
|
12
12
|
|
|
13
13
|
const strapiInstance = strapi({
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getLocalScript } = require('../../utils/helpers');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `$ strapi watch-admin`
|
|
7
|
+
* @param {import('../../../types/core/commands').AddCommandOptions} options
|
|
8
|
+
*/
|
|
9
|
+
module.exports = ({ command }) => {
|
|
10
|
+
command
|
|
11
|
+
.command('watch-admin')
|
|
12
|
+
.option('--browser <name>', 'Open the browser', true)
|
|
13
|
+
.description('Start the admin development server')
|
|
14
|
+
.action(getLocalScript('watch-admin'));
|
|
15
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { Command } = require('commander');
|
|
4
|
+
|
|
5
|
+
const strapiCommands = {
|
|
6
|
+
'admin/create-user': require('./actions/admin/create-user/command'),
|
|
7
|
+
'admin/reset-user-password': require('./actions/admin/reset-user-password/command'),
|
|
8
|
+
build: require('./actions/build/command'),
|
|
9
|
+
'configuration/dump': require('./actions/configuration/dump/command'),
|
|
10
|
+
'configuration/restore': require('./actions/configuration/restore/command'),
|
|
11
|
+
console: require('./actions/console/command'),
|
|
12
|
+
'content-types/list': require('./actions/content-types/list/command'),
|
|
13
|
+
'controllers/list': require('./actions/controllers/list/command'),
|
|
14
|
+
develop: require('./actions/develop/command'),
|
|
15
|
+
export: require('./actions/export/command'),
|
|
16
|
+
generate: require('./actions/generate/command'),
|
|
17
|
+
'hooks/list': require('./actions/hooks/list/command'),
|
|
18
|
+
import: require('./actions/import/command'),
|
|
19
|
+
install: require('./actions/install/command'),
|
|
20
|
+
'middlewares/list': require('./actions/middlewares/list/command'),
|
|
21
|
+
new: require('./actions/new/command'),
|
|
22
|
+
'policies/list': require('./actions/policies/list/command'),
|
|
23
|
+
report: require('./actions/report/command'),
|
|
24
|
+
'routes/list': require('./actions/routes/list/command'),
|
|
25
|
+
'services/list': require('./actions/services/list/command'),
|
|
26
|
+
start: require('./actions/start/command'),
|
|
27
|
+
'telemetry/disable': require('./actions/telemetry/disable/command'),
|
|
28
|
+
'telemetry/enable': require('./actions/telemetry/enable/command'),
|
|
29
|
+
'templates/generate': require('./actions/templates/generate/command'),
|
|
30
|
+
transfer: require('./actions/transfer/command'),
|
|
31
|
+
'ts/generate-types': require('./actions/ts/generate-types/command'),
|
|
32
|
+
uninstall: require('./actions/uninstall/command'),
|
|
33
|
+
version: require('./actions/version/command'),
|
|
34
|
+
'watch-admin': require('./actions/watch-admin/command'),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const buildStrapiCommand = (argv, command = new Command()) => {
|
|
38
|
+
// Initial program setup
|
|
39
|
+
command.storeOptionsAsProperties(false).allowUnknownOption(true);
|
|
40
|
+
|
|
41
|
+
// Help command
|
|
42
|
+
command.helpOption('-h, --help', 'Display help for command');
|
|
43
|
+
command.addHelpCommand('help [command]', 'Display help for command');
|
|
44
|
+
|
|
45
|
+
// Load all commands
|
|
46
|
+
Object.keys(strapiCommands).forEach((name) => {
|
|
47
|
+
try {
|
|
48
|
+
// Add this command to the Commander command object
|
|
49
|
+
strapiCommands[name]({ command, argv });
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.error(`Failed to load command ${name}`, e);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return command;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const runStrapiCommand = async (argv = process.argv, command = new Command()) => {
|
|
59
|
+
await buildStrapiCommand(argv, command).parseAsync(argv);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
module.exports = {
|
|
63
|
+
runStrapiCommand,
|
|
64
|
+
buildStrapiCommand,
|
|
65
|
+
strapiCommands,
|
|
66
|
+
};
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
const inquirer = require('inquirer');
|
|
8
8
|
const { InvalidOptionArgumentError, Option } = require('commander');
|
|
9
9
|
const { bold, green, cyan } = require('chalk');
|
|
10
|
+
const { isNaN } = require('lodash/fp');
|
|
10
11
|
const { exitWith } = require('./helpers');
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -40,6 +41,18 @@ const getParseListWithChoices = (choices, errorMessage = 'Invalid options:') =>
|
|
|
40
41
|
};
|
|
41
42
|
};
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* argParser: Parse a string as an integer
|
|
46
|
+
*/
|
|
47
|
+
const parseInteger = (value) => {
|
|
48
|
+
// parseInt takes a string and a radix
|
|
49
|
+
const parsedValue = parseInt(value, 10);
|
|
50
|
+
if (isNaN(parsedValue)) {
|
|
51
|
+
throw new InvalidOptionArgumentError(`Not an integer: ${value}`);
|
|
52
|
+
}
|
|
53
|
+
return parsedValue;
|
|
54
|
+
};
|
|
55
|
+
|
|
43
56
|
/**
|
|
44
57
|
* argParser: Parse a string as a URL object
|
|
45
58
|
*/
|
|
@@ -131,6 +144,7 @@ module.exports = {
|
|
|
131
144
|
getParseListWithChoices,
|
|
132
145
|
parseList,
|
|
133
146
|
parseURL,
|
|
147
|
+
parseInteger,
|
|
134
148
|
promptEncryptionKey,
|
|
135
149
|
confirmMessage,
|
|
136
150
|
forceOption,
|
|
@@ -12,9 +12,21 @@ const {
|
|
|
12
12
|
createLogger,
|
|
13
13
|
} = require('@strapi/logger');
|
|
14
14
|
const ora = require('ora');
|
|
15
|
-
const { readableBytes, exitWith } = require('
|
|
15
|
+
const { readableBytes, exitWith } = require('./helpers');
|
|
16
16
|
const strapi = require('../../index');
|
|
17
|
-
const { getParseListWithChoices } = require('
|
|
17
|
+
const { getParseListWithChoices, parseInteger } = require('./commander');
|
|
18
|
+
|
|
19
|
+
const exitMessageText = (process, error = false) => {
|
|
20
|
+
const processCapitalized = process[0].toUpperCase() + process.slice(1);
|
|
21
|
+
|
|
22
|
+
if (!error) {
|
|
23
|
+
return chalk.bold(
|
|
24
|
+
chalk.green(`${processCapitalized} process has been completed successfully!`)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return chalk.bold(chalk.red(`${processCapitalized} process failed.`));
|
|
29
|
+
};
|
|
18
30
|
|
|
19
31
|
const pad = (n) => {
|
|
20
32
|
return (n < 10 ? '0' : '') + String(n);
|
|
@@ -90,12 +102,23 @@ const DEFAULT_IGNORED_CONTENT_TYPES = [
|
|
|
90
102
|
'admin::audit-log',
|
|
91
103
|
];
|
|
92
104
|
|
|
93
|
-
const
|
|
105
|
+
const abortTransfer = async ({ engine, strapi }) => {
|
|
106
|
+
try {
|
|
107
|
+
await engine.abortTransfer();
|
|
108
|
+
await strapi.destroy();
|
|
109
|
+
} catch (e) {
|
|
110
|
+
// ignore because there's not much else we can do
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const createStrapiInstance = async (opts = {}) => {
|
|
94
117
|
try {
|
|
95
118
|
const appContext = await strapi.compile();
|
|
96
|
-
const app = strapi(appContext);
|
|
119
|
+
const app = strapi({ ...opts, ...appContext });
|
|
97
120
|
|
|
98
|
-
app.log.level = logLevel;
|
|
121
|
+
app.log.level = opts.logLevel || 'error';
|
|
99
122
|
return await app.load();
|
|
100
123
|
} catch (err) {
|
|
101
124
|
if (err.code === 'ECONNREFUSED') {
|
|
@@ -107,6 +130,13 @@ const createStrapiInstance = async (logLevel = 'error') => {
|
|
|
107
130
|
|
|
108
131
|
const transferDataTypes = Object.keys(TransferGroupPresets);
|
|
109
132
|
|
|
133
|
+
const throttleOption = new Option(
|
|
134
|
+
'--throttle <delay after each entity>',
|
|
135
|
+
`Add a delay in milliseconds between each transferred entity`
|
|
136
|
+
)
|
|
137
|
+
.argParser(parseInteger)
|
|
138
|
+
.hideHelp(); // This option is not publicly documented
|
|
139
|
+
|
|
110
140
|
const excludeOption = new Option(
|
|
111
141
|
'--exclude <comma-separated data types>',
|
|
112
142
|
`Exclude data using comma-separated types. Available types: ${transferDataTypes.join(',')}`
|
|
@@ -212,14 +242,33 @@ const loadersFactory = (defaultLoaders = {}) => {
|
|
|
212
242
|
};
|
|
213
243
|
};
|
|
214
244
|
|
|
245
|
+
/**
|
|
246
|
+
* Get the telemetry data to be sent for a didDEITSProcess* event from an initialized transfer engine object
|
|
247
|
+
*
|
|
248
|
+
* @param {import('@strapi/data-transfer/types').ITransferEngine} engine Initialized transfer engine
|
|
249
|
+
* @returns {object} Telemetry properties object
|
|
250
|
+
*/
|
|
251
|
+
const getTransferTelemetryPayload = (engine) => {
|
|
252
|
+
return {
|
|
253
|
+
eventProperties: {
|
|
254
|
+
source: engine?.sourceProvider?.name,
|
|
255
|
+
destination: engine?.destinationProvider?.name,
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
};
|
|
259
|
+
|
|
215
260
|
module.exports = {
|
|
216
261
|
loadersFactory,
|
|
217
262
|
buildTransferTable,
|
|
218
263
|
getDefaultExportName,
|
|
264
|
+
getTransferTelemetryPayload,
|
|
219
265
|
DEFAULT_IGNORED_CONTENT_TYPES,
|
|
220
266
|
createStrapiInstance,
|
|
221
267
|
excludeOption,
|
|
268
|
+
exitMessageText,
|
|
222
269
|
onlyOption,
|
|
270
|
+
throttleOption,
|
|
223
271
|
validateExcludeOnly,
|
|
224
272
|
formatDiagnostic,
|
|
273
|
+
abortTransfer,
|
|
225
274
|
};
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* Helper functions for the Strapi CLI
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const { yellow, red, green } = require('chalk');
|
|
8
8
|
const { isString, isArray } = require('lodash/fp');
|
|
9
|
+
const resolveCwd = require('resolve-cwd');
|
|
10
|
+
const { has } = require('lodash/fp');
|
|
9
11
|
|
|
10
12
|
const bytesPerKb = 1024;
|
|
11
13
|
const sizes = ['B ', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
|
@@ -46,9 +48,9 @@ const exitWith = (code, message = undefined, options = {}) => {
|
|
|
46
48
|
|
|
47
49
|
const log = (message) => {
|
|
48
50
|
if (code === 0) {
|
|
49
|
-
logger.log(
|
|
51
|
+
logger.log(green(message));
|
|
50
52
|
} else {
|
|
51
|
-
logger.error(
|
|
53
|
+
logger.error(red(message));
|
|
52
54
|
}
|
|
53
55
|
};
|
|
54
56
|
|
|
@@ -107,9 +109,58 @@ const ifOptions = (conditionCallback, isMetCallback = () => {}, isNotMetCallback
|
|
|
107
109
|
};
|
|
108
110
|
};
|
|
109
111
|
|
|
112
|
+
const assertCwdContainsStrapiProject = (name) => {
|
|
113
|
+
const logErrorAndExit = () => {
|
|
114
|
+
console.log(
|
|
115
|
+
`You need to run ${yellow(
|
|
116
|
+
`strapi ${name}`
|
|
117
|
+
)} in a Strapi project. Make sure you are in the right directory.`
|
|
118
|
+
);
|
|
119
|
+
process.exit(1);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
const pkgJSON = require(`${process.cwd()}/package.json`);
|
|
124
|
+
if (!has('dependencies.@strapi/strapi', pkgJSON)) {
|
|
125
|
+
logErrorAndExit(name);
|
|
126
|
+
}
|
|
127
|
+
} catch (err) {
|
|
128
|
+
logErrorAndExit(name);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const getLocalScript =
|
|
133
|
+
(name) =>
|
|
134
|
+
(...args) => {
|
|
135
|
+
assertCwdContainsStrapiProject(name);
|
|
136
|
+
|
|
137
|
+
const cmdPath = resolveCwd.silent(`@strapi/strapi/lib/commands/actions/${name}/action`);
|
|
138
|
+
if (!cmdPath) {
|
|
139
|
+
console.log(
|
|
140
|
+
`Error loading the local ${yellow(
|
|
141
|
+
name
|
|
142
|
+
)} command. Strapi might not be installed in your "node_modules". You may need to run "yarn install".`
|
|
143
|
+
);
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const script = require(cmdPath);
|
|
148
|
+
|
|
149
|
+
Promise.resolve()
|
|
150
|
+
.then(() => {
|
|
151
|
+
return script(...args);
|
|
152
|
+
})
|
|
153
|
+
.catch((error) => {
|
|
154
|
+
console.error(error);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
|
|
110
159
|
module.exports = {
|
|
111
160
|
exitWith,
|
|
112
161
|
assertUrlHasProtocol,
|
|
113
162
|
ifOptions,
|
|
114
163
|
readableBytes,
|
|
164
|
+
getLocalScript,
|
|
165
|
+
assertCwdContainsStrapiProject,
|
|
115
166
|
};
|
|
@@ -61,7 +61,7 @@ const contentTypeSchemaValidator = yup.object().shape({
|
|
|
61
61
|
|
|
62
62
|
// should match the GraphQL regex
|
|
63
63
|
if (!regressedValues.every((value) => GRAPHQL_ENUM_REGEX.test(value))) {
|
|
64
|
-
const message = `Invalid enumeration value. Values should have at least one alphabetical character
|
|
64
|
+
const message = `Invalid enumeration value. Values should have at least one alphabetical character preceding the first occurence of a number. Update your enumeration '${attrName}'.`;
|
|
65
65
|
|
|
66
66
|
return this.createError({ message });
|
|
67
67
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { join } = require('path');
|
|
4
4
|
const fse = require('fs-extra');
|
|
5
|
-
const { defaultsDeep, getOr, get } = require('lodash/fp');
|
|
5
|
+
const { defaultsDeep, defaults, getOr, get } = require('lodash/fp');
|
|
6
6
|
const { env } = require('@strapi/utils');
|
|
7
7
|
const loadConfigFile = require('../../app-configuration/load-config-file');
|
|
8
8
|
const loadFiles = require('../../../load/load-files');
|
|
@@ -101,7 +101,12 @@ const loadPlugins = async (strapi) => {
|
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
const pluginServer = loadConfigFile(serverEntrypointPath);
|
|
104
|
-
plugins[pluginName] =
|
|
104
|
+
plugins[pluginName] = {
|
|
105
|
+
...defaultPlugin,
|
|
106
|
+
...pluginServer,
|
|
107
|
+
config: defaults(defaultPlugin.config, pluginServer.config),
|
|
108
|
+
routes: pluginServer.routes ?? defaultPlugin.routes,
|
|
109
|
+
};
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
// TODO: validate plugin format
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { has } = require('lodash/fp');
|
|
3
|
+
const { has, isPlainObject } = require('lodash/fp');
|
|
4
4
|
|
|
5
5
|
const ALLOWED_TYPES = [
|
|
6
6
|
'biginteger',
|
|
@@ -44,7 +44,7 @@ const customFieldsRegistry = (strapi) => {
|
|
|
44
44
|
throw new Error(`Custom fields require a 'name' and 'type' key`);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
const { name, plugin, type } = cf;
|
|
47
|
+
const { name, plugin, type, inputSize } = cf;
|
|
48
48
|
if (!ALLOWED_TYPES.includes(type)) {
|
|
49
49
|
throw new Error(
|
|
50
50
|
`Custom field type: '${type}' is not a valid Strapi type or it can't be used with a Custom Field`
|
|
@@ -56,6 +56,23 @@ const customFieldsRegistry = (strapi) => {
|
|
|
56
56
|
throw new Error(`Custom field name: '${name}' is not a valid object key`);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
// Validate inputSize when provided
|
|
60
|
+
if (inputSize) {
|
|
61
|
+
if (
|
|
62
|
+
!isPlainObject(inputSize) ||
|
|
63
|
+
!has('default', inputSize) ||
|
|
64
|
+
!has('isResizable', inputSize)
|
|
65
|
+
) {
|
|
66
|
+
throw new Error(`inputSize should be an object with 'default' and 'isResizable' keys`);
|
|
67
|
+
}
|
|
68
|
+
if (![4, 6, 8, 12].includes(inputSize.default)) {
|
|
69
|
+
throw new Error('Custom fields require a valid default input size');
|
|
70
|
+
}
|
|
71
|
+
if (typeof inputSize.isResizable !== 'boolean') {
|
|
72
|
+
throw new Error('Custom fields should specify if their input is resizable');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
59
76
|
// When no plugin is specified, or it isn't found in Strapi, default to global
|
|
60
77
|
const uid = strapi.plugin(plugin) ? `plugin::${plugin}.${name}` : `global::${name}`;
|
|
61
78
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExtendableContext } from 'koa';
|
|
2
2
|
import { Strapi } from '../../';
|
|
3
3
|
|
|
4
|
-
interface PolicyContext extends
|
|
4
|
+
interface PolicyContext extends ExtendableContext {
|
|
5
5
|
type: string;
|
|
6
|
-
is(name): boolean;
|
|
6
|
+
is(name: string): boolean;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export type Policy<T = unknown> = (
|
|
@@ -22,7 +22,6 @@ const createCollectionTypeController = ({ contentType }) => {
|
|
|
22
22
|
const sanitizedQuery = await this.sanitizeQuery(ctx);
|
|
23
23
|
const { results, pagination } = await strapi.service(uid).find(sanitizedQuery);
|
|
24
24
|
const sanitizedResults = await this.sanitizeOutput(results, ctx);
|
|
25
|
-
|
|
26
25
|
return this.transformResponse(sanitizedResults, { pagination });
|
|
27
26
|
},
|
|
28
27
|
|
|
@@ -18,7 +18,7 @@ const createController = ({ contentType }) => {
|
|
|
18
18
|
return transformResponse(data, meta, { contentType });
|
|
19
19
|
},
|
|
20
20
|
|
|
21
|
-
sanitizeOutput(data, ctx) {
|
|
21
|
+
async sanitizeOutput(data, ctx) {
|
|
22
22
|
const auth = getAuthFromKoaContext(ctx);
|
|
23
23
|
|
|
24
24
|
return sanitize.contentAPI.output(data, contentType, { auth });
|
package/lib/factories.js
CHANGED
|
@@ -45,13 +45,12 @@ const createCoreService = (uid, cfg = {}) => {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
const createCoreRouter = (uid, cfg = {}) => {
|
|
48
|
-
const { prefix, config = {}, only, except } = cfg;
|
|
48
|
+
const { prefix, config = {}, only, except, type } = cfg;
|
|
49
49
|
let routes;
|
|
50
50
|
|
|
51
51
|
return {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
},
|
|
52
|
+
type,
|
|
53
|
+
prefix,
|
|
55
54
|
get routes() {
|
|
56
55
|
if (!routes) {
|
|
57
56
|
const contentType = strapi.contentType(uid);
|
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
/* eslint-disable no-nested-ternary */
|
|
4
|
-
|
|
5
|
-
const chalk = require('chalk');
|
|
6
|
-
|
|
7
|
-
const codeToColor = (code) => {
|
|
8
|
-
return code >= 500
|
|
9
|
-
? chalk.red(code)
|
|
10
|
-
: code >= 400
|
|
11
|
-
? chalk.yellow(code)
|
|
12
|
-
: code >= 300
|
|
13
|
-
? chalk.cyan(code)
|
|
14
|
-
: code >= 200
|
|
15
|
-
? chalk.green(code)
|
|
16
|
-
: code;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
3
|
/**
|
|
20
4
|
* @type {import('./').MiddlewareFactory}
|
|
21
5
|
*/
|
|
@@ -25,6 +9,6 @@ module.exports = (_, { strapi }) => {
|
|
|
25
9
|
await next();
|
|
26
10
|
const delta = Math.ceil(Date.now() - start);
|
|
27
11
|
|
|
28
|
-
strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${
|
|
12
|
+
strapi.log.http(`${ctx.method} ${ctx.url} (${delta} ms) ${ctx.status}`);
|
|
29
13
|
};
|
|
30
14
|
};
|