@strapi/strapi 4.9.0 → 4.9.2

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/bin/strapi.js CHANGED
@@ -258,6 +258,14 @@ program
258
258
  .description('Enable anonymous telemetry and metadata sending to Strapi analytics')
259
259
  .action(getLocalScript('opt-in-telemetry'));
260
260
 
261
+ program
262
+ .command('report')
263
+ .description('Get system stats for debugging and submitting issues')
264
+ .option('-u, --uuid', 'Include Project UUID')
265
+ .option('-d, --dependencies', 'Include Project Dependencies')
266
+ .option('--all', 'Include All Information')
267
+ .action(getLocalScript('report'));
268
+
261
269
  program
262
270
  .command('ts:generate-types')
263
271
  .description(`Generate TypeScript typings for your schemas`)
package/lib/Strapi.js CHANGED
@@ -43,6 +43,7 @@ const apisRegistry = require('./core/registries/apis');
43
43
  const bootstrap = require('./core/bootstrap');
44
44
  const loaders = require('./core/loaders');
45
45
  const { destroyOnSignal } = require('./utils/signals');
46
+ const getNumberOfDynamicZones = require('./services/utils/dynamic-zones');
46
47
  const sanitizersRegistry = require('./core/registries/sanitizers');
47
48
  const convertCustomFieldType = require('./utils/convert-custom-field-type');
48
49
 
