@friggframework/core 2.0.0--canary.689.dadb9f7.0 → 2.0.0--canary.689.e2b05a4.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.
@@ -1,6 +1,7 @@
1
1
  const {
2
2
  assertEntityIdsInput,
3
3
  integrationNotFound,
4
+ loadIntegration,
4
5
  } = require('../utils/assert-entity-ids-input');
5
6
 
6
7
  /**
@@ -30,10 +31,10 @@ class AddEntitiesToIntegration {
30
31
  async execute(integrationId, entityIds) {
31
32
  assertEntityIdsInput(integrationId, entityIds);
32
33
 
33
- const integration = await this.integrationRepository
34
- .findIntegrationById(integrationId)
35
- .catch(() => null);
36
- if (!integration) throw integrationNotFound(integrationId);
34
+ const integration = await loadIntegration(
35
+ this.integrationRepository,
36
+ integrationId
37
+ );
37
38
 
38
39
  const entities = await this.moduleRepository.findEntitiesByIds(
39
40
  entityIds
@@ -62,7 +62,7 @@ class CreateIntegration {
62
62
 
63
63
  // A concurrent request may have created a matching row between the
64
64
  // lookup above and this insert; re-check before any side effects run.
65
- const survivor = await this._findDuplicate(
65
+ const survivor = await this._findSurvivor(
66
66
  userId,
67
67
  config?.type,
68
68
  entities
@@ -135,7 +135,7 @@ class CreateIntegration {
135
135
  return mapIntegrationClassToIntegrationDTO(integrationInstance);
136
136
  }
137
137
 
138
- async _findDuplicate(userId, type, entityIds) {
138
+ async _findMatches(userId, type, entityIds) {
139
139
  const candidates =
140
140
  await this.integrationRepository.findIntegrationsByUserId(userId);
141
141
  const target = new Set((entityIds ?? []).map(String));
@@ -163,7 +163,6 @@ class CreateIntegration {
163
163
  [...target].every((id) => current.has(id))
164
164
  );
165
165
  });
166
- if (exact.length) return this._pickOldest(exact);
167
166
 
168
167
  // Entities may have been attached after create (addEntitiesToIntegration),
169
168
  // so a reconnect that sends the original entities must still find the
@@ -173,9 +172,32 @@ class CreateIntegration {
173
172
  const current = entitySet(integration);
174
173
  return [...target].every((id) => current.has(id));
175
174
  });
176
- return target.size && supersets.length
177
- ? this._pickOldest(supersets)
178
- : null;
175
+ return { exact, supersets: target.size ? supersets : [] };
176
+ }
177
+
178
+ async _findDuplicate(userId, type, entityIds) {
179
+ const { exact, supersets } = await this._findMatches(
180
+ userId,
181
+ type,
182
+ entityIds
183
+ );
184
+ if (exact.length) return this._pickOldest(exact);
185
+ return supersets.length ? this._pickOldest(supersets) : null;
186
+ }
187
+
188
+ // After an insert the new row is itself an exact match, so the survivor
189
+ // is the oldest of every exact or superset match (the new row included):
190
+ // an older integration that already holds these entities always wins.
191
+ async _findSurvivor(userId, type, entityIds) {
192
+ const { exact, supersets } = await this._findMatches(
193
+ userId,
194
+ type,
195
+ entityIds
196
+ );
197
+ // supersets includes the exact matches; it is empty only for an
198
+ // empty entity set, where exact matching alone applies.
199
+ const matches = supersets.length ? supersets : exact;
200
+ return matches.length ? this._pickOldest(matches) : null;
179
201
  }
180
202
 
181
203
  _pickOldest(records) {
@@ -1,6 +1,7 @@
1
1
  const {
2
2
  assertEntityIdsInput,
3
3
  integrationNotFound,
4
+ loadIntegration,
4
5
  } = require('../utils/assert-entity-ids-input');
5
6
 
6
7
  /**
@@ -29,10 +30,10 @@ class RemoveEntitiesFromIntegration {
29
30
  async execute(integrationId, entityIds) {
30
31
  assertEntityIdsInput(integrationId, entityIds);
31
32
 
32
- const integration = await this.integrationRepository
33
- .findIntegrationById(integrationId)
34
- .catch(() => null);
35
- if (!integration) throw integrationNotFound(integrationId);
33
+ const integration = await loadIntegration(
34
+ this.integrationRepository,
35
+ integrationId
36
+ );
36
37
 
37
38
  const removing = new Set(entityIds.map(String));
38
39
  const attached = await this.moduleRepository.findEntitiesByIds(
@@ -20,4 +20,23 @@ function integrationNotFound(integrationId) {
20
20
  return error;
21
21
  }
22
22
 
23
- module.exports = { assertEntityIdsInput, integrationNotFound };
23
+ /**
24
+ * Loads an integration, mapping the repositories' "not found" error to
25
+ * INTEGRATION_NOT_FOUND. Any other failure (connection, invalid id) is
26
+ * rethrown unchanged.
27
+ * @param {Object} integrationRepository
28
+ * @param {string} integrationId
29
+ * @returns {Promise<Object>} The integration record.
30
+ */
31
+ async function loadIntegration(integrationRepository, integrationId) {
32
+ try {
33
+ return await integrationRepository.findIntegrationById(integrationId);
34
+ } catch (error) {
35
+ if (/^Integration with id .* not found$/.test(error?.message)) {
36
+ throw integrationNotFound(integrationId);
37
+ }
38
+ throw error;
39
+ }
40
+ }
41
+
42
+ module.exports = { assertEntityIdsInput, integrationNotFound, loadIntegration };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.689.dadb9f7.0",
4
+ "version": "2.0.0--canary.689.e2b05a4.0",
5
5
  "dependencies": {
6
6
  "@aws-sdk/client-apigatewaymanagementapi": "^3.588.0",
7
7
  "@aws-sdk/client-kms": "^3.588.0",
@@ -47,9 +47,9 @@
47
47
  }
48
48
  },
49
49
  "devDependencies": {
50
- "@friggframework/eslint-config": "2.0.0--canary.689.dadb9f7.0",
51
- "@friggframework/prettier-config": "2.0.0--canary.689.dadb9f7.0",
52
- "@friggframework/test": "2.0.0--canary.689.dadb9f7.0",
50
+ "@friggframework/eslint-config": "2.0.0--canary.689.e2b05a4.0",
51
+ "@friggframework/prettier-config": "2.0.0--canary.689.e2b05a4.0",
52
+ "@friggframework/test": "2.0.0--canary.689.e2b05a4.0",
53
53
  "@prisma/client": "^6.19.3",
54
54
  "@types/lodash": "4.17.15",
55
55
  "@typescript-eslint/eslint-plugin": "^8.0.0",
@@ -89,5 +89,5 @@
89
89
  "publishConfig": {
90
90
  "access": "public"
91
91
  },
92
- "gitHead": "dadb9f7e6217f7530852d5b0ad2d6e1e7d0bb2d7"
92
+ "gitHead": "e2b05a436ac65f9c98cada9c325ff8ec633fcd8f"
93
93
  }