strapi-plugin-comments 2.2.17 → 2.3.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.
package/README.md CHANGED
@@ -372,6 +372,12 @@ Return a flat structure of comments by specified Author for example `Author` wit
372
372
  **Example URL**: `https://localhost:1337/api/comments/author/1` - get comments by `ID:1` of Strapi User
373
373
  **Example URL**: `https://localhost:1337/api/comments/author/1/generic` - get comments by `ID:1` of Generic User
374
374
 
375
+ #### Skipping fields
376
+
377
+ To skip a field from the response you can use a query param called `omit`. It is a list of `Comment` entity fields you want to ignore. For example `?omit[]=author&omit[]=related`.
378
+
379
+ **Remember!** `id` field is required so it will not be skipped.
380
+
375
381
  **Example response body**
376
382
 
377
383
  ```json
@@ -931,6 +937,46 @@ For developers who upgrades their Strapi instance custom field from Comments plu
931
937
 
932
938
  Read more about this feature in [Strapi's docs](https://docs-next.strapi.io/user-docs/latest/plugins/introduction-to-plugins.html#custom-fields).
933
939
 
940
+ ## Model lifecycle hooks
941
+
942
+ Comments plugin allows to register lifecycle hooks for `Comment` and `Comment report` content types.
943
+
944
+ You can read more about lifecycle hooks [here](https://docs.strapi.io/dev-docs/backend-customization/models#lifecycle-hooks). (You can set a listener for all of the hooks).
945
+
946
+ Lifecycle hooks can be register either in `register()` or `bootstrap()` methods of your server. You can register more than one listener for a specified lifecycle hook. For example: you want to do three things on report creation and do not want to handle all of these actions in one big function. You can split logic in as many listeners as you want.
947
+
948
+ Listeners can by sync and `async`.
949
+
950
+ >Be aware that lifecycle hooks registered in `register()` may be fired by plugin's bootstrapping. If you want listen to events triggered after server's startup use `bootstrap()`.
951
+
952
+ Example:
953
+
954
+ ```ts
955
+ const commentsCommonService = strapi
956
+ .plugin("comments")
957
+ .service("common");
958
+
959
+ commentsCommonService.registerLifecycleHook({
960
+ callback: async ({ action, result }) => {
961
+ const saveResult = await logIntoSystem(action, result);
962
+
963
+ console.log(saveResult);
964
+ },
965
+ contentTypeName: "comment",
966
+ hookName: "afterCreate",
967
+ });
968
+
969
+ commentsCommonService.registerLifecycleHook({
970
+ callback: async ({ action, result }) => {
971
+ const saveResult = await logIntoSystem(action, result);
972
+
973
+ console.log(saveResult);
974
+ },
975
+ contentTypeName: "report",
976
+ hookName: "afterCreate",
977
+ });
978
+ ```
979
+
934
980
  ## 🤝 Contributing
935
981
 
936
982
  <div>
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.newlineAndIndentContinueMarkdownList = void 0;
6
+ exports.newlineAndIndentContinueMarkdownList = newlineAndIndentContinueMarkdownList;
7
7
  const codemirror5_1 = __importDefault(require("codemirror5"));
8
8
  var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, unorderedListRE = /[*+-]\s/;
9
9
  function newlineAndIndentContinueMarkdownList(cm) {
@@ -45,7 +45,6 @@ function newlineAndIndentContinueMarkdownList(cm) {
45
45
  }
46
46
  cm.replaceSelections(replacements);
47
47
  }
48
- exports.newlineAndIndentContinueMarkdownList = newlineAndIndentContinueMarkdownList;
49
48
  function incrementRemainingMarkdownListNumbers(cm, pos) {
50
49
  var startLine = pos.line, lookAhead = 0, skipCount = 0;
51
50
  var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1];
@@ -5,7 +5,7 @@ export declare const asString: () => string;
5
5
  export declare const fromInput: (value: unknown) => CommentsFieldValue;
6
6
  export declare const toOutput: (state: CommentsFieldValue) => string;
7
7
  export declare function assertCorrectState(state: any): asserts state is CommentsFieldValue;
8
- export declare const handleStateSliceChange: (key: keyof CommentsFieldValue, setState: Dispatch<SetStateAction<CommentsFieldValue>>) => (value: string | number | Date | PopulateField[] | undefined) => void;
8
+ export declare const handleStateSliceChange: (key: keyof CommentsFieldValue, setState: Dispatch<SetStateAction<CommentsFieldValue>>) => (value: CommentsFieldValue[typeof key]) => void;
9
9
  export declare const handlePopulateChange: (key: PopulateField, setState: Dispatch<SetStateAction<CommentsFieldValue>>) => () => void;
10
10
  export declare const getRenderTypeOptions: (translate: typeof getMessage) => {
11
11
  value: string;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getApprovalStatusOptions = exports.getFilterByOptions = exports.getSortByDateOptions = exports.getRenderTypeOptions = exports.handlePopulateChange = exports.handleStateSliceChange = exports.assertCorrectState = exports.toOutput = exports.fromInput = exports.asString = void 0;
3
+ exports.getApprovalStatusOptions = exports.getFilterByOptions = exports.getSortByDateOptions = exports.getRenderTypeOptions = exports.handlePopulateChange = exports.handleStateSliceChange = exports.toOutput = exports.fromInput = exports.asString = void 0;
4
+ exports.assertCorrectState = assertCorrectState;
4
5
  const lodash_1 = require("lodash");
5
6
  const utils_1 = require("../../../../utils");
6
7
  const consts_1 = require("./consts");
@@ -37,7 +38,6 @@ function assertCorrectState(state) {
37
38
  }
38
39
  });
39
40
  }
40
- exports.assertCorrectState = assertCorrectState;
41
41
  const handleStateSliceChange = (key, setState) => (value) => {
42
42
  return setState((current) => ({
43
43
  ...current,
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  export declare function mapDispatchToProps(dispatch: any): {
3
2
  setConfig: (data: any) => {
4
3
  data: any;
@@ -9,8 +8,8 @@ declare const _default: import("react-redux").ConnectedComponent<({ setConfig }:
9
8
  setConfig: any;
10
9
  }) => JSX.Element, {
11
10
  setConfig: any;
12
- context?: React.Context<import("react-redux").ReactReduxContextValue<any, import("redux").AnyAction>> | undefined;
13
- store?: import("redux").Store<any, import("redux").AnyAction> | undefined;
11
+ context?: import("react-redux/es/components/Context").ReactReduxContextInstance | undefined;
12
+ store?: import("redux").Store | undefined;
14
13
  }>;
15
14
  export default _default;
16
15
  //# sourceMappingURL=index.d.ts.map
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.mapDispatchToProps = void 0;
6
+ exports.mapDispatchToProps = mapDispatchToProps;
7
7
  const react_1 = __importDefault(require("react"));
8
8
  const react_redux_1 = require("react-redux");
9
9
  const redux_1 = require("redux");
@@ -42,7 +42,6 @@ const mapStateToProps = (0, selectors_1.default)();
42
42
  function mapDispatchToProps(dispatch) {
43
43
  return (0, redux_1.bindActionCreators)({ setConfig: actions_1.setConfig }, dispatch);
44
44
  }
45
- exports.mapDispatchToProps = mapDispatchToProps;
46
45
  const withConnect = (0, react_redux_1.connect)(mapStateToProps, mapDispatchToProps);
47
46
  exports.default = (0, redux_1.compose)(withConnect)(App);
48
47
  //# sourceMappingURL=index.js.map
@@ -4,8 +4,8 @@ declare const _default: import("react-redux").ConnectedComponent<React.MemoExoti
4
4
  config: any;
5
5
  }) => JSX.Element | null>, {
6
6
  config: any;
7
- context?: React.Context<import("react-redux").ReactReduxContextValue<any, import("redux").AnyAction>> | undefined;
8
- store?: import("redux").Store<any, import("redux").AnyAction> | undefined;
7
+ context?: import("react-redux/es/components/Context").ReactReduxContextInstance | undefined;
8
+ store?: import("redux").Store | undefined;
9
9
  }>;
10
10
  export default _default;
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.mapDispatchToProps = void 0;
29
+ exports.mapDispatchToProps = mapDispatchToProps;
30
30
  const react_1 = __importStar(require("react"));
31
31
  const react_redux_1 = require("react-redux");
32
32
  const redux_1 = require("redux");
@@ -95,7 +95,6 @@ const mapStateToProps = (0, selectors_1.default)();
95
95
  function mapDispatchToProps(dispatch) {
96
96
  return (0, redux_1.bindActionCreators)({}, dispatch);
97
97
  }
98
- exports.mapDispatchToProps = mapDispatchToProps;
99
98
  const withConnect = (0, react_redux_1.connect)(mapStateToProps, mapDispatchToProps);
100
99
  exports.default = (0, redux_1.compose)(withConnect)((0, react_1.memo)(Details, react_fast_compare_1.default));
101
100
  //# sourceMappingURL=index.js.map
@@ -4,8 +4,8 @@ declare const _default: import("react-redux").ConnectedComponent<React.MemoExoti
4
4
  config: any;
5
5
  }) => JSX.Element>, {
6
6
  config: any;
7
- context?: React.Context<import("react-redux").ReactReduxContextValue<any, import("redux").AnyAction>> | undefined;
8
- store?: import("redux").Store<any, import("redux").AnyAction> | undefined;
7
+ context?: import("react-redux/es/components/Context").ReactReduxContextInstance | undefined;
8
+ store?: import("redux").Store | undefined;
9
9
  }>;
10
10
  export default _default;
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.mapDispatchToProps = void 0;
29
+ exports.mapDispatchToProps = mapDispatchToProps;
30
30
  const react_1 = __importStar(require("react"));
31
31
  const react_redux_1 = require("react-redux");
32
32
  const redux_1 = require("redux");
@@ -127,7 +127,6 @@ const mapStateToProps = (0, selectors_1.default)();
127
127
  function mapDispatchToProps(dispatch) {
128
128
  return (0, redux_1.bindActionCreators)({}, dispatch);
129
129
  }
130
- exports.mapDispatchToProps = mapDispatchToProps;
131
130
  const withConnect = (0, react_redux_1.connect)(mapStateToProps, mapDispatchToProps);
132
131
  exports.default = (0, redux_1.compose)(withConnect)((0, react_1.memo)(Discover, react_fast_compare_1.default));
133
132
  //# sourceMappingURL=index.js.map
@@ -4,8 +4,8 @@ declare const _default: import("react-redux").ConnectedComponent<React.MemoExoti
4
4
  config: any;
5
5
  }) => JSX.Element>, {
6
6
  config: any;
7
- context?: React.Context<import("react-redux").ReactReduxContextValue<any, import("redux").AnyAction>> | undefined;
8
- store?: import("redux").Store<any, import("redux").AnyAction> | undefined;
7
+ context?: import("react-redux/es/components/Context").ReactReduxContextInstance | undefined;
8
+ store?: import("redux").Store | undefined;
9
9
  }>;
10
10
  export default _default;
11
11
  //# sourceMappingURL=index.d.ts.map
@@ -1,11 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.assertString = void 0;
3
+ exports.assertString = assertString;
4
4
  const errors_1 = require("./errors");
5
5
  function assertString(value) {
6
6
  if (typeof value !== "string") {
7
7
  throw new errors_1.ValidationError(`String expected, but "${typeof value}" given`);
8
8
  }
9
9
  }
10
- exports.assertString = assertString;
11
10
  //# sourceMappingURL=functions.js.map
@@ -93,6 +93,7 @@ declare const _default: {
93
93
  };
94
94
  };
95
95
  };
96
+ lifecycles: Record<import("../server/utils/types").LifeCycleHookName, import("../types/utils").Effect<import("../server/utils/types").LifeCycleEvent<import("../server/utils/types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
96
97
  };
97
98
  "comment-report": {
98
99
  schema: {
@@ -141,6 +142,7 @@ declare const _default: {
141
142
  };
142
143
  };
143
144
  };
145
+ lifecycles: Record<import("../server/utils/types").LifeCycleHookName, import("../types/utils").Effect<import("../server/utils/types").LifeCycleEvent<import("../server/utils/types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
144
146
  };
145
147
  };
146
148
  export default _default;
@@ -3,14 +3,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const functions_1 = require("../server/utils/functions");
6
7
  const comment_1 = __importDefault(require("./comment"));
7
8
  const report_1 = __importDefault(require("./report"));
8
9
  exports.default = {
9
10
  comment: {
10
11
  schema: comment_1.default,
12
+ lifecycles: (0, functions_1.buildAllHookListeners)("comment", {
13
+ strapi,
14
+ }),
11
15
  },
12
16
  "comment-report": {
13
17
  schema: report_1.default,
18
+ lifecycles: (0, functions_1.buildAllHookListeners)("comment-report", {
19
+ strapi,
20
+ }),
14
21
  },
15
22
  };
16
23
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-comments",
3
- "version": "2.2.17",
3
+ "version": "2.3.1",
4
4
  "description": "Strapi - Comments plugin",
5
5
  "strapi": {
6
6
  "name": "comments",
@@ -15,9 +15,9 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@strapi/design-system": "1.18.0",
18
- "@strapi/plugin-graphql": "^4.24.4",
19
- "@strapi/utils": "^4.24.4",
20
- "@strapi/types": "4.24.4",
18
+ "@strapi/plugin-graphql": "^4.25.8",
19
+ "@strapi/utils": "^4.25.8",
20
+ "@strapi/types": "4.25.8",
21
21
  "no-profanity": "^1.4.2",
22
22
  "styled-components": "^5.3.8",
23
23
  "match-sorter": "^4.0.2",
@@ -15,7 +15,7 @@ const controllers = {
15
15
  async findAllFlat(ctx) {
16
16
  const { params = {}, query, sort, pagination } = ctx;
17
17
  const { relation } = (0, functions_2.parseParams)(params);
18
- const { sort: querySort, pagination: queryPagination, fields, ...filterQuery } = query || {};
18
+ const { sort: querySort, pagination: queryPagination, fields, omit = [], ...filterQuery } = query || {};
19
19
  try {
20
20
  (0, functions_1.assertParamsPresent)(params, ["relation"]);
21
21
  return this.getService("common").findAllFlat((0, parsers_1.flatInput)({
@@ -24,6 +24,7 @@ const controllers = {
24
24
  sort: sort || querySort,
25
25
  pagination: pagination || queryPagination,
26
26
  fields,
27
+ omit,
27
28
  }));
28
29
  }
29
30
  catch (e) {
@@ -33,7 +34,7 @@ const controllers = {
33
34
  async findAllInHierarchy(ctx) {
34
35
  const { params, query, sort } = ctx;
35
36
  const { relation } = (0, functions_2.parseParams)(params);
36
- const { sort: querySort, fields, ...filterQuery } = query || {};
37
+ const { sort: querySort, fields, omit, ...filterQuery } = query || {};
37
38
  try {
38
39
  (0, functions_1.assertParamsPresent)(params, ["relation"]);
39
40
  return await this.getService("common").findAllInHierarchy({
@@ -42,6 +43,7 @@ const controllers = {
42
43
  query: filterQuery,
43
44
  sort: sort || querySort,
44
45
  fields,
46
+ omit,
45
47
  }),
46
48
  dropBlockedThreads: true,
47
49
  });
@@ -53,7 +55,7 @@ const controllers = {
53
55
  async findAllPerAuthor(ctx) {
54
56
  const { params = {}, query, sort, pagination } = ctx;
55
57
  const { id, type } = (0, functions_2.parseParams)(params);
56
- const { sort: querySort, pagination: queryPagination, fields, ...filterQuery } = query || {};
58
+ const { sort: querySort, pagination: queryPagination, fields, omit = [], ...filterQuery } = query || {};
57
59
  try {
58
60
  (0, functions_1.assertParamsPresent)(params, ["id"]);
59
61
  return this.getService("common").findAllPerAuthor((0, parsers_1.flatInput)({
@@ -61,6 +63,7 @@ const controllers = {
61
63
  sort: sort || querySort,
62
64
  pagination: pagination || queryPagination,
63
65
  fields,
66
+ omit,
64
67
  }), id, ![constants_1.AUTHOR_TYPE.GENERIC.toLowerCase(), constants_1.AUTHOR_TYPE.GENERIC].includes(type));
65
68
  }
66
69
  catch (e) {
@@ -6,5 +6,6 @@ export declare const flatInput: <T, TKeys = keyof T>(payload: FlatInput<OnlyStri
6
6
  pagination: any;
7
7
  sort: any;
8
8
  fields: import("strapi-typed").StrapiRequestQueryFieldsClause<OnlyStrings<TKeys>> | undefined;
9
+ omit: string[] | undefined;
9
10
  };
10
11
  //# sourceMappingURL=parsers.d.ts.map
@@ -7,7 +7,7 @@ exports.flatInput = void 0;
7
7
  const error_1 = __importDefault(require("../../utils/error"));
8
8
  const functions_1 = require("../../utils/functions");
9
9
  const flatInput = (payload) => {
10
- const { relation, query, sort, pagination, fields } = payload;
10
+ const { relation, query, sort, pagination, fields, omit } = payload;
11
11
  const { populate = {}, filterBy, filterByValue, ...restQuery } = query;
12
12
  const filters = restQuery?.filters || restQuery;
13
13
  const orOperator = (filters?.$or || []).filter((_) => !Object.keys(_).includes("removed"));
@@ -65,6 +65,7 @@ const flatInput = (payload) => {
65
65
  pagination,
66
66
  sort,
67
67
  fields,
68
+ omit,
68
69
  };
69
70
  };
70
71
  exports.flatInput = flatInput;
package/server/index.d.ts CHANGED
@@ -9,7 +9,7 @@ declare const _default: {
9
9
  routes: {
10
10
  [key: string]: {
11
11
  type: string;
12
- routes: import("strapi-typed").StrapiRoute[];
12
+ routes: Array<import("strapi-typed").StrapiRoute>;
13
13
  };
14
14
  };
15
15
  services: {
@@ -121,7 +121,7 @@ module.exports = ({ strapi }) => ({
121
121
  });
122
122
  const relatedEntities = await this.getCommonService().findRelatedEntitiesFor(entities);
123
123
  const result = entities
124
- .map((_) => (0, functions_2.filterOurResolvedReports)(this.getCommonService().sanitizeCommentEntity(_, [], defaultAuthorUserPopulate?.populate)))
124
+ .map((_) => (0, functions_2.filterOurResolvedReports)(this.getCommonService().sanitizeCommentEntity(_, [], [], defaultAuthorUserPopulate?.populate)))
125
125
  .map((_) => this.getCommonService().mergeRelatedEntityTo(_, relatedEntities));
126
126
  const pageCount = Math.floor(total / pageSize);
127
127
  return {
@@ -197,7 +197,7 @@ module.exports = ({ strapi }) => ({
197
197
  ..._.related,
198
198
  gotThread: isCommentWithThread,
199
199
  }, []),
200
- }, [], defaultAuthorUserPopulate?.populate));
200
+ }, [], [], defaultAuthorUserPopulate?.populate));
201
201
  });
202
202
  const pageCount = Math.floor(total / pageSize);
203
203
  return {
@@ -291,7 +291,7 @@ module.exports = ({ strapi }) => ({
291
291
  const selectedEntity = this.getCommonService().sanitizeCommentEntity({
292
292
  ...entity,
293
293
  threadOf: entity.threadOf || null,
294
- }, [], defaultAuthorUserPopulate?.populate);
294
+ }, [], [], defaultAuthorUserPopulate?.populate);
295
295
  return {
296
296
  entity: relatedEntity,
297
297
  selected: selectedEntity,
@@ -9,6 +9,11 @@ const error_1 = __importDefault(require("./../utils/error"));
9
9
  const functions_1 = require("./utils/functions");
10
10
  const parsers_1 = require("./utils/parsers");
11
11
  const PAGE_SIZE = 10;
12
+ const REQUIRED_FIELDS = ["id"];
13
+ const lifecycleHookListeners = {
14
+ comment: {},
15
+ "comment-report": {}
16
+ };
12
17
  module.exports = ({ strapi }) => ({
13
18
  async getConfig(prop, defaultValue, useLocal = false) {
14
19
  const queryProp = (0, functions_1.buildConfigQueryProp)(prop);
@@ -33,8 +38,9 @@ module.exports = ({ strapi }) => ({
33
38
  const result = strapi.config.get(`plugin.comments${queryProp ? "." + queryProp : ""}`);
34
39
  return (0, lodash_1.isNil)(result) ? defaultValue : result;
35
40
  },
36
- async findAllFlat({ query = {}, populate = {}, sort, pagination, fields, isAdmin = false, }, relatedEntity = null) {
37
- const defaultSelect = ["id", "related"];
41
+ async findAllFlat({ query = {}, populate = {}, sort, pagination, fields, isAdmin = false, omit: baseOmit = [], }, relatedEntity = null) {
42
+ const omit = baseOmit.filter((field) => !REQUIRED_FIELDS.includes(field));
43
+ const defaultSelect = ["id", "related"].filter((field) => !omit.includes(field));
38
44
  const populateClause = {
39
45
  authorUser: true,
40
46
  ...((0, lodash_1.isObject)(populate) ? populate : {}),
@@ -94,9 +100,11 @@ module.exports = ({ strapi }) => ({
94
100
  firstThreadItemId: (0, lodash_1.first)(nestedEntries)?.id,
95
101
  };
96
102
  }));
97
- const relatedEntities = relatedEntity !== null
98
- ? [relatedEntity]
99
- : await this.findRelatedEntitiesFor([...entries]);
103
+ const relatedEntities = omit.includes("related")
104
+ ? []
105
+ : relatedEntity !== null
106
+ ? [relatedEntity]
107
+ : await this.findRelatedEntitiesFor([...entries]);
100
108
  const hasRelatedEntitiesToMap = relatedEntities.filter((_) => _).length > 0;
101
109
  const result = entries.map((_) => {
102
110
  const threadedItem = entriesWithThreads.find((item) => item.id === _.id);
@@ -118,7 +126,7 @@ module.exports = ({ strapi }) => ({
118
126
  threadOf: primitiveThreadOf || _.threadOf,
119
127
  gotThread: (threadedItem?.itemsInTread || 0) > 0,
120
128
  threadFirstItemId: threadedItem?.firstThreadItemId,
121
- }, doNotPopulateAuthor, authorUserPopulate);
129
+ }, doNotPopulateAuthor, omit, authorUserPopulate);
122
130
  });
123
131
  return {
124
132
  data: hasRelatedEntitiesToMap
@@ -127,8 +135,8 @@ module.exports = ({ strapi }) => ({
127
135
  ...((0, lodash_1.isEmpty)(meta) ? {} : { meta }),
128
136
  };
129
137
  },
130
- async findAllInHierarchy({ query, populate = {}, sort, fields, startingFromId = null, dropBlockedThreads = false, isAdmin = false, }, relatedEntity) {
131
- const entities = await this.findAllFlat({ query, populate, sort, fields, isAdmin }, relatedEntity);
138
+ async findAllInHierarchy({ query, populate = {}, sort, fields, startingFromId = null, dropBlockedThreads = false, isAdmin = false, omit = [], }, relatedEntity) {
139
+ const entities = await this.findAllFlat({ query, populate, sort, fields, isAdmin, omit }, relatedEntity);
132
140
  return (0, functions_1.buildNestedStructure)(entities?.data, startingFromId, "threadOf", dropBlockedThreads, false);
133
141
  },
134
142
  async findOne(criteria) {
@@ -225,18 +233,18 @@ module.exports = ({ strapi }) => ({
225
233
  return false;
226
234
  }
227
235
  },
228
- sanitizeCommentEntity(entity, blockedAuthorProps, populate) {
236
+ sanitizeCommentEntity(entity, blockedAuthorProps, omit = [], populate) {
229
237
  const fieldsToPopulate = (0, lodash_1.isArray)(populate)
230
238
  ? populate
231
239
  : Object.keys(populate || {});
232
- return {
240
+ return (0, lodash_1.omit)({
233
241
  ...(0, functions_1.buildAuthorModel)({
234
242
  ...entity,
235
243
  threadOf: (0, lodash_1.isObject)(entity.threadOf)
236
244
  ? (0, functions_1.buildAuthorModel)(entity.threadOf, blockedAuthorProps, fieldsToPopulate)
237
245
  : entity.threadOf,
238
246
  }, blockedAuthorProps, fieldsToPopulate),
239
- };
247
+ }, omit);
240
248
  },
241
249
  isValidUserContext(user) {
242
250
  return user ? !(0, lodash_1.isNil)(user?.id) : true;
@@ -272,5 +280,17 @@ module.exports = ({ strapi }) => ({
272
280
  const enabledCollections = await this.getConfig("enabledCollections", []);
273
281
  return enabledCollections.includes(uid);
274
282
  },
283
+ registerLifecycleHook({ callback, contentTypeName, hookName }) {
284
+ if (!lifecycleHookListeners[contentTypeName][hookName]) {
285
+ lifecycleHookListeners[contentTypeName][hookName] = [];
286
+ }
287
+ lifecycleHookListeners[contentTypeName][hookName]?.push(callback);
288
+ },
289
+ async runLifecycleHook({ contentTypeName, event, hookName }) {
290
+ const hookListeners = lifecycleHookListeners[contentTypeName][hookName] ?? [];
291
+ for (const listener of hookListeners) {
292
+ await listener(event);
293
+ }
294
+ },
275
295
  });
276
296
  //# sourceMappingURL=common.js.map
@@ -1,4 +1,5 @@
1
1
  import { ConfigParamKeys, RegExpCollection } from "../../types";
2
+ import { LifeCycleHookName } from "./types";
2
3
  export declare const CONFIG_PARAMS: ConfigParamKeys;
3
4
  export declare const APPROVAL_STATUS: {
4
5
  PENDING: string;
@@ -10,4 +11,5 @@ export declare const AUTHOR_TYPE: {
10
11
  STRAPI: string;
11
12
  };
12
13
  export declare const REGEX: RegExpCollection;
14
+ export declare const LIFECYCLE_HOOKS: ReadonlyArray<LifeCycleHookName>;
13
15
  //# sourceMappingURL=constants.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.REGEX = exports.AUTHOR_TYPE = exports.APPROVAL_STATUS = exports.CONFIG_PARAMS = void 0;
3
+ exports.LIFECYCLE_HOOKS = exports.REGEX = exports.AUTHOR_TYPE = exports.APPROVAL_STATUS = exports.CONFIG_PARAMS = void 0;
4
4
  exports.CONFIG_PARAMS = {
5
5
  ENABLED_COLLECTIONS: "enabledCollections",
6
6
  APPROVAL_FLOW: "approvalFlow",
@@ -24,4 +24,24 @@ exports.REGEX = {
24
24
  email: /\S+@\S+\.\S+/,
25
25
  sorting: /^(?<path>[a-z0-9-_\:\.]+)\:+(asc|desc)$/i,
26
26
  };
27
+ exports.LIFECYCLE_HOOKS = [
28
+ "beforeCreate",
29
+ "beforeCreateMany",
30
+ "afterCreate",
31
+ "afterCreateMany",
32
+ "beforeUpdate",
33
+ "beforeUpdateMany",
34
+ "afterUpdate",
35
+ "afterUpdateMany",
36
+ "beforeDelete",
37
+ "beforeDeleteMany",
38
+ "afterDelete",
39
+ "afterDeleteMany",
40
+ "beforeCount",
41
+ "afterCount",
42
+ "beforeFindOne",
43
+ "afterFindOne",
44
+ "beforeFindMany",
45
+ "afterFindMany",
46
+ ];
27
47
  //# sourceMappingURL=constants.js.map
@@ -1,6 +1,10 @@
1
- import { StrapiQueryParams, StrapiQueryParamsParsed } from "strapi-typed";
1
+ import { StrapiQueryParams, StrapiQueryParamsParsed, StrapiContext } from "strapi-typed";
2
+ import { ContentType, LifeCycleEvent, LifeCycleHookName } from "./types";
3
+ import { Effect } from "../../types/utils";
2
4
  export declare const getPluginService: <T>(name: string) => T;
3
5
  export declare const parseParams: <T = StrapiQueryParamsParsed>(params: StrapiQueryParams) => T;
4
6
  export declare const assertParamsPresent: <T>(params: unknown, keys: string[]) => asserts params is T;
5
7
  export declare const assertNotEmpty: <T>(value: T | null | undefined, customError?: Error) => asserts value is T;
8
+ export declare const buildHookListener: (contentTypeName: ContentType, { strapi }: StrapiContext) => (hookName: LifeCycleHookName) => [LifeCycleHookName, Effect<LifeCycleEvent>];
9
+ export declare const buildAllHookListeners: (contentTypeName: ContentType, context: StrapiContext) => Record<LifeCycleHookName, Effect<LifeCycleEvent>>;
6
10
  //# sourceMappingURL=functions.d.ts.map
@@ -3,8 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.assertNotEmpty = exports.assertParamsPresent = exports.parseParams = exports.getPluginService = void 0;
6
+ exports.buildAllHookListeners = exports.buildHookListener = exports.assertNotEmpty = exports.assertParamsPresent = exports.parseParams = exports.getPluginService = void 0;
7
7
  const error_1 = __importDefault(require("./error"));
8
+ const constants_1 = require("./constants");
8
9
  const getPluginService = (name) => strapi.plugin("comments").service(name);
9
10
  exports.getPluginService = getPluginService;
10
11
  const parseParams = (params) => Object.keys(params).reduce((prev, curr) => {
@@ -33,4 +34,20 @@ const assertNotEmpty = (value, customError) => {
33
34
  throw (customError ?? new error_1.default(400, "Non-empty value expected, empty given"));
34
35
  };
35
36
  exports.assertNotEmpty = assertNotEmpty;
37
+ const buildHookListener = (contentTypeName, { strapi }) => (hookName) => [
38
+ hookName,
39
+ async (event) => {
40
+ const commonService = strapi
41
+ .plugin("comments")
42
+ .service("common");
43
+ await commonService.runLifecycleHook({
44
+ contentTypeName,
45
+ hookName,
46
+ event,
47
+ });
48
+ },
49
+ ];
50
+ exports.buildHookListener = buildHookListener;
51
+ const buildAllHookListeners = (contentTypeName, context) => Object.fromEntries(constants_1.LIFECYCLE_HOOKS.map((0, exports.buildHookListener)(contentTypeName, context)));
52
+ exports.buildAllHookListeners = buildAllHookListeners;
36
53
  //# sourceMappingURL=functions.js.map
@@ -0,0 +1,23 @@
1
+ import { Effect } from "../../types/utils";
2
+ export type ContentType = "comment" | "comment-report";
3
+ export type LifeCycleHookName = "beforeCreate" | "beforeCreateMany" | "afterCreate" | "afterCreateMany" | "beforeUpdate" | "beforeUpdateMany" | "afterUpdate" | "afterUpdateMany" | "beforeDelete" | "beforeDeleteMany" | "afterDelete" | "afterDeleteMany" | "beforeCount" | "afterCount" | "beforeFindOne" | "afterFindOne" | "beforeFindMany" | "afterFindMany";
4
+ export interface LifeCycleEvent<THookName extends LifeCycleHookName = LifeCycleHookName, TResult = unknown, TParams = Record<string, unknown>> {
5
+ action: THookName;
6
+ model: {
7
+ singularName: string;
8
+ uid: string;
9
+ tableName: string;
10
+ attributes: Record<string, unknown>;
11
+ lifecycles: Partial<Record<LifeCycleHookName, Effect<LifeCycleEvent>>>;
12
+ indexes: Array<{
13
+ type?: string;
14
+ name: string;
15
+ columns: string[];
16
+ }>;
17
+ columnToAttribute: Record<string, string>;
18
+ };
19
+ state: Record<string, unknown>;
20
+ params: TParams;
21
+ result?: TResult | TResult[];
22
+ }
23
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map