@strapi/strapi 4.0.0-next.8 → 4.0.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.
Files changed (147) hide show
  1. package/README.md +14 -14
  2. package/bin/strapi.js +46 -60
  3. package/lib/Strapi.js +152 -74
  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 -19
  18. package/lib/core/bootstrap.js +3 -95
  19. package/lib/core/domain/content-type/index.js +5 -11
  20. package/lib/core/domain/module/index.js +42 -11
  21. package/lib/core/domain/module/validation.js +16 -19
  22. package/lib/core/loaders/admin.js +2 -2
  23. package/lib/core/loaders/apis.js +148 -9
  24. package/lib/core/loaders/components.js +4 -6
  25. package/lib/core/loaders/index.js +1 -0
  26. package/lib/core/loaders/middlewares.js +23 -123
  27. package/lib/core/loaders/plugins/get-enabled-plugins.js +55 -19
  28. package/lib/core/loaders/plugins/get-user-plugins-config.js +37 -0
  29. package/lib/core/loaders/plugins/index.js +30 -16
  30. package/lib/core/loaders/policies.js +1 -1
  31. package/lib/core/loaders/src-index.js +39 -0
  32. package/lib/core/registries/apis.js +29 -0
  33. package/lib/core/registries/content-types.js +61 -12
  34. package/lib/core/registries/controllers.d.ts +7 -0
  35. package/lib/core/registries/controllers.js +91 -7
  36. package/lib/core/registries/hooks.d.ts +20 -0
  37. package/lib/core/registries/hooks.js +87 -0
  38. package/lib/core/registries/middlewares.d.ts +5 -0
  39. package/lib/core/registries/middlewares.js +64 -5
  40. package/lib/core/registries/modules.js +3 -3
  41. package/lib/core/registries/plugins.js +2 -2
  42. package/lib/core/registries/policies.d.ts +9 -0
  43. package/lib/core/registries/policies.js +64 -5
  44. package/lib/core/registries/services.d.ts +7 -0
  45. package/lib/core/registries/services.js +86 -17
  46. package/lib/core/utils.js +22 -0
  47. package/lib/core-api/controller/collection-type.js +45 -26
  48. package/lib/core-api/controller/index.d.ts +25 -0
  49. package/lib/core-api/controller/index.js +33 -11
  50. package/lib/core-api/controller/single-type.js +29 -15
  51. package/lib/core-api/controller/transform.js +62 -6
  52. package/lib/core-api/routes/index.js +71 -0
  53. package/lib/core-api/service/collection-type.js +43 -21
  54. package/lib/core-api/service/index.d.ts +21 -0
  55. package/lib/core-api/service/index.js +8 -67
  56. package/lib/core-api/service/pagination.js +125 -0
  57. package/lib/core-api/service/single-type.js +17 -19
  58. package/lib/factories.d.ts +48 -0
  59. package/lib/factories.js +84 -0
  60. package/lib/index.d.ts +10 -31
  61. package/lib/index.js +5 -1
  62. package/lib/middlewares/body.js +33 -0
  63. package/lib/middlewares/compression.js +8 -0
  64. package/lib/middlewares/cors.js +58 -0
  65. package/lib/middlewares/errors.js +40 -0
  66. package/lib/middlewares/favicon.js +19 -0
  67. package/lib/middlewares/index.d.ts +5 -0
  68. package/lib/middlewares/index.js +30 -116
  69. package/lib/middlewares/ip.js +8 -0
  70. package/lib/middlewares/logger.js +27 -0
  71. package/lib/middlewares/powered-by.js +20 -0
  72. package/lib/middlewares/public/index.js +72 -77
  73. package/lib/middlewares/query.js +46 -0
  74. package/lib/middlewares/response-time.js +15 -0
  75. package/lib/middlewares/responses.js +19 -0
  76. package/lib/middlewares/security.js +51 -0
  77. package/lib/middlewares/session/index.js +6 -6
  78. package/lib/migrations/draft-publish.js +57 -0
  79. package/lib/services/auth/index.js +87 -0
  80. package/lib/services/core-store.js +64 -49
  81. package/lib/services/cron.js +54 -0
  82. package/lib/services/entity-service/attributes/index.js +31 -0
  83. package/lib/services/entity-service/attributes/transforms.js +20 -0
  84. package/lib/services/entity-service/components.js +39 -15
  85. package/lib/services/entity-service/index.d.ts +91 -0
  86. package/lib/services/entity-service/index.js +118 -60
  87. package/lib/services/entity-service/params.js +52 -94
  88. package/lib/services/entity-validator/index.js +76 -43
  89. package/lib/services/entity-validator/validators.js +131 -43
  90. package/lib/services/errors.js +77 -0
  91. package/lib/services/fs.js +1 -1
  92. package/lib/services/metrics/index.js +38 -36
  93. package/lib/services/server/admin-api.js +14 -0
  94. package/lib/services/server/api.js +36 -0
  95. package/lib/services/server/compose-endpoint.js +141 -0
  96. package/lib/services/server/content-api.js +16 -0
  97. package/lib/{server.js → services/server/http-server.js} +0 -0
  98. package/lib/services/server/index.js +127 -0
  99. package/lib/services/server/koa.js +64 -0
  100. package/lib/services/server/middleware.js +122 -0
  101. package/lib/services/server/policy.js +32 -0
  102. package/lib/services/server/register-middlewares.js +110 -0
  103. package/lib/services/server/register-routes.js +106 -0
  104. package/lib/services/server/routing.js +120 -0
  105. package/lib/services/webhook-runner.js +1 -1
  106. package/lib/utils/ee.js +3 -3
  107. package/lib/utils/get-dirs.js +17 -0
  108. package/lib/utils/index.js +2 -0
  109. package/lib/utils/signals.js +24 -0
  110. package/lib/utils/update-notifier/index.js +2 -1
  111. package/package.json +94 -97
  112. package/lib/commands/generate.js +0 -76
  113. package/lib/core/app-configuration/load-functions.js +0 -28
  114. package/lib/core-api/index.js +0 -39
  115. package/lib/load/check-reserved-filename.js +0 -10
  116. package/lib/load/load-config-files.js +0 -22
  117. package/lib/load/require-file-parse.js +0 -15
  118. package/lib/middlewares/boom/defaults.json +0 -5
  119. package/lib/middlewares/boom/index.js +0 -147
  120. package/lib/middlewares/cors/index.js +0 -66
  121. package/lib/middlewares/cron/defaults.json +0 -5
  122. package/lib/middlewares/cron/index.js +0 -43
  123. package/lib/middlewares/favicon/defaults.json +0 -7
  124. package/lib/middlewares/favicon/index.js +0 -32
  125. package/lib/middlewares/gzip/defaults.json +0 -6
  126. package/lib/middlewares/gzip/index.js +0 -19
  127. package/lib/middlewares/helmet/defaults.json +0 -18
  128. package/lib/middlewares/helmet/index.js +0 -9
  129. package/lib/middlewares/ip/defaults.json +0 -7
  130. package/lib/middlewares/ip/index.js +0 -25
  131. package/lib/middlewares/language/defaults.json +0 -9
  132. package/lib/middlewares/language/index.js +0 -40
  133. package/lib/middlewares/logger/defaults.json +0 -5
  134. package/lib/middlewares/logger/index.js +0 -37
  135. package/lib/middlewares/parser/defaults.json +0 -11
  136. package/lib/middlewares/parser/index.js +0 -71
  137. package/lib/middlewares/poweredBy/defaults.json +0 -5
  138. package/lib/middlewares/poweredBy/index.js +0 -16
  139. package/lib/middlewares/public/defaults.json +0 -8
  140. package/lib/middlewares/responseTime/defaults.json +0 -5
  141. package/lib/middlewares/responseTime/index.js +0 -25
  142. package/lib/middlewares/responses/defaults.json +0 -5
  143. package/lib/middlewares/responses/index.js +0 -18
  144. package/lib/middlewares/router/defaults.json +0 -7
  145. package/lib/middlewares/router/index.js +0 -58
  146. package/lib/middlewares/router/utils/composeEndpoint.js +0 -177
  147. package/lib/utils/get-prefixed-dependencies.js +0 -7
