@adobe/spacecat-shared-data-access 3.71.0 → 3.71.2

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 CHANGED
@@ -1,3 +1,15 @@
1
+ ## [@adobe/spacecat-shared-data-access-v3.71.2](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.71.1...@adobe/spacecat-shared-data-access-v3.71.2) (2026-05-26)
2
+
3
+ ### Bug Fixes
4
+
5
+ * (data-access) batch getAllFixesWithSuggestionsByOpportunityId (SITES-45307) ([#1619](https://github.com/adobe/spacecat-shared/issues/1619)) ([608f4cd](https://github.com/adobe/spacecat-shared/commit/608f4cda59af41c701426b8b53c29770efd42a1c))
6
+
7
+ ## [@adobe/spacecat-shared-data-access-v3.71.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.71.0...@adobe/spacecat-shared-data-access-v3.71.1) (2026-05-25)
8
+
9
+ ### Bug Fixes
10
+
11
+ * **data-access:** make Config.toDynamoItem tolerant of mocks missing ([#1626](https://github.com/adobe/spacecat-shared/issues/1626)) ([4e5b583](https://github.com/adobe/spacecat-shared/commit/4e5b583757fda39a2928f6da34f082f18460be86))
12
+
1
13
  ## [@adobe/spacecat-shared-data-access-v3.71.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.70.2...@adobe/spacecat-shared-data-access-v3.71.0) (2026-05-25)
2
14
 
3
15
  ### Features
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-data-access",
3
- "version": "3.71.0",
3
+ "version": "3.71.2",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "engines": {
@@ -177,69 +177,104 @@ class FixEntityCollection extends BaseCollection {
177
177
 
178
178
  try {
179
179
  const fixEntitySuggestionCollection = this.entityRegistry.getCollection('FixEntitySuggestionCollection');
180
- const suggestionCollection = this.entityRegistry.getCollection('SuggestionCollection');
181
180
 
182
- // Query fix entity suggestions by opportunity ID and created date
183
181
  const fixEntitySuggestions = await fixEntitySuggestionCollection
184
182
  .allByOpportunityIdAndFixEntityCreatedDate(opportunityId, fixEntityCreatedDate);
185
183
 
186
- if (fixEntitySuggestions.length === 0) {
187
- return [];
184
+ return this.#buildFixesWithSuggestions(fixEntitySuggestions);
185
+ } catch (error) {
186
+ if (error instanceof DataAccessError) {
187
+ throw error;
188
188
  }
189
+ this.log.error('Failed to get all fixes with suggestions by created date', error);
190
+ throw new DataAccessError('Failed to get all fixes with suggestions by created date', this, error);
191
+ }
192
+ }
189
193
 
190
- // Group suggestions by fix entity ID
191
- const suggestionsByFixEntityId = {};
192
- const fixEntityIds = new Set();
194
+ /**
195
+ * Gets all fixes with their suggestions for a specific opportunity.
196
+ * Fetches all junction records for the opportunity, then batch-loads
197
+ * fix entities and suggestions. Actual PostgREST call count is
198
+ * 1 + ceil(N/50) + ceil(M/50) due to batchGetByKeys chunking.
199
+ *
200
+ * @async
201
+ * @param {string} opportunityId - The ID of the opportunity.
202
+ * @returns {Promise<Array>} - A promise that resolves to an array of objects containing:
203
+ * - fixEntity: The FixEntity model
204
+ * - suggestions: Array of associated Suggestion models
205
+ * @throws {DataAccessError} - Throws an error if the query fails.
206
+ * @throws {ValidationError} - Throws an error if opportunityId is not provided.
207
+ */
208
+ async getAllFixesWithSuggestionsByOpportunityId(opportunityId) {
209
+ guardId('opportunityId', opportunityId, 'FixEntityCollection');
193
210
 
194
- for (const fixEntitySuggestion of fixEntitySuggestions) {
195
- const fixEntityId = fixEntitySuggestion.getFixEntityId();
196
- const suggestionId = fixEntitySuggestion.getSuggestionId();
211
+ try {
212
+ const fixEntitySuggestionCollection = this.entityRegistry.getCollection('FixEntitySuggestionCollection');
197
213
 
198
- fixEntityIds.add(fixEntityId);
214
+ const fixEntitySuggestions = await fixEntitySuggestionCollection
215
+ .allByIndexKeys({ opportunityId });
199
216
 
200
- if (!suggestionsByFixEntityId[fixEntityId]) {
201
- suggestionsByFixEntityId[fixEntityId] = [];
202
- }
203
- suggestionsByFixEntityId[fixEntityId].push(suggestionId);
217
+ return this.#buildFixesWithSuggestions(fixEntitySuggestions);
218
+ } catch (error) {
219
+ if (error instanceof DataAccessError) {
220
+ throw error;
204
221
  }
222
+ this.log.error('Failed to get all fixes with suggestions by opportunity ID', error);
223
+ throw new DataAccessError('Failed to get all fixes with suggestions by opportunity ID', this, error);
224
+ }
225
+ }
205
226
 
206
- // Get all fix entities
207
- const fixEntities = await this.batchGetByKeys(
208
- Array.from(fixEntityIds).map((id) => ({ [this.idName]: id })),
209
- );
210
-
211
- // Get all suggestions
212
- const allSuggestionIds = Object.values(suggestionsByFixEntityId).flat();
213
- const suggestions = await suggestionCollection.batchGetByKeys(
214
- allSuggestionIds.map((id) => ({ [suggestionCollection.idName]: id })),
215
- );
216
-
217
- // Create a map of suggestions by ID for quick lookup
218
- const suggestionsById = {};
219
- for (const suggestion of suggestions.data) {
220
- suggestionsById[suggestion.getId()] = suggestion;
221
- }
227
+ async #buildFixesWithSuggestions(fixEntitySuggestions) {
228
+ if (fixEntitySuggestions.length === 0) {
229
+ return [];
230
+ }
231
+
232
+ const suggestionCollection = this.entityRegistry.getCollection('SuggestionCollection');
233
+
234
+ const suggestionsByFixEntityId = {};
235
+ const fixEntityIds = new Set();
236
+
237
+ for (const fixEntitySuggestion of fixEntitySuggestions) {
238
+ const fixEntityId = fixEntitySuggestion.getFixEntityId();
239
+ const suggestionId = fixEntitySuggestion.getSuggestionId();
240
+
241
+ fixEntityIds.add(fixEntityId);
222
242
 
223
- // Combine fix entities with their suggestions
224
- const result = [];
225
- for (const fixEntity of fixEntities.data) {
226
- const fixEntityId = fixEntity.getId();
227
- const suggestionIds = suggestionsByFixEntityId[fixEntityId] || [];
228
- const suggestionsForFixEntity = suggestionIds
229
- .map((id) => suggestionsById[id])
230
- .filter(Boolean);
231
-
232
- result.push({
233
- fixEntity,
234
- suggestions: suggestionsForFixEntity,
235
- });
243
+ if (!suggestionsByFixEntityId[fixEntityId]) {
244
+ suggestionsByFixEntityId[fixEntityId] = [];
236
245
  }
246
+ suggestionsByFixEntityId[fixEntityId].push(suggestionId);
247
+ }
237
248
 
238
- return result;
239
- } catch (error) {
240
- this.log.error('Failed to get all fixes with suggestions by created date', error);
241
- throw new DataAccessError('Failed to get all fixes with suggestions by created date', this, error);
249
+ const fixEntities = await this.batchGetByKeys(
250
+ Array.from(fixEntityIds).map((id) => ({ [this.idName]: id })),
251
+ );
252
+
253
+ const allSuggestionIds = Object.values(suggestionsByFixEntityId).flat();
254
+ const suggestions = await suggestionCollection.batchGetByKeys(
255
+ allSuggestionIds.map((id) => ({ [suggestionCollection.idName]: id })),
256
+ );
257
+
258
+ const suggestionsById = {};
259
+ for (const suggestion of suggestions.data) {
260
+ suggestionsById[suggestion.getId()] = suggestion;
261
+ }
262
+
263
+ const result = [];
264
+ for (const fixEntity of fixEntities.data) {
265
+ const fixEntityId = fixEntity.getId();
266
+ const suggestionIds = suggestionsByFixEntityId[fixEntityId] || [];
267
+ const suggestionsForFixEntity = suggestionIds
268
+ .map((id) => suggestionsById[id])
269
+ .filter(Boolean);
270
+
271
+ result.push({
272
+ fixEntity,
273
+ suggestions: suggestionsForFixEntity,
274
+ });
242
275
  }
276
+
277
+ return result;
243
278
  }
244
279
  }
245
280
 
@@ -40,4 +40,6 @@ export interface FixEntityCollection extends BaseCollection<FixEntity> {
40
40
  findByOpportunityIdAndStatus(opportunityId: string, status: string): Promise<FixEntity | null>;
41
41
  getSuggestionsByFixEntityId(fixEntityId: string): Promise<{data: Array<Suggestion>, unprocessed: Array<string>}>;
42
42
  setSuggestionsForFixEntity(opportunityId: string, fixEntity: FixEntity, suggestions: Array<Suggestion>): Promise<{createdItems: Array<FixEntitySuggestion>, errorItems: Array<FixEntitySuggestion>, removedCount: number}>;
43
+ getAllFixesWithSuggestionByCreatedAt(opportunityId: string, fixEntityCreatedDate: string): Promise<Array<{fixEntity: FixEntity, suggestions: Array<Suggestion>}>>;
44
+ getAllFixesWithSuggestionsByOpportunityId(opportunityId: string): Promise<Array<{fixEntity: FixEntity, suggestions: Array<Suggestion>}>>;
43
45
  }
@@ -1077,7 +1077,7 @@ Config.toDynamoItem = (config) => ({
1077
1077
  brandConfig: config.getBrandConfig(),
1078
1078
  brandProfile: config.getBrandProfile(),
1079
1079
  cdnLogsConfig: config.getCdnLogsConfig(),
1080
- scraperConfig: config.getScraperConfig(),
1080
+ scraperConfig: config.getScraperConfig?.(),
1081
1081
  llmo: config.getLlmoConfig(),
1082
1082
  tokowakaConfig: config.getTokowakaConfig(),
1083
1083
  edgeOptimizeConfig: config.getEdgeOptimizeConfig(),