@strapi/strapi 4.0.0-next.7 → 4.0.1

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.
Files changed (157) hide show
  1. package/README.md +14 -14
  2. package/bin/strapi.js +46 -60
  3. package/lib/Strapi.js +193 -98
  4. package/lib/commands/build.js +19 -8
  5. package/lib/commands/console.js +1 -1
  6. package/lib/commands/content-types/list.js +22 -0
  7. package/lib/commands/controllers/list.js +22 -0
  8. package/lib/commands/develop.js +22 -27
  9. package/lib/commands/generate-template.js +4 -5
  10. package/lib/commands/hooks/list.js +22 -0
  11. package/lib/commands/middlewares/list.js +22 -0
  12. package/lib/commands/new.js +3 -1
  13. package/lib/commands/policies/list.js +22 -0
  14. package/lib/commands/routes/list.js +28 -0
  15. package/lib/commands/services/list.js +22 -0
  16. package/lib/commands/watchAdmin.js +18 -9
  17. package/lib/core/app-configuration/index.js +3 -36
  18. package/lib/core/bootstrap.js +25 -0
  19. package/lib/core/domain/content-type/index.js +26 -29
  20. package/lib/core/domain/content-type/validator.js +22 -3
  21. package/lib/core/domain/module/index.js +42 -11
  22. package/lib/core/domain/module/validation.js +16 -19
  23. package/lib/core/loaders/admin.js +16 -0
  24. package/lib/core/loaders/apis.js +159 -0
  25. package/lib/core/loaders/{load-components.js → components.js} +5 -6
  26. package/lib/core/loaders/index.js +11 -0
  27. package/lib/core/loaders/middlewares.js +36 -0
  28. package/lib/core/{load-plugins → loaders/plugins}/get-enabled-plugins.js +55 -19
  29. package/lib/core/loaders/plugins/get-user-plugins-config.js +37 -0
  30. package/lib/core/{load-plugins → loaders/plugins}/index.js +35 -19
  31. package/lib/core/loaders/policies.js +28 -0
  32. package/lib/core/loaders/src-index.js +39 -0
  33. package/lib/core/registries/apis.js +29 -0
  34. package/lib/core/registries/content-types.js +66 -10
  35. package/lib/core/registries/controllers.d.ts +7 -0
  36. package/lib/core/registries/controllers.js +92 -7
  37. package/lib/core/registries/hooks.d.ts +20 -0
  38. package/lib/core/registries/hooks.js +87 -0
  39. package/lib/core/registries/middlewares.d.ts +5 -0
  40. package/lib/core/registries/middlewares.js +65 -5
  41. package/lib/core/registries/modules.js +3 -3
  42. package/lib/core/registries/plugins.js +2 -2
  43. package/lib/core/registries/policies.d.ts +9 -0
  44. package/lib/core/registries/policies.js +65 -5
  45. package/lib/core/registries/services.d.ts +7 -0
  46. package/lib/core/registries/services.js +88 -17
  47. package/lib/core/utils.js +35 -0
  48. package/lib/core-api/controller/collection-type.js +45 -26
  49. package/lib/core-api/controller/index.d.ts +25 -0
  50. package/lib/core-api/controller/index.js +33 -11
  51. package/lib/core-api/controller/single-type.js +29 -15
  52. package/lib/core-api/controller/transform.js +62 -6
  53. package/lib/core-api/routes/index.js +71 -0
  54. package/lib/core-api/service/collection-type.js +43 -21
  55. package/lib/core-api/service/index.d.ts +21 -0
  56. package/lib/core-api/service/index.js +8 -67
  57. package/lib/core-api/service/pagination.js +125 -0
  58. package/lib/core-api/service/single-type.js +17 -19
  59. package/lib/factories.d.ts +48 -0
  60. package/lib/factories.js +84 -0
  61. package/lib/index.d.ts +10 -31
  62. package/lib/index.js +5 -1
  63. package/lib/middlewares/body.js +33 -0
  64. package/lib/middlewares/compression.js +8 -0
  65. package/lib/middlewares/cors.js +58 -0
  66. package/lib/middlewares/errors.js +40 -0
  67. package/lib/middlewares/favicon.js +19 -0
  68. package/lib/middlewares/index.d.ts +5 -0
  69. package/lib/middlewares/index.js +30 -116
  70. package/lib/middlewares/ip.js +8 -0
  71. package/lib/middlewares/logger.js +27 -0
  72. package/lib/middlewares/powered-by.js +20 -0
  73. package/lib/middlewares/public/index.js +72 -77
  74. package/lib/middlewares/query.js +46 -0
  75. package/lib/middlewares/response-time.js +15 -0
  76. package/lib/middlewares/responses.js +19 -0
  77. package/lib/middlewares/security.js +51 -0
  78. package/lib/middlewares/session/index.js +6 -6
  79. package/lib/migrations/draft-publish.js +57 -0
  80. package/lib/services/auth/index.js +87 -0
  81. package/lib/services/core-store.js +64 -51
  82. package/lib/services/cron.js +54 -0
  83. package/lib/services/entity-service/attributes/index.js +31 -0
  84. package/lib/services/entity-service/attributes/transforms.js +20 -0
  85. package/lib/services/entity-service/components.js +39 -15
  86. package/lib/services/entity-service/index.d.ts +91 -0
  87. package/lib/services/entity-service/index.js +120 -59
  88. package/lib/services/entity-service/params.js +52 -94
  89. package/lib/services/entity-validator/index.js +76 -43
  90. package/lib/services/entity-validator/validators.js +131 -43
  91. package/lib/services/errors.js +77 -0
  92. package/lib/{core → services}/fs.js +1 -1
  93. package/lib/services/metrics/index.js +38 -36
  94. package/lib/services/server/admin-api.js +14 -0
  95. package/lib/services/server/api.js +36 -0
  96. package/lib/services/server/compose-endpoint.js +141 -0
  97. package/lib/services/server/content-api.js +16 -0
  98. package/lib/{server.js → services/server/http-server.js} +0 -0
  99. package/lib/services/server/index.js +127 -0
  100. package/lib/services/server/koa.js +64 -0
  101. package/lib/services/server/middleware.js +122 -0
  102. package/lib/services/server/policy.js +32 -0
  103. package/lib/services/server/register-middlewares.js +110 -0
  104. package/lib/services/server/register-routes.js +106 -0
  105. package/lib/services/server/routing.js +120 -0
  106. package/lib/services/webhook-runner.js +1 -1
  107. package/lib/utils/ee.js +3 -3
  108. package/lib/utils/get-dirs.js +17 -0
  109. package/lib/utils/index.js +2 -0
  110. package/lib/utils/is-initialized.js +1 -1
  111. package/lib/utils/signals.js +24 -0
  112. package/lib/utils/startup-logger.js +2 -2
  113. package/lib/utils/update-notifier/index.js +3 -2
  114. package/package.json +94 -97
  115. package/lib/commands/generate.js +0 -76
  116. package/lib/core/loaders/bootstrap.js +0 -176
  117. package/lib/core/loaders/load-apis.js +0 -20
  118. package/lib/core/loaders/load-functions.js +0 -21
  119. package/lib/core/loaders/load-middlewares.js +0 -136
  120. package/lib/core/loaders/load-modules.js +0 -21
  121. package/lib/core/loaders/load-policies.js +0 -36
  122. package/lib/core/loaders/walk.js +0 -27
  123. package/lib/core-api/index.js +0 -39
  124. package/lib/load/check-reserved-filename.js +0 -10
  125. package/lib/load/load-config-files.js +0 -22
  126. package/lib/load/require-file-parse.js +0 -15
  127. package/lib/middlewares/boom/defaults.json +0 -5
  128. package/lib/middlewares/boom/index.js +0 -147
  129. package/lib/middlewares/cors/index.js +0 -66
  130. package/lib/middlewares/cron/defaults.json +0 -5
  131. package/lib/middlewares/cron/index.js +0 -43
  132. package/lib/middlewares/favicon/defaults.json +0 -7
  133. package/lib/middlewares/favicon/index.js +0 -32
  134. package/lib/middlewares/gzip/defaults.json +0 -6
  135. package/lib/middlewares/gzip/index.js +0 -19
  136. package/lib/middlewares/helmet/defaults.json +0 -18
  137. package/lib/middlewares/helmet/index.js +0 -9
  138. package/lib/middlewares/ip/defaults.json +0 -7
  139. package/lib/middlewares/ip/index.js +0 -25
  140. package/lib/middlewares/language/defaults.json +0 -9
  141. package/lib/middlewares/language/index.js +0 -40
  142. package/lib/middlewares/logger/defaults.json +0 -5
  143. package/lib/middlewares/logger/index.js +0 -37
  144. package/lib/middlewares/parser/defaults.json +0 -11
  145. package/lib/middlewares/parser/index.js +0 -71
  146. package/lib/middlewares/poweredBy/defaults.json +0 -5
  147. package/lib/middlewares/poweredBy/index.js +0 -16
  148. package/lib/middlewares/public/defaults.json +0 -8
  149. package/lib/middlewares/responseTime/defaults.json +0 -5
  150. package/lib/middlewares/responseTime/index.js +0 -25
  151. package/lib/middlewares/responses/defaults.json +0 -5
  152. package/lib/middlewares/responses/index.js +0 -18
  153. package/lib/middlewares/router/defaults.json +0 -7
  154. package/lib/middlewares/router/index.js +0 -56
  155. package/lib/middlewares/router/utils/composeEndpoint.js +0 -25
  156. package/lib/middlewares/router/utils/routerChecker.js +0 -96
  157. package/lib/utils/get-prefixed-dependencies.js +0 -7
