@strapi/strapi 4.0.0 → 4.0.4

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/README.md CHANGED
@@ -84,8 +84,8 @@ Complete installation requirements can be found in the documentation under <a hr
84
84
 
85
85
  **Database:**
86
86
 
87
- - MySQL >= 5.6
88
- - MariaDB >= 10.1
87
+ - MySQL >= 5.7.8
88
+ - MariaDB >= 10.2.7
89
89
  - PostgreSQL >= 10
90
90
  - SQLite >= 3
91
91
 
package/bin/strapi.js CHANGED
@@ -133,7 +133,6 @@ program
133
133
 
134
134
  program
135
135
  .command('build')
136
- .option('--clean', 'Remove the build and .cache folders', false)
137
136
  .option('--no-optimization', 'Build the Administration without assets optimization')
138
137
  .description('Builds the strapi admin app')
139
138
  .action(getLocalScript('build'));
@@ -213,4 +212,9 @@ program
213
212
  .description('List all the application services')
214
213
  .action(getLocalScript('services/list'));
215
214
 
215
+ program
216
+ .command('controllers:list')
217
+ .description('List all the application controllers')
218
+ .action(getLocalScript('controllers/list'));
219
+
216
220
  program.parseAsync(process.argv);
@@ -12,7 +12,7 @@ const getEnabledPlugins = require('../core/loaders/plugins/get-enabled-plugins')
12
12
  /**
13
13
  * `$ strapi build`
14
14
  */