@@ -249,6 +250,9 @@ class Strapi {
249
250
  groupProperties: {
250
251
  database: strapi.config.get('database.connection.client'),
251
252
  plugins: Object.keys(strapi.plugins),
253
+ numberOfAllContentTypes: _.size(this.contentTypes), // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.
254
+ numberOfComponents: _.size(this.components),
255
+ numberOfDynamicZones: getNumberOfDynamicZones(),
252
256
  // TODO: to add back
253
257
  // providers: this.config.installedProviders,
254
258
  },
@@ -468,7 +472,7 @@ class Strapi {
468
472
  await this.startWebhooks();
469
473
 
470
474
  await this.server.initMiddlewares();
471
- await this.server.initRouting();
475
+ this.server.initRouting();
472
476
 
473
477
  await this.contentAPI.permissions.registerActions();
474
478
 
@@ -536,17 +540,17 @@ class Strapi {
536
540
  // plugins
537
541
  await this.container.get('modules')[lifecycleName]();
538
542
 
539
- // user
540
- const userLifecycleFunction = this.app && this.app[lifecycleName];
541
- if (isFunction(userLifecycleFunction)) {
542
- await userLifecycleFunction({ strapi: this });
543
- }
544
-
545
543
  // admin
546
544
  const adminLifecycleFunction = this.admin && this.admin[lifecycleName];
547
545
  if (isFunction(adminLifecycleFunction)) {
548
546
  await adminLifecycleFunction({ strapi: this });
549
547
  }
548
+
549
+ // user
550
+ const userLifecycleFunction = this.app && this.app[lifecycleName];
551
+ if (isFunction(userLifecycleFunction)) {
552
+ await userLifecycleFunction({ strapi: this });
553
+ }
550
554
  }
551
555
 
552
556
  getModel(uid) {
@@ -0,0 +1,35 @@
1
+ 'use strict';
2
+
3
+ const { EOL } = require('os');
4
+ const strapi = require('../index');
5
+
6
+ module.exports = async ({ uuid, dependencies, all }) => {
7
+ const config = {
8
+ reportUUID: Boolean(all || uuid),
9
+ reportDependencies: Boolean(all || dependencies),
10
+ };
11
+
12
+ const appContext = await strapi.compile();
13
+ const app = await strapi(appContext).register();
14
+
15
+ let debugInfo = `Launched In: ${Date.now() - app.config.launchedAt} ms
16
+ Environment: ${app.config.environment}
17
+ OS: ${process.platform}-${process.arch}
18
+ Strapi Version: ${app.config.info.strapi}
19
+ Node/Yarn Version: ${process.env.npm_config_user_agent}
20
+ Edition: ${app.EE ? 'Enterprise' : 'Community'}
21
+ Database: ${app?.config?.database?.connection?.client ?? 'unknown'}`;
22
+
23
+ if (config.reportUUID) {
24
+ debugInfo += `${EOL}UUID: ${app.config.uuid}`;
25
+ }
26
+
27
+ if (config.reportDependencies) {
28
+ debugInfo += `${EOL}Dependencies: ${JSON.stringify(app.config.info.dependencies, null, 2)}
29
+ Dev Dependencies: ${JSON.stringify(app.config.info.devDependencies, null, 2)}`;
30
+ }
31
+
32
+ console.log(debugInfo);
33
+
34
+ await app.destroy();
35
+ };
@@ -24,6 +24,7 @@ const {
24
24
  loadersFactory,
25
25
  exitMessageText,
26
26
  abortTransfer,
27
+ getTransferTelemetryPayload,
27
28
  } = require('./utils');
28
29
  const { exitWith } = require('../utils/helpers');
29
30
  /**
@@ -103,19 +104,10 @@ module.exports = async (opts) => {
103
104
  updateLoader(stage, data);
104
105
  });
105
106
 
106
- const getTelemetryPayload = (/* payload */) => {
107
- return {
108
- eventProperties: {
109
- source: engine.sourceProvider.name,
110
- destination: engine.destinationProvider.name,
111
- },
112
- };
113
- };
114
-
115
107
  progress.on('transfer::start', async () => {
116
108
  console.log(`Starting export...`);
117
109
 
118
- await strapi.telemetry.send('didDEITSProcessStart', getTelemetryPayload());
110
+ await strapi.telemetry.send('didDEITSProcessStart', getTransferTelemetryPayload(engine));
119
111
  });
120
112
 
121
113
  let results;
@@ -134,11 +126,13 @@ module.exports = async (opts) => {
134
126
  throw new TransferEngineTransferError(`Export file not created "${outFile}"`);
135
127
  }
136
128
  } catch {
137
- await strapi.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
129
+ await strapi.telemetry.send('didDEITSProcessFail', getTransferTelemetryPayload(engine));
138
130
  exitWith(1, exitMessageText('export', true));
139
131
  }
140
132
 
141
- await strapi.telemetry.send('didDEITSProcessFinish', getTelemetryPayload());
133
+ // Note: we need to await telemetry or else the process ends before it is sent
134
+ await strapi.telemetry.send('didDEITSProcessFinish', getTransferTelemetryPayload(engine));
135
+
142
136
  try {
143
137
  const table = buildTransferTable(results.engine);
144
138
  console.log(table.toString());
@@ -20,6 +20,7 @@ const {
20
20
  loadersFactory,
21
21
  exitMessageText,
22
22
  abortTransfer,
23
+ getTransferTelemetryPayload,
23
24
  } = require('./utils');
24
25
  const { exitWith } = require('../utils/helpers');
25
26
 
@@ -122,18 +123,12 @@ module.exports = async (opts) => {
122
123
  updateLoader(stage, data);
123
124
  });
124
125
 
125
- const getTelemetryPayload = () => {
126
- return {
127
- eventProperties: {
128
- source: engine.sourceProvider.name,
129
- destination: engine.destinationProvider.name,
130
- },
131
- };
132
- };
133
-
134
126
  progress.on('transfer::start', async () => {
135
127
  console.log('Starting import...');
136
- await strapiInstance.telemetry.send('didDEITSProcessStart', getTelemetryPayload());
128
+ await strapiInstance.telemetry.send(
129
+ 'didDEITSProcessStart',
130
+ getTransferTelemetryPayload(engine)
131
+ );
137
132
  });
138
133
 
139
134
  let results;
@@ -146,7 +141,7 @@ module.exports = async (opts) => {
146
141
 
147
142
  results = await engine.transfer();
148
143
  } catch (e) {
149
- await strapiInstance.telemetry.send('didDEITSProcessFail', getTelemetryPayload());
144
+ await strapiInstance.telemetry.send('didDEITSProcessFail', getTransferTelemetryPayload(engine));
150
145
  exitWith(1, exitMessageText('import', true));
151
146
  }
152
147
 
@@ -157,7 +152,8 @@ module.exports = async (opts) => {
157
152
  console.error('There was an error displaying the results of the transfer.');
158
153
  }
159
154
 
160
- await strapiInstance.telemetry.send('didDEITSProcessFinish', getTelemetryPayload());
155
+ // Note: we need to await telemetry or else the process ends before it is sent
156
+ await strapiInstance.telemetry.send('didDEITSProcessFinish', getTransferTelemetryPayload(engine));
161
157
  await strapiInstance.destroy();
162
158
 
163
159
  exitWith(0, exitMessageText('import'));
@@ -21,6 +21,7 @@ const {
21
21
  loadersFactory,
22
22
  exitMessageText,
23
23
  abortTransfer,
24
+ getTransferTelemetryPayload,
24
25
  } = require('./utils');
25
26
  const { exitWith } = require('../utils/helpers');
26
27
 
@@ -161,10 +162,14 @@ module.exports = async (opts) => {
161
162
  updateLoader(stage, data).fail();
162
163
  });
