@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.
Files changed (237) hide show
  1. package/CHANGELOG.md +66 -67
  2. package/CLAUDE.md +148 -124
  3. package/README.md +165 -130
  4. package/admin-scripts/index.js +52 -0
  5. package/admin-scripts/repositories/admin-api-key-repository-documentdb.js +21 -0
  6. package/admin-scripts/repositories/admin-api-key-repository-factory.js +51 -0
  7. package/admin-scripts/repositories/admin-api-key-repository-interface.js +121 -0
  8. package/admin-scripts/repositories/admin-api-key-repository-mongo.js +155 -0
  9. package/admin-scripts/repositories/admin-api-key-repository-postgres.js +189 -0
  10. package/admin-scripts/repositories/admin-process-repository-documentdb.js +21 -0
  11. package/admin-scripts/repositories/admin-process-repository-factory.js +49 -0
  12. package/admin-scripts/repositories/admin-process-repository-interface.js +150 -0
  13. package/admin-scripts/repositories/admin-process-repository-mongo.js +213 -0
  14. package/admin-scripts/repositories/admin-process-repository-postgres.js +251 -0
  15. package/admin-scripts/repositories/script-execution-repository-documentdb.js +21 -0
  16. package/admin-scripts/repositories/script-execution-repository-factory.js +51 -0
  17. package/admin-scripts/repositories/script-execution-repository-interface.js +193 -0
  18. package/admin-scripts/repositories/script-execution-repository-mongo.js +278 -0
  19. package/admin-scripts/repositories/script-execution-repository-postgres.js +320 -0
  20. package/admin-scripts/repositories/script-schedule-repository-documentdb.js +21 -0
  21. package/admin-scripts/repositories/script-schedule-repository-factory.js +49 -0
  22. package/admin-scripts/repositories/script-schedule-repository-interface.js +108 -0
  23. package/admin-scripts/repositories/script-schedule-repository-mongo.js +179 -0
  24. package/admin-scripts/repositories/script-schedule-repository-postgres.js +210 -0
  25. package/application/commands/admin-script-commands.js +348 -0
  26. package/application/commands/integration-commands.js +12 -6
  27. package/application/index.js +5 -3
  28. package/assertions/get.js +17 -7
  29. package/associations/association.js +59 -57
  30. package/core/CLAUDE.md +222 -156
  31. package/core/Worker.js +33 -12
  32. package/credential/credential-router.js +262 -0
  33. package/credential/repositories/credential-repository-documentdb.js +71 -1
  34. package/credential/repositories/credential-repository-factory.js +4 -6
  35. package/credential/repositories/credential-repository-interface.js +8 -2
  36. package/credential/repositories/credential-repository-mongo.js +45 -4
  37. package/credential/repositories/credential-repository-postgres.js +44 -3
  38. package/credential/repositories/credential-repository.js +3 -1
  39. package/credential/use-cases/delete-credential-for-user.js +50 -0
  40. package/credential/use-cases/get-credential-for-user.js +21 -3
  41. package/credential/use-cases/list-credentials-for-user.js +31 -0
  42. package/credential/use-cases/reauthorize-credential.js +103 -0
  43. package/credential/use-cases/update-authentication-status.js +5 -2
  44. package/database/MONGODB_TRANSACTION_FIX.md +72 -52
  45. package/database/config.js +13 -59
  46. package/database/documentdb-encryption-service.js +29 -13
  47. package/database/documentdb-utils.js +21 -12
  48. package/database/encryption/README.md +53 -36
  49. package/database/encryption/encryption-schema-registry.js +29 -23
  50. package/database/encryption/field-encryption-service.js +15 -4
  51. package/database/encryption/logger.js +3 -2
  52. package/database/encryption/prisma-encryption-extension.js +5 -8
  53. package/database/prisma.js +22 -14
  54. package/database/repositories/health-check-repository-factory.js +7 -5
  55. package/database/repositories/health-check-repository-interface.js +15 -5
  56. package/database/repositories/health-check-repository-postgres.js +1 -1
  57. package/database/use-cases/check-database-health-use-case.js +3 -2
  58. package/database/use-cases/check-database-state-use-case.js +8 -7
  59. package/database/use-cases/get-database-state-via-worker-use-case.js +15 -12
  60. package/database/use-cases/get-migration-status-use-case.js +4 -2
  61. package/database/use-cases/run-database-migration-use-case.js +41 -9
  62. package/database/use-cases/test-encryption-use-case.js +4 -5
  63. package/database/use-cases/trigger-database-migration-use-case.js +9 -8
  64. package/database/utils/mongodb-collection-utils.js +11 -3
  65. package/database/utils/mongodb-schema-init.js +10 -4
  66. package/database/utils/prisma-runner.js +144 -74
  67. package/database/utils/prisma-schema-parser.js +2 -2
  68. package/docs/PROCESS_MANAGEMENT_QUEUE_SPEC.md +135 -80
  69. package/encrypt/Cryptor.js +54 -49
  70. package/encrypt/aes-encryption-key-provider.js +82 -0
  71. package/encrypt/encryption-key-provider-interface.js +50 -0
  72. package/errors/fetch-error.js +1 -1
  73. package/generated/prisma-mongodb/edge.js +59 -4
  74. package/generated/prisma-mongodb/index-browser.js +49 -1
  75. package/generated/prisma-mongodb/index.d.ts +4023 -61
  76. package/generated/prisma-mongodb/index.js +59 -4
  77. package/generated/prisma-mongodb/package.json +1 -1
  78. package/generated/prisma-mongodb/schema.prisma +87 -0
  79. package/generated/prisma-mongodb/wasm.js +59 -4
  80. package/generated/prisma-postgresql/edge.js +58 -4
  81. package/generated/prisma-postgresql/index-browser.js +48 -1
  82. package/generated/prisma-postgresql/index.d.ts +4738 -54
  83. package/generated/prisma-postgresql/index.js +58 -4
  84. package/generated/prisma-postgresql/package.json +1 -1
  85. package/generated/prisma-postgresql/schema.prisma +85 -0
  86. package/generated/prisma-postgresql/wasm.js +58 -4
  87. package/handlers/WEBHOOKS.md +104 -81
  88. package/handlers/app-definition-loader.js +53 -10
  89. package/handlers/app-handler-helpers.js +14 -3
  90. package/handlers/backend-utils.js +0 -1
  91. package/handlers/database-migration-handler.js +64 -45
  92. package/handlers/middleware/admin-auth.js +53 -0
  93. package/handlers/routers/HEALTHCHECK.md +170 -135
  94. package/handlers/routers/admin.js +474 -0
  95. package/handlers/routers/auth.js +51 -9
  96. package/handlers/routers/db-migration.handler.js +2 -3
  97. package/handlers/routers/db-migration.js +102 -66
  98. package/handlers/routers/docs.js +180 -0
  99. package/handlers/routers/health.js +84 -283
  100. package/handlers/routers/integration-defined-routers.js +44 -33
  101. package/handlers/routers/integration-webhook-routers.js +73 -52
  102. package/handlers/routers/middleware/loadUser.js +39 -0
  103. package/handlers/routers/middleware/requireAdmin.js +43 -0
  104. package/handlers/routers/middleware/requireLoggedInUser.js +19 -0
  105. package/handlers/routers/user.js +30 -14
  106. package/handlers/routers/websocket.js +18 -4
  107. package/handlers/use-cases/check-integrations-health-use-case.js +13 -6
  108. package/handlers/workers/db-migration.js +74 -35
  109. package/handlers/workers/integration-defined-workers.js +31 -20
  110. package/index.js +50 -16
  111. package/infrastructure/scheduler/index.js +15 -11
  112. package/infrastructure/scheduler/netlify-scheduler-adapter.js +185 -0
  113. package/infrastructure/scheduler/scheduler-service-factory.js +38 -31
  114. package/integrations/WEBHOOK-QUICKSTART.md +21 -14
  115. package/integrations/index.js +4 -0
  116. package/integrations/integration-base.js +9 -6
  117. package/integrations/integration-router.js +1828 -157
  118. package/integrations/options.js +47 -20
  119. package/integrations/repositories/integration-mapping-repository-factory.js +4 -8
  120. package/integrations/repositories/integration-repository-documentdb.js +53 -24
  121. package/integrations/repositories/integration-repository-factory.js +6 -6
  122. package/integrations/repositories/integration-repository-interface.js +27 -9
  123. package/integrations/repositories/integration-repository-postgres.js +3 -3
  124. package/integrations/repositories/process-repository-factory.js +4 -7
  125. package/integrations/repositories/process-repository-interface.js +9 -5
  126. package/integrations/repositories/process-repository-mongo.js +7 -3
  127. package/integrations/repositories/process-repository-postgres.js +2 -2
  128. package/integrations/tests/doubles/config-capturing-integration.js +9 -8
  129. package/integrations/tests/doubles/dummy-integration-class.js +81 -8
  130. package/integrations/tests/doubles/test-integration-repository.js +51 -11
  131. package/integrations/use-cases/create-integration.js +36 -32
  132. package/integrations/use-cases/create-process.js +20 -9
  133. package/integrations/use-cases/delete-integration-for-user.js +5 -4
  134. package/integrations/use-cases/execute-proxy-request.js +564 -0
  135. package/integrations/use-cases/get-integration-for-user.js +25 -10
  136. package/integrations/use-cases/get-integration-instance-by-definition.js +13 -7
  137. package/integrations/use-cases/get-integrations-for-user.js +4 -1
  138. package/integrations/use-cases/get-possible-integrations.js +1 -1
  139. package/integrations/use-cases/get-process.js +5 -6
  140. package/integrations/use-cases/index.js +3 -1
  141. package/integrations/use-cases/load-integration-context.js +1 -5
  142. package/integrations/use-cases/update-process-state.js +10 -8
  143. package/integrations/utils/map-integration-dto.js +9 -3
  144. package/jest-setup.js +1 -1
  145. package/jest-teardown.js +1 -1
  146. package/lambda/TimeoutCatcher.js +32 -30
  147. package/lambda/index.js +1 -1
  148. package/logs/index.js +3 -3
  149. package/modules/domain/entities/AuthorizationSession.js +131 -0
  150. package/modules/domain/entities/index.js +10 -0
  151. package/modules/module.js +4 -9
  152. package/modules/repositories/authorization-session-repository-factory.js +53 -0
  153. package/modules/repositories/authorization-session-repository-interface.js +75 -0
  154. package/modules/repositories/authorization-session-repository-mongo.js +169 -0
  155. package/modules/repositories/authorization-session-repository-postgres.js +170 -0
  156. package/modules/repositories/module-repository-documentdb.js +89 -41
  157. package/modules/repositories/module-repository-factory.js +4 -6
  158. package/modules/repositories/module-repository-interface.js +13 -0
  159. package/modules/repositories/module-repository-mongo.js +40 -5
  160. package/modules/repositories/module-repository-postgres.js +42 -5
  161. package/modules/repositories/module-repository.js +28 -0
  162. package/modules/requester/api-key.js +0 -2
  163. package/modules/requester/basic.js +0 -1
  164. package/modules/requester/oauth-2.js +3 -14
  165. package/modules/test/mock-api/definition.js +15 -10
  166. package/modules/test/mock-api/mocks/hubspot.js +36 -36
  167. package/modules/tests/doubles/test-module-factory.js +10 -4
  168. package/modules/tests/doubles/test-module-repository.js +1 -1
  169. package/modules/use-cases/delete-module-entity.js +23 -0
  170. package/modules/use-cases/get-authorization-requirements.js +110 -0
  171. package/modules/use-cases/get-entities-for-user.js +1 -1
  172. package/modules/use-cases/get-entity-options-by-id.js +8 -6
  173. package/modules/use-cases/get-module-entity-by-id.js +16 -0
  174. package/modules/use-cases/get-module.js +12 -9
  175. package/modules/use-cases/process-authorization-callback.js +12 -6
  176. package/modules/use-cases/process-authorization-step.js +160 -0
  177. package/modules/use-cases/refresh-entity-options.js +8 -6
  178. package/modules/use-cases/start-authorization-session.js +86 -0
  179. package/modules/use-cases/test-module-auth.js +8 -6
  180. package/modules/use-cases/update-module-entity.js +27 -0
  181. package/modules/utils/map-module-dto.js +2 -2
  182. package/openapi/openapi-spec-generator.js +370 -0
  183. package/openapi/openapi-v1.yaml +1360 -0
  184. package/openapi/openapi-v2.yaml +1535 -0
  185. package/package.json +7 -9
  186. package/prisma-mongodb/schema.prisma +87 -0
  187. package/prisma-postgresql/migrations/20260222000000_add_admin_process_and_script_schedule/migration.sql +55 -0
  188. package/prisma-postgresql/schema.prisma +85 -0
  189. package/providers/index.js +13 -0
  190. package/providers/resolve-provider.js +93 -0
  191. package/queues/index.js +19 -0
  192. package/queues/providers/index.js +7 -0
  193. package/queues/providers/netlify-background-provider.js +76 -0
  194. package/queues/providers/qstash-queue-provider.js +122 -0
  195. package/queues/queue-client-interface.js +55 -0
  196. package/queues/queue-provider-factory.js +93 -0
  197. package/queues/queue-provider.js +46 -0
  198. package/queues/queuer-util.js +33 -25
  199. package/syncs/repositories/sync-repository-documentdb.js +39 -19
  200. package/syncs/repositories/sync-repository-factory.js +4 -4
  201. package/syncs/repositories/sync-repository-interface.js +6 -2
  202. package/syncs/repositories/sync-repository-postgres.js +19 -13
  203. package/syncs/sync.js +104 -100
  204. package/token/repositories/token-repository-factory.js +4 -6
  205. package/types/assertions/index.d.ts +72 -72
  206. package/types/core/index.d.ts +98 -53
  207. package/types/errors/index.d.ts +61 -54
  208. package/types/eslint-config/index.d.ts +40 -40
  209. package/types/lambda/index.d.ts +26 -26
  210. package/types/logs/index.d.ts +4 -4
  211. package/types/prettier-config/index.d.ts +5 -5
  212. package/types/test-environment/index.d.ts +14 -14
  213. package/types/tsconfig.json +95 -93
  214. package/user/repositories/user-repository-factory.js +4 -4
  215. package/user/tests/doubles/test-user-repository.js +5 -2
  216. package/user/use-cases/authenticate-user.js +2 -4
  217. package/user/use-cases/authenticate-with-shared-secret.js +1 -1
  218. package/user/use-cases/create-individual-user.js +8 -7
  219. package/user/use-cases/create-organization-user.js +1 -1
  220. package/user/use-cases/create-token-for-user-id.js +1 -1
  221. package/user/use-cases/delete-user.js +47 -0
  222. package/user/use-cases/get-user-from-adopter-jwt.js +0 -2
  223. package/user/use-cases/get-user-from-bearer-token.js +7 -3
  224. package/user/use-cases/get-user-from-x-frigg-headers.js +14 -11
  225. package/user/use-cases/login-user.js +8 -8
  226. package/user/user.js +18 -4
  227. package/utils/backend-path.js +2 -2
  228. package/utils/index.js +4 -1
  229. package/websocket/repositories/websocket-connection-repository-documentdb.js +46 -21
  230. package/websocket/repositories/websocket-connection-repository-factory.js +4 -8
  231. package/websocket/repositories/websocket-connection-repository-mongo.js +26 -16
  232. package/websocket/repositories/websocket-connection-repository-postgres.js +26 -15
  233. package/websocket/repositories/websocket-connection-repository.js +26 -20
  234. package/websocket/websocket-message-sender-interface.js +38 -0
  235. package/database/adapters/lambda-invoker.js +0 -97
  236. package/database/repositories/migration-status-repository-s3.js +0 -137
  237. 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 };