15
- module.exports = async ({ clean, optimization }) => {
15
+ module.exports = async ({ optimization, forceBuild = true }) => {
16
16
  const dir = process.cwd();
17
17
 
18
18
  const strapiInstance = strapi({
@@ -28,14 +28,14 @@ module.exports = async ({ clean, optimization }) => {
28
28
 
29
29
  console.log(`Building your admin UI with ${green(env)} configuration ...`);
30
30
 
31
- if (clean) {
32
- await strapiAdmin.clean({ dir });
33
- }
31
+ // Always remove the .cache and build folders
32
+ await strapiAdmin.clean({ dir });
34
33
 
35
34
  ee({ dir });
36
35
 
37
36
  return strapiAdmin
38
37
  .build({
38
+ forceBuild,
39
39
  dir,
40
40
  plugins,
41
41
  // front end build env is always production for now
@@ -47,7 +47,7 @@ module.exports = async ({ clean, optimization }) => {
47
47
  },
48
48
  })
49
49
  .then(() => {
50
- process.exit();
50
+ console.log('Admin UI built successfully');
51
51
  })
52
52
  .catch(err => {
53
53
  console.error(err);
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ const CLITable = require('cli-table3');
4
+ const chalk = require('chalk');
5
+
6
+ const strapi = require('../../index');
7
+
8
+ module.exports = async function() {
9
+ const app = await strapi().register();
10
+
11
+ const list = app.container.get('controllers').keys();
12
+
13
+ const infoTable = new CLITable({
14
+ head: [chalk.blue('Name')],
15
+ });
16
+
17
+ list.forEach(name => infoTable.push([name]));
18
+
19
+ console.log(infoTable.toString());
20
+
21
+ await app.destroy();
22
+ };
@@ -10,6 +10,7 @@ const { getOr } = require('lodash/fp');
10
10
  const { createLogger } = require('@strapi/logger');
11
11
  const loadConfiguration = require('../core/app-configuration');
12
12
  const strapi = require('../index');
13
+ const buildAdmin = require('./build');
13
14
 
14
15
  /**
15
16
  * `$ strapi develop`
@@ -20,24 +21,20 @@ module.exports = async function({ build, watchAdmin, polling, browser }) {
20
21
  const config = loadConfiguration(dir);
21
22
  const logger = createLogger(config.logger, {});
22
23
 
23
- const adminWatchIgnoreFiles = getOr([], 'admin.watchIgnoreFiles')(config);
24
- const serveAdminPanel = getOr(true, 'admin.serveAdminPanel')(config);
25
-
26
- const buildExists = fs.existsSync(path.join(dir, 'build'));
27
- // Don't run the build process if the admin is in watch mode
28
- if (build && !watchAdmin && serveAdminPanel && !buildExists) {
29
- try {
30
- execa.sync('npm run -s build -- --no-optimization', {
31
- stdio: 'inherit',
32
- shell: true,
33
- });
34
- } catch (err) {
35
- process.exit(1);
36
- }
37
- }
38
-
39
24
  try {
40
25
  if (cluster.isMaster) {
26
+ const serveAdminPanel = getOr(true, 'admin.serveAdminPanel')(config);
27
+
28
+ const buildExists = fs.existsSync(path.join(dir, 'build'));
29
+ // Don't run the build process if the admin is in watch mode
30
+ if (build && !watchAdmin && serveAdminPanel && !buildExists) {
31
+ try {
32
+ await buildAdmin({ optimization: false, forceBuild: false });
33
+ } catch (err) {
34
+ process.exit(1);
35
+ }
36
+ }
37
+
41
38
  if (watchAdmin) {
42
39
  try {
43
40
  execa('npm', ['run', '-s', 'strapi', 'watch-admin', '--', '--browser', browser], {
@@ -74,6 +71,7 @@ module.exports = async function({ build, watchAdmin, polling, browser }) {
74
71
  serveAdminPanel: watchAdmin ? false : true,
75
72
  });
76
73
 
74
+ const adminWatchIgnoreFiles = getOr([], 'admin.watchIgnoreFiles')(config);
77
75
  watchFileChanges({
78
76
  dir,
79
77
  strapiInstance,
@@ -121,15 +119,15 @@ function watchFileChanges({ dir, strapiInstance, watchIgnoreFiles, polling }) {
121
119
  ignored: [
122
120
  /(^|[/\\])\../, // dot files
123
121
  /tmp/,
124
- 'admin',
125
- 'admin/**',
126
- 'src/extensions/**/admin',
127
- 'src/extensions/**/admin/**',
122
+ '**/src/admin/**',
123
+ '**/src/plugins/**/admin/',
128
124
  '**/documentation',
129
125
  '**/documentation/**',
130
126
  '**/node_modules',
131
127
  '**/node_modules/**',
132
128
  '**/plugins.json',
129
+ '**/build',
130
+ '**/build/**',
133
131
  '**/index.html',
134
132
  '**/public',
135
133
  '**/public/**',
@@ -5,7 +5,7 @@ const { statSync, existsSync } = require('fs');
5
5
  const _ = require('lodash');
6
6
  const { get, has, pick, pickBy, defaultsDeep, map, prop, pipe } = require('lodash/fp');
7
7
  const { isKebabCase } = require('@strapi/utils');
8
- const loadConfigFile = require('../../app-configuration/load-config-file');
8
+ const getUserPluginsConfig = require('./get-user-plugins-config');
9
9
 
10
10
  const isStrapiPlugin = info => get('strapi.kind', info) === 'plugin';
11
11
  const INTERNAL_PLUGINS = [
@@ -60,7 +60,12 @@ const getEnabledPlugins = async strapi => {
60
60
  const installedPlugins = {};
61
61
  for (const dep in strapi.config.get('info.dependencies', {})) {
62
62
  const packagePath = join(dep, 'package.json');
63
- const packageInfo = require(packagePath);
63
+ let packageInfo;
64
+ try {
65
+ packageInfo = require(packagePath);
66
+ } catch {
67
+ continue;
68
+ }
64
69
 
65
70
  if (isStrapiPlugin(packageInfo)) {
66
71
  validatePluginName(packageInfo.strapi.name);
@@ -72,10 +77,7 @@ const getEnabledPlugins = async strapi => {
72
77
  }
73
78
 
74
79
  const declaredPlugins = {};
75
- const userPluginConfigPath = join(strapi.dirs.config, 'plugins.js');
76
- const userPluginsConfig = existsSync(userPluginConfigPath)
77
- ? loadConfigFile(userPluginConfigPath)
78
- : {};
80
+ const userPluginsConfig = await getUserPluginsConfig();
79
81
 
80
82
  _.forEach(userPluginsConfig, (declaration, pluginName) => {
81
83
  validatePluginName(pluginName);
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ const { join } = require('path');
4
+ const fse = require('fs-extra');
5
+ const { merge } = require('lodash/fp');
6
+ const loadConfigFile = require('../../app-configuration/load-config-file');
7
+
8
+ /**
9
+ * Return user defined plugins' config
10
+ * first load config from `config/plugins.js`
11
+ * and then merge config from `config/env/{env}/plugins.js`
12
+ * @return {Promise<{}>}
13
+ */
14
+ const getUserPluginsConfig = async () => {
15
+ const globalUserConfigPath = join(strapi.dirs.config, 'plugins.js');
16
+ const currentEnvUserConfigPath = join(
17
+ strapi.dirs.config,
18
+ 'env',
19
+ process.env.NODE_ENV,
20
+ 'plugins.js'
21
+ );
22
+ let config = {};
23
+
24
+ // assign global user config if exists
25
+ if (await fse.pathExists(globalUserConfigPath)) {
26
+ config = loadConfigFile(globalUserConfigPath);
27
+ }
28
+
29
+ // and merge user config by environment if exists
30
+ if (await fse.pathExists(currentEnvUserConfigPath)) {
31
+ config = merge(config, loadConfigFile(currentEnvUserConfigPath));
32
+ }
33
+
34
+ return config;
35
+ };
36
+
37
+ module.exports = getUserPluginsConfig;
@@ -7,6 +7,7 @@ const { env } = require('@strapi/utils');
7
7
  const loadConfigFile = require('../../app-configuration/load-config-file');
8
8
  const loadFiles = require('../../../load/load-files');
9
9
  const getEnabledPlugins = require('./get-enabled-plugins');
10
+ const getUserPluginsConfig = require('./get-user-plugins-config');
10
11
 
11
12
  const defaultPlugin = {
12
13
  bootstrap() {},
@@ -66,10 +67,7 @@ const formatContentTypes = plugins => {
66
67
  };
67
68
 
68
69
  const applyUserConfig = async plugins => {
69
- const userPluginConfigPath = join(strapi.dirs.config, 'plugins.js');
70
- const userPluginsConfig = (await fse.pathExists(userPluginConfigPath))
71
- ? loadConfigFile(userPluginConfigPath)
72
- : {};
70
+ const userPluginsConfig = await getUserPluginsConfig();
73
71
 
74
72
  for (const pluginName in plugins) {
75
73
  const plugin = plugins[pluginName];
@@ -13,18 +13,13 @@ const getLimitConfigDefaults = () => ({
13
13
  });
14
14
 
15
15
  /**
16
- * if there is max limit set and limit exceeds this number, return configured max limit
16
+ * Should maxLimit be used as the limit or not
17
17
  * @param {number} limit - limit you want to cap
18
18
  * @param {number?} maxLimit - maxlimit used has capping
19
- * @returns {number}
19
+ * @returns {boolean}
20
20
  */
21
- const applyMaxLimit = (limit, maxLimit) => {
22
- if (maxLimit && (limit === -1 || limit > maxLimit)) {
23
- return maxLimit;
24
- }
25
-
26
- return limit;
27
- };
21
+ const shouldApplyMaxLimit = (limit, maxLimit = null, { isPagedPagination = false } = {}) =>
22
+ (!isPagedPagination && limit === -1) || (maxLimit && limit > maxLimit);
28
23
 
29
24
  const shouldCount = params => {
30
25
  if (has('pagination.withCount', params)) {
@@ -81,17 +76,17 @@ const getPaginationInfo = params => {
81
76
 
82
77
  return {
83
78
  page: Math.max(1, toNumber(pagination.page || 1)),
84
- pageSize: applyMaxLimit(pageSize, maxLimit),
79
+ pageSize: shouldApplyMaxLimit(pageSize, maxLimit, { isPagedPagination: true })
80
+ ? maxLimit
81
+ : Math.max(1, pageSize),
85
82
  };
86
83
  }
87
84
 
88
- const limit = isUndefined(pagination.limit)
89
- ? defaultLimit
90
- : Math.max(1, toNumber(pagination.limit));
85
+ const limit = isUndefined(pagination.limit) ? defaultLimit : toNumber(pagination.limit);
91
86
 
92
87
  return {
93
88
  start: Math.max(0, toNumber(pagination.start || 0)),
94
- limit: applyMaxLimit(limit, maxLimit),
89
+ limit: shouldApplyMaxLimit(limit, maxLimit) ? maxLimit || -1 : Math.max(1, limit),
95
90
  };
96
91
  };
97
92
 
@@ -89,35 +89,5 @@ module.exports = (config, { strapi }) => {
89
89
  ]);
90
90
  }
91
91
 
92
- if (!strapi.config.serveAdminPanel) return async (ctx, next) => next();
93
-
94
- const buildDir = path.resolve(strapi.dirs.root, 'build');
95
- const serveAdmin = async (ctx, next) => {
96
- await next();
97
-
98
- if (ctx.method !== 'HEAD' && ctx.method !== 'GET') {
99
- return;
100
- }
101
-
102
- if (ctx.body != null || ctx.status !== 404) {
103
- return;
104
- }
105
-
106
- ctx.type = 'html';
107
- ctx.body = fs.createReadStream(path.join(buildDir + '/index.html'));
108
- };
109
-
110
- strapi.server.routes([
111
- {
112
- method: 'GET',
113
- path: `${strapi.config.admin.path}/:path*`,
114
- handler: [
115
- serveAdmin,
116
- serveStatic(buildDir, { maxage: maxAge, defer: false, index: 'index.html' }),
117
- ],
118
- config: { auth: false },
119
- },
120
- ]);
121
-
122
92
  return null;
123
93
  };
@@ -104,7 +104,9 @@ const addMaxFloatValidator = (validator, { attr }) =>
104
104
  * @returns {StringSchema}
105
105
  */
106
106
  const addStringRegexValidator = (validator, { attr }) =>
107
- _.isUndefined(attr.regex) ? validator : validator.matches(new RegExp(attr.regex));
107
+ _.isUndefined(attr.regex)
108
+ ? validator
109
+ : validator.matches(new RegExp(attr.regex), { excludeEmptyString: !attr.required });
108
110
 
109
111
  /**
110
112
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.0.0",
3
+ "version": "4.0.4",
4
4
  "description": "An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MySQL, MariaDB, PostgreSQL, SQLite",
5
5
  "keywords": [
6
6
  "strapi",
@@ -74,27 +74,28 @@
74
74
  "bin": "./bin"
75
75
  },
76
76
  "scripts": {
77
- "postinstall": "node lib/utils/success.js"
77
+ "postinstall": "node lib/utils/success.js",
78
+ "test:unit": "jest --verbose"
78
79
  },
79
80
  "dependencies": {
80
81
  "@koa/cors": "3.1.0",
81
82
  "@koa/router": "10.1.1",
82
- "@strapi/admin": "4.0.0",
83
- "@strapi/database": "4.0.0",
84
- "@strapi/generate-new": "4.0.0",
85
- "@strapi/generators": "4.0.0",
86
- "@strapi/logger": "4.0.0",
87
- "@strapi/plugin-content-manager": "4.0.0",
88
- "@strapi/plugin-content-type-builder": "4.0.0",
89
- "@strapi/plugin-email": "4.0.0",
90
- "@strapi/plugin-upload": "4.0.0",
91
- "@strapi/utils": "4.0.0",
83
+ "@strapi/admin": "4.0.4",
84
+ "@strapi/database": "4.0.4",
85
+ "@strapi/generate-new": "4.0.4",
86
+ "@strapi/generators": "4.0.4",
87
+ "@strapi/logger": "4.0.4",
88
+ "@strapi/plugin-content-manager": "4.0.4",
89
+ "@strapi/plugin-content-type-builder": "4.0.4",
90
+ "@strapi/plugin-email": "4.0.4",
91
+ "@strapi/plugin-upload": "4.0.4",
92
+ "@strapi/utils": "4.0.4",
92
93
  "bcryptjs": "2.4.3",
93
94
  "boxen": "5.1.2",
94
95
  "chalk": "4.1.2",
95
96
  "chokidar": "3.5.2",
96
97
  "ci-info": "3.2.0",
97
- "cli-table3": "0.6.0",
98
+ "cli-table3": "0.6.1",
98
99
  "commander": "8.2.0",
99
100
  "configstore": "5.0.1",
100
101
  "debug": "4.3.2",
@@ -131,8 +132,8 @@
131
132
  "supertest": "^6.1.6"
132
133
  },
133
134
  "engines": {
134
- "node": ">=12.x.x <=16.x.x",
135
+ "node": ">=12.22.0 <=16.x.x",
135
136
  "npm": ">=6.0.0"
136
137
  },
137
- "gitHead": "b181702f0202b2c6d645d42b195a831f25cd0b03"
138
+ "gitHead": "d81919ac2272948b3f5d3b25a4cf8cc7b6994460"
138
139
  }