@strapi/strapi 4.2.3 → 4.3.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.
Files changed (91) hide show
  1. package/bin/strapi.js +13 -0
  2. package/lib/Strapi.js +41 -10
  3. package/lib/commands/admin-create.js +2 -1
  4. package/lib/commands/admin-reset.js +2 -1
  5. package/lib/commands/build.js +8 -46
  6. package/lib/commands/builders/admin.js +56 -0
  7. package/lib/commands/builders/index.js +9 -0
  8. package/lib/commands/builders/typescript.js +32 -0
  9. package/lib/commands/configurationDump.js +2 -1
  10. package/lib/commands/configurationRestore.js +3 -1
  11. package/lib/commands/console.js +4 -3
  12. package/lib/commands/content-types/list.js +2 -1
  13. package/lib/commands/controllers/list.js +2 -1
  14. package/lib/commands/develop.js +111 -74
  15. package/lib/commands/hooks/list.js +2 -1
  16. package/lib/commands/middlewares/list.js +2 -1
  17. package/lib/commands/policies/list.js +2 -1
  18. package/lib/commands/routes/list.js +2 -1
  19. package/lib/commands/services/list.js +2 -1
  20. package/lib/commands/start.js +18 -2
  21. package/lib/commands/ts/generate-types.js +26 -0
  22. package/lib/commands/watchAdmin.js +5 -10
  23. package/lib/compile.js +20 -0
  24. package/lib/core/app-configuration/index.js +4 -3
  25. package/lib/core/app-configuration/load-config-file.js +3 -1
  26. package/lib/core/bootstrap.js +2 -2
  27. package/lib/core/domain/content-type/validator.js +29 -8
  28. package/lib/core/loaders/apis.js +6 -5
  29. package/lib/core/loaders/components.js +5 -4
  30. package/lib/core/loaders/middlewares.js +4 -2
  31. package/lib/core/loaders/plugins/get-enabled-plugins.js +2 -1
  32. package/lib/core/loaders/plugins/get-user-plugins-config.js +2 -2
  33. package/lib/core/loaders/plugins/index.js +1 -1
  34. package/lib/core/loaders/policies.js +4 -2
  35. package/lib/core/loaders/src-index.js +6 -4
  36. package/lib/core/registries/policies.d.ts +1 -1
  37. package/lib/core-api/controller/index.d.ts +16 -14
  38. package/lib/core-api/service/index.d.ts +10 -9
  39. package/lib/global.d.ts +61 -0
  40. package/lib/index.d.ts +2 -24
  41. package/lib/index.js +1 -0
  42. package/lib/load/load-files.js +3 -1
  43. package/lib/middlewares/favicon.js +1 -1
  44. package/lib/middlewares/public/index.js +1 -1
  45. package/lib/services/cron.js +7 -3
  46. package/lib/services/entity-service/index.d.ts +7 -1
  47. package/lib/services/entity-service/index.js +11 -1
  48. package/lib/services/fs.js +1 -1
  49. package/lib/services/metrics/index.js +5 -1
  50. package/lib/services/metrics/sender.js +7 -0
  51. package/lib/services/server/middleware.js +1 -1
  52. package/lib/services/utils/upload-files.js +1 -1
  53. package/lib/types/core/attributes/base.d.ts +74 -0
  54. package/lib/types/core/attributes/biginteger.d.ts +22 -0
  55. package/lib/types/core/attributes/boolean.d.ts +20 -0
  56. package/lib/types/core/attributes/common.d.ts +42 -0
  57. package/lib/types/core/attributes/component.d.ts +41 -0
  58. package/lib/types/core/attributes/date-time.d.ts +22 -0
  59. package/lib/types/core/attributes/date.d.ts +22 -0
  60. package/lib/types/core/attributes/decimal.d.ts +22 -0
  61. package/lib/types/core/attributes/dynamic-zone.d.ts +29 -0
  62. package/lib/types/core/attributes/email.d.ts +24 -0
  63. package/lib/types/core/attributes/enumeration.d.ts +28 -0
  64. package/lib/types/core/attributes/float.d.ts +22 -0
  65. package/lib/types/core/attributes/index.d.ts +26 -0
  66. package/lib/types/core/attributes/integer.d.ts +22 -0
  67. package/lib/types/core/attributes/json.d.ts +14 -0
  68. package/lib/types/core/attributes/media.d.ts +36 -0
  69. package/lib/types/core/attributes/password.d.ts +22 -0
  70. package/lib/types/core/attributes/relation.d.ts +66 -0
  71. package/lib/types/core/attributes/richtext.d.ts +22 -0
  72. package/lib/types/core/attributes/string.d.ts +30 -0
  73. package/lib/types/core/attributes/text.d.ts +30 -0
  74. package/lib/types/core/attributes/time.d.ts +22 -0
  75. package/lib/types/core/attributes/timestamp.d.ts +22 -0
  76. package/lib/types/core/attributes/uid.d.ts +57 -0
  77. package/lib/types/core/attributes/utils.d.ts +99 -0
  78. package/lib/types/core/index.d.ts +3 -0
  79. package/lib/types/core/schemas/index.d.ts +126 -0
  80. package/lib/types/core/strapi/index.d.ts +391 -0
  81. package/lib/types/factories.d.ts +60 -0
  82. package/lib/types/index.d.ts +4 -0
  83. package/lib/types/utils.d.ts +95 -0
  84. package/lib/utils/get-dirs.js +24 -10
  85. package/lib/utils/import-default.js +10 -0
  86. package/lib/utils/index.js +2 -0
  87. package/lib/utils/lifecycles.js +15 -0
  88. package/lib/utils/machine-id.js +2 -2
  89. package/lib/utils/update-notifier/index.js +1 -1
  90. package/package.json +18 -16
  91. package/lib/factories.d.ts +0 -48