@@ -0,0 +1,71 @@
1
+ 'use strict';
2
+
3
+ const { isSingleType } = require('@strapi/utils').contentTypes;
4
+
5
+ const createRoutes = ({ contentType }) => {
6
+ if (isSingleType(contentType)) {
7
+ return getSingleTypeRoutes(contentType);
8
+ }
9
+
10
+ return getCollectionTypeRoutes(contentType);
11
+ };
12
+
13
+ const getSingleTypeRoutes = ({ uid, info }) => {
14
+ return {
15
+ find: {
16
+ method: 'GET',
17
+ path: `/${info.singularName}`,
18
+ handler: `${uid}.find`,
19
+ config: {},
20
+ },
21
+ update: {
22
+ method: 'PUT',
23
+ path: `/${info.singularName}`,
24
+ handler: `${uid}.update`,
25
+ config: {},
26
+ },
27
+ delete: {
28
+ method: 'DELETE',
29
+ path: `/${info.singularName}`,
30
+ handler: `${uid}.delete`,
31
+ config: {},
32
+ },
33
+ };
34
+ };
35
+
36
+ const getCollectionTypeRoutes = ({ uid, info }) => {
37
+ return {
38
+ find: {
39
+ method: 'GET',
40
+ path: `/${info.pluralName}`,
41
+ handler: `${uid}.find`,
42
+ config: {},
43
+ },
44
+ findOne: {
45
+ method: 'GET',
46
+ path: `/${info.pluralName}/:id`,
47
+ handler: `${uid}.findOne`,
48
+ config: {},
49
+ },
50
+ create: {
51
+ method: 'POST',
52
+ path: `/${info.pluralName}`,
53
+ handler: `${uid}.create`,
54
+ config: {},
55
+ },
56
+ update: {
57
+ method: 'PUT',
58
+ path: `/${info.pluralName}/:id`,
59
+ handler: `${uid}.update`,
60
+ config: {},
61
+ },
62
+ delete: {
63
+ method: 'DELETE',
64
+ path: `/${info.pluralName}/:id`,
65
+ handler: `${uid}.delete`,
66
+ config: {},
67
+ },
68
+ };
69
+ };
70
+
71
+ module.exports = { createRoutes };
@@ -7,6 +7,13 @@ const {
7
7
  constants: { PUBLISHED_AT_ATTRIBUTE },
8
8
  } = require('@strapi/utils').contentTypes;
