@friggframework/core 2.0.0-next.3 → 2.0.0-next.31

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.
@@ -0,0 +1,12 @@
1
+ const Boom = require('@hapi/boom');
2
+
3
+ // CheckLoggedIn Middleware
4
+ const requireLoggedInUser = (req, res, next) => {
5
+ if (!req.user || !req.user.isLoggedIn()) {
6
+ throw Boom.unauthorized('Invalid Token');
7
+ }
8
+
9
+ next();
10
+ };
11
+
12
+ module.exports = { requireLoggedInUser };
@@ -0,0 +1,41 @@
1
+ const express = require('express');
2
+ const { createAppHandler } = require('../app-handler-helpers');
3
+ const { checkRequiredParams } = require('@friggframework/core');
4
+ const { User } = require('../backend-utils');
5
+ const catchAsyncError = require('express-async-handler');
6
+
7
+ const router = express();
8
+
9
+ // define the login endpoint
10
+ router.route('/user/login').post(
11
+ catchAsyncError(async (req, res) => {
12
+ const { username, password } = checkRequiredParams(req.body, [
13
+ 'username',
14
+ 'password',
15
+ ]);
16
+ const user = await User.loginUser({ username, password });
17
+ const token = await user.createUserToken(120);
18
+ res.status(201);
19
+ res.json({ token });
20
+ })
21
+ );
22
+
23
+ router.route('/user/create').post(
24
+ catchAsyncError(async (req, res) => {
25
+ const { username, password } = checkRequiredParams(req.body, [
26
+ 'username',
27
+ 'password',
28
+ ]);
29
+ const user = await User.createIndividualUser({
30
+ username,
31
+ password,
32
+ });
33
+ const token = await user.createUserToken(120);
34
+ res.status(201);
35
+ res.json({ token });
36
+ })
37
+ );
38
+
39
+ const handler = createAppHandler('HTTP Event: User', router);
40
+
41
+ module.exports = { handler, router };
@@ -0,0 +1,55 @@
1
+ const { createHandler } = require('@friggframework/core');
2
+ const { WebsocketConnection } = require('@friggframework/core');
3
+
4
+ const handleWebSocketConnection = async (event, context) => {
5
+ // Handle different WebSocket events
6
+ switch (event.requestContext.eventType) {
7
+ case 'CONNECT':
8
+ // Handle new connection
9
+ try {
10
+ const connectionId = event.requestContext.connectionId;
11
+ await WebsocketConnection.create({ connectionId });
12
+ console.log(`Stored new connection: ${connectionId}`);
13
+ return { statusCode: 200, body: 'Connected.' };
14
+ } catch (error) {
15
+ console.error('Error storing connection:', error);
16
+ return { statusCode: 500, body: 'Error connecting.' };
17
+ }
18
+
19
+ case 'DISCONNECT':
20
+ // Handle disconnection
21
+ try {
22
+ const connectionId = event.requestContext.connectionId;
23
+ await WebsocketConnection.deleteOne({ connectionId });
24
+ console.log(`Removed connection: ${connectionId}`);
25
+ return { statusCode: 200, body: 'Disconnected.' };
26
+ } catch (error) {
27
+ console.error('Error removing connection:', error);
28
+ return { statusCode: 500, body: 'Error disconnecting.' };
29
+ }
30
+
31
+ case 'MESSAGE':
32
+ // Handle incoming message
33
+ const message = JSON.parse(event.body);
34
+ console.log('Received message:', message);
35
+
36
+ // Process the message and send a response
37
+ const responseMessage = { message: 'Message received' };
38
+ return {
39
+ statusCode: 200,
40
+ body: JSON.stringify(responseMessage),
41
+ };
42
+
43
+ default:
44
+ return { statusCode: 400, body: 'Unhandled event type.' };
45
+ }
46
+ };
47
+
48
+ const handler = createHandler({
49
+ eventName: 'WebSocket Event',
50
+ method: handleWebSocketConnection,
51
+ shouldUseDatabase: true, // Set to true as we're using the database
52
+ isUserFacingResponse: true, // This is a server-to-server response
53
+ });
54
+
55
+ module.exports = { handler };
@@ -0,0 +1,24 @@
1
+ const { createHandler } = require('@friggframework/core');
2
+ const { integrationFactory, createQueueWorker } = require('../backend-utils');
3
+
4
+ const handlers = {};
5
+ integrationFactory.integrationClasses.forEach((IntegrationClass) => {
6
+ const defaultQueueWorker = createQueueWorker(IntegrationClass, integrationFactory);
7
+
8
+ handlers[`${IntegrationClass.Definition.name}`] = {
9
+ queueWorker: createHandler({
10
+ eventName: `Queue Worker for ${IntegrationClass.Definition.name}`,
11
+ isUserFacingResponse: false,
12
+ method: async (event, context) => {
13
+ const worker = new defaultQueueWorker();
14
+ await worker.run(event, context);
15
+ return {
16
+ message: 'Successfully processed the Generic Queue Worker',
17
+ input: event,
18
+ };
19
+ },
20
+ }),
21
+ };
22
+ });
23
+
24
+ module.exports = { handlers };
package/index.js CHANGED
@@ -59,6 +59,7 @@ const {
59
59
  ModuleFactory,
60
60
  Auther,
61
61
  } = require('./module-plugin/index');
