@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
@@ -2,10 +2,12 @@
2
2
 
3
3
  const { pickBy, has } = require('lodash/fp');
4
4
  const { createContentType } = require('../domain/content-type');
5
+ const { addNamespace, hasNamespace } = require('../utils');
5
6
 
6
7
  const validateKeySameToSingularName = contentTypes => {
7
8
  for (const ctName in contentTypes) {
8
9
  const contentType = contentTypes[ctName];
10
+
9
11
  if (ctName !== contentType.schema.info.singularName) {
10
12
  throw new Error(
11
13
  `The key of the content-type should be the same as its singularName. Found ${ctName} and ${contentType.schema.info.singularName}.`
@@ -18,22 +20,76 @@ const contentTypesRegistry = () => {
18
20
  const contentTypes = {};
19
21
 
20
22
  return {
21
- get(ctUID) {
22
- return contentTypes[ctUID];
23
+ /**
24
+ * Returns this list of registered contentTypes uids
25
+ * @returns {string[]}
26
+ */
27
+ keys() {
28
+ return Object.keys(contentTypes);
29
+ },
30
+
31
+ /**
32
+ * Returns the instance of a contentType. Instantiate the contentType if not already done
33
+ * @param {string} uid
34
+ * @returns
35
+ */
36
+ get(uid) {
37
+ return contentTypes[uid];
38
+ },
39
+
40
+ /**
41
+ * Returns a map with all the contentTypes in a namespace
42
+ * @param {string} namespace
43
+ */
44
+ getAll(namespace) {
45
+ return pickBy((_, uid) => hasNamespace(uid, namespace))(contentTypes);
23
46
  },
24
- getAll(prefix = '') {
25
- return pickBy((ct, ctUID) => ctUID.startsWith(prefix))(contentTypes);
47
+
48
+ /**
49
+ * Registers a contentType
50
+ * @param {string} uid
51
+ * @param {Object} contentType
52
+ */
53
+ set(uid, contentType) {
54
+ contentTypes[uid] = contentType;
55
+ return this;
26
56
  },
27
- add(namespace, rawContentTypes) {
28
- validateKeySameToSingularName(rawContentTypes);
29
- for (const rawCtName in rawContentTypes) {
30
- const rawContentType = rawContentTypes[rawCtName];
31
- const uid = `${namespace}.${rawContentType.schema.info.singularName}`;
57
+
58
+ /**
59
+ * Registers a map of contentTypes for a specific namespace
60
+ * @param {string} namespace
61
+ * @param {{ [key: string]: Object }} newContentTypes
62
+ */
63
+ add(namespace, newContentTypes) {
64
+ validateKeySameToSingularName(newContentTypes);
65
+
66
+ for (const rawCtName in newContentTypes) {
67
+ const uid = addNamespace(rawCtName, namespace);
68
+
32
69
  if (has(uid, contentTypes)) {
33
70
  throw new Error(`Content-type ${uid} has already been registered.`);
34
71
  }
35
- contentTypes[uid] = createContentType(uid, rawContentType);
72
+
73
+ contentTypes[uid] = createContentType(uid, newContentTypes[rawCtName]);
74
+ }
75
+ },
76
+
77
+ /**
78
+ * Wraps a contentType to extend it
79
+ * @param {string} uid
80
+ * @param {(contentType: Object) => Object} extendFn
81
+ */
82
+ extend(ctUID, extendFn) {
83
+ const currentContentType = this.get(ctUID);
84
+
85
+ if (!currentContentType) {
86
+ throw new Error(`Content-Type ${ctUID} doesn't exist`);
36
87
  }
88
+
89
+ const newContentType = extendFn(currentContentType);
90
+ contentTypes[ctUID] = newContentType;
91
+
92
+ return this;
37
93
  },
38
94
  };
39
95
  };
@@ -0,0 +1,7 @@
1
+ import { Strapi } from '../../';
2
+
3
+ export type Controller = {
4
+ [key: string]: (...args: any) => any;
5
+ };
6
+
7
+ export type ControllerFactory = ({ strapi: Strapi }) => Controller;
@@ -1,29 +1,114 @@
1
1
  'use strict';
2
2
 
3
3
  const { pickBy, has } = require('lodash/fp');
4
+ const { addNamespace, hasNamespace } = require('../utils');
4
5
 
5
- const policiesRegistry = () => {
6
+ /**
7
+ * @typedef {import('./controllers').Controller} Controller
8
+ * @typedef {import('./controllers').ControllerFactory} ControllerFactory
9
+ */
10
+
11
+ const controllersRegistry = () => {
6
12
  const controllers = {};
13
+ const instances = {};
7
14
 
8
15
  return {
9
- get(controllerUID) {
10
- return controllers[controllerUID];
16
+ /**
17
+ * Returns this list of registered controllers uids
18
+ * @returns {string[]}
19
+ */
20
+ keys() {
21
+ return Object.keys(controllers);
11
22
  },
12
- getAll(prefix = '') {
13
- return pickBy((controller, controllerUID) => controllerUID.startsWith(prefix))(controllers);
23
+
24
+ /**
25
+ * Returns the instance of a controller. Instantiate the controller if not already done
26
+ * @param {string} uid
27
+ * @returns {Controller}
28
+ */
29
+ get(uid) {
30
+ if (instances[uid]) {
31
+ return instances[uid];
32
+ }
33
+
34
+ const controller = controllers[uid];
35
+
36
+ if (controller) {
37
+ instances[uid] = typeof controller === 'function' ? controller({ strapi }) : controller;
38
+ return instances[uid];
39
+ }
40
+ },
41
+
42
+ /**
43
+ * Returns a map with all the controller in a namespace
44
+ * @param {string} namespace
45
+ * @returns {{ [key: string]: Controller }}
46
+ */
47
+ getAll(namespace) {
48
+ const filteredControllers = pickBy((_, uid) => hasNamespace(uid, namespace))(controllers);
49
+
50
+ const map = {};
51
+ for (const uid in filteredControllers) {
52
+ Object.defineProperty(map, uid, {
53
+ enumerable: true,
54
+ get: () => {
55
+ return this.get(uid);
56
+ },
57
+ });
58
+ }
59
+
60
+ return map;
14
61
  },
62
+
63
+ /**
64
+ * Registers a controller
65
+ * @param {string} uid
66
+ * @param {Controller} controller
67
+ */
68
+ set(uid, value) {
69
+ controllers[uid] = value;
70
+ delete instances[uid];
71
+ return this;
72
+ },
73
+
74
+ /**
75
+ * Registers a map of controllers for a specific namespace
76
+ * @param {string} namespace
77
+ * @param {{ [key: string]: Controller|ControllerFactory }} newControllers
78
+ * @returns
79
+ */
15
80
  add(namespace, newControllers) {
16
81
  for (const controllerName in newControllers) {
17
82
  const controller = newControllers[controllerName];
18
- const uid = `${namespace}.${controllerName}`;
83
+ const uid = addNamespace(controllerName, namespace);
19
84
 
20
85
  if (has(uid, controllers)) {
21
86
  throw new Error(`Controller ${uid} has already been registered.`);
22
87
  }
23
88
  controllers[uid] = controller;
24
89
  }
90
+
91
+ return this;
92
+ },
93
+
94
+ /**
95
+ * Wraps a controller to extend it
96
+ * @param {string} uid
97
+ * @param {(controller: Controller) => Controller} extendFn
98
+ */
99
+ extend(controllerUID, extendFn) {
100
+ const currentController = this.get(controllerUID);
101
+
102
+ if (!currentController) {
103
+ throw new Error(`Controller ${controllerUID} doesn't exist`);
104
+ }
105
+
106
+ const newController = extendFn(currentController);
107
+ instances[controllerUID] = newController;
108
+
109
+ return this;
25
110
  },
26
111
  };
27
112
  };
28
113
 
29
- module.exports = policiesRegistry;
114
+ module.exports = controllersRegistry;
@@ -0,0 +1,20 @@
1
+
2
+ type Handler = (context: any) => any;
3
+
4
+ type AsyncHook = {
5
+ handlers: Handler[];
6
+ register(handler: Handler): this;
7
+ delete(handler: Handler): this;
8
+ call(): Promise<void>;
9
+ };
10
+
11
+
12
+ type SyncHook = {
13
+ get handlers(): Handler[];
14
+ register(handler: Handler): this;
15
+ delete(handler: Handler): this;
16
+ call(): void;
17
+ };
18
+
19
+
20
+ export type Hook = AsyncHook|SyncHook
@@ -0,0 +1,87 @@
1
+ 'use strict';
2
+
3
+ const { pickBy } = require('lodash/fp');
4
+ const { addNamespace, hasNamespace } = require('../utils');
5
+
6
+ /**
7
+ * @typedef {import('./hooks').Hook} Hook
8
+ */
9
+
10
+ const hooksRegistry = () => {
11
+ const hooks = {};
12
+
13
+ return {
14
+ /**
15
+ * Returns this list of registered hooks uids
16
+ * @returns {string[]}
17
+ */
18
+ keys() {
19
+ return Object.keys(hooks);
20
+ },
21
+
22
+ /**
23
+ * Returns the instance of a hook.
24
+ * @param {string} uid
25
+ * @returns {Hook}
26
+ */
27
+ get(uid) {
28
+ return hooks[uid];
29
+ },
30
+
31
+ /**
32
+ * Returns a map with all the hooks in a namespace
33
+ * @param {string} namespace
34
+ * @returns {{ [key: string]: Hook }}
35
+ */
36
+ getAll(namespace) {
37
+ return pickBy((_, uid) => hasNamespace(uid, namespace))(hooks);
38
+ },
39
+
40
+ /**
41
+ * Registers a hook
42
+ * @param {string} uid
43
+ * @param {Hook} hook
44
+ */
45
+ set(uid, hook) {
46
+ hooks[uid] = hook;
47
+ return this;
48
+ },
49
+
50
+ /**
51
+ * Registers a map of hooks for a specific namespace
52
+ * @param {string} namespace
53
+ * @param {{ [key: string]: Hook }} newHooks
54
+ * @returns
55
+ */
56
+ add(namespace, hooks) {
57
+ for (const hookName in hooks) {
58
+ const hook = hooks[hookName];
59
+ const uid = addNamespace(hookName, namespace);
60
+
61
+ this.set(uid, hook);
62
+ }
63
+
64
+ return this;
65
+ },
66
+
67
+ /**
68
+ * Wraps a hook to extend it
69
+ * @param {string} uid
70
+ * @param {(hook: Hook) => Hook} extendFn
71
+ */
72
+ extend(uid, extendFn) {
73
+ const currentHook = this.get(uid);
74
+
75
+ if (!currentHook) {
76
+ throw new Error(`Hook ${uid} doesn't exist`);
77
+ }
78
+
79
+ const newHook = extendFn(currentHook);
80
+ hooks[uid] = newHook;
81
+
82
+ return this;
83
+ },
84
+ };
85
+ };
86
+
87
+ module.exports = hooksRegistry;
@@ -0,0 +1,5 @@
1
+ import { BaseContext, Middleware as KoaMiddleware } from 'koa';
2
+ import { Strapi } from '../../';
3
+ import { MiddlewareFactory } from '../../middlewares';
4
+
5
+ export type Middleware = KoaMiddleware | MiddlewareFactory;
@@ -1,21 +1,63 @@
1
1
  'use strict';
2
2
 
3
3
  const { pickBy, has } = require('lodash/fp');
4
+ const { addNamespace, hasNamespace } = require('../utils');
4
5
 
6
+ /**
7
+ * @typedef {import('./middlewares').Middleware} Middleware
8
+ */
9
+
10
+ // TODO: move instantiation part here instead of in the server service
5
11
  const middlewaresRegistry = () => {
6
12
  const middlewares = {};
7
13
 
8
14
  return {
9
- get(middlewareUID) {
10
- return middlewares[middlewareUID];
15
+ /**
16
+ * Returns this list of registered middlewares uids
17
+ * @returns {string[]}
18
+ */
19
+ keys() {
20
+ return Object.keys(middlewares);
21
+ },
22
+
23
+ /**
24
+ * Returns the instance of a middleware. Instantiate the middleware if not already done
25
+ * @param {string} uid
26
+ * @returns {Middleware}
27
+ */
28
+ get(uid) {
29
+ return middlewares[uid];
11
30
  },
12
- getAll(prefix = '') {
13
- return pickBy((middleware, middlewareUID) => middlewareUID.startsWith(prefix))(middlewares);
31
+
32
+ /**
33
+ * Returns a map with all the middlewares in a namespace
34
+ * @param {string} namespace
35
+ * @returns {{ [key: string]: Middleware }}
36
+ */
37
+ getAll(namespace) {
38
+ return pickBy((_, uid) => hasNamespace(uid, namespace))(middlewares);
14
39
  },
40
+
41
+ /**
42
+ * Registers a middleware
43
+ * @param {string} uid
44
+ * @param {Middleware} middleware
45
+ */
46
+ set(uid, middleware) {
47
+ middlewares[uid] = middleware;
48
+ return this;
49
+ },
50
+
51
+ /**
52
+ * Registers a map of middlewares for a specific namespace
53
+ * @param {string} namespace
54
+ * @param {{ [key: string]: Middleware }} newMiddlewares
55
+ * @returns
56
+ */
15
57
  add(namespace, rawMiddlewares) {
16
58
  for (const middlewareName in rawMiddlewares) {
17
59
  const middleware = rawMiddlewares[middlewareName];
18
- const uid = `${namespace}.${middlewareName}`;
60
+ const uid = addNamespace(middlewareName, namespace);
19
61
 
20
62
  if (has(uid, middlewares)) {
21
63
  throw new Error(`Middleware ${uid} has already been registered.`);
@@ -23,6 +65,24 @@ const middlewaresRegistry = () => {
23
65
  middlewares[uid] = middleware;
24
66
  }
25
67
  },
68
+
69
+ /**
70
+ * Wraps a middleware to extend it
71
+ * @param {string} uid
72
+ * @param {(middleware: Middleware) => Middleware} extendFn
73
+ */
74
+ extend(uid, extendFn) {
75
+ const currentMiddleware = this.get(uid);
76
+
77
+ if (!currentMiddleware) {
78
+ throw new Error(`Middleware ${uid} doesn't exist`);
79
+ }
80
+
81
+ const newMiddleware = extendFn(currentMiddleware);
82
+ middlewares[uid] = newMiddleware;
83
+
84
+ return this;
85
+ },
26
86
  };
27
87
  };
28
88
 
@@ -25,17 +25,17 @@ const modulesRegistry = strapi => {
25
25
  },
26
26
  async bootstrap() {
27
27
  for (const mod of Object.values(modules)) {
28
- await mod.bootstrap(strapi);
28
+ await mod.bootstrap();
29
29
  }
30
30
  },
31
31
  async register() {
32
32
  for (const mod of Object.values(modules)) {
33
- await mod.register(strapi);
33
+ await mod.register();
34
34
  }
35
35
  },
36
36
  async destroy() {
37
37
  for (const mod of Object.values(modules)) {
38
- await mod.destroy(strapi);
38
+ await mod.destroy();
39
39
  }
40
40
  },
41
41
  };
@@ -17,8 +17,8 @@ const pluginsRegistry = strapi => {
17
17
  throw new Error(`Plugin ${name} has already been registered.`);
18
18
  }
19
19
 
20
- const moduleInstance = strapi.container.get('modules').add(`plugin::${name}`, pluginConfig);
21
- plugins[name] = moduleInstance;
20
+ const pluginModule = strapi.container.get('modules').add(`plugin::${name}`, pluginConfig);
21
+ plugins[name] = pluginModule;
22
22
 
23
23
  return plugins[name];
24
24
  },
@@ -0,0 +1,9 @@
1
+ import { BaseContext } from 'koa';
2
+ import { Strapi } from '../../';
3
+
4
+ interface PolicyContext extends BaseContext {
5
+ type: string;
6
+ is(name): boolean;
7
+ }
8
+
9
+ export type Policy = (ctx: PolicyContext, { strapi: Strapi }) => boolean | undefined;
@@ -1,21 +1,63 @@
1
1
  'use strict';
2
2
 
3
3
  const { pickBy, has } = require('lodash/fp');
4
+ const { addNamespace, hasNamespace } = require('../utils');
4
5
 
6
+ /**
7
+ * @typedef {import('./policies').Policy} Policy
8
+ */
9
+
10
+ // TODO: move instantiation part here instead of in the policy utils
5
11
  const policiesRegistry = () => {
6
12
  const policies = {};
7
13
 
8
14
  return {
9
- get(policyUID) {
10
- return policies[policyUID];
15
+ /**
16
+ * Returns this list of registered policies uids
17
+ * @returns {string[]}
18
+ */
19
+ keys() {
20
+ return Object.keys(policies);
21
+ },
22
+
23
+ /**
24
+ * Returns the instance of a policy. Instantiate the policy if not already done
25
+ * @param {string} uid
26
+ * @returns {Policy}
27
+ */
28
+ get(uid) {
29
+ return policies[uid];
11
30
  },
12
- getAll(prefix = '') {
13
- return pickBy((policy, policyUID) => policyUID.startsWith(prefix))(policies);
31
+
32
+ /**
33
+ * Returns a map with all the policies in a namespace
34
+ * @param {string} namespace
35
+ * @returns {{ [key: string]: Policy }}
36
+ */
37
+ getAll(namespace) {
38
+ return pickBy((_, uid) => hasNamespace(uid, namespace))(policies);
14
39
  },
40
+
41
+ /**
42
+ * Registers a policy
43
+ * @param {string} uid
44
+ * @param {Policy} policy
45
+ */
46
+ set(uid, policy) {
47
+ policies[uid] = policy;
48
+ return this;
49
+ },
50
+
51
+ /**
52
+ * Registers a map of policies for a specific namespace
53
+ * @param {string} namespace
54
+ * @param {{ [key: string]: Policy }} newPolicies
55
+ * @returns
56
+ */
15
57
  add(namespace, newPolicies) {
16
58
  for (const policyName in newPolicies) {
17
59
  const policy = newPolicies[policyName];
18
- const uid = `${namespace}.${policyName}`;
60
+ const uid = addNamespace(policyName, namespace);
19
61
 
20
62
  if (has(uid, policies)) {
21
63
  throw new Error(`Policy ${uid} has already been registered.`);
@@ -23,6 +65,24 @@ const policiesRegistry = () => {
23
65
  policies[uid] = policy;
24
66
  }
25
67
  },
68
+
69
+ /**
70
+ * Wraps a policy to extend it
71
+ * @param {string} uid
72
+ * @param {(policy: Policy) => Policy} extendFn
73
+ */
74
+ extend(uid, extendFn) {
75
+ const currentPolicy = this.get(uid);
76
+
77
+ if (!currentPolicy) {
78
+ throw new Error(`Policy ${uid} doesn't exist`);
79
+ }
80
+
81
+ const newPolicy = extendFn(currentPolicy);
82
+ policies[uid] = newPolicy;
83
+
84
+ return this;
85
+ },
26
86
  };
27
87
  };
28
88
 
@@ -0,0 +1,7 @@
1
+ import { Strapi } from '../../';
2
+
3
+ export type Service = {
4
+ [key: string]: (...args: any) => any;
5
+ };
6
+
7
+ export type ServiceFactory = ({ strapi: Strapi }) => Service;