9
9
 
10
+ const {
11
+ getPaginationInfo,
12
+ convertPagedToStartLimit,
13
+ shouldCount,
14
+ transformPaginationResponse,
15
+ } = require('./pagination');
16
+
10
17
  const setPublishedAt = data => {
11
18
  data[PUBLISHED_AT_ATTRIBUTE] = propOr(new Date(), PUBLISHED_AT_ATTRIBUTE, data);
12
19
  };
@@ -15,42 +22,57 @@ const setPublishedAt = data => {
15
22
  *
16
23
  * Returns a collection type service to handle default core-api actions
17
24
  */
18
- const createCollectionTypeService = ({ model, strapi, utils }) => {
19
- const { uid } = model;
20
-
21
- const { sanitizeInput, getFetchParams } = utils;
25
+ const createCollectionTypeService = ({ contentType }) => {
26
+ const { uid } = contentType;
22
27
 
23
28
  return {
24
- find(opts = {}) {
25
- const params = getFetchParams(opts.params);
29
+ async find(params = {}) {
30
+ const fetchParams = this.getFetchParams(params);
26
31
 
27
- return strapi.entityService.findPage(uid, { params });
28
- },
32
+ const paginationInfo = getPaginationInfo(fetchParams);
33
+
34
+ const results = await strapi.entityService.findMany(uid, {
35
+ ...fetchParams,
36
+ ...convertPagedToStartLimit(paginationInfo),
37
+ });
29
38
 
30
- findOne(entityId, opts = {}) {
31
- const params = getFetchParams(opts.params);
39
+ if (shouldCount(fetchParams)) {
40
+ const count = await strapi.entityService.count(uid, { ...fetchParams, ...paginationInfo });
41
+
42
+ return {
43
+ results,
44
+ pagination: transformPaginationResponse(paginationInfo, count),
45
+ };
46
+ }
47
+
48
+ return {
49
+ results,
50
+ pagination: paginationInfo,
51
+ };
52
+ },
32
53
 
33
- return strapi.entityService.findOne(uid, entityId, { params });
54
+ findOne(entityId, params = {}) {
55
+ return strapi.entityService.findOne(uid, entityId, this.getFetchParams(params));
34
56
  },
35
57
 
36
- create({ params, data, files } = {}) {
37
- const sanitizedData = sanitizeInput(data);
58
+ create(params = {}) {
59
+ const { data } = params;
38
60
 
39
- if (hasDraftAndPublish(model)) {
40
- setPublishedAt(sanitizedData);
61
+ if (hasDraftAndPublish(contentType)) {
62
+ setPublishedAt(data);
41
63
  }
42
64
 
43
- return strapi.entityService.create(uid, { params, data: sanitizedData, files });
65
+ return strapi.entityService.create(uid, { ...params, data });
44
66
  },
45
67
 
46
- update(entityId, { params, data, files } = {}) {
47
- const sanitizedData = sanitizeInput(data);
68
+ update(entityId, params = {}) {
69
+ const { data } = params;
48
70
 
49
- return strapi.entityService.update(uid, entityId, { params, data: sanitizedData, files });
71
+ return strapi.entityService.update(uid, entityId, { ...params, data });
50
72
  },
51
73
 
52
- delete(entityId, { params } = {}) {
53
- return strapi.entityService.delete(uid, entityId, { params });
74
+ delete(entityId, params = {}) {
75
+ return strapi.entityService.delete(uid, entityId, params);
54
76
  },
55
77
  };
56
78
  };
@@ -0,0 +1,21 @@
1
+ type Entity = object;
2
+
3
+ interface BaseService {
4
+ getFetchParams(params: object): object;
5
+ }
6
+
7
+ export interface SingleTypeService extends BaseService {
8
+ find(params: object): Promise<Entity>;
9
+ createOrUpdate(params: object): Promise<Entity>;
10
+ delete(params: object): Promise<Entity>;
11
+ }
12
+
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>;
19
+ }
20
+
21
+ export type Service = SingleTypeService | CollectionTypeService;
@@ -1,10 +1,7 @@
1
1
  'use strict';
2
2
 
3
- const _ = require('lodash');
4
-
5
3
  const {
6
4
  isSingleType,
7
- getNonWritableAttributes,
8
5
  constants: { DP_PUB_STATE_LIVE },
9
6
  } = require('@strapi/utils').contentTypes;
10
7
 
@@ -16,62 +13,18 @@ const createCollectionTypeService = require('./collection-type');
16
13
  * @param {{ model: object, strapi: object }} context
17
14
  * @returns {object}
18
15
  */
19
- const createService = ({ model, strapi }) => {
20
- const utils = createUtils({ model });
21
-
22
- if (isSingleType(model)) {
23
- return createSingleTypeService({ model, strapi, utils });
24
- }
16
+ const createService = ({ contentType }) => {
17
+ const proto = { getFetchParams };
25
18
 
26
- return createCollectionTypeService({ model, strapi, utils });
27
- };
28
-
29
- /**
30
- * Default limit values from config
31
- * @return {{maxLimit: number, defaultLimit: number}}
32
- */
33
- const getLimitConfigDefaults = () => ({
34
- defaultLimit: _.toNumber(strapi.config.get('api.rest.defaultLimit', 100)),
35
- maxLimit: _.toNumber(strapi.config.get('api.rest.maxLimit')) || null,
36
- });
19
+ let service;
37
20
 
38
- /**
39
- * if there is max limit set and limit exceeds this number, return configured max limit
40
- * @param {number} limit - limit you want to cap
41
- * @param {number?} maxLimit - maxlimit used has capping
42
- * @returns {number}
43
- */
44
- const applyMaxLimit = (limit, maxLimit) => {
45
- if (maxLimit && (limit === -1 || limit > maxLimit)) {
46
- return maxLimit;
21
+ if (isSingleType(contentType)) {
22
+ service = createSingleTypeService({ contentType });
23
+ } else {
24
+ service = createCollectionTypeService({ contentType });
47
25
  }
48
26
 
49
- return limit;
50
- };
51
-
52
- const applyDefaultPagination = params => {
53
- const { defaultLimit, maxLimit } = getLimitConfigDefaults();
54
-
55
- if (_.isUndefined(params.pagination) || !_.isPlainObject(params.pagination)) {
56
- return {
57
- limit: defaultLimit,
58
- };
59
- }
60
-
61
- const { pagination } = params;
62
-
63
- if (!_.isUndefined(pagination.pageSize)) {
64
- return {
65
- page: pagination.page,
66
- pageSize: applyMaxLimit(_.toNumber(pagination.pageSize), maxLimit),
67
- };
68
- }
69
-
70
- const limit = _.isUndefined(pagination.limit) ? defaultLimit : _.toNumber(pagination.limit);
71
- return {
72
- start: pagination.start,
73
- limit: applyMaxLimit(limit, maxLimit),
74
- };
27
+ return Object.assign(Object.create(proto), service);
75
28
  };
76
29
 
77
30
  /**
@@ -83,18 +36,6 @@ const getFetchParams = (params = {}) => {
83
36
  return {
84
37
  publicationState: DP_PUB_STATE_LIVE,
85
38
  ...params,
86
- pagination: applyDefaultPagination(params),
87
- };
88
- };
89
-
90
- /**
91
- * Mixins
92
- */
93
- const createUtils = ({ model }) => {
94
- return {
95
- // make sure to keep the call to getNonWritableAttributes dynamic
96
- sanitizeInput: data => _.omit(data, getNonWritableAttributes(model)),
97
- getFetchParams,
98
39
  };
99
40
  };
100
41
 
@@ -0,0 +1,125 @@
1
+ 'use strict';
2
+
3
+ const { has, toNumber, isUndefined } = require('lodash/fp');
4
+ const { ValidationError } = require('@strapi/utils').errors;
5
+
6
+ /**
7
+ * Default limit values from config
8
+ * @return {{maxLimit: number, defaultLimit: number}}
9
+ */
10
+ const getLimitConfigDefaults = () => ({
11
+ defaultLimit: toNumber(strapi.config.get('api.rest.defaultLimit', 25)),
12
+ maxLimit: toNumber(strapi.config.get('api.rest.maxLimit')) || null,
13
+ });
14
+
15
+ /**
16
+ * Should maxLimit be used as the limit or not
17
+ * @param {number} limit - limit you want to cap
18
+ * @param {number?} maxLimit - maxlimit used has capping
19
+ * @returns {boolean}
20
+ */
21
+ const shouldApplyMaxLimit = (limit, maxLimit = null, { isPagedPagination = false } = {}) =>
22
+ (!isPagedPagination && limit === -1) || (maxLimit && limit > maxLimit);
23
+
24
+ const shouldCount = params => {
25
+ if (has('pagination.withCount', params)) {
26
+ const { withCount } = params.pagination;
27
+
28
+ if (typeof withCount === 'boolean') {
29
+ return withCount;
30
+ }
31
+
32
+ if (['true', 't', '1', 1].includes(withCount)) {
33
+ return true;
34
+ }
35
+
36
+ if (['false', 'f', '0', 0].includes(withCount)) {
37
+ return false;
38
+ }
39
+
40
+ throw new ValidationError(
41
+ 'Invalid withCount parameter. Expected "t","1","true","false","0","f"'
42
+ );
43
+ }
44
+
45
+ return Boolean(strapi.config.get('api.rest.withCount', true));
46
+ };
47
+
48
+ const isOffsetPagination = pagination => has('start', pagination) || has('limit', pagination);
49
+ const isPagedPagination = pagination => has('page', pagination) || has('pageSize', pagination);
50
+
51
+ const getPaginationInfo = params => {
52
+ const { defaultLimit, maxLimit } = getLimitConfigDefaults();
53
+
54
+ const { pagination } = params;
55
+
56
+ const isPaged = isPagedPagination(pagination);
57
+ const isOffset = isOffsetPagination(pagination);
58
+
59
+ if (!isPaged && !isOffset) {
60
+ return {
61
+ page: 1,
62
+ pageSize: defaultLimit,
63
+ };
64
+ }
65
+
66
+ if (isOffset && isPaged) {
67
+ throw new ValidationError(
68
+ 'Invalid pagination parameters. Expected either start/limit or page/pageSize'
69
+ );
70
+ }
71
+
72
+ if (isPagedPagination(pagination)) {
73
+ const pageSize = isUndefined(pagination.pageSize)
74
+ ? defaultLimit
75
+ : Math.max(1, toNumber(pagination.pageSize));
76
+
77
+ return {
78
+ page: Math.max(1, toNumber(pagination.page || 1)),
79
+ pageSize: shouldApplyMaxLimit(pageSize, maxLimit, { isPagedPagination: true })
80
+ ? maxLimit
81
+ : Math.max(1, pageSize),
82
+ };
83
+ }
84
+
85
+ const limit = isUndefined(pagination.limit) ? defaultLimit : toNumber(pagination.limit);
86
+
87
+ return {
88
+ start: Math.max(0, toNumber(pagination.start || 0)),
89
+ limit: shouldApplyMaxLimit(limit, maxLimit) ? maxLimit || -1 : Math.max(1, limit),
90
+ };
91
+ };
92
+
93
+ const convertPagedToStartLimit = pagination => {
94
+ if (isPagedPagination(pagination)) {
95
+ const { page, pageSize } = pagination;
96
+ return {
97
+ start: (page - 1) * pageSize,
98
+ limit: pageSize,
99
+ };
100
+ }
101
+
102
+ return pagination;
103
+ };
104
+
105
+ const transformPaginationResponse = (paginationInfo, count) => {
106
+ if (paginationInfo.page) {
107
+ return {
108
+ ...paginationInfo,
109
+ pageCount: Math.ceil(count / paginationInfo.pageSize),
110
+ total: count,
111
+ };
112
+ }
113
+
114
+ return {
115
+ ...paginationInfo,
116
+ total: count,
117
+ };
118
+ };
119
+
120
+ module.exports = {
121
+ getPaginationInfo,
122
+ convertPagedToStartLimit,
123
+ transformPaginationResponse,
124
+ shouldCount,
125
+ };
@@ -1,20 +1,24 @@
1
1
  'use strict';
2
2
 
3
+ const { ValidationError } = require('@strapi/utils').errors;
4
+
3
5
  /**
4
6
  * Returns a single type service to handle default core-api actions
5
7
  */
6
- const createSingleTypeService = ({ model, strapi, utils }) => {
7
- const { uid } = model;
8
- const { sanitizeInput, getFetchParams } = utils;
8
+ const createSingleTypeService = ({ contentType }) => {
9
+ const { uid } = contentType;
9
10
 
11
+ /**
12
+ * @type {import('./').SingleTypeService}
13
+ */
10
14
  return {
11
15
  /**
12
16
  * Returns singleType content
13
17
  *
14
18
  * @return {Promise}
15
19
  */
16
- find({ params } = {}) {
17
- return strapi.entityService.find(uid, { params: getFetchParams(params) });
20
+ find(params = {}) {
21
+ return strapi.entityService.findMany(uid, this.getFetchParams(params));
18
22
  },
19
23
 
20
24
  /**
@@ -22,25 +26,19 @@ const createSingleTypeService = ({ model, strapi, utils }) => {
22
26
  *
23
27
  * @return {Promise}
24
28
  */
25
- async createOrUpdate({ params, data, files } = {}) {
26
- const entity = await this.find({ params });
27
-
28
- const sanitizedData = sanitizeInput(data);
29
+ async createOrUpdate({ data, ...params } = {}) {
30
+ const entity = await this.find(params);
29
31
 
30
32
  if (!entity) {
31
33
  const count = await strapi.query(uid).count();
32
34
  if (count >= 1) {
33
- throw strapi.errors.badRequest('singleType.alreadyExists');
35
+ throw new ValidationError('singleType.alreadyExists');
34
36
  }
35
37
 
36
- return strapi.entityService.create(uid, { params, data: sanitizedData, files });
37
- } else {
38
- return strapi.entityService.update(uid, entity.id, {
39
- params,
40
- data: sanitizedData,
41
- files,
42
- });
38
+ return strapi.entityService.create(uid, { ...params, data });
43
39
  }
40
+
41
+ return strapi.entityService.update(uid, entity.id, { ...params, data });
44
42
  },
45
43
 
46
44
  /**
@@ -48,8 +46,8 @@ const createSingleTypeService = ({ model, strapi, utils }) => {
48
46
  *
49
47
  * @return {Promise}
50
48
  */
51
- async delete({ params } = {}) {
52
- const entity = await this.find({ params });
49
+ async delete(params = {}) {
50
+ const entity = await this.find(params);
53
51
 
54
52
  if (!entity) return;
55
53
 
@@ -0,0 +1,48 @@
1
+ import { Service } from './core-api/service';
2
+ import { Controller } from './core-api/controller';
3
+ import { Middleware } from './middlewares';
4
+ import { Policy } from './core/registries/policies';
5
+
6
+ type ControllerConfig = Controller;
7
+
8
+ type ServiceConfig = Service;
9
+
10
+ type HandlerConfig = {
11
+ auth: false | { scope: string[] };
12
+ policies: Array<string | Policy>;
13
+ middlewares: Array<string | Middleware>;
14
+ };
15
+
16
+ type SingleTypeRouterConfig = {
17
+ find: HandlerConfig;
18
+ update: HandlerConfig;
19
+ delete: HandlerConfig;
20
+ };
21
+
22
+ type CollectionTypeRouterConfig = {
23
+ find: HandlerConfig;
24
+ findOne: HandlerConfig;
25
+ create: HandlerConfig;
26
+ update: HandlerConfig;
27
+ delete: HandlerConfig;
28
+ };
29
+
30
+ type RouterConfig = {
31
+ prefix: string;
32
+ only: string[];
33
+ except: string[];
34
+ config: SingleTypeRouterConfig | CollectionTypeRouterConfig;
35
+ };
36
+
37
+ interface Route {
38
+ method: string;
39
+ path: string;
40
+ }
41
+ interface Router {
42
+ prefix: string;
43
+ routes: Route[];
44
+ }
45
+
46
+ export function createCoreRouter(uid: string, cfg: RouterConfig): () => Router;
47
+ export function createCoreController(uid: string, cfg: ControllerConfig): () => Controller;
48
+ export function createCoreService(uid: string, cfg: ServiceConfig): () => Service;
@@ -0,0 +1,84 @@
1
+ 'use strict';
2
+
3
+ const { pipe, omit, pick } = require('lodash/fp');
4
+
5
+ const { createController } = require('./core-api/controller');
6
+ const { createService } = require('./core-api/service');
7
+ const { createRoutes } = require('./core-api/routes');
8
+
9
+ const createCoreController = (uid, cfg = {}) => {
10
+ return ({ strapi }) => {
11
+ const baseController = createController({
12
+ contentType: strapi.contentType(uid),
13
+ });
14
+
15
+ let userCtrl = typeof cfg === 'function' ? cfg({ strapi }) : cfg;
16
+
17
+ for (const methodName of Object.keys(baseController)) {
18
+ if (userCtrl[methodName] === undefined) {
19
+ userCtrl[methodName] = baseController[methodName];
20
+ }
21
+ }
22
+
23
+ Object.setPrototypeOf(userCtrl, baseController);
24
+ return userCtrl;
25
+ };
26
+ };
27
+
28
+ const createCoreService = (uid, cfg = {}) => {
29
+ return ({ strapi }) => {
30
+ const baseService = createService({
31
+ contentType: strapi.contentType(uid),
32
+ });
33
+
34
+ let userService = typeof cfg === 'function' ? cfg({ strapi }) : cfg;
35
+
36
+ for (const methodName of Object.keys(baseService)) {
37
+ if (userService[methodName] === undefined) {
38
+ userService[methodName] = baseService[methodName];
39
+ }
40
+ }
41
+
42
+ Object.setPrototypeOf(userService, baseService);
43
+ return userService;
44
+ };
45
+ };
46
+
47
+ const createCoreRouter = (uid, cfg = {}) => {
48
+ const { prefix, config = {}, only, except } = cfg;
49
+ let routes;
50
+
51
+ return {
52
+ get prefix() {
53
+ return prefix;
54
+ },
55
+ get routes() {
56
+ if (!routes) {
57
+ const contentType = strapi.contentType(uid);
58
+
59
+ const defaultRoutes = createRoutes({ contentType });
60
+
61
+ Object.keys(defaultRoutes).forEach(routeName => {
62
+ const defaultRoute = defaultRoutes[routeName];
63
+
64
+ Object.assign(defaultRoute.config, config[routeName] || {});
65
+ });
66
+
67
+ const selectedRoutes = pipe(
68
+ routes => (except ? omit(except, routes) : routes),
69
+ routes => (only ? pick(only, routes) : routes)
70
+ )(defaultRoutes);
71
+
72
+ routes = Object.values(selectedRoutes);
73
+ }
74
+
75
+ return routes;
76
+ },
77
+ };
78
+ };
79
+
80
+ module.exports = {
81
+ createCoreController,
82
+ createCoreService,
83
+ createCoreRouter,
84
+ };
package/lib/index.d.ts CHANGED
@@ -1,40 +1,15 @@
1
1
  import { Database } from '@strapi/database';
2
- import { Strapi } from './Strapi';
2
+ import { EntityService } from './services/entity-service';
3
+ import { Strapi as StrapiClass } from './Strapi';
3
4
 
4
- type ID = number | string;
5
-
6
- interface Options<T> {
7
- params: Params<T>;
8
- }
9
-
10
- interface Params<T> {
11
- fields: (keyof T)[];
12
- }
13
-
14
- interface EntityService {
15
- uploadFiles<T extends keyof AllTypes>(uid: T);
16
- wrapOptions<T extends keyof AllTypes>(uid: T);
17
-
18
- find<T extends keyof AllTypes>(uid: T): Promise<AllTypes[T][]>;
19
- findPage<T extends keyof AllTypes>(uid: T): Promise<any>;
20
- findWithRelationCounts<T extends keyof AllTypes>(uid: T): Promise<any>;
21
- findOne<T extends keyof AllTypes>(
22
- uid: T,
23
- id: ID,
24
- opts: Options<AllTypes[T]>
25
- ): Promise<AllTypes[T]>;
26
-
27
- count<T extends keyof AllTypes>(uid: T): Promise<any>;
28
- create<T extends keyof AllTypes>(uid: T): Promise<any>;
29
- update<T extends keyof AllTypes>(uid: T): Promise<any>;
30
- delete<T extends keyof AllTypes>(uid: T): Promise<any>;
31
- }
32
-
33
- interface StrapiInterface extends Strapi {
5
+ export * as factories from './factories';
6
+ interface StrapiInterface extends StrapiClass {
34
7
  query: Database['query'];
35
8
  entityService: EntityService;
36
9
  }
37
10
 
11
+ export type Strapi = StrapiInterface;
12
+
38
13
  declare global {
39
14
  interface AllTypes {}
40
15
  }
@@ -44,5 +19,9 @@ declare global {
44
19
  strapi: StrapiInterface;
45
20
  }
46
21
 
22
+ export type Strapi = StrapiInterface;
23
+
47
24
  const strapi: StrapiInterface;
48
25
  }
26
+
27
+ export default function(opts): Strapi;
package/lib/index.js CHANGED
@@ -1,3 +1,7 @@
1
1
  'use strict';
2
2
 
3
- module.exports = require('./Strapi');
3
+ const Strapi = require('./Strapi');
4
+
5
+ Strapi.factories = require('./factories');
6
+
7
+ module.exports = Strapi;