@@ -6,7 +6,7 @@ const chalk = require('chalk');
6
6
  const inquirer = require('inquirer');
7
7
 
8
8
  // All directories that a template could need
9
- const TEMPLATE_CONTENT = ['api', 'components', 'config/functions/bootstrap.js', 'data'];
9
+ const TEMPLATE_CONTENT = ['src', 'data'];
10
10
 
11
11
  /**
12
12
  *
@@ -54,10 +54,9 @@ async function writeTemplateJson(rootPath) {
54
54
  * @returns boolean
55
55
  */
56
56
  async function templateConfigExists(rootPath) {
57
- const jsonConfig = await fse.pathExists(join(rootPath, 'template.json'));
58
- const functionConfig = await fse.pathExists(join(rootPath, 'template.js'));
59
-
60
- return jsonConfig || functionConfig;
57
+ const configExists = await fse.pathExists(join(rootPath, 'template.json'));
58
+ console.log(`checking: ${join(rootPath, 'template.json')}. result ${configExists}`);
59
+ return configExists;
61
60
  }
62
61
 
63
62
  module.exports = async function generateTemplate(directory) {
@@ -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('hooks').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
+ };
@@ -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('middlewares').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
+ };
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const { generateNewApp } = require('@strapi/generate-new');
4
+
3
5
  /**
4
6
  * `$ strapi new`
5
7
  *
@@ -7,5 +9,5 @@
7
9
  */
