@friggframework/core 2.0.0--canary.548.c8ae0ca.0 → 2.0.0--canary.545.c40eca4.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 +29 -23
- 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 +22 -14
- 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/generated/prisma-mongodb/edge.js +59 -4
- package/generated/prisma-mongodb/index-browser.js +49 -1
- package/generated/prisma-mongodb/index.d.ts +4023 -61
- package/generated/prisma-mongodb/index.js +59 -4
- package/generated/prisma-mongodb/package.json +1 -1
- package/generated/prisma-mongodb/schema.prisma +87 -0
- package/generated/prisma-mongodb/wasm.js +59 -4
- package/generated/prisma-postgresql/edge.js +58 -4
- package/generated/prisma-postgresql/index-browser.js +48 -1
- package/generated/prisma-postgresql/index.d.ts +4738 -54
- package/generated/prisma-postgresql/index.js +58 -4
- package/generated/prisma-postgresql/package.json +1 -1
- package/generated/prisma-postgresql/schema.prisma +85 -0
- package/generated/prisma-postgresql/wasm.js +58 -4
- 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 +0 -1
- 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 +50 -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 +1828 -157
- 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.js +4 -9
- 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 +87 -0
- package/prisma-postgresql/migrations/20260222000000_add_admin_process_and_script_schedule/migration.sql +55 -0
- package/prisma-postgresql/schema.prisma +85 -0
- 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/infrastructure/scheduler/eventbridge-scheduler-adapter.js +0 -184
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const { IntegrationBase } = require('../../integration-base');
|
|
2
|
+
const { Options } = require('../../options');
|
|
2
3
|
|
|
3
4
|
class DummyModule {
|
|
4
5
|
static definition = {
|
|
5
|
-
getName: () => 'dummy'
|
|
6
|
+
getName: () => 'dummy',
|
|
6
7
|
};
|
|
7
8
|
}
|
|
8
9
|
|
|
@@ -11,21 +12,25 @@ class DummyIntegration extends IntegrationBase {
|
|
|
11
12
|
name: 'dummy',
|
|
12
13
|
version: '1.0.0',
|
|
13
14
|
modules: {
|
|
14
|
-
dummy: DummyModule
|
|
15
|
+
dummy: DummyModule,
|
|
15
16
|
},
|
|
16
17
|
display: {
|
|
17
18
|
label: 'Dummy Integration',
|
|
18
19
|
description: 'A dummy integration for testing',
|
|
19
20
|
detailsUrl: 'https://example.com',
|
|
20
|
-
icon: 'dummy-icon'
|
|
21
|
-
}
|
|
21
|
+
icon: 'dummy-icon',
|
|
22
|
+
},
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
static getOptionDetails() {
|
|
26
|
+
const options = new Options({
|
|
27
|
+
module: Object.values(this.Definition.modules)[0],
|
|
28
|
+
...this.Definition,
|
|
29
|
+
});
|
|
25
30
|
return {
|
|
26
31
|
name: this.Definition.name,
|
|
27
32
|
version: this.Definition.version,
|
|
28
|
-
|
|
33
|
+
...options.get(),
|
|
29
34
|
};
|
|
30
35
|
}
|
|
31
36
|
|
|
@@ -41,11 +46,11 @@ class DummyIntegration extends IntegrationBase {
|
|
|
41
46
|
};
|
|
42
47
|
|
|
43
48
|
this.updateIntegrationStatus = {
|
|
44
|
-
execute: jest.fn().mockResolvedValue({})
|
|
49
|
+
execute: jest.fn().mockResolvedValue({}),
|
|
45
50
|
};
|
|
46
51
|
|
|
47
52
|
this.updateIntegrationMessages = {
|
|
48
|
-
execute: jest.fn().mockResolvedValue({})
|
|
53
|
+
execute: jest.fn().mockResolvedValue({}),
|
|
49
54
|
};
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -102,4 +107,72 @@ class DummyIntegration extends IntegrationBase {
|
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
|
|
110
|
+
class DummyIntegrationWithGlobalEntity extends IntegrationBase {
|
|
111
|
+
static Definition = {
|
|
112
|
+
name: 'dummy-with-global',
|
|
113
|
+
version: '1.0.0',
|
|
114
|
+
modules: { dummy: DummyModule },
|
|
115
|
+
display: { label: 'Dummy With Global', description: 'Test' },
|
|
116
|
+
entities: {
|
|
117
|
+
sharedService: {
|
|
118
|
+
type: 'shared-api',
|
|
119
|
+
global: true,
|
|
120
|
+
required: true,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
constructor(params) {
|
|
126
|
+
super(params);
|
|
127
|
+
this.sendSpy = jest.fn();
|
|
128
|
+
this.integrationRepository = {
|
|
129
|
+
updateIntegrationById: jest.fn().mockResolvedValue({}),
|
|
130
|
+
findIntegrationById: jest.fn().mockResolvedValue({}),
|
|
131
|
+
};
|
|
132
|
+
this.updateIntegrationStatus = { execute: jest.fn().mockResolvedValue({}) };
|
|
133
|
+
this.updateIntegrationMessages = { execute: jest.fn().mockResolvedValue({}) };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async loadDynamicUserActions() { return {}; }
|
|
137
|
+
async send(event, data) { this.sendSpy(event, data); return { event, data }; }
|
|
138
|
+
async initialize() { return; }
|
|
139
|
+
async onCreate() { return; }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
class DummyIntegrationWithOptionalGlobalEntity extends IntegrationBase {
|
|
143
|
+
static Definition = {
|
|
144
|
+
name: 'dummy-with-optional-global',
|
|
145
|
+
version: '1.0.0',
|
|
146
|
+
modules: { dummy: DummyModule },
|
|
147
|
+
display: { label: 'Dummy With Optional Global', description: 'Test' },
|
|
148
|
+
entities: {
|
|
149
|
+
optionalService: {
|
|
150
|
+
type: 'optional-api',
|
|
151
|
+
global: true,
|
|
152
|
+
required: false,
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
constructor(params) {
|
|
158
|
+
super(params);
|
|
159
|
+
this.sendSpy = jest.fn();
|
|
160
|
+
this.integrationRepository = {
|
|
161
|
+
updateIntegrationById: jest.fn().mockResolvedValue({}),
|
|
162
|
+
findIntegrationById: jest.fn().mockResolvedValue({}),
|
|
163
|
+
};
|
|
164
|
+
this.updateIntegrationStatus = { execute: jest.fn().mockResolvedValue({}) };
|
|
165
|
+
this.updateIntegrationMessages = { execute: jest.fn().mockResolvedValue({}) };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async loadDynamicUserActions() { return {}; }
|
|
169
|
+
async send(event, data) { this.sendSpy(event, data); return { event, data }; }
|
|
170
|
+
async initialize() { return; }
|
|
171
|
+
async onCreate() { return; }
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
module.exports = {
|
|
175
|
+
DummyIntegration,
|
|
176
|
+
DummyIntegrationWithGlobalEntity,
|
|
177
|
+
DummyIntegrationWithOptionalGlobalEntity,
|
|
178
|
+
};
|
|
@@ -31,13 +31,21 @@ class TestIntegrationRepository {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
async findIntegrationsByUserId(userId) {
|
|
34
|
-
const results = Array.from(this.store.values()).filter(
|
|
35
|
-
|
|
34
|
+
const results = Array.from(this.store.values()).filter(
|
|
35
|
+
(r) => r.userId === userId
|
|
36
|
+
);
|
|
37
|
+
this.operationHistory.push({
|
|
38
|
+
operation: 'findByUserId',
|
|
39
|
+
userId,
|
|
40
|
+
count: results.length,
|
|
41
|
+
});
|
|
36
42
|
return results;
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
async findIntegrationByUserId(userId) {
|
|
40
|
-
const record = Array.from(this.store.values()).find(
|
|
46
|
+
const record = Array.from(this.store.values()).find(
|
|
47
|
+
(r) => r.userId === userId
|
|
48
|
+
);
|
|
41
49
|
this.operationHistory.push({
|
|
42
50
|
operation: 'findSingleByUserId',
|
|
43
51
|
userId,
|
|
@@ -49,30 +57,52 @@ class TestIntegrationRepository {
|
|
|
49
57
|
async updateIntegrationMessages(id, type, title, body, timestamp) {
|
|
50
58
|
const rec = this.store.get(id);
|
|
51
59
|
if (!rec) {
|
|
52
|
-
this.operationHistory.push({
|
|
60
|
+
this.operationHistory.push({
|
|
61
|
+
operation: 'updateMessages',
|
|
62
|
+
id,
|
|
63
|
+
success: false,
|
|
64
|
+
});
|
|
53
65
|
return false;
|
|
54
66
|
}
|
|
55
67
|
if (!rec.messages[type]) rec.messages[type] = [];
|
|
56
68
|
rec.messages[type].push({ title, message: body, timestamp });
|
|
57
|
-
this.operationHistory.push({
|
|
69
|
+
this.operationHistory.push({
|
|
70
|
+
operation: 'updateMessages',
|
|
71
|
+
id,
|
|
72
|
+
type,
|
|
73
|
+
success: true,
|
|
74
|
+
});
|
|
58
75
|
return true;
|
|
59
76
|
}
|
|
60
77
|
|
|
61
78
|
async updateIntegrationConfig(id, config) {
|
|
62
79
|
const rec = this.store.get(id);
|
|
63
80
|
if (!rec) {
|
|
64
|
-
this.operationHistory.push({
|
|
81
|
+
this.operationHistory.push({
|
|
82
|
+
operation: 'updateConfig',
|
|
83
|
+
id,
|
|
84
|
+
success: false,
|
|
85
|
+
});
|
|
65
86
|
throw new Error(`Integration with id ${id} not found`);
|
|
66
87
|
}
|
|
67
88
|
rec.config = config;
|
|
68
|
-
this.operationHistory.push({
|
|
89
|
+
this.operationHistory.push({
|
|
90
|
+
operation: 'updateConfig',
|
|
91
|
+
id,
|
|
92
|
+
success: true,
|
|
93
|
+
});
|
|
69
94
|
return rec;
|
|
70
95
|
}
|
|
71
96
|
|
|
72
97
|
async deleteIntegrationById(id) {
|
|
73
98
|
const existed = this.store.has(id);
|
|
74
99
|
const result = this.store.delete(id);
|
|
75
|
-
this.operationHistory.push({
|
|
100
|
+
this.operationHistory.push({
|
|
101
|
+
operation: 'delete',
|
|
102
|
+
id,
|
|
103
|
+
existed,
|
|
104
|
+
success: result,
|
|
105
|
+
});
|
|
76
106
|
return result;
|
|
77
107
|
}
|
|
78
108
|
|
|
@@ -80,9 +110,19 @@ class TestIntegrationRepository {
|
|
|
80
110
|
const rec = this.store.get(id);
|
|
81
111
|
if (rec) {
|
|
82
112
|
rec.status = status;
|
|
83
|
-
this.operationHistory.push({
|
|
113
|
+
this.operationHistory.push({
|
|
114
|
+
operation: 'updateStatus',
|
|
115
|
+
id,
|
|
116
|
+
status,
|
|
117
|
+
success: true,
|
|
118
|
+
});
|
|
84
119
|
} else {
|
|
85
|
-
this.operationHistory.push({
|
|
120
|
+
this.operationHistory.push({
|
|
121
|
+
operation: 'updateStatus',
|
|
122
|
+
id,
|
|
123
|
+
status,
|
|
124
|
+
success: false,
|
|
125
|
+
});
|
|
86
126
|
}
|
|
87
127
|
return !!rec;
|
|
88
128
|
}
|
|
@@ -96,4 +136,4 @@ class TestIntegrationRepository {
|
|
|
96
136
|
}
|
|
97
137
|
}
|
|
98
138
|
|
|
99
|
-
module.exports = { TestIntegrationRepository };
|
|
139
|
+
module.exports = { TestIntegrationRepository };
|
|
@@ -1,56 +1,60 @@
|
|
|
1
|
-
// Removed Integration wrapper - using IntegrationBase directly
|
|
2
1
|
const {
|
|
3
2
|
mapIntegrationClassToIntegrationDTO,
|
|
4
3
|
} = require('../utils/map-integration-dto');
|
|
5
4
|
|
|
6
|
-
/**
|
|
7
|
-
* Use case for creating a new integration instance.
|
|
8
|
-
* @class CreateIntegration
|
|
9
|
-
*/
|
|
10
5
|
class CreateIntegration {
|
|
11
|
-
/**
|
|
12
|
-
* Creates a new CreateIntegration instance.
|
|
13
|
-
* @param {Object} params - Configuration parameters.
|
|
14
|
-
* @param {import('../repositories/integration-repository-interface').IntegrationRepositoryInterface} params.integrationRepository - Repository for integration data operations.
|
|
15
|
-
* @param {import('../integration-classes').IntegrationClasses} params.integrationClasses - Array of available integration classes.
|
|
16
|
-
* @param {import('../../modules/module-factory').ModuleFactory} params.moduleFactory - Service for module instantiation and management.
|
|
17
|
-
*/
|
|
18
6
|
constructor({ integrationRepository, integrationClasses, moduleFactory }) {
|
|
19
7
|
this.integrationRepository = integrationRepository;
|
|
20
8
|
this.integrationClasses = integrationClasses;
|
|
21
9
|
this.moduleFactory = moduleFactory;
|
|
22
10
|
}
|
|
23
11
|
|
|
24
|
-
/**
|
|
25
|
-
* Executes the integration creation process.
|
|
26
|
-
* @async
|
|
27
|
-
* @param {string[]} entities - Array of entity IDs to associate with the integration.
|
|
28
|
-
* @param {string} userId - ID of the user creating the integration.
|
|
29
|
-
* @param {Object} config - Configuration object for the integration.
|
|
30
|
-
* @param {string} config.type - Type of integration to create.
|
|
31
|
-
* @returns {Promise<Object>} The created integration DTO.
|
|
32
|
-
* @throws {Error} When integration class is not found for the specified type.
|
|
33
|
-
*/
|
|
34
12
|
async execute(entities, userId, config) {
|
|
35
|
-
const integrationRecord =
|
|
36
|
-
await this.integrationRepository.createIntegration(
|
|
37
|
-
entities,
|
|
38
|
-
userId,
|
|
39
|
-
config
|
|
40
|
-
);
|
|
41
|
-
|
|
42
13
|
const integrationClass = this.integrationClasses.find(
|
|
43
14
|
(integrationClass) =>
|
|
44
|
-
integrationClass.Definition.name ===
|
|
45
|
-
integrationRecord.config.type
|
|
15
|
+
integrationClass.Definition.name === config.type
|
|
46
16
|
);
|
|
47
17
|
|
|
48
18
|
if (!integrationClass) {
|
|
49
19
|
throw new Error(
|
|
50
|
-
`No integration class found for type: ${
|
|
20
|
+
`No integration class found for type: ${config.type}`
|
|
51
21
|
);
|
|
52
22
|
}
|
|
53
23
|
|
|
24
|
+
const allEntities = [...entities];
|
|
25
|
+
|
|
26
|
+
if (integrationClass.Definition?.entities) {
|
|
27
|
+
for (const [entityKey, entityConfig] of Object.entries(
|
|
28
|
+
integrationClass.Definition.entities
|
|
29
|
+
)) {
|
|
30
|
+
if (entityConfig.global === true) {
|
|
31
|
+
const globalEntity =
|
|
32
|
+
await this.moduleFactory.moduleRepository.findEntity({
|
|
33
|
+
moduleName: entityConfig.type,
|
|
34
|
+
isGlobal: true,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
if (globalEntity && globalEntity.credential?.authIsValid) {
|
|
38
|
+
allEntities.push(globalEntity.id.toString());
|
|
39
|
+
} else if (entityConfig.required !== false) {
|
|
40
|
+
const reason = !globalEntity
|
|
41
|
+
? 'not found'
|
|
42
|
+
: 'exists but credential is invalid';
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Required global entity "${entityConfig.type}" ${reason}. Admin must configure this entity first.`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const integrationRecord =
|
|
52
|
+
await this.integrationRepository.createIntegration(
|
|
53
|
+
allEntities,
|
|
54
|
+
userId,
|
|
55
|
+
config
|
|
56
|
+
);
|
|
57
|
+
|
|
54
58
|
const modules = [];
|
|
55
59
|
for (const entityId of integrationRecord.entitiesIds) {
|
|
56
60
|
const moduleInstance = await this.moduleFactory.getModuleInstance(
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CreateProcess Use Case
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Creates a new process record for tracking long-running operations.
|
|
5
5
|
* Validates required fields and delegates persistence to the repository.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Design Philosophy:
|
|
8
8
|
* - Use cases encapsulate business logic
|
|
9
9
|
* - Validation happens at the use case layer
|
|
10
10
|
* - Repositories handle only data access
|
|
11
11
|
* - Process model is generic and reusable
|
|
12
|
-
*
|
|
12
|
+
*
|
|
13
13
|
* @example
|
|
14
14
|
* const createProcess = new CreateProcess({ processRepository });
|
|
15
15
|
* const process = await createProcess.execute({
|
|
@@ -68,7 +68,9 @@ class CreateProcess {
|
|
|
68
68
|
|
|
69
69
|
// Delegate to repository
|
|
70
70
|
try {
|
|
71
|
-
const createdProcess = await this.processRepository.create(
|
|
71
|
+
const createdProcess = await this.processRepository.create(
|
|
72
|
+
processToCreate
|
|
73
|
+
);
|
|
72
74
|
return createdProcess;
|
|
73
75
|
} catch (error) {
|
|
74
76
|
throw new Error(`Failed to create process: ${error.message}`);
|
|
@@ -83,11 +85,15 @@ class CreateProcess {
|
|
|
83
85
|
*/
|
|
84
86
|
_validateProcessData(processData) {
|
|
85
87
|
const requiredFields = ['userId', 'integrationId', 'name', 'type'];
|
|
86
|
-
const missingFields = requiredFields.filter(
|
|
88
|
+
const missingFields = requiredFields.filter(
|
|
89
|
+
(field) => !processData[field]
|
|
90
|
+
);
|
|
87
91
|
|
|
88
92
|
if (missingFields.length > 0) {
|
|
89
93
|
throw new Error(
|
|
90
|
-
`Missing required fields for process creation: ${missingFields.join(
|
|
94
|
+
`Missing required fields for process creation: ${missingFields.join(
|
|
95
|
+
', '
|
|
96
|
+
)}`
|
|
91
97
|
);
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -115,14 +121,19 @@ class CreateProcess {
|
|
|
115
121
|
if (processData.results && typeof processData.results !== 'object') {
|
|
116
122
|
throw new Error('results must be an object');
|
|
117
123
|
}
|
|
118
|
-
if (
|
|
124
|
+
if (
|
|
125
|
+
processData.childProcesses &&
|
|
126
|
+
!Array.isArray(processData.childProcesses)
|
|
127
|
+
) {
|
|
119
128
|
throw new Error('childProcesses must be an array');
|
|
120
129
|
}
|
|
121
|
-
if (
|
|
130
|
+
if (
|
|
131
|
+
processData.parentProcessId &&
|
|
132
|
+
typeof processData.parentProcessId !== 'string'
|
|
133
|
+
) {
|
|
122
134
|
throw new Error('parentProcessId must be a string');
|
|
123
135
|
}
|
|
124
136
|
}
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
module.exports = { CreateProcess };
|
|
128
|
-
|
|
@@ -59,10 +59,11 @@ class DeleteIntegrationForUser {
|
|
|
59
59
|
|
|
60
60
|
for (const entityId of integrationRecord.entitiesIds) {
|
|
61
61
|
try {
|
|
62
|
-
const moduleInstance =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
const moduleInstance =
|
|
63
|
+
await this.moduleFactory.getModuleInstance(
|
|
64
|
+
entityId,
|
|
65
|
+
integrationRecord.userId
|
|
66
|
+
);
|
|
66
67
|
modules.push(moduleInstance);
|
|
67
68
|
} catch (error) {
|
|
68
69
|
console.error(
|