@@ -6,7 +6,8 @@ const chalk = require('chalk');
6
6
  const strapi = require('../../index');
7
7
 
8
8
  module.exports = async function() {
9
- const app = await strapi().register();
9
+ const appContext = await strapi.compile();
10
+ const app = await strapi(appContext).register();
10
11
 
11
12
  const list = app.container.get('services').keys();
12
13
 
@@ -1,8 +1,24 @@
1
1
  'use strict';
2
-
2
+ const fs = require('fs');
3
+ const tsUtils = require('@strapi/typescript-utils');
3
4
  const strapi = require('../index');
4
5
 
5
6
  /**
6
7
  * `$ strapi start`
7
8
  */
8
- module.exports = () => strapi().start();
9
+ module.exports = async () => {
10
+ const appDir = process.cwd();
11
+
12
+ const isTSProject = await tsUtils.isUsingTypeScript(appDir);
13
+
14
+ const outDir = await tsUtils.resolveOutDir(appDir);
15
+ const distDir = isTSProject ? outDir : appDir;
16
+
17
+ const buildDirExists = fs.existsSync(outDir);
18
+ if (isTSProject && !buildDirExists)
19
+ throw new Error(
20
+ `${outDir} directory not found. Please run the build command before starting your application`
21
+ );
22
+
23
+ return strapi({ appDir, distDir }).start();
24
+ };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ const tsUtils = require('@strapi/typescript-utils');
4
+
5
+ const strapi = require('../../index');
6
+
7
+ module.exports = async function({ outDir, file, verbose, silent }) {
8
+ if (verbose && silent) {
9
+ console.error('You cannot enable verbose and silent flags at the same time, exiting...');
10
+ process.exit(1);
11
+ }
12
+
13
+ const appContext = await strapi.compile();
14
+ const app = await strapi(appContext).register();
15
+
16
+ await tsUtils.generators.generateSchemasDefinitions({
17
+ strapi: app,
18
+ outDir: outDir || appContext.appDir,
19
+ file,
20
+ dirs: appContext,
21
+ verbose,
22
+ silent,
23
+ });
24
+
25
+ app.destroy();
26
+ };
@@ -3,16 +3,15 @@
3
3
  const strapiAdmin = require('@strapi/admin');
4
4
  const { getConfigUrls, getAbsoluteServerUrl } = require('@strapi/utils');
5
5
 
6
- const ee = require('../utils/ee');
6
+ const getEnabledPlugins = require('../core/loaders/plugins/get-enabled-plugins');
7
7
  const addSlash = require('../utils/addSlash');
8
8
  const strapi = require('../index');
9
- const getEnabledPlugins = require('../core/loaders/plugins/get-enabled-plugins');
10
9
 
11
10
  module.exports = async function({ browser }) {
12
- const dir = process.cwd();
11
+ const appContext = await strapi.compile();
13
12
 
14
13
  const strapiInstance = strapi({
15
- dir,
14
+ ...appContext,
16
15
  autoReload: true,
17
16
  serveAdminPanel: false,
18
17
  });
@@ -23,14 +22,12 @@ module.exports = async function({ browser }) {
23
22
 
24
23
  const adminPort = strapiInstance.config.get('admin.port', 8000);
25
24
  const adminHost = strapiInstance.config.get('admin.host', 'localhost');
26
- const adminWatchIgnoreFiles = strapiInstance.config.get('admin.watchIgnoreFiles', []);
27
25
 
28
26
  const backendURL = getAbsoluteServerUrl(strapiInstance.config, true);
29
27
 
30
- ee({ dir });
31
-
32
28
  strapiAdmin.watchAdmin({
33
- dir,
29
+ appDir: appContext.appDir,
30
+ buildDestDir: appContext.distDir,
34
31
  plugins,
35
32
  port: adminPort,
36
33
  host: adminHost,
@@ -38,8 +35,6 @@ module.exports = async function({ browser }) {
38
35
  options: {
39
36
  backend: backendURL,
40
37
  adminPath: addSlash(adminPath),
41
- watchIgnoreFiles: adminWatchIgnoreFiles,
42
- features: ee.isEE ? ee.features.getEnabled() : [],
43
38
  },
44
39
  });
45
40
  };
package/lib/compile.js ADDED
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ const tsUtils = require('@strapi/typescript-utils');
4
+
5
+ module.exports = async dir => {
6
+ const appDir = dir || process.cwd();
7
+ const isTSProject = await tsUtils.isUsingTypeScript(appDir);
8
+ const outDir = await tsUtils.resolveOutDir(appDir);
9
+
10
+ if (isTSProject) {
11
+ await tsUtils.compile(appDir, {
12
+ watch: false,
13
+ configOptions: { options: { incremental: true } },
14
+ });
15
+ }
16
+
17
+ const distDir = isTSProject ? outDir : appDir;
18
+
19
+ return { appDir, distDir };
20
+ };
@@ -31,12 +31,13 @@ const defaultConfig = {
31
31
  },
32
32
  };
33
33
 
34
- module.exports = (dir, initialConfig = {}) => {
34
+ module.exports = (dirs, initialConfig = {}) => {
35
+ const { appDir, distDir } = dirs;
35
36
  const { autoReload = false, serveAdminPanel = true } = initialConfig;
36
37
 
37
- const pkgJSON = require(path.resolve(dir, 'package.json'));
38
+ const pkgJSON = require(path.resolve(appDir, 'package.json'));
38
39
 
39
- const configDir = path.resolve(dir || process.cwd(), 'config');
40
+ const configDir = path.resolve(distDir || process.cwd(), 'config');
40
41
 
41
42
  const rootConfig = {
42
43
  launchedAt: Date.now(),
@@ -4,9 +4,11 @@ const path = require('path');
4
4
  const fs = require('fs');
5
5
  const { templateConfiguration, env } = require('@strapi/utils');
6
6
 
7
+ const importDefault = require('../../utils/import-default');
8
+
7
9
  const loadJsFile = file => {
8
10
  try {
9
- const jsModule = require(file);
11
+ const jsModule = importDefault(file);
10
12
 
11
13
  // call if function
12
14
  if (typeof jsModule === 'function') {
@@ -25,9 +25,9 @@ module.exports = async function({ strapi }) {
25
25
  }
26
26
 
27
27
  // ensure public repository exists
28
- if (!(await fse.pathExists(strapi.dirs.public))) {
28
+ if (!(await fse.pathExists(strapi.dirs.static.public))) {
29
29
  throw new Error(
30
- `The public folder (${strapi.dirs.public}) doesn't exist or is not accessible. Please make sure it exists.`
30
+ `The public folder (${strapi.dirs.static.public}) doesn't exist or is not accessible. Please make sure it exists.`
31
31
  );
32
32
  }
33
33
  };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const _ = require('lodash');
4
- const { yup, toRegressedEnumValue, startsWithANumber } = require('@strapi/utils');
4
+ const { yup, toRegressedEnumValue } = require('@strapi/utils');
5
5
 
6
6
  const LIFECYCLES = [
7
7
  'beforeCreate',
@@ -24,6 +24,20 @@ const LIFECYCLES = [
24
24
  'afterDeleteMany',
25
25
  ];
26
26
 
27
+ /**
28
+ * For enumerations the least common denomiator is GraphQL, where
29
+ * values needs to match the secure name regex:
30
+ * GraphQL Spec https://spec.graphql.org/June2018/#sec-Names
31
+ *
32
+ * Therefore we need to make sure our users only use values, which
33
+ * can be returned by GraphQL, by checking the regressed values
34
+ * agains the GraphQL regex.
35
+ *
36
+ * TODO V5: check if we can avoid this coupling by moving this logic
37
+ * into the GraphQL plugin.
38
+ */
39
+ const GRAPHQL_ENUM_REGEX = new RegExp('^[_A-Za-z][_0-9A-Za-z]*$');
40
+
27
41
  const lifecyclesShape = _.mapValues(_.keyBy(LIFECYCLES), () =>
28
42
  yup
29
43
  .mixed()
@@ -54,22 +68,29 @@ const contentTypeSchemaValidator = yup.object().shape({
54
68
  for (const attrName in attributes) {
55
69
  const attr = attributes[attrName];
56
70
  if (attr.type === 'enumeration') {
57
- // should not start by a number
58
- if (attr.enum.some(startsWithANumber)) {
59
- const message = `Enum values should not start with a number. Please modify your enumeration '${attrName}'.`;
71
+ const regressedValues = attr.enum.map(toRegressedEnumValue);
72
+
73
+ // should match the GraphQL regex
74
+ if (!regressedValues.every(value => GRAPHQL_ENUM_REGEX.test(value))) {
75
+ const message = `Invalid enumeration value. Values should have at least one alphabetical character preceeding the first occurence of a number. Update your enumeration '${attrName}'.`;
60
76
 
61
77
  return this.createError({ message });
62
78
  }
63
79
 
80
+ // should not contain empty values
81
+ if (regressedValues.some(value => value === '')) {
82
+ return this.createError({
83
+ message: `At least one value of the enumeration '${attrName}' appears to be empty. Only alphanumerical characters are taken into account.`,
84
+ });
85
+ }
86
+
64
87
  // should not collide
65
88
  const duplicates = _.uniq(
66
- attr.enum
67
- .map(toRegressedEnumValue)
68
- .filter((value, index, values) => values.indexOf(value) !== index)
89
+ regressedValues.filter((value, index, values) => values.indexOf(value) !== index)
69
90
  );
70
91
 
71
92
  if (duplicates.length) {
72
- const message = `Some enum values of the field '${attrName}' collide when normalized: ${duplicates.join(
93
+ const message = `Some enumeration values of the field '${attrName}' collide when normalized: ${duplicates.join(
73
94
  ', '
74
95
  )}. Please modify your enumeration.`;
75
96
 
@@ -5,6 +5,7 @@ const { existsSync } = require('fs-extra');
5
5
  const _ = require('lodash');
6
6
  const fse = require('fs-extra');
7
7
  const { isKebabCase } = require('@strapi/utils');
8
+ const { importDefault } = require('../../utils');
8
9
 
9
10
  const DEFAULT_CONTENT_TYPE = {
10
11
  schema: {},
@@ -19,11 +20,11 @@ const isDirectory = fd => fd.isDirectory();
19
20
  const isDotFile = fd => fd.name.startsWith('.');
20
21
 
21
22
  module.exports = async strapi => {
22
- if (!existsSync(strapi.dirs.api)) {
23
- throw new Error('Missing api folder. Please create one at `./src/api`');
23
+ if (!existsSync(strapi.dirs.dist.api)) {
24
+ return;
24
25
  }
25
26
 
26
- const apisFDs = await (await fse.readdir(strapi.dirs.api, { withFileTypes: true }))
27
+ const apisFDs = await (await fse.readdir(strapi.dirs.dist.api, { withFileTypes: true }))
27
28
  .filter(isDirectory)
28
29
  .filter(_.negate(isDotFile));
29
30
 
@@ -32,7 +33,7 @@ module.exports = async strapi => {
32
33
  // only load folders
33
34
  for (const apiFD of apisFDs) {
34
35
  const apiName = normalizeName(apiFD.name);
35
- const api = await loadAPI(join(strapi.dirs.api, apiFD.name));
36
+ const api = await loadAPI(join(strapi.dirs.dist.api, apiFD.name));
36
37
 
37
38
  apis[apiName] = api;
38
39
  }
@@ -154,7 +155,7 @@ const loadFile = file => {
154
155
 
155
156
  switch (ext) {
156
157
  case '.js':
157
- return require(file);
158
+ return importDefault(file);
158
159
  case '.json':
159
160
  return fse.readJSON(file);
160
161
  default:
@@ -6,19 +6,20 @@ const { pathExists } = require('fs-extra');
6
6
  const loadFiles = require('../../load/load-files');
7
7
 
8
8
  module.exports = async strapi => {
9
- if (!(await pathExists(strapi.dirs.components))) {
9
+ if (!(await pathExists(strapi.dirs.dist.components))) {
10
10
  return {};
11
11
  }
12
12
 
13
- const map = await loadFiles(strapi.dirs.components, '*/*.*(js|json)');
13
+ const map = await loadFiles(strapi.dirs.dist.components, '*/*.*(js|json)');
14
14
 
15
15
  return Object.keys(map).reduce((acc, category) => {
16
16
  Object.keys(map[category]).forEach(key => {
17
17
  const schema = map[category][key];
18
18
 
19
- const filePath = join(strapi.dirs.components, category, schema.__filename__);
20
-
21
19
  if (!schema.collectionName) {
20
+ // NOTE: We're using the filepath from the app directory instead of the dist for information purpose
21
+ const filePath = join(strapi.dirs.app.components, category, schema.__filename__);
22
+
22
23
  return strapi.stopWithError(
23
24
  `Component ${key} is missing a "collectionName" property.\nVerify file ${filePath}.`
24
25
  );
@@ -3,6 +3,8 @@
3
3
  const { join, extname, basename } = require('path');
4
4
  const fse = require('fs-extra');
5
5
 
6
+ const { importDefault } = require('../../utils');
7
+
6
8
  // TODO:: allow folders with index.js inside for bigger policies
7
9
  module.exports = async function loadMiddlewares(strapi) {
8
10
  const localMiddlewares = await loadLocalMiddlewares(strapi);
@@ -13,7 +15,7 @@ module.exports = async function loadMiddlewares(strapi) {
13
15
  };
14
16
 
15
17
  const loadLocalMiddlewares = async strapi => {
16
- const dir = strapi.dirs.middlewares;
18
+ const dir = strapi.dirs.dist.middlewares;
17
19
 
18
20
  if (!(await fse.pathExists(dir))) {
19
21
  return {};
@@ -28,7 +30,7 @@ const loadLocalMiddlewares = async strapi => {
28
30
 
29
31
  if (fd.isFile() && extname(name) === '.js') {
30
32
  const key = basename(name, '.js');
31
- middlewares[key] = require(fullPath);
33
+ middlewares[key] = importDefault(fullPath);
32
34
  }
33
35
  }
34
36
 
@@ -29,10 +29,11 @@ const toDetailedDeclaration = declaration => {
29
29
  let detailedDeclaration = pick(['enabled'], declaration);
30
30
  if (has('resolve', declaration)) {
31
31
  let pathToPlugin = '';
32
+
32
33
  try {
33
34
  pathToPlugin = dirname(require.resolve(declaration.resolve));
34
35
  } catch (e) {
35
- pathToPlugin = resolve(strapi.dirs.root, declaration.resolve);
36
+ pathToPlugin = resolve(strapi.dirs.app.root, declaration.resolve);
36
37
 
37
38
  if (!existsSync(pathToPlugin) || !statSync(pathToPlugin).isDirectory()) {
38
39
  throw new Error(`${declaration.resolve} couldn't be resolved`);
@@ -12,9 +12,9 @@ const loadConfigFile = require('../../app-configuration/load-config-file');
12
12
  * @return {Promise<{}>}
13
13
  */
14
14
  const getUserPluginsConfig = async () => {
15
- const globalUserConfigPath = join(strapi.dirs.config, 'plugins.js');
15
+ const globalUserConfigPath = join(strapi.dirs.dist.config, 'plugins.js');
16
16
  const currentEnvUserConfigPath = join(
17
- strapi.dirs.config,
17
+ strapi.dirs.dist.config,
18
18
  'env',
19
19
  process.env.NODE_ENV,
20
20
  'plugins.js'
@@ -26,7 +26,7 @@ const defaultPlugin = {
26
26
  };
27
27
 
28
28
  const applyUserExtension = async plugins => {
29
- const extensionsDir = strapi.dirs.extensions;
29
+ const extensionsDir = strapi.dirs.dist.extensions;
30
30
  if (!(await fse.pathExists(extensionsDir))) {
31
31
  return;
32
32
  }
@@ -3,9 +3,11 @@
3
3
  const { join, extname, basename } = require('path');
4
4
  const fse = require('fs-extra');
5
5
 
6
+ const { importDefault } = require('../../utils');
7
+
6
8
  // TODO:: allow folders with index.js inside for bigger policies
7
9
  module.exports = async function loadPolicies(strapi) {
8
- const dir = strapi.dirs.policies;
10
+ const dir = strapi.dirs.dist.policies;
9
11
 
10
12
  if (!(await fse.pathExists(dir))) {
11
13
  return;
@@ -20,7 +22,7 @@ module.exports = async function loadPolicies(strapi) {
20
22
 
21
23
  if (fd.isFile() && extname(name) === '.js') {
22
24
  const key = basename(name, '.js');
23
- policies[key] = require(fullPath);
25
+ policies[key] = importDefault(fullPath);
24
26
  }
25
27
  }
26
28
 
@@ -4,6 +4,8 @@ const { resolve } = require('path');
4
4
  const { statSync, existsSync } = require('fs');
5
5
  const { yup } = require('@strapi/utils');
6
6
 
7
+ const { importDefault } = require('../../utils');
8
+
7
9
  const srcSchema = yup
8
10
  .object()
9
11
  .shape({
@@ -18,16 +20,16 @@ const validateSrcIndex = srcIndex => {
18
20
  };
19
21
 
20
22
  module.exports = strapi => {
21
- if (!existsSync(strapi.dirs.src)) {
22
- throw new Error('Missing src folder. Please create one at `./src`');
23
+ if (!existsSync(strapi.dirs.dist.src)) {
24
+ return;
23
25
  }
24
26
 
25
- const pathToSrcIndex = resolve(strapi.dirs.src, 'index.js');
27
+ const pathToSrcIndex = resolve(strapi.dirs.dist.src, 'index.js');
26
28
  if (!existsSync(pathToSrcIndex) || statSync(pathToSrcIndex).isDirectory()) {
27
29
  return {};
28
30
  }
29
31
 
30
- const srcIndex = require(pathToSrcIndex);
32
+ const srcIndex = importDefault(pathToSrcIndex);
31
33
 
32
34
  try {
33
35
  validateSrcIndex(srcIndex);
@@ -6,4 +6,4 @@ interface PolicyContext extends BaseContext {
6
6
  is(name): boolean;
7
7
  }
8
8
 
9
- export type Policy = (ctx: PolicyContext, { strapi: Strapi }) => boolean | undefined;
9
+ export type Policy<T=unknown> = (ctx: PolicyContext,cfg:T, { strapi: Strapi }) => boolean | undefined;
@@ -1,25 +1,27 @@
1
- import { Context } from 'koa';
1
+ import { Context, Next } from 'koa';
2
2
 
3
- type Response = object;
3
+ type ControllerResponse<T = unknown> = T | Promise<T> | undefined;
4
4
 
5
- interface BaseController {
5
+ interface Controller {
6
6
  transformResponse(data: object, meta: object): object;
7
7
  sanitizeOutput(data: object, ctx: Context): Promise<object>;
8
8
  sanitizeInput(data: object, ctx: Context): Promise<object>;
9
9
  }
10
10
 
11
- export interface SingleTypeController extends BaseController {
12
- find(ctx: Context): Promise<Response>;
13
- update(ctx: Context): Promise<Response>;
14
- delete(ctx: Context): Promise<Response>;
11
+ export interface SingleTypeController extends Controller {
12
+ find?(ctx: Context, next: Next): ControllerResponse;
13
+ update?(ctx: Context, next: Next): ControllerResponse;
14
+ delete?(ctx: Context, next: Next): ControllerResponse;
15
15
  }
16
16
 
17
- export interface CollectionTypeController extends BaseController {
18
- find(ctx: Context): Promise<Response>;
19
- findOne(ctx: Context): Promise<Response>;
20
- create(ctx: Context): Promise<Response>;
21
- update(ctx: Context): Promise<Response>;
22
- delete(ctx: Context): Promise<Response>;
17
+ export interface CollectionTypeController extends Controller {
18
+ find?(ctx: Context, next: Next): ControllerResponse;
19
+ findOne?(ctx: Context, next: Next): ControllerResponse;
20
+ create?(ctx: Context, next: Next): ControllerResponse;
21
+ update?(ctx: Context, next: Next): ControllerResponse;
22
+ delete?(ctx: Context, next: Next): ControllerResponse;
23
23
  }
24
24
 
25
- export type Controller = SingleTypeController | CollectionTypeController;
25
+ export type GenericController = Partial<Controller> & {
26
+ [method: string | number | symbol]: (ctx: Context) => unknown;
27
+ };
@@ -1,21 +1,22 @@
1
1
  type Entity = object;
2
2
 
3
3
  interface BaseService {
4
- getFetchParams(params: object): object;
4
+ getFetchParams?(params: object): object;
5
5
  }
6
6
 
7
7
  export interface SingleTypeService extends BaseService {
8
- find(params: object): Promise<Entity>;
9
- createOrUpdate(params: object): Promise<Entity>;
10
- delete(params: object): Promise<Entity>;
8
+ find?(params: object): Promise<Entity> | Entity;
9
+ createOrUpdate?(params: object): Promise<Entity> | Entity;
10
+ delete?(params: object): Promise<Entity> | Entity;
11
11
  }
12
12
 
13
13
  export interface CollectionTypeService extends BaseService {
14
- find(params: object): Promise<Entity[]>;
15
- findOne(params: object): Promise<Entity>;
16
- create(params: object): Promise<Entity>;
17
- update(params: object): Promise<Entity>;
18
- delete(params: object): Promise<Entity>;
14
+ find?(params: object): Promise<Entity[]> | Entity;
15
+ findOne?(entityId: string,params: object): Promise<Entity> | Entity;
16
+ create?(params: object): Promise<Entity> | Entity;
17
+ update?(entityId: string,params: object): Promise<Entity> | Entity;
18
+ delete?(entityId: string,params: object): Promise<Entity> | Entity;
19
19
  }
20
20
 
21
21
  export type Service = SingleTypeService | CollectionTypeService;
22
+
@@ -0,0 +1,61 @@
1
+ import type { Strapi as StrapiInterface } from './types/core';
2
+ import type { CollectionTypeSchema, SingleTypeSchema, ComponentSchema, ContentTypeSchema } from './types/core/schemas';
3
+ import type { KeysBy } from './types/utils';
4
+
5
+ declare global {
6
+ namespace Strapi {
7
+ /**
8
+ * Map of UID / schemas used as a schemas database for other types.
9
+ * It must be extended by the user application or plugins.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * declare global {
14
+ * namespace Strapi {
15
+ * interface Schemas {
16
+ * 'xxx::xxx.uid: ContentTypeSchema | ComponentSchema;
17
+ * }
18
+ * }
19
+ * }
20
+ * ```
21
+ */
22
+ interface Schemas {}
23
+
24
+ /**
25
+ * Literal union type of every content type registered in Strapi.Schemas
26
+ */
27
+ type ContentTypeUIDs = KeysBy<Schemas, ContentTypeSchema>;
28
+
29
+ /**
30
+ * Literal union type of every collection type registered in Strapi.Schemas
31
+ */
32
+ type CollectionTypeUIDs = KeysBy<Schemas, CollectionTypeSchema>;
33
+
34
+ /**
35
+ * Literal union type of every single type registered in Strapi.Schemas
36
+ */
37
+ type SingleTypeUIDs = KeysBy<Schemas, SingleTypeSchema>;
38
+
39
+ /**
40
+ * Literal union type of every component registered in Strapi.Schemas
41
+ */
42
+ type ComponentUIDs = KeysBy<Schemas, ComponentSchema>;
43
+
44
+ /**
45
+ * Global shorthand to access the `StrapiInterface` type
46
+ */
47
+ type Strapi = StrapiInterface;
48
+ }
49
+
50
+ /**
51
+ * Strapi global variable definition
52
+ **/
53
+ export const strapi: StrapiInterface;
54
+
55
+ /**
56
+ * Adds the strapi global variable to the NodeJS Global interface
57
+ */
58
+ export interface Global {
59
+ strapi: StrapiInterface;
60
+ }
61
+ }
package/lib/index.d.ts CHANGED
@@ -1,27 +1,5 @@
1
- import { Database } from '@strapi/database';
2
- import { EntityService } from './services/entity-service';
3
- import { Strapi as StrapiClass } from './Strapi';
1
+ import './global';
4
2
 
5
- export * as factories from './factories';
6
- interface StrapiInterface extends StrapiClass {
7
- query: Database['query'];
8
- entityService: EntityService;
9
- }
10
-
11
- export type Strapi = StrapiInterface;
12
-
13
- declare global {
14
- interface AllTypes {}
15
- }
16
-
17
- declare global {
18
- export interface Global {
19
- strapi: StrapiInterface;
20
- }
21
-
22
- export type Strapi = StrapiInterface;
23
-
24
- const strapi: StrapiInterface;
25
- }
3
+ export * from './types';
26
4
 
27
5
  export default function(opts): Strapi;
package/lib/index.js CHANGED
@@ -3,5 +3,6 @@
3
3
  const Strapi = require('./Strapi');
4
4
 
5
5
  Strapi.factories = require('./factories');
6
+ Strapi.compile = require('./compile');
6
7
 
7
8
  module.exports = Strapi;
@@ -3,6 +3,8 @@
3
3
  const path = require('path');
4
4
  const _ = require('lodash');
5
5
  const fse = require('fs-extra');
6
+
7
+ const { importDefault } = require('../utils');
6
8
  const glob = require('./glob');
7
9
  const filePathToPath = require('./filepath-to-prop-path');
8
10
 
@@ -19,7 +21,7 @@ const filePathToPath = require('./filepath-to-prop-path');
19
21
  const loadFiles = async (
20
22
  dir,
21
23
  pattern,
22
- { requireFn = require, shouldUseFileNameAsKey = () => true, globArgs = {} } = {}
24
+ { requireFn = importDefault, shouldUseFileNameAsKey = () => true, globArgs = {} } = {}
23
25
  ) => {
24
26
  const root = {};
25
27
  const files = await glob(pattern, { cwd: dir, ...globArgs });
@@ -15,5 +15,5 @@ const defaults = {
15
15
  module.exports = (config, { strapi }) => {
16
16
  const { maxAge, path: faviconPath } = defaultsDeep(defaults, config);
17
17
 
18
- return favicon(resolve(strapi.dirs.root, faviconPath), { maxAge });
18
+ return favicon(resolve(strapi.dirs.app.root, faviconPath), { maxAge });
19
19
  };
@@ -80,7 +80,7 @@ module.exports = (config, { strapi }) => {
80
80
  {
81
81
  method: 'GET',
82
82
  path: '/(.*)',
83
- handler: koaStatic(strapi.dirs.public, {
83
+ handler: koaStatic(strapi.dirs.static.public, {
84
84
  maxage: maxAge,
85
85
  defer: true,
86
86
  }),