8
10
 
9
11
  module.exports = function(...args) {
10
- return require('@strapi/generate-new')(...args);
12
+ return generateNewApp(...args);
11
13
  };
@@ -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('policies').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
+ };
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ const CLITable = require('cli-table3');
4
+ const chalk = require('chalk');
5
+ const { toUpper } = require('lodash/fp');
6
+
7
+ const strapi = require('../../index');
8
+
9
+ module.exports = async function() {
10
+ const app = await strapi().load();
11
+
12
+ const list = app.server.listRoutes();
13
+
14
+ const infoTable = new CLITable({
15
+ head: [chalk.blue('Method'), chalk.blue('Path')],
16
+ colWidths: [20],
17
+ });
18
+
19
+ list
20
+ .filter(route => route.methods.length)
21
+ .forEach(route => {
22
+ infoTable.push([route.methods.map(toUpper).join('|'), route.path]);
23
+ });
24
+
25
+ console.log(infoTable.toString());
26
+
27
+ await app.destroy();
28
+ };
@@ -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('services').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
+ };
@@ -1,33 +1,42 @@
1
1
  'use strict';
2
2
 
3
- // eslint-disable-next-line node/no-extraneous-require
4
3
  const strapiAdmin = require('@strapi/admin');
5
- const { getOr } = require('lodash/fp');
6
4
  const { getConfigUrls, getAbsoluteServerUrl } = require('@strapi/utils');