62
+ const utils = require('./utils');
62
63
 
63
64
  // const {Sync } = require('./syncs/model');
64
65
 
@@ -137,4 +138,7 @@ module.exports = {
137
138
 
138
139
  // queues
139
140
  QueuerUtil,
141
+
142
+ // utils
143
+ ...utils,
140
144
  };
@@ -7,7 +7,11 @@ function createIntegrationRouter(params) {
7
7
  const router = get(params, 'router', express());
8
8
  const factory = get(params, 'factory');
9
9
  const getUserId = get(params, 'getUserId', (req) => null);
10
- const requireLoggedInUser = get(params, 'requireLoggedInUser', (req, res, next) => next());
10
+ const requireLoggedInUser = get(
11
+ params,
12
+ 'requireLoggedInUser',
13
+ (req, res, next) => next()
14
+ );
11
15
 
12
16
  router.all('/api/entities*', requireLoggedInUser);
13
17
  router.all('/api/authorize', requireLoggedInUser);
@@ -43,22 +47,23 @@ function checkRequiredParams(params, requiredKeys) {
43
47
  }
44
48
 
45
49
  function setIntegrationRoutes(router, factory, getUserId) {
46
- const {moduleFactory, integrationFactory, IntegrationHelper} = factory;
50
+ const { moduleFactory, integrationFactory, IntegrationHelper } = factory;
47
51
  router.route('/api/integrations').get(
48
52
  catchAsyncError(async (req, res) => {
49
53
  const results = await integrationFactory.getIntegrationOptions();
50
- results.entities.authorized = await moduleFactory.getEntitiesForUser(
51
- getUserId(req)
52
- );
53
- results.integrations = await IntegrationHelper.getIntegrationsForUserId(
54
- getUserId(req)
55
- );
54
+ results.entities.authorized =
55
+ await moduleFactory.getEntitiesForUser(getUserId(req));
56
+ results.integrations =
57
+ await IntegrationHelper.getIntegrationsForUserId(
58
+ getUserId(req)
59
+ );
56
60
 
57
61
  for (const integrationRecord of results.integrations) {
58
- const integration = await integrationFactory.getInstanceFromIntegrationId({
59
- integrationId: integrationRecord.id,
60
- userId: getUserId(req),
61
- });
62
+ const integration =
63
+ await integrationFactory.getInstanceFromIntegrationId({
64
+ integrationId: integrationRecord.id,
65
+ userId: getUserId(req),
66
+ });
62
67
  integrationRecord.userActions = integration.userActions;
63
68
  }
64
69
  res.json(results);
@@ -75,21 +80,22 @@ function setIntegrationRoutes(router, factory, getUserId) {
75
80
  get(params.config, 'type');
76
81
 
77
82
  // create integration
78
- const integration =
79
- await integrationFactory.createIntegration(
80
- params.entities,
81
- getUserId(req),
82
- params.config,
83
- );
83
+ const integration = await integrationFactory.createIntegration(
84
+ params.entities,
85
+ getUserId(req),
86
+ params.config
87
+ );
84
88
 
85
89
  // post integration initialization
86
90
  debug(
87
91
  `Calling onCreate on the ${integration?.constructor?.Config?.name} Integration with no arguments`
88
92
  );
89
- await integration.onCreate();
93
+ await integration.send('ON_CREATE', {});
90
94
 
91
95
  res.status(201).json(
92
- await IntegrationHelper.getFormattedIntegration(integration.record)
96
+ await IntegrationHelper.getFormattedIntegration(
97
+ integration.record
98
+ )
93
99
  );
94
100
  })
95
101
  );
@@ -108,19 +114,19 @@ function setIntegrationRoutes(router, factory, getUserId) {
108
114
  `Calling onUpdate on the ${integration?.constructor?.Config?.name} Integration arguments: `,
109
115
  params
110
116
  );
111
- await integration.onUpdate(params);
117
+ await integration.send('ON_UPDATE', params);
112
118
 
113
119
  res.json(
114
- await IntegrationHelper.getFormattedIntegration(integration.record)
120
+ await IntegrationHelper.getFormattedIntegration(
121
+ integration.record
122
+ )
115
123
  );
116
124
  })
117
125
  );
