@adobe/spacecat-shared-data-access 4.3.0 → 4.4.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 CHANGED
@@ -1,3 +1,15 @@
1
+ ## [@adobe/spacecat-shared-data-access-v4.4.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.3.1...@adobe/spacecat-shared-data-access-v4.4.0) (2026-07-09)
2
+
3
+ ### Features
4
+
5
+ * **fix-entity:** add allByOpportunityIds for site-wide fix queries ([#1792](https://github.com/adobe/spacecat-shared/issues/1792)) ([25309bf](https://github.com/adobe/spacecat-shared/commit/25309bff4be7d90c0f7cdbf854c48a20adfd3e57))
6
+
7
+ ## [@adobe/spacecat-shared-data-access-v4.3.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.3.0...@adobe/spacecat-shared-data-access-v4.3.1) (2026-07-09)
8
+
9
+ ### Bug Fixes
10
+
11
+ * **ticket-suggestion:** use createdAt as belongs_to sort key instead of updatedAt ([#1798](https://github.com/adobe/spacecat-shared/issues/1798)) ([711eecd](https://github.com/adobe/spacecat-shared/commit/711eecdc187ec9a21a79dedca808e6622bd18933)), closes [#2661](https://github.com/adobe/spacecat-shared/issues/2661)
12
+
1
13
  ## [@adobe/spacecat-shared-data-access-v4.3.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v4.2.0...@adobe/spacecat-shared-data-access-v4.3.0) (2026-07-09)
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": "4.3.0",
3
+ "version": "4.4.0",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "engines": {
@@ -15,6 +15,11 @@ import ValidationError from '../../errors/validation.error.js';
15
15
  import { guardId, guardArray, guardString } from '../../util/guards.js';
16
16
  import { resolveUpdates } from '../../util/util.js';
17
17
 
18
+ // PostgREST GET requests serialize IN-filters into the URL, so large ID lists must be
19
+ // chunked to stay well under the ~8KB URL length limit (see batchGetByKeys / llmo-brand-presence
20
+ // for the same pattern elsewhere in this package).
21
+ const IN_FILTER_CHUNK_SIZE = 50;
22
+
18
23
  /**
19
24
  * FixEntityCollection - A collection class responsible for managing FixEntities.
20
25
  * Extends the BaseCollection to provide specific methods for interacting with
@@ -226,6 +231,49 @@ class FixEntityCollection extends BaseCollection {
226
231
  }
227
232
  }
228
233
 
234
+ /**
235
+ * Gets all fixes across a set of opportunities (e.g. every opportunity for a site),
236
+ * by filtering on opportunityId IN (...). Chunks the IN-filter to stay under
237
+ * PostgREST's URL length limit.
238
+ *
239
+ * @async
240
+ * @param {string[]} opportunityIds - The IDs of the opportunities.
241
+ * @returns {Promise<FixEntity[]>} - A promise that resolves to an array of FixEntity models.
242
+ * @throws {DataAccessError} - Throws an error if the query fails.
243
+ * @throws {ValidationError} - Throws an error if opportunityIds is not an array of strings.
244
+ */
245
+ async allByOpportunityIds(opportunityIds) {
246
+ guardArray('opportunityIds', opportunityIds, 'FixEntityCollection', 'string');
247
+
248
+ if (opportunityIds.length === 0) {
249
+ return [];
250
+ }
251
+
252
+ try {
253
+ const uniqueIds = [...new Set(opportunityIds)];
254
+
255
+ const chunks = [];
256
+ for (let i = 0; i < uniqueIds.length; i += IN_FILTER_CHUNK_SIZE) {
257
+ chunks.push(uniqueIds.slice(i, i + IN_FILTER_CHUNK_SIZE));
258
+ }
259
+
260
+ const results = await Promise.all(
261
+ chunks.map((chunk) => this.all(
262
+ {},
263
+ { where: (attrs, op) => op.in(attrs.opportunityId, chunk) },
264
+ )),
265
+ );
266
+
267
+ return results.flat();
268
+ } catch (error) {
269
+ if (error instanceof DataAccessError) {
270
+ throw error;
271
+ }
272
+ this.log.error('Failed to get all fixes by opportunity IDs', error);
273
+ throw new DataAccessError('Failed to get all fixes by opportunity IDs', this, error);
274
+ }
275
+ }
276
+
229
277
  async #buildFixesWithSuggestions(fixEntitySuggestions) {
230
278
  if (fixEntitySuggestions.length === 0) {
231
279
  return [];
@@ -29,7 +29,10 @@ const schema = new SchemaBuilder(TicketSuggestion, TicketSuggestionCollection)
29
29
  type: 'string', required: false, readOnly: true, postgrestIgnore: true,
30
30
  })
31
31
  .addAttribute('updatedBy', { type: 'string', required: false, postgrestIgnore: true })
32
- .addReference('belongs_to', 'Ticket')
32
+ // Sort key uses createdAt (not the default updatedAt) because ticket_suggestions is
33
+ // append-only — the table has no updated_at column, so ORDER BY updated_at would
34
+ // cause PostgREST to error on allByTicketId queries.
35
+ .addReference('belongs_to', 'Ticket', ['createdAt'])
33
36
  .addAttribute('suggestionId', {
34
37
  type: 'string',
35
38
  required: true,