163
164
 
164
- let results;
165
- try {
165
+ progress.on('transfer::start', async () => {
166
166
  console.log(`Starting transfer...`);
167
167
 
168
+ await strapi.telemetry.send('didDEITSProcessStart', getTransferTelemetryPayload(engine));
169
+ });
170
+
171
+ let results;
172
+ try {
168
173
  // Abort transfer if user interrupts process
169
174
  ['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach((signal) => {
170
175
  process.removeAllListeners(signal);
@@ -173,10 +178,19 @@ module.exports = async (opts) => {
173
178
 
174
179
  results = await engine.transfer();
175
180
  } catch (e) {
181
+ await strapi.telemetry.send('didDEITSProcessFail', getTransferTelemetryPayload(engine));
176
182
  exitWith(1, exitMessageText('transfer', true));
177
183
  }
178
184
 
179
- const table = buildTransferTable(results.engine);
180
- console.log(table.toString());
185
+ // Note: we need to await telemetry or else the process ends before it is sent
186
+ await strapi.telemetry.send('didDEITSProcessFinish', getTransferTelemetryPayload(engine));
187
+
188
+ try {
189
+ const table = buildTransferTable(results.engine);
190
+ console.log(table.toString());
191
+ } catch (e) {
192
+ console.error('There was an error displaying the results of the transfer.');
193
+ }
194
+
181
195
  exitWith(0, exitMessageText('transfer'));
182
196
  };
@@ -242,10 +242,26 @@ const loadersFactory = (defaultLoaders = {}) => {
242
242
  };
243
243
  };
244
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
+
245
260
  module.exports = {
246
261
  loadersFactory,
247
262
  buildTransferTable,
248
263
  getDefaultExportName,
264
+ getTransferTelemetryPayload,
249
265
  DEFAULT_IGNORED_CONTENT_TYPES,
250
266
  createStrapiInstance,
251
267
  excludeOption,
@@ -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 preceeding the first occurence of a number. Update your enumeration '${attrName}'.`;
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
  }
@@ -12,7 +12,7 @@ const defaults = {
12
12
  useDefaults: true,
13
13
  directives: {
14
14
  'connect-src': ["'self'", 'https:'],
15
- 'img-src': ["'self'", 'data:', 'blob:', 'https://dl.airtable.com'],
15
+ 'img-src': ["'self'", 'data:', 'blob:', 'https://market-assets.strapi.io'],
16
16
  'media-src': ["'self'", 'data:', 'blob:'],
17
17
  upgradeInsecureRequests: null,
18
18
  },
@@ -3,7 +3,6 @@
3
3
  const os = require('os');
4
4
  const path = require('path');
5
5
  const _ = require('lodash');
6
- const { map, values, sumBy, pipe, flatMap, propEq } = require('lodash/fp');
7
6
  const isDocker = require('is-docker');
8
7
  const fetch = require('node-fetch');
9
8
  const ciEnv = require('ci-info');
@@ -41,14 +40,6 @@ module.exports = (strapi) => {
41
40
  const serverRootPath = strapi.dirs.app.root;
42
41
  const adminRootPath = path.join(strapi.dirs.app.root, 'src', 'admin');
43
42
 
44
- const getNumberOfDynamicZones = () => {
45
- return pipe(
46
- map('attributes'),
47
- flatMap(values),
48
- sumBy(propEq('type', 'dynamiczone'))
49
- )(strapi.contentTypes);
50
- };
51
-
52
43
  const anonymousUserProperties = {
53
44
  environment: strapi.config.environment,
54
45
  os: os.type(),
@@ -66,9 +57,6 @@ module.exports = (strapi) => {
66
57
  useTypescriptOnAdmin: isUsingTypeScriptSync(adminRootPath),
67
58
  projectId: uuid,
68
59
  isHostedOnStrapiCloud: env('STRAPI_HOSTING', null) === 'strapi.cloud',
69
- numberOfAllContentTypes: _.size(strapi.contentTypes), // TODO: V5: This event should be renamed numberOfContentTypes in V5 as the name is already taken to describe the number of content types using i18n.
70
- numberOfComponents: _.size(strapi.components),
71
- numberOfDynamicZones: getNumberOfDynamicZones(),
72
60
  };
73
61
 
74
62
  addPackageJsonStrapiMetadata(anonymousGroupProperties, strapi);
@@ -92,8 +92,8 @@ const createServer = (strapi) => {
92
92
  return this;
93
93
  },
94
94
 
95
- async initRouting() {
96
- await registerAllRoutes(strapi);
95
+ initRouting() {
96
+ registerAllRoutes(strapi);
97
97
 
98
98
  return this;
99
99
  },
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ const { map, values, sumBy, pipe, flatMap, propEq } = require('lodash/fp');
4
+
5
+ const getNumberOfDynamicZones = () => {
6
+ return pipe(
7
+ map('attributes'),
8
+ flatMap(values),
9
+ sumBy(propEq('type', 'dynamiczone'))
10
+ )(strapi.contentTypes);
11
+ };
12
+
13
+ module.exports = getNumberOfDynamicZones;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.9.0",
3
+ "version": "4.9.2",
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,26 +74,26 @@
74
74
  },
75
75
  "scripts": {
76
76
  "postinstall": "node lib/utils/success.js",
77
- "test:unit": "jest",
78
- "test:unit:watch": "jest --watch",
79
- "lint": "eslint ."
77
+ "test:unit": "run -T jest",
78
+ "test:unit:watch": "run -T jest --watch",
79
+ "lint": "run -T eslint ."
80
80
  },
81
81
  "dependencies": {
82
82
  "@koa/cors": "3.4.3",
83
83
  "@koa/router": "10.1.1",
84
- "@strapi/admin": "4.9.0",
85
- "@strapi/data-transfer": "4.9.0",
86
- "@strapi/database": "4.9.0",
87
- "@strapi/generate-new": "4.9.0",
88
- "@strapi/generators": "4.9.0",
89
- "@strapi/logger": "4.9.0",
90
- "@strapi/permissions": "4.9.0",
91
- "@strapi/plugin-content-manager": "4.9.0",
92
- "@strapi/plugin-content-type-builder": "4.9.0",
93
- "@strapi/plugin-email": "4.9.0",
94
- "@strapi/plugin-upload": "4.9.0",
95
- "@strapi/typescript-utils": "4.9.0",
96
- "@strapi/utils": "4.9.0",
84
+ "@strapi/admin": "4.9.2",
85
+ "@strapi/data-transfer": "4.9.2",
86
+ "@strapi/database": "4.9.2",
87
+ "@strapi/generate-new": "4.9.2",
88
+ "@strapi/generators": "4.9.2",
89
+ "@strapi/logger": "4.9.2",
90
+ "@strapi/permissions": "4.9.2",
91
+ "@strapi/plugin-content-manager": "4.9.2",
92
+ "@strapi/plugin-content-type-builder": "4.9.2",
93
+ "@strapi/plugin-email": "4.9.2",
94
+ "@strapi/plugin-upload": "4.9.2",
95
+ "@strapi/typescript-utils": "4.9.2",
96
+ "@strapi/utils": "4.9.2",
97
97
  "bcryptjs": "2.4.3",
98
98
  "boxen": "5.1.2",
99
99
  "chalk": "4.1.2",
@@ -142,5 +142,5 @@
142
142
  "node": ">=14.19.1 <=18.x.x",
143
143
  "npm": ">=6.0.0"
144
144
  },
145
- "gitHead": "ffe3f4621ccc968ce56fda9a8317ec30d4bad205"
145
+ "gitHead": "91e0be2708e4d1e8ec731c75e73e54c0dfacb67d"
146
146
  }