118
126
 
119
127
  router.route('/api/integrations/:integrationId').delete(
120
128
  catchAsyncError(async (req, res) => {
121
- const params = checkRequiredParams(req.params, [
122
- 'integrationId',
123
- ]);
129
+ const params = checkRequiredParams(req.params, ['integrationId']);
124
130
  const integration =
125
131
  await integrationFactory.getInstanceFromIntegrationId({
126
132
  userId: getUserId(req),
@@ -128,9 +134,9 @@ function setIntegrationRoutes(router, factory, getUserId) {
128
134
  });
129
135
 
130
136
  debug(
131
- `Calling onUpdate on the ${integration?.constructor?.Config?.name} Integration with no arguments`
137
+ `Calling onUpdate on the ${integration?.constructor?.Definition?.name} Integration with no arguments`
132
138
  );
133
- await integration.onDelete();
139
+ await integration.send('ON_DELETE');
134
140
  await IntegrationHelper.deleteIntegrationForUserById(
135
141
  getUserId(req),
136
142
  params.integrationId
@@ -142,79 +148,101 @@ function setIntegrationRoutes(router, factory, getUserId) {
142
148
 
143
149
  router.route('/api/integrations/:integrationId/config/options').get(
144
150
  catchAsyncError(async (req, res) => {
145
- const params = checkRequiredParams(req.params, [
146
- 'integrationId',
147
- ]);
151
+ const params = checkRequiredParams(req.params, ['integrationId']);
148
152
  const integration =
149
153
  await integrationFactory.getInstanceFromIntegrationId(params);
150
- res.json(await integration.getConfigOptions());
154
+ res.json(await integration.send('GET_CONFIG_OPTIONS'));
151
155
  })
152
156
  );
153
157
 
154
- router.route('/api/integrations/:integrationId/config/options/refresh').post(
155
- catchAsyncError(async (req, res) => {
156
- const params = checkRequiredParams(req.params, [
157
- 'integrationId',
158
- ]);
159
- const integration =
160
- await integrationFactory.getInstanceFromIntegrationId(params);
161
-
162
- res.json(
163
- await integration.refreshConfigOptions(req.body)
164
- );
165
- })
166
- );
167
-
168
- router.route('/api/integrations/:integrationId/actions/:actionId/options').get(
158
+ router
159
+ .route('/api/integrations/:integrationId/config/options/refresh')
160
+ .post(
161
+ catchAsyncError(async (req, res) => {
162
+ const params = checkRequiredParams(req.params, [
163
+ 'integrationId',
164
+ ]);
165
+ const integration =
166
+ await integrationFactory.getInstanceFromIntegrationId(
167
+ params
168
+ );
169
+
170
+ res.json(
171
+ await integration.send('REFRESH_CONFIG_OPTIONS', req.body)
172
+ );
173
+ })
174
+ );
175
+ router.route('/api/integrations/:integrationId/actions').all(
169
176
  catchAsyncError(async (req, res) => {
170
- const params = checkRequiredParams(req.params, [
171
- 'integrationId',
172
- 'actionId'
173
- ]);
177
+ const params = checkRequiredParams(req.params, ['integrationId']);
174
178
  const integration =
175
179
  await integrationFactory.getInstanceFromIntegrationId(params);
176
-
177
- res.json(
178
- await integration.getActionOptions(params.actionId)
179
- );
180
+ res.json(await integration.send('GET_USER_ACTIONS', req.body));
180
181
  })
181
182
  );
182
183
 
183
- router.route('/api/integrations/:integrationId/actions/:actionId/options/refresh').post(
184
- catchAsyncError(async (req, res) => {
185
- const params = checkRequiredParams(req.params, [
186
- 'integrationId',
187
- 'actionId'
188
- ]);
189
- const integration =
190
- await integrationFactory.getInstanceFromIntegrationId(params);
184
+ router
185
+ .route('/api/integrations/:integrationId/actions/:actionId/options')
186
+ .all(
187
+ catchAsyncError(async (req, res) => {
188
+ const params = checkRequiredParams(req.params, [
189
+ 'integrationId',
190
+ 'actionId',
191
+ ]);
192
+ const integration =
193
+ await integrationFactory.getInstanceFromIntegrationId(
194
+ params
195
+ );
196
+
197
+ res.json(
198
+ await integration.send('GET_USER_ACTION_OPTIONS', {
199
+ actionId: params.actionId,
200
+ data: req.body,
201
+ })
202
+ );
203
+ })
204
+ );
191
205
 
192
- res.json(
193
- await integration.refreshActionOptions(params.actionId, req.body)
194
- );
195
- })
196
- );
206
+ router
207
+ .route(
208
+ '/api/integrations/:integrationId/actions/:actionId/options/refresh'
209
+ )
210
+ .post(
211
+ catchAsyncError(async (req, res) => {
212
+ const params = checkRequiredParams(req.params, [
213
+ 'integrationId',
214
+ 'actionId',
215
+ ]);
216
+ const integration =
217
+ await integrationFactory.getInstanceFromIntegrationId(
218
+ params
219
+ );
220
+
221
+ res.json(
222
+ await integration.send('REFRESH_USER_ACTION_OPTIONS', {
223
+ actionId: params.actionId,
224
+ data: req.body,
225
+ })
226
+ );
227
+ })
228
+ );
197
229
 
198
230
  router.route('/api/integrations/:integrationId/actions/:actionId').post(
199
231
  catchAsyncError(async (req, res) => {
200
232
  const params = checkRequiredParams(req.params, [
201
233
  'integrationId',
202
- 'actionId'
234
+ 'actionId',
203
235
  ]);
204
236
  const integration =
205
237
  await integrationFactory.getInstanceFromIntegrationId(params);
206
238
 
207
- res.json(
208
- await integration.notify(params.actionId, req.body)
209
- );
239
+ res.json(await integration.send(params.actionId, req.body));
210
240
  })
211
241
  );
212
242
 
213
243
  router.route('/api/integrations/:integrationId').get(
214
244
  catchAsyncError(async (req, res) => {
215
- const params = checkRequiredParams(req.params, [
216
- 'integrationId',
217
- ]);
245
+ const params = checkRequiredParams(req.params, ['integrationId']);
218
246
  const integration = await IntegrationHelper.getIntegrationById(
219
247
  params.integrationId
220
248
  );
@@ -231,13 +259,12 @@ function setIntegrationRoutes(router, factory, getUserId) {
231
259
 
232
260
  router.route('/api/integrations/:integrationId/test-auth').get(
233
261
  catchAsyncError(async (req, res) => {
234
- const params = checkRequiredParams(req.params, [
235
- 'integrationId',
236
- ]);
237
- const instance = await integrationFactory.getInstanceFromIntegrationId({
238
- userId: getUserId(req),
239
- integrationId: params.integrationId,
240
- });
262
+ const params = checkRequiredParams(req.params, ['integrationId']);
263
+ const instance =
264
+ await integrationFactory.getInstanceFromIntegrationId({
265
+ userId: getUserId(req),
266
+ integrationId: params.integrationId,
267
+ });
241
268
 
242
269
  if (!instance) {
243
270
  throw Boom.notFound();
@@ -260,7 +287,7 @@ function setIntegrationRoutes(router, factory, getUserId) {
260
287
  }
261
288
 
262
289
  function setEntityRoutes(router, factory, getUserId) {
263
- const {moduleFactory, IntegrationHelper} = factory;
290
+ const { moduleFactory, IntegrationHelper } = factory;
264
291
  const getModuleInstance = async (req, entityType) => {
265
292
  if (!moduleFactory.checkIsValidType(entityType)) {
266
293
  throw Boom.badRequest(
@@ -269,14 +296,15 @@ function setEntityRoutes(router, factory, getUserId) {
269
296
  )}`
270
297
  );
271
298
  }
272
- return await moduleFactory.getInstanceFromTypeName(entityType, getUserId(req));
299
+ return await moduleFactory.getInstanceFromTypeName(
300
+ entityType,
301
+ getUserId(req)
302
+ );
273
303
  };
274
304
 
275
305
  router.route('/api/authorize').get(
276
306
  catchAsyncError(async (req, res) => {
277
- const params = checkRequiredParams(req.query, [
278
- 'entityType',
279
- ]);
307
+ const params = checkRequiredParams(req.query, ['entityType']);
280
308
  const module = await getModuleInstance(req, params.entityType);
281
309
  const areRequirementsValid =
282
310
  module.validateAuthorizationRequirements();
@@ -330,11 +358,9 @@ function setEntityRoutes(router, factory, getUserId) {
330
358
  null,
331
359
  null,
332
360
  getUserId(req)
333
- )
334
-
335
- res.json(
336
- await module.findOrCreateEntity(entityDetails)
337
361
  );
362
+
363
+ res.json(await module.findOrCreateEntity(entityDetails));
338
364
  })
339
365
  );
340
366
 
@@ -349,9 +375,7 @@ function setEntityRoutes(router, factory, getUserId) {
349
375
  throw Boom.forbidden('Credential does not belong to user');
350
376
  }
351
377
 
352
- const params = checkRequiredParams(req.query, [
353
- 'entityType',
354
- ]);
378
+ const params = checkRequiredParams(req.query, ['entityType']);
355
379
  const module = await getModuleInstance(req, params.entityType);
356
380
 
357
381
  res.json(await module.getEntityOptions());
@@ -384,7 +408,7 @@ function setEntityRoutes(router, factory, getUserId) {
384
408
  ],
385
409
  });
386
410
  } else {
387
- res.json({status: 'ok'});
411
+ res.json({ status: 'ok' });
388
412
  }
389
413
  })
390
414
  );
@@ -409,7 +433,7 @@ function setEntityRoutes(router, factory, getUserId) {
409
433
  catchAsyncError(async (req, res) => {
410
434
  const params = checkRequiredParams(req.params, [
411
435
  'entityId',
412
- getUserId(req)
436
+ getUserId(req),
413
437
  ]);
414
438
  const module = await moduleFactory.getModuleInstanceFromEntityId(
415
439
  params.entityId,
@@ -428,7 +452,7 @@ function setEntityRoutes(router, factory, getUserId) {
428
452
  catchAsyncError(async (req, res) => {
429
453
  const params = checkRequiredParams(req.params, [
430
454
  'entityId',
431
- getUserId(req)
455
+ getUserId(req),
432
456
  ]);
433
457
  const module = await moduleFactory.getModuleInstanceFromEntityId(
434
458
  params.entityId,
@@ -1,6 +1,5 @@
1
1
  const { RequiredPropertyError } = require('../errors');
2
2
  const { get, getAndVerifyType } = require('../assertions');
3
- const { ModuleManager } = require('../module-plugin');
4
3
 
5
4
  class Options {
6
5
  constructor(params) {
@@ -18,7 +17,7 @@ class Options {
18
17
  }
19
18
 
20
19
  this.display = {};
21
- this.display.name = get(params.display, 'name');
20
+ this.display.name = get(params.display, 'label');
22
21
  this.display.description = get(params.display, 'description');
23
22
  this.display.detailsUrl = get(params.display, 'detailsUrl');
24
23
  this.display.icon = get(params.display, 'icon');
@@ -26,7 +25,7 @@ class Options {
26
25
 
27
26
  get() {
28
27
  return {
29
- type: this.module.getName(),
28
+ type: this.module.definition.getName(),
30
29
 
31
30
  // Flag for if the User can configure any settings
32
31
  hasUserConfig: this.hasUserConfig,