@friggframework/core 2.0.0--canary.550.b8b9a2b.0 → 2.0.0--canary.545.e256e95.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/CHANGELOG.md +66 -67
- package/CLAUDE.md +148 -124
- package/README.md +165 -130
- package/admin-scripts/index.js +52 -0
- package/admin-scripts/repositories/admin-api-key-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-api-key-repository-factory.js +51 -0
- package/admin-scripts/repositories/admin-api-key-repository-interface.js +121 -0
- package/admin-scripts/repositories/admin-api-key-repository-mongo.js +155 -0
- package/admin-scripts/repositories/admin-api-key-repository-postgres.js +189 -0
- package/admin-scripts/repositories/admin-process-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/admin-process-repository-factory.js +49 -0
- package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
- package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
- package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
- package/admin-scripts/repositories/script-execution-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-execution-repository-factory.js +51 -0
- package/admin-scripts/repositories/script-execution-repository-interface.js +193 -0
- package/admin-scripts/repositories/script-execution-repository-mongo.js +278 -0
- package/admin-scripts/repositories/script-execution-repository-postgres.js +320 -0
- package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
- package/admin-scripts/repositories/script-schedule-repository-factory.js +49 -0
- package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
- package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
- package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
- package/application/commands/admin-script-commands.js +348 -0
- package/application/commands/integration-commands.js +12 -6
- package/application/index.js +5 -3
- package/assertions/get.js +17 -7
- package/associations/association.js +59 -57
- package/core/CLAUDE.md +222 -156
- package/core/Worker.js +33 -12
- package/credential/credential-router.js +262 -0
- package/credential/repositories/credential-repository-documentdb.js +71 -1
- package/credential/repositories/credential-repository-factory.js +4 -6
- package/credential/repositories/credential-repository-interface.js +8 -2
- package/credential/repositories/credential-repository-mongo.js +45 -4
- package/credential/repositories/credential-repository-postgres.js +44 -3
- package/credential/repositories/credential-repository.js +3 -1
- package/credential/use-cases/delete-credential-for-user.js +50 -0
- package/credential/use-cases/get-credential-for-user.js +21 -3
- package/credential/use-cases/list-credentials-for-user.js +31 -0
- package/credential/use-cases/reauthorize-credential.js +103 -0
- package/credential/use-cases/update-authentication-status.js +5 -2
- package/database/MONGODB_TRANSACTION_FIX.md +72 -52
- package/database/config.js +13 -59
- package/database/documentdb-encryption-service.js +29 -13
- package/database/documentdb-utils.js +21 -12
- package/database/encryption/README.md +53 -36
- package/database/encryption/encryption-schema-registry.js +67 -21
- package/database/encryption/field-encryption-service.js +15 -4
- package/database/encryption/logger.js +3 -2
- package/database/encryption/prisma-encryption-extension.js +5 -8
- package/database/prisma.js +27 -16
- package/database/repositories/health-check-repository-factory.js +7 -5
- package/database/repositories/health-check-repository-interface.js +15 -5
- package/database/repositories/health-check-repository-postgres.js +1 -1
- package/database/use-cases/check-database-health-use-case.js +3 -2
- package/database/use-cases/check-database-state-use-case.js +8 -7
- package/database/use-cases/get-database-state-via-worker-use-case.js +15 -12
- package/database/use-cases/get-migration-status-use-case.js +4 -2
- package/database/use-cases/run-database-migration-use-case.js +41 -9
- package/database/use-cases/test-encryption-use-case.js +4 -5
- package/database/use-cases/trigger-database-migration-use-case.js +9 -8
- package/database/utils/mongodb-collection-utils.js +11 -3
- package/database/utils/mongodb-schema-init.js +10 -4
- package/database/utils/prisma-runner.js +144 -74
- package/database/utils/prisma-schema-parser.js +2 -2
- package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +135 -80
- package/encrypt/Cryptor.js +54 -49
- package/encrypt/aes-encryption-key-provider.js +82 -0
- package/encrypt/encryption-key-provider-interface.js +50 -0
- package/errors/fetch-error.js +1 -1
- package/extensions/bootstrap-runner.js +43 -0
- package/extensions/extension-loader.js +167 -0
- package/extensions/index.js +37 -0
- package/extensions/initialize-app.js +123 -0
- package/extensions/route-mounter.js +59 -0
- package/extensions/schema-composer.js +188 -0
- package/generated/prisma-mongodb/edge.js +60 -5
- package/generated/prisma-mongodb/index-browser.js +49 -1
- package/generated/prisma-mongodb/index.d.ts +4025 -63
- package/generated/prisma-mongodb/index.js +66 -11
- package/generated/{prisma-postgresql/query-engine-debian-openssl-3.0.x → prisma-mongodb/libquery_engine-debian-openssl-3.0.x.so.node} +0 -0
- package/generated/{prisma-postgresql/query-engine-rhel-openssl-3.0.x → prisma-mongodb/libquery_engine-rhel-openssl-3.0.x.so.node} +0 -0
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/runtime/library.js +146 -0
- package/generated/prisma-mongodb/schema.prisma +89 -2
- package/generated/prisma-mongodb/wasm.js +60 -5
- package/generated/prisma-postgresql/edge.js +59 -5
- package/generated/prisma-postgresql/index-browser.js +48 -1
- package/generated/prisma-postgresql/index.d.ts +4742 -54
- package/generated/prisma-postgresql/index.js +65 -11
- package/generated/{prisma-mongodb/query-engine-debian-openssl-3.0.x → prisma-postgresql/libquery_engine-debian-openssl-3.0.x.so.node} +0 -0
- package/generated/{prisma-mongodb/query-engine-rhel-openssl-3.0.x → prisma-postgresql/libquery_engine-rhel-openssl-3.0.x.so.node} +0 -0
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/runtime/library.js +146 -0
- package/generated/prisma-postgresql/schema.prisma +87 -2
- package/generated/prisma-postgresql/wasm.js +59 -5
- package/handlers/WEBHOOKS.md +104 -81
- package/handlers/app-definition-loader.js +53 -10
- package/handlers/app-handler-helpers.js +14 -3
- package/handlers/backend-utils.js +3 -17
- package/handlers/database-migration-handler.js +64 -45
- package/handlers/middleware/admin-auth.js +53 -0
- package/handlers/routers/HEALTHCHECK.md +170 -135
- package/handlers/routers/admin.js +474 -0
- package/handlers/routers/auth.js +51 -9
- package/handlers/routers/db-migration.handler.js +2 -3
- package/handlers/routers/db-migration.js +102 -66
- package/handlers/routers/docs.js +180 -0
- package/handlers/routers/health.js +84 -283
- package/handlers/routers/integration-defined-routers.js +44 -33
- package/handlers/routers/integration-webhook-routers.js +73 -52
- package/handlers/routers/middleware/loadUser.js +39 -0
- package/handlers/routers/middleware/requireAdmin.js +43 -0
- package/handlers/routers/middleware/requireLoggedInUser.js +19 -0
- package/handlers/routers/user.js +30 -14
- package/handlers/routers/websocket.js +18 -4
- package/handlers/use-cases/check-integrations-health-use-case.js +13 -6
- package/handlers/workers/db-migration.js +74 -35
- package/handlers/workers/integration-defined-workers.js +31 -20
- package/index.js +60 -16
- package/infrastructure/scheduler/index.js +15 -11
- package/infrastructure/scheduler/netlify-scheduler-adapter.js +185 -0
- package/infrastructure/scheduler/scheduler-service-factory.js +38 -31
- package/integrations/WEBHOOK-QUICKSTART.md +21 -14
- package/integrations/index.js +4 -0
- package/integrations/integration-base.js +9 -6
- package/integrations/integration-router.js +1841 -153
- package/integrations/options.js +47 -20
- package/integrations/repositories/integration-mapping-repository-factory.js +4 -8
- package/integrations/repositories/integration-repository-documentdb.js +53 -24
- package/integrations/repositories/integration-repository-factory.js +6 -6
- package/integrations/repositories/integration-repository-interface.js +27 -9
- package/integrations/repositories/integration-repository-postgres.js +3 -3
- package/integrations/repositories/process-repository-factory.js +4 -7
- package/integrations/repositories/process-repository-interface.js +9 -5
- package/integrations/repositories/process-repository-mongo.js +7 -3
- package/integrations/repositories/process-repository-postgres.js +2 -2
- package/integrations/tests/doubles/config-capturing-integration.js +9 -8
- package/integrations/tests/doubles/dummy-integration-class.js +81 -8
- package/integrations/tests/doubles/test-integration-repository.js +51 -11
- package/integrations/use-cases/create-integration.js +36 -32
- package/integrations/use-cases/create-process.js +20 -9
- package/integrations/use-cases/delete-integration-for-user.js +5 -4
- package/integrations/use-cases/execute-proxy-request.js +564 -0
- package/integrations/use-cases/get-integration-for-user.js +25 -10
- package/integrations/use-cases/get-integration-instance-by-definition.js +13 -7
- package/integrations/use-cases/get-integrations-for-user.js +4 -1
- package/integrations/use-cases/get-possible-integrations.js +1 -1
- package/integrations/use-cases/get-process.js +5 -6
- package/integrations/use-cases/index.js +3 -1
- package/integrations/use-cases/load-integration-context.js +1 -5
- package/integrations/use-cases/update-process-state.js +10 -8
- package/integrations/utils/map-integration-dto.js +9 -3
- package/jest-setup.js +1 -1
- package/jest-teardown.js +1 -1
- package/lambda/TimeoutCatcher.js +32 -30
- package/lambda/index.js +1 -1
- package/logs/index.js +3 -3
- package/modules/domain/entities/AuthorizationSession.js +131 -0
- package/modules/domain/entities/index.js +10 -0
- package/modules/module-factory.js +1 -1
- package/modules/module.js +44 -11
- package/modules/repositories/authorization-session-repository-factory.js +53 -0
- package/modules/repositories/authorization-session-repository-interface.js +75 -0
- package/modules/repositories/authorization-session-repository-mongo.js +169 -0
- package/modules/repositories/authorization-session-repository-postgres.js +170 -0
- package/modules/repositories/module-repository-documentdb.js +89 -41
- package/modules/repositories/module-repository-factory.js +4 -6
- package/modules/repositories/module-repository-interface.js +13 -0
- package/modules/repositories/module-repository-mongo.js +40 -5
- package/modules/repositories/module-repository-postgres.js +42 -5
- package/modules/repositories/module-repository.js +28 -0
- package/modules/requester/api-key.js +0 -2
- package/modules/requester/basic.js +0 -1
- package/modules/requester/oauth-2.js +3 -14
- package/modules/test/mock-api/definition.js +15 -10
- package/modules/test/mock-api/mocks/hubspot.js +36 -36
- package/modules/tests/doubles/test-module-factory.js +10 -4
- package/modules/tests/doubles/test-module-repository.js +1 -1
- package/modules/use-cases/delete-module-entity.js +23 -0
- package/modules/use-cases/get-authorization-requirements.js +110 -0
- package/modules/use-cases/get-entities-for-user.js +1 -1
- package/modules/use-cases/get-entity-options-by-id.js +8 -6
- package/modules/use-cases/get-module-entity-by-id.js +16 -0
- package/modules/use-cases/get-module.js +12 -9
- package/modules/use-cases/process-authorization-callback.js +12 -6
- package/modules/use-cases/process-authorization-step.js +160 -0
- package/modules/use-cases/refresh-entity-options.js +8 -6
- package/modules/use-cases/start-authorization-session.js +86 -0
- package/modules/use-cases/test-module-auth.js +8 -6
- package/modules/use-cases/update-module-entity.js +27 -0
- package/modules/utils/map-module-dto.js +2 -2
- package/openapi/openapi-spec-generator.js +370 -0
- package/openapi/openapi-v1.yaml +1360 -0
- package/openapi/openapi-v2.yaml +1535 -0
- package/package.json +7 -9
- package/prisma-mongodb/schema.prisma +89 -2
- package/prisma-postgresql/migrations/20260222000000_add_admin_process_and_script_schedule/migration.sql +55 -0
- package/prisma-postgresql/schema.prisma +87 -2
- package/providers/index.js +13 -0
- package/providers/resolve-provider.js +93 -0
- package/queues/index.js +19 -0
- package/queues/providers/index.js +7 -0
- package/queues/providers/netlify-background-provider.js +76 -0
- package/queues/providers/qstash-queue-provider.js +122 -0
- package/queues/queue-client-interface.js +55 -0
- package/queues/queue-provider-factory.js +93 -0
- package/queues/queue-provider.js +46 -0
- package/queues/queuer-util.js +33 -25
- package/syncs/repositories/sync-repository-documentdb.js +39 -19
- package/syncs/repositories/sync-repository-factory.js +4 -4
- package/syncs/repositories/sync-repository-interface.js +6 -2
- package/syncs/repositories/sync-repository-postgres.js +19 -13
- package/syncs/sync.js +104 -100
- package/token/repositories/token-repository-factory.js +4 -6
- package/types/assertions/index.d.ts +72 -72
- package/types/core/index.d.ts +98 -53
- package/types/errors/index.d.ts +61 -54
- package/types/eslint-config/index.d.ts +40 -40
- package/types/lambda/index.d.ts +26 -26
- package/types/logs/index.d.ts +4 -4
- package/types/prettier-config/index.d.ts +5 -5
- package/types/test-environment/index.d.ts +14 -14
- package/types/tsconfig.json +95 -93
- package/user/repositories/user-repository-factory.js +4 -4
- package/user/tests/doubles/test-user-repository.js +5 -2
- package/user/use-cases/authenticate-user.js +2 -4
- package/user/use-cases/authenticate-with-shared-secret.js +1 -1
- package/user/use-cases/create-individual-user.js +8 -7
- package/user/use-cases/create-organization-user.js +1 -1
- package/user/use-cases/create-token-for-user-id.js +1 -1
- package/user/use-cases/delete-user.js +47 -0
- package/user/use-cases/get-user-from-adopter-jwt.js +0 -2
- package/user/use-cases/get-user-from-bearer-token.js +7 -3
- package/user/use-cases/get-user-from-x-frigg-headers.js +14 -11
- package/user/use-cases/login-user.js +8 -8
- package/user/user.js +18 -4
- package/utils/backend-path.js +2 -2
- package/utils/index.js +4 -1
- package/websocket/repositories/websocket-connection-repository-documentdb.js +46 -21
- package/websocket/repositories/websocket-connection-repository-factory.js +4 -8
- package/websocket/repositories/websocket-connection-repository-mongo.js +26 -16
- package/websocket/repositories/websocket-connection-repository-postgres.js +26 -15
- package/websocket/repositories/websocket-connection-repository.js +26 -20
- package/websocket/websocket-message-sender-interface.js +38 -0
- package/database/adapters/lambda-invoker.js +0 -97
- package/database/repositories/migration-status-repository-s3.js +0 -137
- package/generated/prisma-mongodb/runtime/binary.d.ts +0 -1
- package/generated/prisma-mongodb/runtime/binary.js +0 -289
- package/generated/prisma-postgresql/runtime/binary.d.ts +0 -1
- package/generated/prisma-postgresql/runtime/binary.js +0 -289
- package/infrastructure/scheduler/eventbridge-scheduler-adapter.js +0 -184
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const catchAsyncError = require('express-async-handler');
|
|
2
|
+
const {
|
|
3
|
+
GetUserFromBearerToken,
|
|
4
|
+
} = require('../../../user/use-cases/get-user-from-bearer-token');
|
|
5
|
+
const {
|
|
6
|
+
createUserRepository,
|
|
7
|
+
} = require('../../../user/repositories/user-repository-factory');
|
|
8
|
+
const { loadAppDefinition } = require('../../app-definition-loader');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Load user from bearer token middleware
|
|
12
|
+
* Uses DDD pattern: Handler → Use Case → Repository
|
|
13
|
+
*/
|
|
14
|
+
module.exports = catchAsyncError(async (req, res, next) => {
|
|
15
|
+
const authorizationHeader = req.headers.authorization;
|
|
16
|
+
|
|
17
|
+
if (authorizationHeader) {
|
|
18
|
+
// Initialize dependencies following DDD pattern
|
|
19
|
+
const { userConfig } = loadAppDefinition();
|
|
20
|
+
const userRepository = createUserRepository({ userConfig });
|
|
21
|
+
const getUserFromBearerToken = new GetUserFromBearerToken({
|
|
22
|
+
userRepository,
|
|
23
|
+
userConfig,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
// Execute use case to load user
|
|
28
|
+
req.user = await getUserFromBearerToken.execute(
|
|
29
|
+
authorizationHeader
|
|
30
|
+
);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
// Don't fail - just leave req.user undefined
|
|
33
|
+
// Let requireLoggedInUser middleware handle auth failures
|
|
34
|
+
console.debug('Failed to load user from token:', error.message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return next();
|
|
39
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Middleware to require admin API key authentication.
|
|
3
|
+
* Checks for x-frigg-admin-api-key header matching ADMIN_API_KEY environment variable.
|
|
4
|
+
* In non-production environments, allows all requests through for easier development.
|
|
5
|
+
*
|
|
6
|
+
* Uses the same header convention as validateAdminApiKey (handlers/middleware/admin-auth.js).
|
|
7
|
+
*
|
|
8
|
+
* @param {import('express').Request} req - Express request object
|
|
9
|
+
* @param {import('express').Response} res - Express response object
|
|
10
|
+
* @param {import('express').NextFunction} next - Express next middleware function
|
|
11
|
+
*/
|
|
12
|
+
const requireAdmin = (req, res, next) => {
|
|
13
|
+
// Allow access in local development (when NODE_ENV is not production)
|
|
14
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
15
|
+
console.log('[requireAdmin] Development mode - bypassing admin auth');
|
|
16
|
+
return next();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const apiKey = req.headers['x-frigg-admin-api-key'];
|
|
20
|
+
|
|
21
|
+
if (!apiKey) {
|
|
22
|
+
console.error('[requireAdmin] Missing x-frigg-admin-api-key header');
|
|
23
|
+
return res.status(401).json({
|
|
24
|
+
status: 'error',
|
|
25
|
+
message: 'Unauthorized - Admin API key required',
|
|
26
|
+
code: 'MISSING_API_KEY',
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (apiKey !== process.env.ADMIN_API_KEY) {
|
|
31
|
+
console.error('[requireAdmin] Invalid API key provided');
|
|
32
|
+
return res.status(401).json({
|
|
33
|
+
status: 'error',
|
|
34
|
+
message: 'Unauthorized - Invalid admin API key',
|
|
35
|
+
code: 'INVALID_API_KEY',
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log('[requireAdmin] Admin authentication successful');
|
|
40
|
+
next();
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
module.exports = { requireAdmin };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const Boom = require('@hapi/boom');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Require logged in user middleware
|
|
5
|
+
* Ensures req.user was successfully loaded by loadUser middleware
|
|
6
|
+
*
|
|
7
|
+
* Uses DDD pattern: Middleware checks domain entity existence
|
|
8
|
+
* req.user is populated by loadUser middleware using GetUserFromBearerToken use case
|
|
9
|
+
*/
|
|
10
|
+
const requireLoggedInUser = (req, res, next) => {
|
|
11
|
+
// Check if user was successfully loaded by loadUser middleware
|
|
12
|
+
if (!req.user || !req.user.getId()) {
|
|
13
|
+
throw Boom.unauthorized('Invalid Token');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
next();
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
module.exports = { requireLoggedInUser };
|
package/handlers/routers/user.js
CHANGED
|
@@ -15,17 +15,33 @@ const catchAsyncError = require('express-async-handler');
|
|
|
15
15
|
const { loadAppDefinition } = require('../app-definition-loader');
|
|
16
16
|
|
|
17
17
|
const router = express();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
|
|
19
|
+
// Lazy-initialized repositories and use cases (deferred until first request)
|
|
20
|
+
let _userRepository, _createIndividualUser, _loginUser, _createTokenForUserId;
|
|
21
|
+
|
|
22
|
+
function ensureInitialized() {
|
|
23
|
+
if (!_userRepository) {
|
|
24
|
+
const { userConfig } = loadAppDefinition();
|
|
25
|
+
_userRepository = createUserRepository();
|
|
26
|
+
_createIndividualUser = new CreateIndividualUser({
|
|
27
|
+
userRepository: _userRepository,
|
|
28
|
+
userConfig,
|
|
29
|
+
});
|
|
30
|
+
_loginUser = new LoginUser({
|
|
31
|
+
userRepository: _userRepository,
|
|
32
|
+
userConfig,
|
|
33
|
+
});
|
|
34
|
+
_createTokenForUserId = new CreateTokenForUserId({
|
|
35
|
+
userRepository: _userRepository,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Lazy initialization middleware — runs once on first request
|
|
41
|
+
router.use((req, res, next) => {
|
|
42
|
+
ensureInitialized();
|
|
43
|
+
next();
|
|
27
44
|
});
|
|
28
|
-
const createTokenForUserId = new CreateTokenForUserId({ userRepository });
|
|
29
45
|
|
|
30
46
|
// define the login endpoint
|
|
31
47
|
router.route('/user/login').post(
|
|
@@ -34,8 +50,8 @@ router.route('/user/login').post(
|
|
|
34
50
|
'username',
|
|
35
51
|
'password',
|
|
36
52
|
]);
|
|
37
|
-
const user = await
|
|
38
|
-
const token = await
|
|
53
|
+
const user = await _loginUser.execute({ username, password });
|
|
54
|
+
const token = await _createTokenForUserId.execute(user.getId(), 120);
|
|
39
55
|
res.status(201);
|
|
40
56
|
res.json({ token });
|
|
41
57
|
})
|
|
@@ -48,11 +64,11 @@ router.route('/user/create').post(
|
|
|
48
64
|
'password',
|
|
49
65
|
]);
|
|
50
66
|
|
|
51
|
-
const user = await
|
|
67
|
+
const user = await _createIndividualUser.execute({
|
|
52
68
|
username,
|
|
53
69
|
password,
|
|
54
70
|
});
|
|
55
|
-
const token = await
|
|
71
|
+
const token = await _createTokenForUserId.execute(user.getId(), 120);
|
|
56
72
|
res.status(201);
|
|
57
73
|
res.json({ token });
|
|
58
74
|
})
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
const { createHandler } = require('@friggframework/core');
|
|
2
|
-
const {
|
|
2
|
+
const {
|
|
3
|
+
createWebsocketConnectionRepository,
|
|
4
|
+
} = require('../../database/websocket-connection-repository-factory');
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
let _websocketConnectionRepository;
|
|
7
|
+
|
|
8
|
+
function getRepository() {
|
|
9
|
+
if (!_websocketConnectionRepository) {
|
|
10
|
+
_websocketConnectionRepository =
|
|
11
|
+
createWebsocketConnectionRepository();
|
|
12
|
+
}
|
|
13
|
+
return _websocketConnectionRepository;
|
|
14
|
+
}
|
|
5
15
|
|
|
6
16
|
const handleWebSocketConnection = async (event, context) => {
|
|
7
17
|
// Handle different WebSocket events
|
|
@@ -10,7 +20,9 @@ const handleWebSocketConnection = async (event, context) => {
|
|
|
10
20
|
// Handle new connection
|
|
11
21
|
try {
|
|
12
22
|
const connectionId = event.requestContext.connectionId;
|
|
13
|
-
await
|
|
23
|
+
await getRepository().createConnection(
|
|
24
|
+
connectionId
|
|
25
|
+
);
|
|
14
26
|
console.log(`Stored new connection: ${connectionId}`);
|
|
15
27
|
return { statusCode: 200, body: 'Connected.' };
|
|
16
28
|
} catch (error) {
|
|
@@ -22,7 +34,9 @@ const handleWebSocketConnection = async (event, context) => {
|
|
|
22
34
|
// Handle disconnection
|
|
23
35
|
try {
|
|
24
36
|
const connectionId = event.requestContext.connectionId;
|
|
25
|
-
await
|
|
37
|
+
await getRepository().deleteConnection(
|
|
38
|
+
connectionId
|
|
39
|
+
);
|
|
26
40
|
console.log(`Removed connection: ${connectionId}`);
|
|
27
41
|
return { statusCode: 200, body: 'Disconnected.' };
|
|
28
42
|
} catch (error) {
|
|
@@ -5,9 +5,10 @@ class CheckIntegrationsHealthUseCase {
|
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
execute() {
|
|
8
|
-
const moduleDefinitions =
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const moduleDefinitions =
|
|
9
|
+
this.moduleFactory && this.moduleFactory.moduleDefinitions
|
|
10
|
+
? this.moduleFactory.moduleDefinitions
|
|
11
|
+
: [];
|
|
11
12
|
|
|
12
13
|
const integrationClasses = Array.isArray(this.integrationClasses)
|
|
13
14
|
? this.integrationClasses
|
|
@@ -15,13 +16,19 @@ class CheckIntegrationsHealthUseCase {
|
|
|
15
16
|
|
|
16
17
|
// Extract module names from definitions
|
|
17
18
|
const moduleTypes = Array.isArray(moduleDefinitions)
|
|
18
|
-
? moduleDefinitions.map(
|
|
19
|
+
? moduleDefinitions.map(
|
|
20
|
+
(def) => def.moduleName || def.name || def.label || 'Unknown'
|
|
21
|
+
)
|
|
19
22
|
: [];
|
|
20
23
|
|
|
21
24
|
// Extract integration names from classes
|
|
22
|
-
const integrationNames = integrationClasses.map(IntegrationClass => {
|
|
25
|
+
const integrationNames = integrationClasses.map((IntegrationClass) => {
|
|
23
26
|
try {
|
|
24
|
-
return
|
|
27
|
+
return (
|
|
28
|
+
IntegrationClass.Definition?.name ||
|
|
29
|
+
IntegrationClass.name ||
|
|
30
|
+
'Unknown'
|
|
31
|
+
);
|
|
25
32
|
} catch {
|
|
26
33
|
return 'Unknown';
|
|
27
34
|
}
|
|
@@ -49,16 +49,28 @@ const {
|
|
|
49
49
|
const {
|
|
50
50
|
CheckDatabaseStateUseCase,
|
|
51
51
|
} = require('../../database/use-cases/check-database-state-use-case');
|
|
52
|
-
const {
|
|
53
|
-
MigrationStatusRepositoryS3,
|
|
54
|
-
} = require('../../database/repositories/migration-status-repository-s3');
|
|
55
|
-
|
|
56
52
|
// Inject prisma-runner as dependency
|
|
57
53
|
const prismaRunner = require('../../database/utils/prisma-runner');
|
|
58
54
|
|
|
59
|
-
//
|
|
60
|
-
const
|
|
61
|
-
|
|
55
|
+
// Migration status repository is loaded from the resolved provider.
|
|
56
|
+
const { resolveProvider } = require('../../providers/resolve-provider');
|
|
57
|
+
|
|
58
|
+
let _migrationStatusRepository = null;
|
|
59
|
+
function getMigrationStatusRepository() {
|
|
60
|
+
if (!_migrationStatusRepository) {
|
|
61
|
+
const provider = resolveProvider();
|
|
62
|
+
const MigrationStatusRepository = provider.MigrationStatusRepositoryS3;
|
|
63
|
+
if (!MigrationStatusRepository) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Provider '${provider.name}' does not export a MigrationStatusRepository`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
const bucketName =
|
|
69
|
+
process.env.S3_BUCKET_NAME || process.env.MIGRATION_STATUS_BUCKET;
|
|
70
|
+
_migrationStatusRepository = new MigrationStatusRepository(bucketName);
|
|
71
|
+
}
|
|
72
|
+
return _migrationStatusRepository;
|
|
73
|
+
}
|
|
62
74
|
|
|
63
75
|
/**
|
|
64
76
|
* Sanitizes error messages to prevent credential leaks
|
|
@@ -68,19 +80,27 @@ const migrationStatusRepository = new MigrationStatusRepositoryS3(bucketName);
|
|
|
68
80
|
function sanitizeError(errorMessage) {
|
|
69
81
|
if (!errorMessage) return 'Unknown error';
|
|
70
82
|
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
return (
|
|
84
|
+
String(errorMessage)
|
|
85
|
+
// Remove PostgreSQL connection strings
|
|
86
|
+
.replace(
|
|
87
|
+
/postgresql:\/\/[^@\s]+@[^\s/]+/gi,
|
|
88
|
+
'postgresql://***:***@***'
|
|
89
|
+
)
|
|
90
|
+
// Remove MongoDB connection strings
|
|
91
|
+
.replace(
|
|
92
|
+
/mongodb(\+srv)?:\/\/[^@\s]+@[^\s/]+/gi,
|
|
93
|
+
'mongodb$1://***:***@***'
|
|
94
|
+
)
|
|
95
|
+
// Remove password parameters
|
|
96
|
+
.replace(/password[=:]\s*[^\s,;)]+/gi, 'password=***')
|
|
97
|
+
// Remove API keys
|
|
98
|
+
.replace(/apikey[=:]\s*[^\s,;)]+/gi, 'apikey=***')
|
|
99
|
+
.replace(/api[_-]?key[=:]\s*[^\s,;)]+/gi, 'api_key=***')
|
|
100
|
+
// Remove tokens
|
|
101
|
+
.replace(/token[=:]\s*[^\s,;)]+/gi, 'token=***')
|
|
102
|
+
.replace(/bearer\s+[^\s,;)]+/gi, 'bearer ***')
|
|
103
|
+
);
|
|
84
104
|
}
|
|
85
105
|
|
|
86
106
|
/**
|
|
@@ -145,11 +165,18 @@ exports.handler = async (event, context) => {
|
|
|
145
165
|
console.log('Database Migration Lambda Started');
|
|
146
166
|
console.log('========================================');
|
|
147
167
|
console.log('Event:', JSON.stringify(event, null, 2));
|
|
148
|
-
console.log(
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
168
|
+
console.log(
|
|
169
|
+
'Context:',
|
|
170
|
+
JSON.stringify(
|
|
171
|
+
{
|
|
172
|
+
requestId: context.requestId,
|
|
173
|
+
functionName: context.functionName,
|
|
174
|
+
remainingTimeInMillis: context.getRemainingTimeInMillis(),
|
|
175
|
+
},
|
|
176
|
+
null,
|
|
177
|
+
2
|
|
178
|
+
)
|
|
179
|
+
);
|
|
153
180
|
|
|
154
181
|
// Extract migration parameters from event
|
|
155
182
|
const { migrationId, dbType, stage } = extractMigrationParams(event);
|
|
@@ -164,7 +191,9 @@ exports.handler = async (event, context) => {
|
|
|
164
191
|
console.log(`========================================`);
|
|
165
192
|
|
|
166
193
|
try {
|
|
167
|
-
const checkDbStateUseCase = new CheckDatabaseStateUseCase({
|
|
194
|
+
const checkDbStateUseCase = new CheckDatabaseStateUseCase({
|
|
195
|
+
prismaRunner,
|
|
196
|
+
});
|
|
168
197
|
const status = await checkDbStateUseCase.execute(dbType, stage);
|
|
169
198
|
|
|
170
199
|
console.log('✓ Database state check completed');
|
|
@@ -217,8 +246,10 @@ exports.handler = async (event, context) => {
|
|
|
217
246
|
|
|
218
247
|
// Update migration status to RUNNING (if migrationId provided)
|
|
219
248
|
if (migrationId) {
|
|
220
|
-
console.log(
|
|
221
|
-
|
|
249
|
+
console.log(
|
|
250
|
+
`\n✓ Updating migration status to RUNNING: ${migrationId}`
|
|
251
|
+
);
|
|
252
|
+
await getMigrationStatusRepository().update({
|
|
222
253
|
migrationId,
|
|
223
254
|
stage,
|
|
224
255
|
state: 'RUNNING',
|
|
@@ -255,8 +286,10 @@ exports.handler = async (event, context) => {
|
|
|
255
286
|
|
|
256
287
|
// Update migration status to COMPLETED (if migrationId provided)
|
|
257
288
|
if (migrationId) {
|
|
258
|
-
console.log(
|
|
259
|
-
|
|
289
|
+
console.log(
|
|
290
|
+
`\n✓ Updating migration status to COMPLETED: ${migrationId}`
|
|
291
|
+
);
|
|
292
|
+
await getMigrationStatusRepository().update({
|
|
260
293
|
migrationId,
|
|
261
294
|
stage,
|
|
262
295
|
state: 'COMPLETED',
|
|
@@ -284,7 +317,6 @@ exports.handler = async (event, context) => {
|
|
|
284
317
|
statusCode: 200,
|
|
285
318
|
body: JSON.stringify(responseBody),
|
|
286
319
|
};
|
|
287
|
-
|
|
288
320
|
} catch (error) {
|
|
289
321
|
console.error('\n========================================');
|
|
290
322
|
console.error('Migration Failed');
|
|
@@ -317,8 +349,10 @@ exports.handler = async (event, context) => {
|
|
|
317
349
|
// Update migration status to FAILED (if migrationId provided)
|
|
318
350
|
if (migrationId) {
|
|
319
351
|
try {
|
|
320
|
-
console.log(
|
|
321
|
-
|
|
352
|
+
console.log(
|
|
353
|
+
`\n✓ Updating migration status to FAILED: ${migrationId}`
|
|
354
|
+
);
|
|
355
|
+
await getMigrationStatusRepository().update({
|
|
322
356
|
migrationId,
|
|
323
357
|
stage,
|
|
324
358
|
state: 'FAILED',
|
|
@@ -327,7 +361,10 @@ exports.handler = async (event, context) => {
|
|
|
327
361
|
failedAt: new Date().toISOString(),
|
|
328
362
|
});
|
|
329
363
|
} catch (updateError) {
|
|
330
|
-
console.error(
|
|
364
|
+
console.error(
|
|
365
|
+
'Failed to update migration status:',
|
|
366
|
+
updateError.message
|
|
367
|
+
);
|
|
331
368
|
// Continue - don't let status update failure block error response
|
|
332
369
|
}
|
|
333
370
|
}
|
|
@@ -337,7 +374,9 @@ exports.handler = async (event, context) => {
|
|
|
337
374
|
error: sanitizedError,
|
|
338
375
|
errorType: error.name || 'Error',
|
|
339
376
|
// Only include stack traces in development environments
|
|
340
|
-
...(stage === 'dev' || stage === 'local' || stage === 'test'
|
|
377
|
+
...(stage === 'dev' || stage === 'local' || stage === 'test'
|
|
378
|
+
? { stack: error.stack }
|
|
379
|
+
: {}),
|
|
341
380
|
};
|
|
342
381
|
|
|
343
382
|
if (migrationId) {
|
|
@@ -2,26 +2,37 @@ const { createHandler } = require('@friggframework/core');
|
|
|
2
2
|
const { loadAppDefinition } = require('../app-definition-loader');
|
|
3
3
|
const { createQueueWorker } = require('../backend-utils');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
const { integrations: integrationClasses } = loadAppDefinition();
|
|
5
|
+
let _handlers;
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
function ensureHandlers() {
|
|
8
|
+
if (!_handlers) {
|
|
9
|
+
_handlers = {};
|
|
10
|
+
const { integrations: integrationClasses } = loadAppDefinition();
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
eventName: `Queue Worker for ${IntegrationClass.Definition.name}`,
|
|
14
|
-
isUserFacingResponse: false,
|
|
15
|
-
method: async (event, context) => {
|
|
16
|
-
const worker = new defaultQueueWorker();
|
|
17
|
-
await worker.run(event, context);
|
|
18
|
-
return {
|
|
19
|
-
message: 'Successfully processed the Generic Queue Worker',
|
|
20
|
-
input: event,
|
|
21
|
-
};
|
|
22
|
-
},
|
|
23
|
-
}),
|
|
24
|
-
};
|
|
25
|
-
});
|
|
12
|
+
integrationClasses.forEach((IntegrationClass) => {
|
|
13
|
+
const defaultQueueWorker = createQueueWorker(IntegrationClass);
|
|
26
14
|
|
|
27
|
-
|
|
15
|
+
_handlers[`${IntegrationClass.Definition.name}`] = {
|
|
16
|
+
queueWorker: createHandler({
|
|
17
|
+
eventName: `Queue Worker for ${IntegrationClass.Definition.name}`,
|
|
18
|
+
isUserFacingResponse: false,
|
|
19
|
+
method: async (event, context) => {
|
|
20
|
+
const worker = new defaultQueueWorker();
|
|
21
|
+
await worker.run(event, context);
|
|
22
|
+
return {
|
|
23
|
+
message: 'Successfully processed the Generic Queue Worker',
|
|
24
|
+
input: event,
|
|
25
|
+
};
|
|
26
|
+
},
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return _handlers;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = {
|
|
35
|
+
get handlers() {
|
|
36
|
+
return ensureHandlers();
|
|
37
|
+
},
|
|
38
|
+
};
|
package/index.js
CHANGED
|
@@ -21,7 +21,6 @@ const {
|
|
|
21
21
|
} = require('./database/index');
|
|
22
22
|
const {
|
|
23
23
|
createUserRepository,
|
|
24
|
-
UserRepositoryMongo,
|
|
25
24
|
UserRepositoryPostgres,
|
|
26
25
|
} = require('./user/repositories/user-repository-factory');
|
|
27
26
|
const {
|
|
@@ -30,9 +29,7 @@ const {
|
|
|
30
29
|
const {
|
|
31
30
|
GetUserFromAdopterJwt,
|
|
32
31
|
} = require('./user/use-cases/get-user-from-adopter-jwt');
|
|
33
|
-
const {
|
|
34
|
-
AuthenticateUser,
|
|
35
|
-
} = require('./user/use-cases/authenticate-user');
|
|
32
|
+
const { AuthenticateUser } = require('./user/use-cases/authenticate-user');
|
|
36
33
|
|
|
37
34
|
const {
|
|
38
35
|
CredentialRepository,
|
|
@@ -43,18 +40,14 @@ const {
|
|
|
43
40
|
const {
|
|
44
41
|
IntegrationMappingRepository,
|
|
45
42
|
} = require('./integrations/repositories/integration-mapping-repository');
|
|
46
|
-
const {
|
|
47
|
-
CreateProcess,
|
|
48
|
-
} = require('./integrations/use-cases/create-process');
|
|
43
|
+
const { CreateProcess } = require('./integrations/use-cases/create-process');
|
|
49
44
|
const {
|
|
50
45
|
UpdateProcessState,
|
|
51
46
|
} = require('./integrations/use-cases/update-process-state');
|
|
52
47
|
const {
|
|
53
48
|
UpdateProcessMetrics,
|
|
54
49
|
} = require('./integrations/use-cases/update-process-metrics');
|
|
55
|
-
const {
|
|
56
|
-
GetProcess,
|
|
57
|
-
} = require('./integrations/use-cases/get-process');
|
|
50
|
+
const { GetProcess } = require('./integrations/use-cases/get-process');
|
|
58
51
|
const { Cryptor } = require('./encrypt');
|
|
59
52
|
const {
|
|
60
53
|
BaseError,
|
|
@@ -70,12 +63,11 @@ const {
|
|
|
70
63
|
checkRequiredParams,
|
|
71
64
|
getModulesDefinitionFromIntegrationClasses,
|
|
72
65
|
LoadIntegrationContextUseCase,
|
|
66
|
+
createProcessRepository,
|
|
73
67
|
} = require('./integrations/index');
|
|
74
68
|
const { TimeoutCatcher } = require('./lambda/index');
|
|
75
69
|
const { debug, initDebugLog, flushDebugLog } = require('./logs/index');
|
|
76
70
|
const {
|
|
77
|
-
Credential,
|
|
78
|
-
Entity,
|
|
79
71
|
ApiKeyRequester,
|
|
80
72
|
BasicAuthRequester,
|
|
81
73
|
OAuth2Requester,
|
|
@@ -86,7 +78,33 @@ const {
|
|
|
86
78
|
const application = require('./application');
|
|
87
79
|
const utils = require('./utils');
|
|
88
80
|
|
|
89
|
-
const {
|
|
81
|
+
const {
|
|
82
|
+
QueuerUtil,
|
|
83
|
+
QueueProvider,
|
|
84
|
+
QueueClientInterface,
|
|
85
|
+
createQueueProvider,
|
|
86
|
+
QUEUE_PROVIDERS,
|
|
87
|
+
} = require('./queues');
|
|
88
|
+
|
|
89
|
+
const {
|
|
90
|
+
EncryptionKeyProviderInterface,
|
|
91
|
+
} = require('./encrypt/encryption-key-provider-interface');
|
|
92
|
+
const {
|
|
93
|
+
AesEncryptionKeyProvider,
|
|
94
|
+
} = require('./encrypt/aes-encryption-key-provider');
|
|
95
|
+
const {
|
|
96
|
+
WebSocketMessageSenderInterface,
|
|
97
|
+
StaleConnectionError,
|
|
98
|
+
} = require('./websocket/websocket-message-sender-interface');
|
|
99
|
+
|
|
100
|
+
const {
|
|
101
|
+
resolveProvider,
|
|
102
|
+
determineProviderName,
|
|
103
|
+
providerPackageName,
|
|
104
|
+
KNOWN_PROVIDERS,
|
|
105
|
+
} = require('./providers');
|
|
106
|
+
|
|
107
|
+
const extensions = require('./extensions');
|
|
90
108
|
|
|
91
109
|
module.exports = {
|
|
92
110
|
// assertions
|
|
@@ -110,7 +128,7 @@ module.exports = {
|
|
|
110
128
|
TokenRepository,
|
|
111
129
|
WebsocketConnectionRepository,
|
|
112
130
|
createUserRepository,
|
|
113
|
-
UserRepositoryMongo,
|
|
131
|
+
get UserRepositoryMongo() { return require('./user/repositories/user-repository-factory').UserRepositoryMongo; },
|
|
114
132
|
UserRepositoryPostgres,
|
|
115
133
|
GetUserFromXFriggHeaders,
|
|
116
134
|
GetUserFromAdopterJwt,
|
|
@@ -138,6 +156,7 @@ module.exports = {
|
|
|
138
156
|
UpdateProcessState,
|
|
139
157
|
UpdateProcessMetrics,
|
|
140
158
|
GetProcess,
|
|
159
|
+
createProcessRepository,
|
|
141
160
|
|
|
142
161
|
// application - Command factories for integration developers
|
|
143
162
|
application,
|
|
@@ -147,6 +166,7 @@ module.exports = {
|
|
|
147
166
|
createEntityCommands: application.createEntityCommands,
|
|
148
167
|
createCredentialCommands: application.createCredentialCommands,
|
|
149
168
|
createSchedulerCommands: application.createSchedulerCommands,
|
|
169
|
+
createAdminScriptCommands: application.createAdminScriptCommands,
|
|
150
170
|
findIntegrationContextByExternalEntityId:
|
|
151
171
|
application.findIntegrationContextByExternalEntityId,
|
|
152
172
|
integrationCommands: application.integrationCommands,
|
|
@@ -160,8 +180,6 @@ module.exports = {
|
|
|
160
180
|
flushDebugLog,
|
|
161
181
|
|
|
162
182
|
// module plugin
|
|
163
|
-
Credential,
|
|
164
|
-
Entity,
|
|
165
183
|
ApiKeyRequester,
|
|
166
184
|
BasicAuthRequester,
|
|
167
185
|
OAuth2Requester,
|
|
@@ -170,6 +188,32 @@ module.exports = {
|
|
|
170
188
|
ModuleFactory,
|
|
171
189
|
// queues
|
|
172
190
|
QueuerUtil,
|
|
191
|
+
QueueProvider,
|
|
192
|
+
QueueClientInterface,
|
|
193
|
+
createQueueProvider,
|
|
194
|
+
QUEUE_PROVIDERS,
|
|
195
|
+
|
|
196
|
+
// encryption interfaces
|
|
197
|
+
EncryptionKeyProviderInterface,
|
|
198
|
+
AesEncryptionKeyProvider,
|
|
199
|
+
|
|
200
|
+
// websocket interfaces
|
|
201
|
+
WebSocketMessageSenderInterface,
|
|
202
|
+
StaleConnectionError,
|
|
203
|
+
|
|
204
|
+
// providers
|
|
205
|
+
resolveProvider,
|
|
206
|
+
determineProviderName,
|
|
207
|
+
providerPackageName,
|
|
208
|
+
KNOWN_PROVIDERS,
|
|
209
|
+
|
|
210
|
+
// extensions
|
|
211
|
+
extensions,
|
|
212
|
+
loadExtensions: extensions.loadExtensions,
|
|
213
|
+
composeSchemas: extensions.composeSchemas,
|
|
214
|
+
mountExtensionRoutes: extensions.mountExtensionRoutes,
|
|
215
|
+
runExtensionBootstraps: extensions.runExtensionBootstraps,
|
|
216
|
+
initializeApp: extensions.initializeApp,
|
|
173
217
|
|
|
174
218
|
// utils
|
|
175
219
|
...utils,
|