@ruiapp/rapid-core 0.1.19 → 0.1.21

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 (54) hide show
  1. package/dist/core/actionHandler.d.ts +2 -0
  2. package/dist/core/pluginManager.d.ts +3 -0
  3. package/dist/core/request.d.ts +2 -1
  4. package/dist/core/routeContext.d.ts +4 -1
  5. package/dist/core/server.d.ts +8 -2
  6. package/dist/dataAccess/dataAccessor.d.ts +2 -1
  7. package/dist/facilities/log/LogFacility.d.ts +33 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +288 -264
  10. package/dist/plugins/auth/AuthPlugin.d.ts +0 -9
  11. package/dist/plugins/dataManage/DataManagePlugin.d.ts +0 -10
  12. package/dist/plugins/entityAccessControl/EntityAccessControlPlugin.d.ts +17 -0
  13. package/dist/plugins/fileManage/FileManagePlugin.d.ts +0 -10
  14. package/dist/plugins/metaManage/MetaManagePlugin.d.ts +0 -8
  15. package/dist/plugins/routeManage/RouteManagePlugin.d.ts +0 -9
  16. package/dist/plugins/webhooks/WebhooksPlugin.d.ts +0 -6
  17. package/dist/server.d.ts +8 -3
  18. package/dist/types.d.ts +11 -0
  19. package/dist/utilities/accessControlUtility.d.ts +5 -0
  20. package/package.json +5 -2
  21. package/rollup.config.js +1 -18
  22. package/src/core/actionHandler.ts +2 -0
  23. package/src/core/pluginManager.ts +12 -0
  24. package/src/core/request.ts +6 -2
  25. package/src/core/routeContext.ts +6 -1
  26. package/src/core/routesBuilder.ts +16 -6
  27. package/src/core/server.ts +8 -2
  28. package/src/dataAccess/dataAccessor.ts +13 -9
  29. package/src/dataAccess/entityManager.ts +24 -24
  30. package/src/facilities/log/LogFacility.ts +36 -0
  31. package/src/helpers/inputHelper.ts +3 -3
  32. package/src/helpers/runCollectionEntityActionHandler.ts +4 -9
  33. package/src/index.ts +2 -1
  34. package/src/plugins/auth/AuthPlugin.ts +3 -31
  35. package/src/plugins/dataManage/DataManagePlugin.ts +0 -32
  36. package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +3 -7
  37. package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +3 -7
  38. package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +3 -7
  39. package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +2 -2
  40. package/src/plugins/dataManage/actionHandlers/findCollectionEntities.ts +0 -1
  41. package/src/plugins/dataManage/actionHandlers/findCollectionEntityById.ts +2 -2
  42. package/src/plugins/dataManage/actionHandlers/queryDatabase.ts +5 -9
  43. package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +2 -6
  44. package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +3 -8
  45. package/src/plugins/entityAccessControl/EntityAccessControlPlugin.ts +107 -0
  46. package/src/plugins/fileManage/FileManagePlugin.ts +0 -31
  47. package/src/plugins/metaManage/MetaManagePlugin.ts +16 -39
  48. package/src/plugins/routeManage/RouteManagePlugin.ts +4 -30
  49. package/src/plugins/routeManage/actionHandlers/httpProxy.ts +2 -1
  50. package/src/plugins/webhooks/WebhooksPlugin.ts +26 -36
  51. package/src/queryBuilder/queryBuilder.ts +3 -3
  52. package/src/server.ts +53 -17
  53. package/src/types.ts +13 -0
  54. package/src/utilities/accessControlUtility.ts +33 -0
