@friggframework/core 2.0.0--canary.397.4957a89.0 → 2.0.0--canary.398.bdb6d27.0
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 +50 -931
- package/core/create-handler.js +0 -1
- package/database/models/WebsocketConnection.js +5 -0
- package/handlers/app-handler-helpers.js +3 -0
- package/handlers/backend-utils.js +34 -35
- package/handlers/routers/auth.js +14 -3
- package/handlers/routers/integration-defined-routers.js +5 -8
- package/handlers/routers/middleware/loadUser.js +15 -0
- package/handlers/routers/middleware/requireLoggedInUser.js +12 -0
- package/handlers/routers/user.js +5 -25
- package/handlers/workers/integration-defined-workers.js +3 -6
- package/index.js +16 -1
- package/integrations/create-frigg-backend.js +31 -0
- package/integrations/index.js +5 -0
- package/integrations/integration-base.js +44 -42
- package/integrations/integration-factory.js +251 -0
- package/integrations/integration-router.js +178 -301
- package/integrations/integration-user.js +144 -0
- package/integrations/options.js +1 -1
- package/integrations/test/integration-base.test.js +144 -0
- package/module-plugin/auther.js +393 -0
- package/module-plugin/entity-manager.js +70 -0
- package/{modules → module-plugin}/index.js +8 -0
- package/module-plugin/manager.js +169 -0
- package/module-plugin/module-factory.js +61 -0
- package/{modules → module-plugin}/test/mock-api/api.js +3 -8
- package/{modules → module-plugin}/test/mock-api/definition.js +8 -12
- package/package.json +5 -5
- package/syncs/sync.js +1 -0
- package/types/integrations/index.d.ts +6 -2
- package/types/module-plugin/index.d.ts +56 -4
- package/types/syncs/index.d.ts +2 -0
- package/credential/credential-repository.js +0 -42
- package/credential/use-cases/get-credential-for-user.js +0 -21
- package/credential/use-cases/update-authentication-status.js +0 -15
- package/handlers/app-definition-loader.js +0 -38
- package/integrations/integration-repository.js +0 -67
- package/integrations/integration.js +0 -233
- package/integrations/tests/doubles/dummy-integration-class.js +0 -90
- package/integrations/tests/doubles/test-integration-repository.js +0 -89
- package/integrations/tests/use-cases/create-integration.test.js +0 -124
- package/integrations/tests/use-cases/delete-integration-for-user.test.js +0 -143
- package/integrations/tests/use-cases/get-integration-for-user.test.js +0 -143
- package/integrations/tests/use-cases/get-integration-instance.test.js +0 -169
- package/integrations/tests/use-cases/get-integrations-for-user.test.js +0 -169
- package/integrations/tests/use-cases/get-possible-integrations.test.js +0 -188
- package/integrations/tests/use-cases/update-integration-messages.test.js +0 -142
- package/integrations/tests/use-cases/update-integration-status.test.js +0 -103
- package/integrations/tests/use-cases/update-integration.test.js +0 -134
- package/integrations/use-cases/create-integration.js +0 -72
- package/integrations/use-cases/delete-integration-for-user.js +0 -73
- package/integrations/use-cases/get-integration-for-user.js +0 -79
- package/integrations/use-cases/get-integration-instance.js +0 -84
- package/integrations/use-cases/get-integrations-for-user.js +0 -77
- package/integrations/use-cases/get-possible-integrations.js +0 -27
- package/integrations/use-cases/index.js +0 -11
- package/integrations/use-cases/update-integration-messages.js +0 -31
- package/integrations/use-cases/update-integration-status.js +0 -28
- package/integrations/use-cases/update-integration.js +0 -92
- package/integrations/utils/map-integration-dto.js +0 -36
- package/modules/module-factory.js +0 -54
- package/modules/module-repository.js +0 -107
- package/modules/module.js +0 -221
- package/modules/tests/doubles/test-module-factory.js +0 -16
- package/modules/tests/doubles/test-module-repository.js +0 -19
- package/modules/use-cases/get-entities-for-user.js +0 -32
- package/modules/use-cases/get-entity-options-by-id.js +0 -58
- package/modules/use-cases/get-entity-options-by-type.js +0 -34
- package/modules/use-cases/get-module-instance-from-type.js +0 -31
- package/modules/use-cases/get-module.js +0 -56
- package/modules/use-cases/process-authorization-callback.js +0 -114
- package/modules/use-cases/refresh-entity-options.js +0 -58
- package/modules/use-cases/test-module-auth.js +0 -54
- package/modules/utils/map-module-dto.js +0 -18
- package/user/tests/doubles/test-user-repository.js +0 -72
- package/user/tests/use-cases/create-individual-user.test.js +0 -24
- package/user/tests/use-cases/create-organization-user.test.js +0 -28
- package/user/tests/use-cases/create-token-for-user-id.test.js +0 -19
- package/user/tests/use-cases/get-user-from-bearer-token.test.js +0 -64
- package/user/tests/use-cases/login-user.test.js +0 -140
- package/user/use-cases/create-individual-user.js +0 -61
- package/user/use-cases/create-organization-user.js +0 -47
- package/user/use-cases/create-token-for-user-id.js +0 -30
- package/user/use-cases/get-user-from-bearer-token.js +0 -77
- package/user/use-cases/login-user.js +0 -122
- package/user/user-repository.js +0 -62
- package/user/user.js +0 -77
- /package/{modules → module-plugin}/ModuleConstants.js +0 -0
- /package/{modules → module-plugin}/credential.js +0 -0
- /package/{modules → module-plugin}/entity.js +0 -0
- /package/{modules → module-plugin}/requester/api-key.js +0 -0
- /package/{modules → module-plugin}/requester/basic.js +0 -0
- /package/{modules → module-plugin}/requester/oauth-2.js +0 -0
- /package/{modules → module-plugin}/requester/requester.js +0 -0
- /package/{modules → module-plugin}/requester/requester.test.js +0 -0
- /package/{modules → module-plugin}/test/auther.test.js +0 -0
- /package/{modules → module-plugin}/test/mock-api/mocks/hubspot.js +0 -0
package/core/create-handler.js
CHANGED
|
@@ -34,7 +34,6 @@ const createHandler = (optionByName = {}) => {
|
|
|
34
34
|
// Helps mongoose reuse the connection. Lowers response times.
|
|
35
35
|
context.callbackWaitsForEmptyEventLoop = false;
|
|
36
36
|
|
|
37
|
-
// todo: this should not be necessary anymore
|
|
38
37
|
if (shouldUseDatabase) {
|
|
39
38
|
await connectToDatabase();
|
|
40
39
|
}
|
|
@@ -8,6 +8,11 @@ const schema = new mongoose.Schema({
|
|
|
8
8
|
// Add a static method to get active connections
|
|
9
9
|
schema.statics.getActiveConnections = async function () {
|
|
10
10
|
try {
|
|
11
|
+
// Return empty array if websockets are not configured
|
|
12
|
+
if (!process.env.WEBSOCKET_API_ENDPOINT) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
|
|
11
16
|
const connections = await this.find({}, 'connectionId');
|
|
12
17
|
return connections.map((conn) => ({
|
|
13
18
|
connectionId: conn.connectionId,
|
|
@@ -3,6 +3,7 @@ const express = require('express');
|
|
|
3
3
|
const bodyParser = require('body-parser');
|
|
4
4
|
const cors = require('cors');
|
|
5
5
|
const Boom = require('@hapi/boom');
|
|
6
|
+
const loadUserManager = require('./routers/middleware/loadUser');
|
|
6
7
|
const serverlessHttp = require('serverless-http');
|
|
7
8
|
|
|
8
9
|
const createApp = (applyMiddleware) => {
|
|
@@ -19,6 +20,8 @@ const createApp = (applyMiddleware) => {
|
|
|
19
20
|
})
|
|
20
21
|
);
|
|
21
22
|
|
|
23
|
+
app.use(loadUserManager);
|
|
24
|
+
|
|
22
25
|
if (applyMiddleware) applyMiddleware(app);
|
|
23
26
|
|
|
24
27
|
// Handle sending error response and logging server errors to console
|
|
@@ -1,12 +1,24 @@
|
|
|
1
|
+
const { createFriggBackend, Worker } = require('@friggframework/core');
|
|
2
|
+
const { findNearestBackendPackageJson } = require('@friggframework/core/utils');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const fs = require('fs-extra');
|
|
5
|
+
|
|
6
|
+
const backendPath = findNearestBackendPackageJson();
|
|
7
|
+
if (!backendPath) {
|
|
8
|
+
throw new Error('Could not find backend package.json');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const backendDir = path.dirname(backendPath);
|
|
12
|
+
const backendFilePath = path.join(backendDir, 'index.js');
|
|
13
|
+
if (!fs.existsSync(backendFilePath)) {
|
|
14
|
+
throw new Error('Could not find index.js');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const backendJsFile = require(backendFilePath);
|
|
1
18
|
const { Router } = require('express');
|
|
2
|
-
const
|
|
3
|
-
const { loadAppDefinition } = require('./app-definition-loader');
|
|
4
|
-
const { IntegrationRepository } = require('../integrations/integration-repository');
|
|
5
|
-
const { ModuleFactory } = require('../modules/module-factory');
|
|
6
|
-
const { GetIntegrationInstance } = require('../integrations/use-cases/get-integration-instance');
|
|
7
|
-
const { getModulesDefinitionFromIntegrationClasses } = require('../integrations/utils/map-integration-dto');
|
|
8
|
-
const { ModuleRepository } = require('../modules/module-repository');
|
|
19
|
+
const appDefinition = backendJsFile.Definition;
|
|
9
20
|
|
|
21
|
+
const backend = createFriggBackend(appDefinition);
|
|
10
22
|
const loadRouterFromObject = (IntegrationClass, routerObject) => {
|
|
11
23
|
const router = Router();
|
|
12
24
|
const { path, method, event } = routerObject;
|
|
@@ -15,10 +27,10 @@ const loadRouterFromObject = (IntegrationClass, routerObject) => {
|
|
|
15
27
|
);
|
|
16
28
|
router[method.toLowerCase()](path, async (req, res, next) => {
|
|
17
29
|
try {
|
|
18
|
-
const integration = new IntegrationClass();
|
|
30
|
+
const integration = new IntegrationClass({});
|
|
19
31
|
await integration.loadModules();
|
|
20
32
|
await integration.registerEventHandlers();
|
|
21
|
-
const result = await integration.send(event, {
|
|
33
|
+
const result = await integration.send(event, {req, res, next});
|
|
22
34
|
res.json(result);
|
|
23
35
|
} catch (error) {
|
|
24
36
|
next(error);
|
|
@@ -27,43 +39,29 @@ const loadRouterFromObject = (IntegrationClass, routerObject) => {
|
|
|
27
39
|
|
|
28
40
|
return router;
|
|
29
41
|
};
|
|
30
|
-
|
|
31
|
-
//todo: this should be in a use case class
|
|
32
|
-
const createQueueWorker = (integrationClass) => {
|
|
42
|
+
const createQueueWorker = (integrationClass, integrationFactory) => {
|
|
33
43
|
class QueueWorker extends Worker {
|
|
34
44
|
async _run(params, context) {
|
|
35
45
|
try {
|
|
36
|
-
let
|
|
46
|
+
let instance;
|
|
37
47
|
if (!params.integrationId) {
|
|
38
|
-
|
|
39
|
-
await
|
|
40
|
-
await
|
|
48
|
+
instance = new integrationClass({});
|
|
49
|
+
await instance.loadModules();
|
|
50
|
+
// await instance.loadUserActions();
|
|
51
|
+
await instance.registerEventHandlers();
|
|
41
52
|
console.log(
|
|
42
53
|
`${params.event} for ${integrationClass.Definition.name} integration with no integrationId`
|
|
43
54
|
);
|
|
44
55
|
} else {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
moduleRepository,
|
|
50
|
-
moduleDefinitions: getModulesDefinitionFromIntegrationClasses(integrationClasses),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const getIntegrationInstance = new GetIntegrationInstance({
|
|
54
|
-
integrationRepository,
|
|
55
|
-
integrationClasses,
|
|
56
|
-
moduleFactory,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// todo: are we going to have the userId available here?
|
|
60
|
-
integrationInstance = await getIntegrationInstance.execute(params.integrationId, params.userId);
|
|
56
|
+
instance =
|
|
57
|
+
await integrationFactory.getInstanceFromIntegrationId({
|
|
58
|
+
integrationId: params.integrationId,
|
|
59
|
+
});
|
|
61
60
|
console.log(
|
|
62
|
-
`${params.event} for ${
|
|
61
|
+
`${params.event} for ${instance.record.config.type} of integrationId: ${params.integrationId}`
|
|
63
62
|
);
|
|
64
63
|
}
|
|
65
|
-
|
|
66
|
-
const res = await integrationInstance.send(params.event, {
|
|
64
|
+
const res = await instance.send(params.event, {
|
|
67
65
|
data: params.data,
|
|
68
66
|
context,
|
|
69
67
|
});
|
|
@@ -81,6 +79,7 @@ const createQueueWorker = (integrationClass) => {
|
|
|
81
79
|
};
|
|
82
80
|
|
|
83
81
|
module.exports = {
|
|
82
|
+
...backend,
|
|
84
83
|
loadRouterFromObject,
|
|
85
84
|
createQueueWorker,
|
|
86
85
|
};
|
package/handlers/routers/auth.js
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
const { createIntegrationRouter } = require('@friggframework/core');
|
|
2
2
|
const { createAppHandler } = require('./../app-handler-helpers');
|
|
3
|
+
const { requireLoggedInUser } = require('./middleware/requireLoggedInUser');
|
|
4
|
+
const {
|
|
5
|
+
moduleFactory,
|
|
6
|
+
integrationFactory,
|
|
7
|
+
IntegrationHelper,
|
|
8
|
+
} = require('./../backend-utils');
|
|
3
9
|
|
|
4
|
-
const router = createIntegrationRouter(
|
|
10
|
+
const router = createIntegrationRouter({
|
|
11
|
+
factory: { moduleFactory, integrationFactory, IntegrationHelper },
|
|
12
|
+
requireLoggedInUser,
|
|
13
|
+
getUserId: (req) => req.user.getUserId(),
|
|
14
|
+
});
|
|
5
15
|
|
|
6
16
|
router.route('/redirect/:appId').get((req, res) => {
|
|
7
17
|
res.redirect(
|
|
8
|
-
`${process.env.FRONTEND_URI}/redirect/${
|
|
18
|
+
`${process.env.FRONTEND_URI}/redirect/${
|
|
19
|
+
req.params.appId
|
|
9
20
|
}?${new URLSearchParams(req.query)}`
|
|
10
21
|
);
|
|
11
22
|
});
|
|
12
23
|
|
|
13
24
|
const handler = createAppHandler('HTTP Event: Auth', router);
|
|
14
25
|
|
|
15
|
-
module.exports = { handler };
|
|
26
|
+
module.exports = { handler, router };
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
const { createAppHandler } = require('./../app-handler-helpers');
|
|
2
2
|
const {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
integrationFactory,
|
|
4
|
+
loadRouterFromObject,
|
|
5
|
+
} = require('./../backend-utils');
|
|
5
6
|
const { Router } = require('express');
|
|
6
|
-
const { loadRouterFromObject } = require('../backend-utils');
|
|
7
7
|
|
|
8
8
|
const handlers = {};
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
//todo: this should be in a use case class
|
|
12
|
-
for (const IntegrationClass of integrationClasses) {
|
|
9
|
+
for (const IntegrationClass of integrationFactory.integrationClasses) {
|
|
13
10
|
const router = Router();
|
|
14
11
|
const basePath = `/api/${IntegrationClass.Definition.name}-integration`;
|
|
15
|
-
|
|
12
|
+
|
|
16
13
|
console.log(`\n│ Configuring routes for ${IntegrationClass.Definition.name} Integration:`);
|
|
17
14
|
|
|
18
15
|
for (const routeDef of IntegrationClass.Definition.routes) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const catchAsyncError = require('express-async-handler');
|
|
2
|
+
const { User } = require('../../backend-utils');
|
|
3
|
+
|
|
4
|
+
module.exports = catchAsyncError(async (req, res, next) => {
|
|
5
|
+
const authorizationHeader = req.headers.authorization;
|
|
6
|
+
|
|
7
|
+
if (authorizationHeader) {
|
|
8
|
+
// Removes "Bearer " and trims
|
|
9
|
+
const token = authorizationHeader.split(' ')[1].trim();
|
|
10
|
+
// Load user for later middleware/routes to use
|
|
11
|
+
req.user = await User.newUser({ token });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return next();
|
|
15
|
+
});
|
|
@@ -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 };
|
package/handlers/routers/user.js
CHANGED
|
@@ -1,29 +1,10 @@
|
|
|
1
1
|
const express = require('express');
|
|
2
2
|
const { createAppHandler } = require('../app-handler-helpers');
|
|
3
3
|
const { checkRequiredParams } = require('@friggframework/core');
|
|
4
|
-
const {
|
|
5
|
-
const {
|
|
6
|
-
CreateIndividualUser,
|
|
7
|
-
} = require('../../user/use-cases/create-individual-user');
|
|
8
|
-
const { LoginUser } = require('../../user/use-cases/login-user');
|
|
9
|
-
const {
|
|
10
|
-
CreateTokenForUserId,
|
|
11
|
-
} = require('../../user/use-cases/create-token-for-user-id');
|
|
4
|
+
const { User } = require('../backend-utils');
|
|
12
5
|
const catchAsyncError = require('express-async-handler');
|
|
13
|
-
const { loadAppDefinition } = require('../app-definition-loader');
|
|
14
6
|
|
|
15
7
|
const router = express();
|
|
16
|
-
const { userConfig } = loadAppDefinition();
|
|
17
|
-
const userRepository = new UserRepository({ userConfig });
|
|
18
|
-
const createIndividualUser = new CreateIndividualUser({
|
|
19
|
-
userRepository,
|
|
20
|
-
userConfig,
|
|
21
|
-
});
|
|
22
|
-
const loginUser = new LoginUser({
|
|
23
|
-
userRepository,
|
|
24
|
-
userConfig,
|
|
25
|
-
});
|
|
26
|
-
const createTokenForUserId = new CreateTokenForUserId({ userRepository });
|
|
27
8
|
|
|
28
9
|
// define the login endpoint
|
|
29
10
|
router.route('/user/login').post(
|
|
@@ -32,8 +13,8 @@ router.route('/user/login').post(
|
|
|
32
13
|
'username',
|
|
33
14
|
'password',
|
|
34
15
|
]);
|
|
35
|
-
const user = await loginUser
|
|
36
|
-
const token = await
|
|
16
|
+
const user = await User.loginUser({ username, password });
|
|
17
|
+
const token = await user.createUserToken(120);
|
|
37
18
|
res.status(201);
|
|
38
19
|
res.json({ token });
|
|
39
20
|
})
|
|
@@ -45,12 +26,11 @@ router.route('/user/create').post(
|
|
|
45
26
|
'username',
|
|
46
27
|
'password',
|
|
47
28
|
]);
|
|
48
|
-
|
|
49
|
-
const user = await createIndividualUser.execute({
|
|
29
|
+
const user = await User.createIndividualUser({
|
|
50
30
|
username,
|
|
51
31
|
password,
|
|
52
32
|
});
|
|
53
|
-
const token = await
|
|
33
|
+
const token = await user.createUserToken(120);
|
|
54
34
|
res.status(201);
|
|
55
35
|
res.json({ token });
|
|
56
36
|
})
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
const { createHandler } = require('@friggframework/core');
|
|
2
|
-
const {
|
|
3
|
-
const { createQueueWorker } = require('../backend-utils');
|
|
2
|
+
const { integrationFactory, createQueueWorker } = require('../backend-utils');
|
|
4
3
|
|
|
5
4
|
const handlers = {};
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
integrationClasses.forEach((IntegrationClass) => {
|
|
9
|
-
const defaultQueueWorker = createQueueWorker(IntegrationClass);
|
|
5
|
+
integrationFactory.integrationClasses.forEach((IntegrationClass) => {
|
|
6
|
+
const defaultQueueWorker = createQueueWorker(IntegrationClass, integrationFactory);
|
|
10
7
|
|
|
11
8
|
handlers[`${IntegrationClass.Definition.name}`] = {
|
|
12
9
|
queueWorker: createHandler({
|
package/index.js
CHANGED
|
@@ -38,20 +38,27 @@ const {
|
|
|
38
38
|
IntegrationModel,
|
|
39
39
|
Options,
|
|
40
40
|
IntegrationMapping,
|
|
41
|
+
IntegrationFactory,
|
|
42
|
+
IntegrationHelper,
|
|
41
43
|
createIntegrationRouter,
|
|
42
44
|
checkRequiredParams,
|
|
45
|
+
createFriggBackend,
|
|
43
46
|
} = require('./integrations/index');
|
|
44
47
|
const { TimeoutCatcher } = require('./lambda/index');
|
|
45
48
|
const { debug, initDebugLog, flushDebugLog } = require('./logs/index');
|
|
46
49
|
const {
|
|
47
50
|
Credential,
|
|
51
|
+
EntityManager,
|
|
48
52
|
Entity,
|
|
53
|
+
ModuleManager,
|
|
49
54
|
ApiKeyRequester,
|
|
50
55
|
BasicAuthRequester,
|
|
51
56
|
OAuth2Requester,
|
|
52
57
|
Requester,
|
|
53
58
|
ModuleConstants,
|
|
54
|
-
|
|
59
|
+
ModuleFactory,
|
|
60
|
+
Auther,
|
|
61
|
+
} = require('./module-plugin/index');
|
|
55
62
|
const utils = require('./utils');
|
|
56
63
|
|
|
57
64
|
// const {Sync } = require('./syncs/model');
|
|
@@ -102,8 +109,11 @@ module.exports = {
|
|
|
102
109
|
IntegrationModel,
|
|
103
110
|
Options,
|
|
104
111
|
IntegrationMapping,
|
|
112
|
+
IntegrationFactory,
|
|
113
|
+
IntegrationHelper,
|
|
105
114
|
checkRequiredParams,
|
|
106
115
|
createIntegrationRouter,
|
|
116
|
+
createFriggBackend,
|
|
107
117
|
|
|
108
118
|
// lambda
|
|
109
119
|
TimeoutCatcher,
|
|
@@ -115,12 +125,17 @@ module.exports = {
|
|
|
115
125
|
|
|
116
126
|
// module plugin
|
|
117
127
|
Credential,
|
|
128
|
+
EntityManager,
|
|
118
129
|
Entity,
|
|
130
|
+
ModuleManager,
|
|
119
131
|
ApiKeyRequester,
|
|
120
132
|
BasicAuthRequester,
|
|
121
133
|
OAuth2Requester,
|
|
122
134
|
Requester,
|
|
123
135
|
ModuleConstants,
|
|
136
|
+
ModuleFactory,
|
|
137
|
+
Auther,
|
|
138
|
+
|
|
124
139
|
// queues
|
|
125
140
|
QueuerUtil,
|
|
126
141
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const {IntegrationFactory, IntegrationHelper} = require('./integration-factory');
|
|
2
|
+
const User = require('./integration-user');
|
|
3
|
+
|
|
4
|
+
function createFriggBackend(appDefinition) {
|
|
5
|
+
const {integrations = [], user=null} = appDefinition
|
|
6
|
+
const integrationFactory = new IntegrationFactory(integrations);
|
|
7
|
+
if (user) {
|
|
8
|
+
if (user.usePassword) {
|
|
9
|
+
User.usePassword = true;
|
|
10
|
+
}
|
|
11
|
+
if (user.primary === 'organization') {
|
|
12
|
+
User.primary = User.OrganizationUser
|
|
13
|
+
}
|
|
14
|
+
if (user.individualUserRequired !== undefined) {
|
|
15
|
+
User.individualUserRequired = user.individualUserRequired
|
|
16
|
+
}
|
|
17
|
+
if (user.organizationUserRequired !== undefined) {
|
|
18
|
+
User.organizationUserRequired = user.organizationUserRequired
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
const backend = {
|
|
23
|
+
integrationFactory,
|
|
24
|
+
moduleFactory: integrationFactory.moduleFactory,
|
|
25
|
+
IntegrationHelper,
|
|
26
|
+
User: User
|
|
27
|
+
}
|
|
28
|
+
return backend
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { createFriggBackend }
|
package/integrations/index.js
CHANGED
|
@@ -2,13 +2,18 @@ const { IntegrationBase } = require('./integration-base');
|
|
|
2
2
|
const { IntegrationModel } = require('./integration-model');
|
|
3
3
|
const { Options } = require('./options');
|
|
4
4
|
const { IntegrationMapping } = require('./integration-mapping');
|
|
5
|
+
const { IntegrationFactory, IntegrationHelper } = require('./integration-factory');
|
|
5
6
|
const { createIntegrationRouter, checkRequiredParams } = require('./integration-router');
|
|
7
|
+
const { createFriggBackend } = require('./create-frigg-backend');
|
|
6
8
|
|
|
7
9
|
module.exports = {
|
|
8
10
|
IntegrationBase,
|
|
9
11
|
IntegrationModel,
|
|
10
12
|
Options,
|
|
11
13
|
IntegrationMapping,
|
|
14
|
+
IntegrationFactory,
|
|
15
|
+
IntegrationHelper,
|
|
12
16
|
createIntegrationRouter,
|
|
13
17
|
checkRequiredParams,
|
|
18
|
+
createFriggBackend
|
|
14
19
|
};
|
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
const { IntegrationMapping } = require('./integration-mapping');
|
|
2
2
|
const { Options } = require('./options');
|
|
3
|
-
const { UpdateIntegrationStatus } = require('./use-cases/update-integration-status');
|
|
4
|
-
const { IntegrationRepository } = require('./integration-repository');
|
|
5
|
-
const { UpdateIntegrationMessages } = require('./use-cases/update-integration-messages');
|
|
6
|
-
|
|
7
3
|
const constantsToBeMigrated = {
|
|
8
4
|
defaultEvents: {
|
|
9
5
|
ON_CREATE: 'ON_CREATE',
|
|
@@ -23,12 +19,6 @@ const constantsToBeMigrated = {
|
|
|
23
19
|
};
|
|
24
20
|
|
|
25
21
|
class IntegrationBase {
|
|
26
|
-
|
|
27
|
-
// todo: maybe we can pass this as Dependency Injection in the sub-class constructor
|
|
28
|
-
integrationRepository = new IntegrationRepository();
|
|
29
|
-
updateIntegrationStatus = new UpdateIntegrationStatus({ integrationRepository: this.integrationRepository });
|
|
30
|
-
updateIntegrationMessages = new UpdateIntegrationMessages({ integrationRepository: this.integrationRepository });
|
|
31
|
-
|
|
32
22
|
static getOptionDetails() {
|
|
33
23
|
const options = new Options({
|
|
34
24
|
module: Object.values(this.Definition.modules)[0], // This is a placeholder until we revamp the frontend
|
|
@@ -36,7 +26,6 @@ class IntegrationBase {
|
|
|
36
26
|
});
|
|
37
27
|
return options.get();
|
|
38
28
|
}
|
|
39
|
-
|
|
40
29
|
/**
|
|
41
30
|
* CHILDREN SHOULD SPECIFY A DEFINITION FOR THE INTEGRATION
|
|
42
31
|
*/
|
|
@@ -61,7 +50,21 @@ class IntegrationBase {
|
|
|
61
50
|
static getCurrentVersion() {
|
|
62
51
|
return this.Definition.version;
|
|
63
52
|
}
|
|
64
|
-
|
|
53
|
+
loadModules() {
|
|
54
|
+
// Load all the modules defined in Definition.modules
|
|
55
|
+
const moduleNames = Object.keys(this.constructor.Definition.modules);
|
|
56
|
+
for (const moduleName of moduleNames) {
|
|
57
|
+
const { definition } =
|
|
58
|
+
this.constructor.Definition.modules[moduleName];
|
|
59
|
+
if (typeof definition.API === 'function') {
|
|
60
|
+
this[moduleName] = { api: new definition.API() };
|
|
61
|
+
} else {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`Module ${moduleName} must be a function that extends IntegrationModule`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
65
68
|
registerEventHandlers() {
|
|
66
69
|
this.on = {
|
|
67
70
|
...this.defaultEvents,
|
|
@@ -70,7 +73,6 @@ class IntegrationBase {
|
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
constructor(params) {
|
|
73
|
-
|
|
74
76
|
this.defaultEvents = {
|
|
75
77
|
[constantsToBeMigrated.defaultEvents.ON_CREATE]: {
|
|
76
78
|
type: constantsToBeMigrated.types.LIFE_CYCLE_EVENT,
|
|
@@ -105,6 +107,7 @@ class IntegrationBase {
|
|
|
105
107
|
handler: this.refreshActionOptions,
|
|
106
108
|
},
|
|
107
109
|
};
|
|
110
|
+
this.loadModules();
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
async send(event, object) {
|
|
@@ -118,7 +121,7 @@ class IntegrationBase {
|
|
|
118
121
|
|
|
119
122
|
async validateConfig() {
|
|
120
123
|
const configOptions = await this.getConfigOptions();
|
|
121
|
-
const currentConfig = this.
|
|
124
|
+
const currentConfig = this.record.config;
|
|
122
125
|
let needsConfig = false;
|
|
123
126
|
for (const option of configOptions) {
|
|
124
127
|
if (option.required) {
|
|
@@ -130,18 +133,17 @@ class IntegrationBase {
|
|
|
130
133
|
)
|
|
131
134
|
) {
|
|
132
135
|
needsConfig = true;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
Date.now()
|
|
139
|
-
);
|
|
136
|
+
this.record.messages.warnings.push({
|
|
137
|
+
title: 'Config Validation Error',
|
|
138
|
+
message: `Missing required field of ${option.label}`,
|
|
139
|
+
timestamp: Date.now(),
|
|
140
|
+
});
|
|
140
141
|
}
|
|
141
142
|
}
|
|
142
143
|
}
|
|
143
144
|
if (needsConfig) {
|
|
144
|
-
|
|
145
|
+
this.record.status = 'NEEDS_CONFIG';
|
|
146
|
+
await this.record.save();
|
|
145
147
|
}
|
|
146
148
|
}
|
|
147
149
|
|
|
@@ -153,36 +155,34 @@ class IntegrationBase {
|
|
|
153
155
|
await this[module].testAuth();
|
|
154
156
|
} catch {
|
|
155
157
|
didAuthPass = false;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
'Authentication Error',
|
|
160
|
-
`There was an error with your ${this[
|
|
158
|
+
this.record.messages.errors.push({
|
|
159
|
+
title: 'Authentication Error',
|
|
160
|
+
message: `There was an error with your ${this[
|
|
161
161
|
module
|
|
162
162
|
].constructor.getName()} Entity.
|
|
163
163
|
Please reconnect/re-authenticate, or reach out to Support for assistance.`,
|
|
164
|
-
Date.now()
|
|
165
|
-
);
|
|
164
|
+
timestamp: Date.now(),
|
|
165
|
+
});
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
if (!didAuthPass) {
|
|
170
|
-
|
|
170
|
+
this.record.status = 'ERROR';
|
|
171
|
+
this.record.markModified('messages.error');
|
|
172
|
+
await this.record.save();
|
|
171
173
|
}
|
|
172
174
|
}
|
|
173
175
|
|
|
174
176
|
async getMapping(sourceId) {
|
|
175
|
-
|
|
176
|
-
return IntegrationMapping.findBy(this.id, sourceId);
|
|
177
|
+
return IntegrationMapping.findBy(this.record.id, sourceId);
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
async upsertMapping(sourceId, mapping) {
|
|
180
181
|
if (!sourceId) {
|
|
181
182
|
throw new Error(`sourceId must be set`);
|
|
182
183
|
}
|
|
183
|
-
// todo: this should be a use case
|
|
184
184
|
return await IntegrationMapping.upsert(
|
|
185
|
-
this.id,
|
|
185
|
+
this.record.id,
|
|
186
186
|
sourceId,
|
|
187
187
|
mapping
|
|
188
188
|
);
|
|
@@ -191,13 +191,15 @@ class IntegrationBase {
|
|
|
191
191
|
/**
|
|
192
192
|
* CHILDREN CAN OVERRIDE THESE CONFIGURATION METHODS
|
|
193
193
|
*/
|
|
194
|
-
async onCreate(
|
|
195
|
-
|
|
194
|
+
async onCreate(params) {
|
|
195
|
+
this.record.status = 'ENABLED';
|
|
196
|
+
await this.record.save();
|
|
197
|
+
return this.record;
|
|
196
198
|
}
|
|
197
199
|
|
|
198
|
-
async onUpdate(params) {
|
|
200
|
+
async onUpdate(params) {}
|
|
199
201
|
|
|
200
|
-
async onDelete(params) {
|
|
202
|
+
async onDelete(params) {}
|
|
201
203
|
|
|
202
204
|
async getConfigOptions() {
|
|
203
205
|
const options = {
|
|
@@ -234,10 +236,10 @@ class IntegrationBase {
|
|
|
234
236
|
const dynamicUserActions = await this.loadDynamicUserActions();
|
|
235
237
|
const filteredDynamicActions = actionType
|
|
236
238
|
? Object.fromEntries(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
239
|
+
Object.entries(dynamicUserActions).filter(
|
|
240
|
+
([_, event]) => event.userActionType === actionType
|
|
241
|
+
)
|
|
242
|
+
)
|
|
241
243
|
: dynamicUserActions;
|
|
242
244
|
return { ...userActions, ...filteredDynamicActions };
|
|
243
245
|
}
|