@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
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queue Provider Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates queue provider instances based on appDefinition or environment configuration.
|
|
5
|
+
* Uses the provider plugin system (resolveProvider) to load the correct
|
|
6
|
+
* queue adapter for the active platform (AWS, Netlify, etc.).
|
|
7
|
+
*
|
|
8
|
+
* Priority order for determining provider:
|
|
9
|
+
* 1. Explicit `provider` option passed to factory
|
|
10
|
+
* 2. `appDefinition.queue.provider` property
|
|
11
|
+
* 3. `QUEUE_PROVIDER` environment variable
|
|
12
|
+
* 4. Default: resolved provider's QueueProvider
|
|
13
|
+
*
|
|
14
|
+
* Special providers (not tied to a platform):
|
|
15
|
+
* - 'qstash' -> Upstash QStash (platform-agnostic)
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const { resolveProvider } = require('../providers/resolve-provider');
|
|
19
|
+
|
|
20
|
+
const QUEUE_PROVIDERS = {
|
|
21
|
+
QSTASH: 'qstash',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// Map legacy QUEUE_PROVIDER values to Frigg provider names
|
|
25
|
+
const LEGACY_PROVIDER_MAP = {
|
|
26
|
+
sqs: 'aws',
|
|
27
|
+
'netlify-background': 'netlify',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Determine the queue provider from config hierarchy
|
|
32
|
+
*
|
|
33
|
+
* @param {Object} [options]
|
|
34
|
+
* @param {string} [options.provider] - Explicit provider override
|
|
35
|
+
* @param {Object} [options.appDefinition] - Frigg app definition object
|
|
36
|
+
* @returns {string|undefined} Provider name, or undefined for auto-detect
|
|
37
|
+
*/
|
|
38
|
+
function determineProvider(options = {}) {
|
|
39
|
+
if (options.provider) {
|
|
40
|
+
return options.provider;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (options.appDefinition?.queue?.provider) {
|
|
44
|
+
return options.appDefinition.queue.provider;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (process.env.QUEUE_PROVIDER) {
|
|
48
|
+
return process.env.QUEUE_PROVIDER;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return undefined; // Let resolveProvider() pick the default
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create a queue provider instance
|
|
56
|
+
*
|
|
57
|
+
* @param {Object} [options]
|
|
58
|
+
* @param {string} [options.provider] - Queue provider name
|
|
59
|
+
* @param {Object} [options.appDefinition] - Frigg app definition (reads queue.provider)
|
|
60
|
+
* @param {Object} [options.providerOptions] - Options passed to the provider constructor
|
|
61
|
+
* @returns {QueueProvider} Implementation of queue provider interface
|
|
62
|
+
*/
|
|
63
|
+
function createQueueProvider(options = {}) {
|
|
64
|
+
const explicit = determineProvider(options);
|
|
65
|
+
const providerOptions = options.providerOptions || {};
|
|
66
|
+
|
|
67
|
+
// QStash is a third-party queue not tied to any platform provider
|
|
68
|
+
if (explicit === QUEUE_PROVIDERS.QSTASH) {
|
|
69
|
+
const { QStashQueueProvider } = require('./providers/qstash-queue-provider');
|
|
70
|
+
return new QStashQueueProvider(providerOptions);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Use the resolved provider's queue adapter.
|
|
74
|
+
// Legacy QUEUE_PROVIDER values (sqs, netlify-background) are mapped
|
|
75
|
+
// to provider names for backward compatibility.
|
|
76
|
+
const providerName = LEGACY_PROVIDER_MAP[explicit] || explicit;
|
|
77
|
+
const providerOverride = providerName ? { provider: providerName } : {};
|
|
78
|
+
const provider = resolveProvider(null, providerOverride);
|
|
79
|
+
|
|
80
|
+
const QueueProviderClass = provider.QueueProvider;
|
|
81
|
+
if (!QueueProviderClass) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`Provider '${provider.name}' does not export a QueueProvider`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
return new QueueProviderClass(providerOptions);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
module.exports = {
|
|
90
|
+
createQueueProvider,
|
|
91
|
+
determineProvider,
|
|
92
|
+
QUEUE_PROVIDERS,
|
|
93
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Queue Provider Interface (Port)
|
|
3
|
+
*
|
|
4
|
+
* Defines the contract for queue message sending.
|
|
5
|
+
* All queue adapters must extend this interface.
|
|
6
|
+
*
|
|
7
|
+
* Following Frigg's hexagonal architecture pattern:
|
|
8
|
+
* - Port defines WHAT the service does (contract)
|
|
9
|
+
* - Adapters implement HOW (AWS SQS, Netlify Background Functions, QStash, etc.)
|
|
10
|
+
*/
|
|
11
|
+
class QueueProvider {
|
|
12
|
+
/**
|
|
13
|
+
* Send a single message to a queue
|
|
14
|
+
*
|
|
15
|
+
* @param {Object} message - Message payload (will be JSON-serialized)
|
|
16
|
+
* @param {string} queueId - Queue identifier (URL, name, or endpoint depending on provider)
|
|
17
|
+
* @returns {Promise<Object>} Provider-specific response
|
|
18
|
+
*/
|
|
19
|
+
async send(message, queueId) {
|
|
20
|
+
throw new Error('Method send must be implemented by subclass');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Send a batch of messages to a queue
|
|
25
|
+
*
|
|
26
|
+
* @param {Object[]} entries - Array of message payloads
|
|
27
|
+
* @param {string} queueId - Queue identifier
|
|
28
|
+
* @returns {Promise<Object>} Provider-specific response
|
|
29
|
+
*/
|
|
30
|
+
async batchSend(entries, queueId) {
|
|
31
|
+
throw new Error('Method batchSend must be implemented by subclass');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Parse an incoming event into an array of message payloads.
|
|
36
|
+
* Each provider has its own event shape (SQS Records, HTTP body, etc.)
|
|
37
|
+
*
|
|
38
|
+
* @param {Object} event - Raw event from the runtime (Lambda event, HTTP request, etc.)
|
|
39
|
+
* @returns {Object[]} Array of parsed message payloads
|
|
40
|
+
*/
|
|
41
|
+
parseEvent(event) {
|
|
42
|
+
throw new Error('Method parseEvent must be implemented by subclass');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { QueueProvider };
|
package/queues/queuer-util.js
CHANGED
|
@@ -1,30 +1,41 @@
|
|
|
1
1
|
const { v4: uuid } = require('uuid');
|
|
2
|
-
const { SQSClient, SendMessageCommand, SendMessageBatchCommand } = require('@aws-sdk/client-sqs');
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (process.env.AWS_ENDPOINT) {
|
|
14
|
-
config.endpoint = process.env.AWS_ENDPOINT;
|
|
15
|
-
}
|
|
16
|
-
return config;
|
|
17
|
-
};
|
|
3
|
+
/**
|
|
4
|
+
* QueuerUtil - Queue message utility.
|
|
5
|
+
*
|
|
6
|
+
* BREAKING CHANGE (v3): A queue client must be set via setQueueClient()
|
|
7
|
+
* before calling send() or batchSend().
|
|
8
|
+
* For AWS/SQS, pass `new SqsQueueClient()` from @friggframework/provider-aws.
|
|
9
|
+
* See docs/architecture-decisions/010-decouple-aws-from-core.md for migration guide.
|
|
10
|
+
*/
|
|
11
|
+
let _queueClient = null;
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
function getQueueClient() {
|
|
14
|
+
if (!_queueClient) {
|
|
15
|
+
throw new Error(
|
|
16
|
+
'QueuerUtil requires a queue client. Call QueuerUtil.setQueueClient() first, e.g.:\n' +
|
|
17
|
+
' const { SqsQueueClient } = require("@friggframework/provider-aws");\n' +
|
|
18
|
+
' QueuerUtil.setQueueClient(new SqsQueueClient());\n' +
|
|
19
|
+
'See docs/architecture-decisions/010-decouple-aws-from-core.md for migration guide.'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return _queueClient;
|
|
23
|
+
}
|
|
20
24
|
|
|
21
25
|
const QueuerUtil = {
|
|
26
|
+
/**
|
|
27
|
+
* Set the queue client. Must be called before send() or batchSend().
|
|
28
|
+
* @param {QueueClientInterface} client
|
|
29
|
+
*/
|
|
30
|
+
setQueueClient(client) {
|
|
31
|
+
_queueClient = client;
|
|
32
|
+
},
|
|
33
|
+
|
|
22
34
|
send: async (message, queueUrl) => {
|
|
23
|
-
|
|
35
|
+
return getQueueClient().sendMessage({
|
|
24
36
|
MessageBody: JSON.stringify(message),
|
|
25
37
|
QueueUrl: queueUrl,
|
|
26
38
|
});
|
|
27
|
-
return sqs.send(command);
|
|
28
39
|
},
|
|
29
40
|
|
|
30
41
|
batchSend: async (entries = [], queueUrl) => {
|
|
@@ -38,23 +49,20 @@ const QueuerUtil = {
|
|
|
38
49
|
});
|
|
39
50
|
// Sends 10, then purges the buffer
|
|
40
51
|
if (buffer.length === batchSize) {
|
|
41
|
-
|
|
42
|
-
Entries: buffer,
|
|
52
|
+
await getQueueClient().sendMessageBatch({
|
|
53
|
+
Entries: [...buffer],
|
|
43
54
|
QueueUrl: queueUrl,
|
|
44
55
|
});
|
|
45
|
-
|
|
46
|
-
// Purge the buffer
|
|
47
|
-
buffer.splice(0, buffer.length);
|
|
56
|
+
buffer.length = 0;
|
|
48
57
|
}
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
// If any remaining entries under 10 are left in the buffer, send and return
|
|
52
61
|
if (buffer.length > 0) {
|
|
53
|
-
|
|
62
|
+
return getQueueClient().sendMessageBatch({
|
|
54
63
|
Entries: buffer,
|
|
55
64
|
QueueUrl: queueUrl,
|
|
56
65
|
});
|
|
57
|
-
return sqs.send(command);
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
// If we're exact... just return an empty object for now
|
|
@@ -69,7 +69,9 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
69
69
|
$set: documentData,
|
|
70
70
|
}
|
|
71
71
|
);
|
|
72
|
-
const updated = await findOne(this.prisma, 'Sync', {
|
|
72
|
+
const updated = await findOne(this.prisma, 'Sync', {
|
|
73
|
+
_id: existing._id,
|
|
74
|
+
});
|
|
73
75
|
return this._mapSync(updated);
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -103,7 +105,9 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
103
105
|
const doc = await findOne(this.prisma, 'Sync', { _id: syncObjectId });
|
|
104
106
|
if (!doc) return null;
|
|
105
107
|
|
|
106
|
-
const identifiers = Array.isArray(doc.dataIdentifiers)
|
|
108
|
+
const identifiers = Array.isArray(doc.dataIdentifiers)
|
|
109
|
+
? [...doc.dataIdentifiers]
|
|
110
|
+
: [];
|
|
107
111
|
identifiers.push({
|
|
108
112
|
syncId: syncObjectId,
|
|
109
113
|
entityId: toObjectId(dataIdentifier.entity),
|
|
@@ -124,7 +128,9 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
124
128
|
}
|
|
125
129
|
);
|
|
126
130
|
|
|
127
|
-
const updated = await findOne(this.prisma, 'Sync', {
|
|
131
|
+
const updated = await findOne(this.prisma, 'Sync', {
|
|
132
|
+
_id: syncObjectId,
|
|
133
|
+
});
|
|
128
134
|
return updated ? this._mapSync(updated) : null;
|
|
129
135
|
}
|
|
130
136
|
|
|
@@ -134,7 +140,8 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
const entry = syncObj.dataIdentifiers.find(
|
|
137
|
-
(identifier) =>
|
|
143
|
+
(identifier) =>
|
|
144
|
+
fromObjectId(identifier.entityId) === String(entityId)
|
|
138
145
|
);
|
|
139
146
|
|
|
140
147
|
if (entry) {
|
|
@@ -178,7 +185,9 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
178
185
|
query.integrationId = toObjectId(filter.integrationId);
|
|
179
186
|
}
|
|
180
187
|
if (filter.entities) {
|
|
181
|
-
query.entityIds = (filter.entities || [])
|
|
188
|
+
query.entityIds = (filter.entities || [])
|
|
189
|
+
.map((id) => toObjectId(id))
|
|
190
|
+
.filter(Boolean);
|
|
182
191
|
delete query.entities;
|
|
183
192
|
}
|
|
184
193
|
return query;
|
|
@@ -190,8 +199,11 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
190
199
|
prepared.integrationId = toObjectId(data.integrationId);
|
|
191
200
|
}
|
|
192
201
|
if (data.entities !== undefined || data.entityIds !== undefined) {
|
|
193
|
-
const list =
|
|
194
|
-
|
|
202
|
+
const list =
|
|
203
|
+
data.entities !== undefined ? data.entities : data.entityIds;
|
|
204
|
+
prepared.entityIds = (list || [])
|
|
205
|
+
.map((id) => toObjectId(id))
|
|
206
|
+
.filter(Boolean);
|
|
195
207
|
}
|
|
196
208
|
if (data.hash !== undefined) prepared.hash = data.hash;
|
|
197
209
|
if (data.name !== undefined) prepared.name = data.name;
|
|
@@ -199,13 +211,17 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
199
211
|
if (data.results !== undefined) prepared.results = data.results;
|
|
200
212
|
if (timestamp) prepared.updatedAt = timestamp;
|
|
201
213
|
if (data.dataIdentifiers !== undefined) {
|
|
202
|
-
prepared.dataIdentifiers = (data.dataIdentifiers || []).map(
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
214
|
+
prepared.dataIdentifiers = (data.dataIdentifiers || []).map(
|
|
215
|
+
(identifier) => ({
|
|
216
|
+
syncId: toObjectId(identifier.syncId),
|
|
217
|
+
entityId: toObjectId(identifier.entityId),
|
|
218
|
+
idData: identifier.idData,
|
|
219
|
+
hash: identifier.hash,
|
|
220
|
+
createdAt: identifier.createdAt
|
|
221
|
+
? new Date(identifier.createdAt)
|
|
222
|
+
: new Date(),
|
|
223
|
+
})
|
|
224
|
+
);
|
|
209
225
|
}
|
|
210
226
|
return prepared;
|
|
211
227
|
}
|
|
@@ -214,7 +230,9 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
214
230
|
if (!doc) return null;
|
|
215
231
|
return {
|
|
216
232
|
id: fromObjectId(doc._id),
|
|
217
|
-
integrationId: doc.integrationId
|
|
233
|
+
integrationId: doc.integrationId
|
|
234
|
+
? fromObjectId(doc.integrationId)
|
|
235
|
+
: null,
|
|
218
236
|
entities: Array.isArray(doc.entityIds)
|
|
219
237
|
? doc.entityIds.map((id) => fromObjectId(id))
|
|
220
238
|
: [],
|
|
@@ -225,8 +243,12 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
225
243
|
name: doc.name ?? null,
|
|
226
244
|
dataIdentifiers: Array.isArray(doc.dataIdentifiers)
|
|
227
245
|
? doc.dataIdentifiers.map((identifier) => ({
|
|
228
|
-
syncId: identifier.syncId
|
|
229
|
-
|
|
246
|
+
syncId: identifier.syncId
|
|
247
|
+
? fromObjectId(identifier.syncId)
|
|
248
|
+
: null,
|
|
249
|
+
entityId: identifier.entityId
|
|
250
|
+
? fromObjectId(identifier.entityId)
|
|
251
|
+
: null,
|
|
230
252
|
idData: identifier.idData,
|
|
231
253
|
hash: identifier.hash,
|
|
232
254
|
}))
|
|
@@ -236,5 +258,3 @@ class SyncRepositoryDocumentDB extends SyncRepositoryInterface {
|
|
|
236
258
|
}
|
|
237
259
|
|
|
238
260
|
module.exports = { SyncRepositoryDocumentDB };
|
|
239
|
-
|
|
240
|
-
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
const { SyncRepositoryMongo } = require('./sync-repository-mongo');
|
|
2
1
|
const { SyncRepositoryPostgres } = require('./sync-repository-postgres');
|
|
3
|
-
const { SyncRepositoryDocumentDB } = require('./sync-repository-documentdb');
|
|
4
2
|
const config = require('../../database/config');
|
|
5
3
|
|
|
6
4
|
/**
|
|
@@ -19,12 +17,14 @@ function createSyncRepository() {
|
|
|
19
17
|
|
|
20
18
|
switch (dbType) {
|
|
21
19
|
case 'mongodb':
|
|
20
|
+
const { SyncRepositoryMongo } = require('./sync-repository-mongo');
|
|
22
21
|
return new SyncRepositoryMongo();
|
|
23
22
|
|
|
24
23
|
case 'postgresql':
|
|
25
24
|
return new SyncRepositoryPostgres();
|
|
26
25
|
|
|
27
26
|
case 'documentdb':
|
|
27
|
+
const { SyncRepositoryDocumentDB } = require('./sync-repository-documentdb');
|
|
28
28
|
return new SyncRepositoryDocumentDB();
|
|
29
29
|
|
|
30
30
|
default:
|
|
@@ -37,7 +37,7 @@ function createSyncRepository() {
|
|
|
37
37
|
module.exports = {
|
|
38
38
|
createSyncRepository,
|
|
39
39
|
// Export adapters for direct testing
|
|
40
|
-
SyncRepositoryMongo,
|
|
40
|
+
get SyncRepositoryMongo() { return require('./sync-repository-mongo').SyncRepositoryMongo; },
|
|
41
41
|
SyncRepositoryPostgres,
|
|
42
|
-
SyncRepositoryDocumentDB,
|
|
42
|
+
get SyncRepositoryDocumentDB() { return require('./sync-repository-documentdb').SyncRepositoryDocumentDB; },
|
|
43
43
|
};
|
|
@@ -56,7 +56,9 @@ class SyncRepositoryInterface {
|
|
|
56
56
|
* @abstract
|
|
57
57
|
*/
|
|
58
58
|
async addDataIdentifier(syncId, dataIdentifier) {
|
|
59
|
-
throw new Error(
|
|
59
|
+
throw new Error(
|
|
60
|
+
'Method addDataIdentifier must be implemented by subclass'
|
|
61
|
+
);
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
/**
|
|
@@ -69,7 +71,9 @@ class SyncRepositoryInterface {
|
|
|
69
71
|
* @abstract
|
|
70
72
|
*/
|
|
71
73
|
getEntityObjIdForEntityIdFromObject(syncObj, entityId) {
|
|
72
|
-
throw new Error(
|
|
74
|
+
throw new Error(
|
|
75
|
+
'Method getEntityObjIdForEntityIdFromObject must be implemented by subclass'
|
|
76
|
+
);
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
/**
|
|
@@ -46,24 +46,26 @@ class SyncRepositoryPostgres extends SyncRepositoryInterface {
|
|
|
46
46
|
...sync,
|
|
47
47
|
id: sync.id?.toString(),
|
|
48
48
|
integrationId: sync.integrationId?.toString(),
|
|
49
|
-
entities: sync.entities?.map(e => ({
|
|
49
|
+
entities: sync.entities?.map((e) => ({
|
|
50
50
|
...e,
|
|
51
51
|
id: e.id?.toString(),
|
|
52
52
|
userId: e.userId?.toString(),
|
|
53
|
-
credentialId: e.credentialId?.toString()
|
|
53
|
+
credentialId: e.credentialId?.toString(),
|
|
54
54
|
})),
|
|
55
|
-
dataIdentifiers: sync.dataIdentifiers?.map(di => ({
|
|
55
|
+
dataIdentifiers: sync.dataIdentifiers?.map((di) => ({
|
|
56
56
|
...di,
|
|
57
57
|
id: di.id?.toString(),
|
|
58
58
|
syncId: di.syncId?.toString(),
|
|
59
59
|
entityId: di.entityId?.toString(),
|
|
60
|
-
entity: di.entity
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
entity: di.entity
|
|
61
|
+
? {
|
|
62
|
+
...di.entity,
|
|
63
|
+
id: di.entity.id?.toString(),
|
|
64
|
+
userId: di.entity.userId?.toString(),
|
|
65
|
+
credentialId: di.entity.credentialId?.toString(),
|
|
66
|
+
}
|
|
67
|
+
: di.entity,
|
|
68
|
+
})),
|
|
67
69
|
};
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -123,7 +125,9 @@ class SyncRepositoryPostgres extends SyncRepositoryInterface {
|
|
|
123
125
|
// Convert IDs in syncData if present
|
|
124
126
|
const convertedData = { ...syncData };
|
|
125
127
|
if (convertedData.integrationId) {
|
|
126
|
-
convertedData.integrationId = this._convertId(
|
|
128
|
+
convertedData.integrationId = this._convertId(
|
|
129
|
+
convertedData.integrationId
|
|
130
|
+
);
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
if (existing) {
|
|
@@ -155,7 +159,9 @@ class SyncRepositoryPostgres extends SyncRepositoryInterface {
|
|
|
155
159
|
// Convert IDs in updates if present
|
|
156
160
|
const convertedUpdates = { ...updates };
|
|
157
161
|
if (convertedUpdates.integrationId) {
|
|
158
|
-
convertedUpdates.integrationId = this._convertId(
|
|
162
|
+
convertedUpdates.integrationId = this._convertId(
|
|
163
|
+
convertedUpdates.integrationId
|
|
164
|
+
);
|
|
159
165
|
}
|
|
160
166
|
|
|
161
167
|
const updated = await this.prisma.sync.update({
|
|
@@ -241,7 +247,7 @@ class SyncRepositoryPostgres extends SyncRepositoryInterface {
|
|
|
241
247
|
},
|
|
242
248
|
},
|
|
243
249
|
});
|
|
244
|
-
return syncs.map(sync => this._convertSyncIds(sync));
|
|
250
|
+
return syncs.map((sync) => this._convertSyncIds(sync));
|
|
245
251
|
}
|
|
246
252
|
|
|
247
253
|
/**
|