7
- const loadConfiguration = require('../core/app-configuration');
5
+
8
6
  const ee = require('../utils/ee');
9
7
  const addSlash = require('../utils/addSlash');
8
+ const strapi = require('../index');
9
+ const getEnabledPlugins = require('../core/loaders/plugins/get-enabled-plugins');
10
10
 
11
11
  module.exports = async function({ browser }) {
12
12
  const dir = process.cwd();
13
13
 
14
- const config = loadConfiguration(dir);
14
+ const strapiInstance = strapi({
15
+ dir,
16
+ autoReload: true,
17
+ serveAdminPanel: false,
18
+ });
19
+
20
+ const plugins = await getEnabledPlugins(strapiInstance);
21
+
22
+ const { adminPath } = getConfigUrls(strapiInstance.config, true);
15
23
 
16
- const { adminPath } = getConfigUrls(config.server, true);
24
+ const adminPort = strapiInstance.config.get('admin.port', 8000);
25
+ const adminHost = strapiInstance.config.get('admin.host', 'localhost');
26
+ const adminWatchIgnoreFiles = strapiInstance.config.get('admin.watchIgnoreFiles', []);
17
27
 
18
- const adminPort = getOr(8000, 'server.admin.port')(config);
19
- const adminHost = getOr('localhost', 'server.admin.host')(config);
20
- const adminWatchIgnoreFiles = getOr([], 'server.admin.watchIgnoreFiles')(config);
28
+ const backendURL = getAbsoluteServerUrl(strapiInstance.config, true);
21
29
 
22
30
  ee({ dir });
23
31
 
24
32
  strapiAdmin.watchAdmin({
25
33
  dir,
34
+ plugins,
26
35
  port: adminPort,
27
36
  host: adminHost,
28
37
  browser,
29
38
  options: {
30
- backend: getAbsoluteServerUrl(config, true),
39
+ backend: backendURL,
31
40
  adminPath: addSlash(adminPath),
32
41
  watchIgnoreFiles: adminWatchIgnoreFiles,
33
42
  features: ee.isEE ? ee.features.getEnabled() : [],
@@ -10,26 +10,10 @@ dotenv.config({ path: process.env.ENV_PATH });
10
10
 
11
11
  process.env.NODE_ENV = process.env.NODE_ENV || 'development';
12
12
 
13
- const getPrefixedDeps = require('../../utils/get-prefixed-dependencies');
14
13
  const loadConfigDir = require('./config-loader');
15
14
 
16
15
  const { version: strapiVersion } = require(path.join(__dirname, '../../../package.json'));
17
16
 
18
- const CONFIG_PATHS = {
19
- admin: 'admin',
20
- api: 'api',
21
- config: 'config',
22
- controllers: 'controllers',
23
- models: 'models',
24
- plugins: 'plugins',
25
- policies: 'policies',
26
- tmp: '.tmp',
27
- services: 'services',
28
- static: 'public',
29
- validators: 'validators',
30
- views: 'views',
31
- };
32
-
33
17
  const defaultConfig = {
34
18
  server: {
35
19
  host: process.env.HOST || os.hostname() || 'localhost',
@@ -39,23 +23,10 @@ const defaultConfig = {
39
23
  admin: { autoOpen: false },
40
24
  },
41
25
  admin: {},
42
- middleware: {
43
- timeout: 1000,
44
- load: {
45
- before: ['responseTime', 'logger', 'cors', 'responses', 'gzip'],
46
- order: [],
47
- after: ['parser', 'router'],
48
- },
49
- settings: {},
50
- },
51
- hook: {
52
- timeout: 1000,
53
- load: {
54
- before: ['responseTime', 'logger', 'cors', 'responses', 'gzip'],
55
- order: [],
56
- after: ['parser', 'router'],
26
+ api: {
27
+ rest: {
28
+ prefix: '/api',
57
29
  },
58
- settings: {},
59
30
  },
60
31
  };
61
32
 
@@ -68,8 +39,6 @@ module.exports = (dir, initialConfig = {}) => {
68
39
 
69
40
  const rootConfig = {
70
41
  launchedAt: Date.now(),
71
- appPath: dir,
72
- paths: CONFIG_PATHS,
73
42
  serveAdminPanel,
74
43
  autoReload,
75
44
  environment: process.env.NODE_ENV,
@@ -79,8 +48,6 @@ module.exports = (dir, initialConfig = {}) => {
79
48
  ...pkgJSON,
80
49
  strapi: strapiVersion,
81
50
  },
82
- installedMiddlewares: getPrefixedDeps('@strapi/middleware', pkgJSON),
83
- installedHooks: getPrefixedDeps('@strapi/hook', pkgJSON),
84
51
  };
85
52
 
86
53
  const baseConfig = omit('plugins', loadConfigDir(configDir)); // plugin config will be loaded later
@@ -0,0 +1,25 @@
1
+ 'use strict';
2
+
3
+ const { getConfigUrls } = require('@strapi/utils');
4
+
5
+ module.exports = function({ strapi }) {
6
+ strapi.config.port = strapi.config.get('server.port') || strapi.config.port;
7
+ strapi.config.host = strapi.config.get('server.host') || strapi.config.host;
8
+
9
+ const { serverUrl, adminUrl, adminPath } = getConfigUrls(strapi.config);
10
+
11
+ strapi.config.server = strapi.config.server || {};
12
+ strapi.config.server.url = serverUrl;
13
+ strapi.config.admin.url = adminUrl;
14
+ strapi.config.admin.path = adminPath;
15
+
16
+ // check if we should serve admin panel
17
+ const shouldServeAdmin = strapi.config.get(
18
+ 'admin.serveAdminPanel',
19
+ strapi.config.get('serveAdminPanel')
20
+ );
21
+
22
+ if (!shouldServeAdmin) {
23
+ strapi.config.serveAdminPanel = false;
24
+ }
25
+ };
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { cloneDeep } = require('lodash/fp');
4
4
  const _ = require('lodash');
5
- const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
5
+ const { hasDraftAndPublish, getPrivateAttributes } = require('@strapi/utils').contentTypes;
6
6
  const {
7
7
  CREATED_AT_ATTRIBUTE,
8
8
  UPDATED_AT_ATTRIBUTE,
@@ -19,11 +19,11 @@ const createContentType = (uid, definition) => {
19
19
  throw new Error(`Content Type Definition is invalid for ${uid}'.\n${e.errors}`);
20
20
  }
21
21
 
22
- const createdContentType = cloneDeep(definition);
22
+ const { schema, actions, lifecycles } = cloneDeep(definition);
23
23
 
24
24
  // general info
25
- Object.assign(createdContentType.schema, {
26
- kind: createdContentType.schema.kind || 'collectionType',
25
+ Object.assign(schema, {
26
+ kind: schema.kind || 'collectionType',
27
27
  __schema__: pickSchema(definition.schema),
28
28
  modelType: 'contentType',
29
29
  modelName: definition.schema.info.singularName,
@@ -31,27 +31,26 @@ const createContentType = (uid, definition) => {
31
31
  });
32
32
 
33
33
  if (uid.startsWith('api::')) {
34
- Object.assign(createdContentType.schema, {
34
+ Object.assign(schema, {
35
35
  uid,
36
36
  apiName: uid.split('::')[1].split('.')[0],
37
- collectionName: definition.schema.collectionName || definition.schema.info.singularName,
38
- globalId: getGlobalId(definition.schema, definition.schema.info.singularName),
37
+ collectionName: schema.collectionName || schema.info.singularName,
38
+ globalId: getGlobalId(schema, schema.info.singularName),
39
39
  });
40
40
  } else if (uid.startsWith('plugin::')) {
41
41
  const pluginName = uid.split('::')[1].split('.')[0];
42
- Object.assign(createdContentType.schema, {
42
+ Object.assign(schema, {
43
43
  uid,
44
44
  plugin: pluginName, // TODO: to be set in load-plugins.js
45
45
  collectionName:
46
- createdContentType.schema.collectionName ||
47
- `${pluginName}_${definition.schema.info.singularName}`.toLowerCase(),
48
- globalId: getGlobalId(definition.schema, definition.schema.info.singularName, pluginName),
46
+ schema.collectionName || `${pluginName}_${schema.info.singularName}`.toLowerCase(),
47
+ globalId: getGlobalId(schema, schema.info.singularName, pluginName),
49
48
  });
50
- } else if (uid.startsWith('strapi::')) {
51
- Object.assign(createdContentType.schema, {
49
+ } else if (uid.startsWith('admin::')) {
50
+ Object.assign(schema, {
52
51
  uid,
53
52
  plugin: 'admin',
54
- globalId: getGlobalId(definition.schema, definition.schema.info.singularName, 'admin'),
53
+ globalId: getGlobalId(schema, schema.info.singularName, 'admin'),
55
54
  });
56
55
  } else {
57
56
  throw new Error(
@@ -59,29 +58,25 @@ const createContentType = (uid, definition) => {
59
58
  );
60
59
  }
61
60
 
62
- Object.defineProperty(createdContentType.schema, 'privateAttributes', {
61
+ Object.defineProperty(schema, 'privateAttributes', {
63
62
  get() {
64
- // FIXME: to fix
65
- // return strapi.getModel(model.uid).privateAttributes;
66
- return [];
63
+ return getPrivateAttributes(schema);
67
64
  },
68
65
  });
69
66
 
70
67
  // attributes
71
- Object.assign(createdContentType.schema.attributes, {
68
+ Object.assign(schema.attributes, {
72
69
  [CREATED_AT_ATTRIBUTE]: {
73
70
  type: 'datetime',
74
- default: () => new Date(),
75
71
  },
76
72
  // TODO: handle on edit set to new date
77
73
  [UPDATED_AT_ATTRIBUTE]: {
78
74
  type: 'datetime',
79
- default: () => new Date(),
80
75
  },
81
76
  });
82
77
 
83
- if (hasDraftAndPublish(createdContentType.schema)) {
84
- createdContentType.schema.attributes[PUBLISHED_AT_ATTRIBUTE] = {
78
+ if (hasDraftAndPublish(schema)) {
79
+ schema.attributes[PUBLISHED_AT_ATTRIBUTE] = {
85
80
  type: 'datetime',
86
81
  configurable: false,
87
82
  writable: true,
@@ -89,12 +84,12 @@ const createContentType = (uid, definition) => {
89
84
  };
90
85
  }
91
86
 
92
- const isPrivate = !_.get(createdContentType.schema, 'options.populateCreatorFields', false);
87
+ const isPrivate = !_.get(schema, 'options.populateCreatorFields', false);
93
88
 
94
- createdContentType.schema.attributes[CREATED_BY_ATTRIBUTE] = {
89
+ schema.attributes[CREATED_BY_ATTRIBUTE] = {
95
90
  type: 'relation',
96
91
  relation: 'oneToOne',
97
- target: 'strapi::user',
92
+ target: 'admin::user',
98
93
  configurable: false,
99
94
  writable: false,
100
95
  visible: false,
@@ -102,10 +97,10 @@ const createContentType = (uid, definition) => {
102
97
  private: isPrivate,
103
98
  };
104
99
 
105
- createdContentType.schema.attributes[UPDATED_BY_ATTRIBUTE] = {
100
+ schema.attributes[UPDATED_BY_ATTRIBUTE] = {
106
101
  type: 'relation',
107
102
  relation: 'oneToOne',
108
- target: 'strapi::user',
103
+ target: 'admin::user',
109
104
  configurable: false,
110
105
  writable: false,
111
106
  visible: false,
@@ -113,7 +108,9 @@ const createContentType = (uid, definition) => {
113
108
  private: isPrivate,
114
109
  };
115
110
 
116
- return createdContentType;
111
+ Object.assign(schema, { actions, lifecycles });
112
+
113
+ return schema;
117
114
  };
118
115
 
119
116
  const getGlobalId = (model, modelName, prefix) => {
@@ -3,9 +3,28 @@
3
3
  const { keyBy, mapValues } = require('lodash');
4
4
  const { yup } = require('@strapi/utils');
5
5
 
6
- // To replace by directly using implemented lifecycles
7
- const lifecycles = ['beforeCreate', 'afterCreate'];
8
- const lifecyclesShape = mapValues(keyBy(lifecycles), () =>
6
+ const LIFECYCLES = [
7
+ 'beforeCreate',
8
+ 'afterCreate',
9
+ 'beforeFindOne',
10
+ 'afterFindOne',
11
+ 'beforeFindMany',
12
+ 'afterFindMany',
13
+ 'beforeCount',
14
+ 'afterCount',
15
+ 'beforeCreateMany',
16
+ 'afterCreateMany',
17
+ 'beforeUpdate',
18
+ 'afterUpdate',
19
+ 'beforeUpdateMany',
20
+ 'afterUpdateMany',
21
+ 'beforeDelete',
22
+ 'afterDelete',
23
+ 'beforeDeleteMany',
24
+ 'afterDeleteMany',
25
+ ];
26
+
27
+ const lifecyclesShape = mapValues(keyBy(LIFECYCLES), () =>
9
28
  yup
10
29
  .mixed()
11
30
  .nullable()
@@ -1,12 +1,33 @@
1
1
  'use strict';
2
2
 
3
+ const _ = require('lodash');
4
+ const { removeNamespace } = require('../../utils');
3
5
  const { validateModule } = require('./validation');
4
6
 
7
+ const uidToPath = uid => uid.replace('::', '.');
8
+
9
+ // Removes the namespace from a map with keys prefixed with a namespace
10
+ const removeNamespacedKeys = (map, namespace) => {
11
+ return _.mapKeys(map, (value, key) => removeNamespace(key, namespace));
12
+ };
13
+
14
+ const defaultModule = {
15
+ config: {},
16
+ routes: [],
17
+ controllers: {},
18
+ services: {},
19
+ contentTypes: {},
20
+ policies: {},
21
+ middlewares: {},
22
+ };
23
+
5
24
  const createModule = (namespace, rawModule, strapi) => {
25
+ _.defaults(rawModule, defaultModule);
26
+
6
27
  try {
7
28
  validateModule(rawModule);
8
29
  } catch (e) {
9
- throw new Error(`strapi-server.js is invalid for plugin ${namespace}.\n${e.errors.join('\n')}`);
30
+ throw new Error(`strapi-server.js is invalid for '${namespace}'.\n${e.errors.join('\n')}`);
10
31
  }
11
32
 
12
33
  const called = {};
@@ -16,21 +37,21 @@ const createModule = (namespace, rawModule, strapi) => {
16
37
  throw new Error(`Bootstrap for ${namespace} has already been called`);
17
38
  }
18
39
  called.bootstrap = true;
19
- await rawModule.bootstrap(strapi);
40
+ await (rawModule.bootstrap && rawModule.bootstrap({ strapi }));
20
41
  },
21
42
  async register() {
22
43
  if (called.register) {
23
44
  throw new Error(`Register for ${namespace} has already been called`);
24
45
  }
25
46
  called.register = true;
26
- await rawModule.register(strapi);
47
+ await (rawModule.register && rawModule.register({ strapi }));
27
48
  },
28
49
  async destroy() {
29
50
  if (called.destroy) {
30
51
  throw new Error(`Destroy for ${namespace} has already been called`);
31
52
  }
32
53
  called.destroy = true;
33
- await rawModule.destroy(strapi);
54
+ await (rawModule.destroy && rawModule.destroy({ strapi }));
34
55
  },
35
56
  load() {
36
57
  strapi.container.get('content-types').add(namespace, rawModule.contentTypes);
@@ -38,38 +59,48 @@ const createModule = (namespace, rawModule, strapi) => {
38
59
  strapi.container.get('policies').add(namespace, rawModule.policies);
39
60
  strapi.container.get('middlewares').add(namespace, rawModule.middlewares);
40
61
  strapi.container.get('controllers').add(namespace, rawModule.controllers);
41
- strapi.container.get('config').set(namespace.replace('::', '.'), rawModule.config);
62
+ strapi.container.get('config').set(uidToPath(namespace), rawModule.config);
63
+ },
64
+ get routes() {
65
+ return rawModule.routes;
66
+ },
67
+ config(path, defaultValue) {
68
+ return strapi.container.get('config').get(`${uidToPath(namespace)}.${path}`, defaultValue);
42
69
  },
43
- routes: rawModule.routes, // TODO: to remove v3
44
70
  contentType(ctName) {
45
71
  return strapi.container.get('content-types').get(`${namespace}.${ctName}`);
46
72
  },
47
73
  get contentTypes() {
48
- return strapi.container.get('content-types').getAll(namespace);
74
+ const contentTypes = strapi.container.get('content-types').getAll(namespace);
75
+ return removeNamespacedKeys(contentTypes, namespace);
49
76
  },
50
77
  service(serviceName) {
51
78
  return strapi.container.get('services').get(`${namespace}.${serviceName}`);
52
79
  },
53
80
  get services() {
54
- return strapi.container.get('services').getAll(namespace);
81
+ const services = strapi.container.get('services').getAll(namespace);
82
+ return removeNamespacedKeys(services, namespace);
55
83
  },
56
84
  policy(policyName) {
57
85
  return strapi.container.get('policies').get(`${namespace}.${policyName}`);
58
86
  },
59
87
  get policies() {
60
- return rawModule.policies;
88
+ const policies = strapi.container.get('policies').getAll(namespace);
89
+ return removeNamespacedKeys(policies, namespace);
61
90
  },
62
91
  middleware(middlewareName) {
63
92
  return strapi.container.get('middlewares').get(`${namespace}.${middlewareName}`);
64
93
  },
65
94
  get middlewares() {
66
- return strapi.container.get('middlewares').getAll(namespace);
95
+ const middlewares = strapi.container.get('middlewares').getAll(namespace);
96
+ return removeNamespacedKeys(middlewares, namespace);
67
97
  },
68
98
  controller(controllerName) {
69
99
  return strapi.container.get('controllers').get(`${namespace}.${controllerName}`);
70
100
  },
71
101
  get controllers() {
72
- return rawModule.controllers;
102
+ const controllers = strapi.container.get('controllers').getAll(namespace);
103
+ return removeNamespacedKeys(controllers, namespace);
73
104
  },
74
105
  };
75
106
  };
@@ -5,25 +5,22 @@ const { yup } = require('@strapi/utils');
5
5
  const strapiServerSchema = yup
6
6
  .object()
7
7
  .shape({
8
- bootstrap: yup
9
- .mixed()
10
- .isFunction()
11
- .required(),
12
- destroy: yup
13
- .mixed()
14
- .isFunction()
15
- .required(),
16
- register: yup
17
- .mixed()
18
- .isFunction()
19
- .required(),
20
- config: yup.object().required(),
21
- routes: yup.array().required(), // may be removed later
22
- controllers: yup.object().required(), // may be removed later
23
- services: yup.object().required(),
24
- policies: yup.object().required(),
25
- middlewares: yup.object().required(), // may be removed later
26
- contentTypes: yup.object().required(),
8
+ bootstrap: yup.mixed().isFunction(),
9
+ destroy: yup.mixed().isFunction(),
10
+ register: yup.mixed().isFunction(),
11
+ config: yup.object(),
12
+ routes: yup.lazy(value => {
13
+ if (Array.isArray(value)) {
14
+ return yup.array();
15
+ } else {
16
+ return yup.object();
17
+ }
18
+ }),
19
+ controllers: yup.object(),
20
+ services: yup.object(),
21
+ policies: yup.object(),
22
+ middlewares: yup.object(),
23
+ contentTypes: yup.object(),
27
24
  })
28
25
  .noUnknown();
29
26
 
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+
5
+ module.exports = strapi => {
6
+ strapi.admin = require('@strapi/admin/strapi-server');
7
+
8
+ strapi.container.get('services').add(`admin::`, strapi.admin.services);
9
+ strapi.container.get('controllers').add(`admin::`, strapi.admin.controllers);
10
+ strapi.container.get('content-types').add(`admin::`, strapi.admin.contentTypes);
11
+ strapi.container.get('policies').add(`admin::`, strapi.admin.policies);
12
+ strapi.container.get('middlewares').add(`admin::`, strapi.admin.middlewares);
13
+
14
+ const userAdminConfig = strapi.config.get('admin');
15
+ strapi.container.get('config').set('admin', _.merge(strapi.admin.config, userAdminConfig));
16
+ };