@@ -0,0 +1,107 @@
1
+ import type { RpdApplicationConfig, RpdDataModelProperty } from "~/types";
2
+
3
+ import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "~/core/server";
4
+ import { find, set } from "lodash";
5
+ import { ActionHandlerContext } from "~/core/actionHandler";
6
+ import { isAccessAllowed } from "~/utilities/accessControlUtility";
7
+ import { RouteContext } from "~/core/routeContext";
8
+
9
+ class EntityAccessControlPlugin implements RapidPlugin {
10
+ constructor() {
11
+ }
12
+
13
+ get code(): string {
14
+ return "entityAccessControl";
15
+ }
16
+
17
+ get description(): string {
18
+ return "";
19
+ }
20
+
21
+ get extendingAbilities(): RpdServerPluginExtendingAbilities[] {
22
+ return [];
23
+ }
24
+
25
+ get configurableTargets(): RpdServerPluginConfigurableTargetOptions[] {
26
+ return [];
27
+ }
28
+
29
+ get configurations(): RpdConfigurationItemOptions[] {
30
+ return [];
31
+ }
32
+
33
+ async onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
34
+ const properties: RpdDataModelProperty[] = [
35
+ {
36
+ name: "permissionPolicies",
37
+ code: "permissionPolicies",
38
+ columnName: "permission_policies",
39
+ type: "json",
40
+ },
41
+ ];
42
+ server.appendModelProperties("model", properties);
43
+ }
44
+
45
+ async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
46
+ const logger = server.getLogger();
47
+ logger.info("Configuring entity access checking policies...")
48
+
49
+ const model = find(applicationConfig.models, (item) => item.singularCode === "model");
50
+ if (!model) {
51
+ return;
52
+ }
53
+
54
+ const { permissionPolicies } = model;
55
+ if (!permissionPolicies) {
56
+ return;
57
+ }
58
+
59
+ const routes = applicationConfig.routes;
60
+ for (const route of routes) {
61
+ const { actions } = route;
62
+ if (!actions) {
63
+ continue;
64
+ }
65
+
66
+ for (const action of route.actions) {
67
+ if (action.code === "findCollectionEntityById") {
68
+ if (permissionPolicies.find) {
69
+ set(action, "config.permissionPolicy", permissionPolicies.find);
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ async onPrepareRouteContext(server: IRpdServer, routeContext: RouteContext) {
77
+ const userId = routeContext.state.userId;
78
+ if (!userId) {
79
+ return;
80
+ }
81
+
82
+ const actions = await server.queryDatabaseObject(
83
+ `select distinct a.* from sys_actions a
84
+ inner join oc_role_sys_action_links ra on a.id = ra.action_id
85
+ inner join oc_role_user_links ru on ru.role_id = ra.role_id
86
+ where ru.user_id = $1;`,
87
+ [userId]
88
+ );
89
+ routeContext.state.allowedActions = actions.map(item => item.code);
90
+ }
91
+
92
+ async beforeRunRouteActions(server: IRpdServer, handlerContext: ActionHandlerContext): Promise<any> {
93
+ // Check permission
94
+ const { routerContext } = handlerContext;
95
+ const { routeConfig } = routerContext;
96
+ for (const actionConfig of routeConfig.actions) {
97
+ const permissionPolicy = actionConfig.config?.permissionPolicy;
98
+ if (permissionPolicy) {
99
+ if (!isAccessAllowed(permissionPolicy, routerContext.state.allowedActions || [])) {
100
+ throw new Error(`Your action of '${actionConfig.code}' is not permitted.`);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ export default EntityAccessControlPlugin;
@@ -34,46 +34,15 @@ class FileManager implements RapidPlugin {
34
34
  return [];
35
35
  }
36
36
 
37
- async initPlugin(server: IRpdServer): Promise<any> {
38
- }
39
-
40
- async registerMiddlewares(server: IRpdServer): Promise<any> {
41
- }
42
-
43
37
  async registerActionHandlers(server: IRpdServer): Promise<any> {
44
38
  server.registerActionHandler(this, downloadDocumentActionHandler);
45
39
  server.registerActionHandler(this, downloadFileActionHandler);
46
40
  server.registerActionHandler(this, uploadFileActionHandler);
47
41
  }
48
42
 
49
- async registerEventHandlers(server: IRpdServer): Promise<any> {
50
- }
51
-
52
- async registerMessageHandlers(server: IRpdServer): Promise<any> {
53
- }
54
-
55
- async registerTaskProcessors(server: IRpdServer): Promise<any> {
56
- }
57
-
58
- async onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
59
- }
60
-
61
- async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
62
- }
63
-
64
- async configureModelProperties(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
65
- }
66
-
67
43
  async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
68
44
  server.appendApplicationConfig({ routes: pluginRoutes });
69
45
  }
70
-
71
- async onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
72
- console.log("fileManager.onApplicationLoaded");
73
- }
74
-
75
- async onApplicationReady(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
76
- }
77
46
  }
78
47
 
79
48
  export default FileManager;
@@ -2,7 +2,6 @@
2
2
  * Meta manager plugin
3
3
  */
4
4
 
5
- import * as _ from "lodash";
6
5
  import {
7
6
  IQueryBuilder,
8
7
  QuoteTableOptions,
@@ -20,6 +19,7 @@ import * as listMetaModels from "./actionHandlers/listMetaModels";
20
19
  import * as listMetaRoutes from "./actionHandlers/listMetaRoutes";
21
20
  import * as getMetaModelDetail from "./actionHandlers/getMetaModelDetail";
22
21
  import { isRelationProperty } from "~/utilities/rapidUtility";
22
+ import { find } from "lodash";
23
23
 
24
24
  class MetaManager implements RapidPlugin {
25
25
  get code(): string {
@@ -42,12 +42,6 @@ class MetaManager implements RapidPlugin {
42
42
  return [];
43
43
  }
44
44
 
45
- async initPlugin(server: IRpdServer): Promise<any> {
46
- }
47
-
48
- async registerMiddlewares(server: IRpdServer): Promise<any> {
49
- }
50
-
51
45
  async registerActionHandlers(server: IRpdServer): Promise<any> {
52
46
  server.registerActionHandler(this, listMetaModels);
53
47
  server.registerActionHandler(this, listMetaRoutes);
@@ -69,37 +63,20 @@ class MetaManager implements RapidPlugin {
69
63
  );
70
64
  }
71
65
 
72
- async registerMessageHandlers(server: IRpdServer): Promise<any> {
73
- }
74
-
75
- async registerTaskProcessors(server: IRpdServer): Promise<any> {
76
- }
77
-
78
- async onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
79
- }
80
-
81
66
  async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
67
+ const logger = server.getLogger();
82
68
  try {
69
+ logger.info("Loading meta of models...");
83
70
  const models: RpdDataModel[] = await listCollections(server, applicationConfig);
84
71
  server.appendApplicationConfig({ models });
85
- } catch (ex) {
86
- console.warn("Failed to loading existing meta of models.", ex);
72
+ } catch (error) {
73
+ logger.crit("Failed to load meta of models.", { error });
87
74
  }
88
75
  }
89
76
 
90
- async configureModelProperties(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
91
- }
92
-
93
- async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
94
- }
95
-
96
77
  async onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
97
- console.log("metaManager.onApplicationLoaded");
98
78
  await syncDatabaseSchema(server, applicationConfig);
99
79
  }
100
-
101
- async onApplicationReady(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
102
- }
103
80
  }
104
81
 
105
82
  export default MetaManager;
@@ -236,17 +213,18 @@ async function syncDatabaseSchema(
236
213
  server: IRpdServer,
237
214
  applicationConfig: RpdApplicationConfig,
238
215
  ) {
239
- console.log("Synchronizing database schema...");
216
+ const logger = server.getLogger();
217
+ logger.info("Synchronizing database schema...");
240
218
  const sqlQueryTableInformations = `SELECT table_schema, table_name FROM information_schema.tables`;
241
219
  const tablesInDb: TableInformation[] = await server.queryDatabaseObject(sqlQueryTableInformations);
242
220
  const { queryBuilder } = server;
243
221
 
244
222
  for (const model of applicationConfig.models) {
245
- console.debug(`Checking data table for '${model.namespace}.${model.singularCode}'...`);
223
+ logger.debug(`Checking data table for '${model.namespace}.${model.singularCode}'...`);
246
224
 
247
225
  const expectedTableSchema = model.schema || server.databaseConfig.dbDefaultSchema;
248
226
  const expectedTableName = model.tableName;
249
- const tableInDb = _.find(tablesInDb, { table_schema: expectedTableSchema, table_name: expectedTableName});
227
+ const tableInDb = find(tablesInDb, { table_schema: expectedTableSchema, table_name: expectedTableName});
250
228
  if (!tableInDb) {
251
229
  await server.queryDatabaseObject(`CREATE TABLE IF NOT EXISTS ${queryBuilder.quoteTable(model)} ()`, []);
252
230
  }
@@ -257,7 +235,7 @@ async function syncDatabaseSchema(
257
235
  const columnsInDb: ColumnInformation[] = await server.queryDatabaseObject(sqlQueryColumnInformations, []);
258
236
 
259
237
  for (const model of applicationConfig.models) {
260
- console.debug(`Checking data columns for '${model.namespace}.${model.singularCode}'...`);
238
+ logger.debug(`Checking data columns for '${model.namespace}.${model.singularCode}'...`);
261
239
 
262
240
  for (const property of model.properties) {
263
241
  let columnDDL;
@@ -265,10 +243,10 @@ async function syncDatabaseSchema(
265
243
  if (property.relation === "one") {
266
244
  const targetModel = applicationConfig.models.find(item => item.singularCode === property.targetSingularCode);
267
245
  if (!targetModel) {
268
- console.warn(`Cannot find target model with singular code "${property.targetSingularCode}".`)
246
+ logger.warn(`Cannot find target model with singular code "${property.targetSingularCode}".`)
269
247
  }
270
248
 
271
- const columnInDb: ColumnInformation | undefined = _.find(columnsInDb, {
249
+ const columnInDb: ColumnInformation | undefined = find(columnsInDb, {
272
250
  table_schema: model.schema || "public",
273
251
  table_name: model.tableName,
274
252
  column_name: property.targetIdColumnName!,
@@ -286,7 +264,7 @@ async function syncDatabaseSchema(
286
264
  }
287
265
  } else if (property.relation === "many") {
288
266
  if (property.linkTableName) {
289
- const tableInDb = _.find(tablesInDb, { table_schema: property.linkSchema || server.databaseConfig.dbDefaultSchema, table_name: property.linkTableName});
267
+ const tableInDb = find(tablesInDb, { table_schema: property.linkSchema || server.databaseConfig.dbDefaultSchema, table_name: property.linkTableName});
290
268
  if (!tableInDb) {
291
269
  columnDDL = generateLinkTableDDL(queryBuilder, {
292
270
  linkSchema: property.linkSchema,
@@ -298,11 +276,11 @@ async function syncDatabaseSchema(
298
276
  } else {
299
277
  const targetModel = applicationConfig.models.find(item => item.singularCode === property.targetSingularCode);
300
278
  if (!targetModel) {
301
- console.warn(`Cannot find target model with singular code "${property.targetSingularCode}".`)
279
+ logger.warn(`Cannot find target model with singular code "${property.targetSingularCode}".`)
302
280
  continue;
303
281
  }
304
282
 
305
- const columnInDb: ColumnInformation | undefined = _.find(columnsInDb, {
283
+ const columnInDb: ColumnInformation | undefined = find(columnsInDb, {
306
284
  table_schema: targetModel.schema || "public",
307
285
  table_name: targetModel.tableName,
308
286
  column_name: property.selfIdColumnName!,
@@ -328,7 +306,7 @@ async function syncDatabaseSchema(
328
306
  }
329
307
  } else {
330
308
  const columnName = property.columnName || property.code;
331
- const columnInDb: ColumnInformation | undefined = _.find(columnsInDb, {
309
+ const columnInDb: ColumnInformation | undefined = find(columnsInDb, {
332
310
  table_schema: model.schema || "public",
333
311
  table_name: model.tableName,
334
312
  column_name: columnName,
@@ -398,7 +376,6 @@ function generateCreateColumnDDL(queryBuilder: IQueryBuilder, options: {
398
376
  } else {
399
377
  const columnType = pgPropertyTypeColumnMap[options.type];
400
378
  if (!columnType) {
401
- console.log('options', options);
402
379
  throw new Error(`Property type "${options.type}" is not supported.`);
403
380
  }
404
381
  columnDDL += ` ${columnType}`;
@@ -30,12 +30,6 @@ class RouteManager implements RapidPlugin {
30
30
  return [];
31
31
  }
32
32
 
33
- async initPlugin(server: IRpdServer): Promise<any> {
34
- }
35
-
36
- async registerMiddlewares(server: IRpdServer): Promise<any> {
37
- }
38
-
39
33
  async registerActionHandlers(server: IRpdServer): Promise<any> {
40
34
  server.registerActionHandler(this, httpProxy);
41
35
  }
@@ -47,23 +41,10 @@ class RouteManager implements RapidPlugin {
47
41
  // server.registerEventHandler("entity.delete", handleEntityEvent.bind(null, server))
48
42
  }
49
43
 
50
- async registerMessageHandlers(server: IRpdServer): Promise<any> {
51
- }
52
-
53
- async registerTaskProcessors(server: IRpdServer): Promise<any> {
54
- }
55
-
56
- async onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
57
- }
58
-
59
- async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
60
- }
61
-
62
- async configureModelProperties(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
63
- }
64
-
65
44
  async configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
45
+ const logger = server.getLogger();
66
46
  try {
47
+ logger.info("Loading meta of routes...");
67
48
  const entityManager = server.getEntityManager("route");
68
49
  const routes = await entityManager.findEntities({
69
50
  orderBy: [
@@ -71,17 +52,10 @@ class RouteManager implements RapidPlugin {
71
52
  ],
72
53
  });
73
54
  applicationConfig.routes.push(...routes);
74
- } catch (ex) {
75
- console.warn("Failed to loading existing meta of routes.", ex.message);
55
+ } catch (error) {
56
+ logger.crit("Failed to load meta of routes.", { error });
76
57
  }
77
58
  }
78
-
79
- async onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
80
- console.log("[routeManager.onApplicationLoaded] onApplicationLoaded");
81
- }
82
-
83
- async onApplicationReady(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
84
- }
85
59
  }
86
60
 
87
61
  export default RouteManager;
@@ -10,7 +10,8 @@ export async function handler(
10
10
  ctx: ActionHandlerContext,
11
11
  options: RunProxyHandlerOptions,
12
12
  ) {
13
- console.debug(`Running ${code} handler...`);
13
+ const { logger } = ctx;
14
+ logger.debug(`Running ${code} handler...`);
14
15
 
15
16
  await doProxy(ctx.routerContext, options);
16
17
  }
@@ -2,7 +2,6 @@
2
2
  * Webhooks plugin
3
3
  */
4
4
 
5
- import * as _ from "lodash";
6
5
  import {
7
6
  RpdApplicationConfig,
8
7
  RpdEntityCreateEventPayload,
@@ -13,6 +12,7 @@ import {
13
12
  import { RpdServerPluginExtendingAbilities, RpdServerPluginConfigurableTargetOptions, RpdConfigurationItemOptions, IRpdServer, RapidPlugin } from "~/core/server";
14
13
  import { fetchWithTimeout } from "~/utilities/httpUtility";
15
14
  import pluginConfig from "./pluginConfig";
15
+ import { indexOf } from "lodash";
16
16
 
17
17
 
18
18
  export interface Webhook {
@@ -30,16 +30,23 @@ export interface Webhook {
30
30
  function listWebhooks(
31
31
  server: IRpdServer,
32
32
  ) {
33
- const entityManager = server.getEntityManager("webhook");
34
- return entityManager.findEntities({
35
- filters: [
36
- {
37
- field: "enabled",
38
- operator: "eq",
39
- value: true,
40
- },
41
- ],
42
- });
33
+ const logger = server.getLogger();
34
+ logger.info("Loading meta of webhooks...");
35
+
36
+ try {
37
+ const entityManager = server.getEntityManager("webhook");
38
+ return entityManager.findEntities({
39
+ filters: [
40
+ {
41
+ field: "enabled",
42
+ operator: "eq",
43
+ value: true,
44
+ },
45
+ ],
46
+ });
47
+ } catch (error) {
48
+ logger.crit("Failed to load meta of webhooks.", { error });
49
+ }
43
50
  }
44
51
 
45
52
 
@@ -70,15 +77,6 @@ class WebhooksPlugin implements RapidPlugin {
70
77
  return [];
71
78
  }
72
79
 
73
- async initPlugin(server: IRpdServer): Promise<any> {
74
- }
75
-
76
- async registerMiddlewares(server: IRpdServer): Promise<any> {
77
- }
78
-
79
- async registerActionHandlers(server: IRpdServer): Promise<any> {
80
- }
81
-
82
80
  async registerEventHandlers(server: IRpdServer): Promise<any> {
83
81
  const events: (keyof RpdServerEventTypes)[] = [
84
82
  "entity.create",
@@ -93,15 +91,6 @@ class WebhooksPlugin implements RapidPlugin {
93
91
  }
94
92
  }
95
93
 
96
- async registerMessageHandlers(server: IRpdServer): Promise<any> {
97
- }
98
-
99
- async registerTaskProcessors(server: IRpdServer): Promise<any> {
100
- }
101
-
102
- async onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
103
- }
104
-
105
94
  async configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
106
95
  server.appendApplicationConfig({
107
96
  models: pluginConfig.models,
@@ -115,7 +104,6 @@ class WebhooksPlugin implements RapidPlugin {
115
104
  }
116
105
 
117
106
  async onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any> {
118
- console.log("[webhooks.onApplicationLoaded] loading webhooks");
119
107
  this.#webhooks = await listWebhooks(server);
120
108
  }
121
109
 
@@ -145,8 +133,10 @@ class WebhooksPlugin implements RapidPlugin {
145
133
  return;
146
134
  }
147
135
 
136
+ const logger = server.getLogger();
137
+
148
138
  for (const webhook of this.#webhooks) {
149
- if (_.indexOf(webhook.events, event) === -1) {
139
+ if (indexOf(webhook.events, event) === -1) {
150
140
  continue;
151
141
  }
152
142
 
@@ -157,8 +147,9 @@ class WebhooksPlugin implements RapidPlugin {
157
147
  continue;
158
148
  }
159
149
 
160
- console.debug(`Triggering webhook. ${webhook.url}`);
150
+ logger.debug(`Triggering webhook. ${webhook.url}`);
161
151
  // TODO: It's better to trigger webhook through message queue.
152
+ const requestBody = { event, payload };
162
153
  try {
163
154
  await fetchWithTimeout(webhook.url, {
164
155
  method: "post",
@@ -166,11 +157,10 @@ class WebhooksPlugin implements RapidPlugin {
166
157
  "Content-Type": "application/json",
167
158
  "x-webhook-secret": webhook.secret || "",
168
159
  },
169
- body: JSON.stringify({ event, payload }),
160
+ body: JSON.stringify(requestBody),
170
161
  });
171
- } catch (err) {
172
- console.warn(new Error("Failed to call webhook. " + err.message));
173
- console.warn(err);
162
+ } catch (error) {
163
+ logger.error("Failed to call webhook.", { error, webhookUrl: webhook.url, requestBody });
174
164
  }
175
165
  }
176
166
  }
@@ -1,4 +1,4 @@
1
- import * as _ from "lodash";
1
+ import { find } from "lodash";
2
2
  import {
3
3
  CountEntityOptions,
4
4
  DeleteEntityOptions,
@@ -148,7 +148,7 @@ export default class QueryBuilder {
148
148
 
149
149
  let property: RpdDataModelProperty | null = null;
150
150
  if (model) {
151
- property = _.find(
151
+ property = find(
152
152
  model.properties,
153
153
  (e: RpdDataModelProperty) => e.code === propertyName,
154
154
  );
@@ -192,7 +192,7 @@ export default class QueryBuilder {
192
192
 
193
193
  let property: RpdDataModelProperty | null = null;
194
194
  if (model) {
195
- property = _.find(
195
+ property = find(
196
196
  model.properties,
197
197
  (e: RpdDataModelProperty) => (e.columnName || e.code) === propertyName,
198
198
  );