@@ -1,30 +1,41 @@
1
1
  const { v4: uuid } = require('uuid');
2
- const { SQSClient, SendMessageCommand, SendMessageBatchCommand } = require('@aws-sdk/client-sqs');
3
2
 
4
- const awsConfigOptions = () => {
5
- const config = {};
6
- if (process.env.IS_OFFLINE) {
7
- config.credentials = {
8
- accessKeyId: 'test-aws-key',
9
- secretAccessKey: 'test-aws-secret',
10
- };
11
- config.region = 'us-east-1';
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
- const sqs = new SQSClient(awsConfigOptions());
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
- const command = new SendMessageCommand({
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
- const command = new SendMessageBatchCommand({
42
- Entries: buffer,
52
+ await getQueueClient().sendMessageBatch({
53
+ Entries: [...buffer],
43
54
  QueueUrl: queueUrl,
44
55
  });
45
- await sqs.send(command);
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
- const command = new SendMessageBatchCommand({
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', { _id: existing._id });
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) ? [...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', { _id: syncObjectId });
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) => fromObjectId(identifier.entityId) === String(entityId)
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 || []).map((id) => toObjectId(id)).filter(Boolean);
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 = data.entities !== undefined ? data.entities : data.entityIds;
194
- prepared.entityIds = (list || []).map((id) => toObjectId(id)).filter(Boolean);
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((identifier) => ({
203
- syncId: toObjectId(identifier.syncId),
204
- entityId: toObjectId(identifier.entityId),
205
- idData: identifier.idData,
206
- hash: identifier.hash,
207
- createdAt: identifier.createdAt ? new Date(identifier.createdAt) : new Date(),
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 ? fromObjectId(doc.integrationId) : null,
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 ? fromObjectId(identifier.syncId) : null,
229
- entityId: identifier.entityId ? fromObjectId(identifier.entityId) : null,
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('Method addDataIdentifier must be implemented by subclass');
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('Method getEntityObjIdForEntityIdFromObject must be implemented by subclass');
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
- ...di.entity,
62
- id: di.entity.id?.toString(),
63
- userId: di.entity.userId?.toString(),
64
- credentialId: di.entity.credentialId?.toString()
65
- } : di.entity
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(convertedData.integrationId);
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(convertedUpdates.integrationId);
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
  /**