@adobe/spacecat-shared-data-access 3.28.0 → 3.30.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-v3.30.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.29.0...@adobe/spacecat-shared-data-access-v3.30.0) (2026-03-25)
2
+
3
+ ### Features
4
+
5
+ * **data-access:** add allByEnrollmentProductCode to SiteCollection ([#1455](https://github.com/adobe/spacecat-shared/issues/1455)) ([0225791](https://github.com/adobe/spacecat-shared/commit/02257915bbf5aa2e15e1320bbcdfa27b236c44b8))
6
+
7
+ ## [@adobe/spacecat-shared-data-access-v3.29.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.28.0...@adobe/spacecat-shared-data-access-v3.29.0) (2026-03-23)
8
+
9
+ ### Features
10
+
11
+ * **page-citability:** add UPDATED_BY_PRERENDER and UPDATED_BY_PAGE_CITABILITY constants ([#1460](https://github.com/adobe/spacecat-shared/issues/1460)) ([dcdf2b0](https://github.com/adobe/spacecat-shared/commit/dcdf2b0af9b9426631e9363949027a267ce7d015))
12
+
1
13
  ## [@adobe/spacecat-shared-data-access-v3.28.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v3.27.1...@adobe/spacecat-shared-data-access-v3.28.0) (2026-03-23)
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.28.0",
3
+ "version": "3.30.0",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "engines": {
@@ -23,6 +23,10 @@ class PageCitability extends BaseModel {
23
23
 
24
24
  static DEFAULT_UPDATED_BY = 'spacecat';
25
25
 
26
+ static UPDATED_BY_PRERENDER = 'prerender';
27
+
28
+ static UPDATED_BY_PAGE_CITABILITY = 'page-citability';
29
+
26
30
  // add any custom methods or overrides here
27
31
  }
28
32
 
@@ -848,5 +848,5 @@ Config.toDynamoItem = (config) => ({
848
848
  llmo: config.getLlmoConfig(),
849
849
  tokowakaConfig: config.getTokowakaConfig(),
850
850
  edgeOptimizeConfig: config.getEdgeOptimizeConfig(),
851
- commerceLlmoConfig: config.getCommerceLlmoConfig(),
851
+ commerceLlmoConfig: config.getCommerceLlmoConfig?.(),
852
852
  });
@@ -145,6 +145,35 @@ class SiteCollection extends BaseCollection {
145
145
  return this.allByProjectId(projectId);
146
146
  }
147
147
 
148
+ /**
149
+ * Returns all sites enrolled in a given product (e.g. 'LLMO', 'ASO').
150
+ * Uses entityRegistry to chain through EntitlementCollection and SiteEnrollmentCollection,
151
+ * then batch-fetches full Site objects.
152
+ *
153
+ * @param {string} productCode - Product code to filter by (e.g. 'LLMO').
154
+ * @returns {Promise<Site[]>}
155
+ */
156
+ async allByEnrollmentProductCode(productCode, options = {}) {
157
+ if (!hasText(productCode)) {
158
+ throw new DataAccessError('productCode is required', this);
159
+ }
160
+
161
+ const siteEnrollmentCollection = this.entityRegistry.getCollection('SiteEnrollmentCollection');
162
+
163
+ // Query 1: get all site IDs enrolled in the given product (single JOIN query)
164
+ const siteIds = await siteEnrollmentCollection.allSiteIdsByProductCode(productCode);
165
+ if (siteIds.length === 0) {
166
+ return [];
167
+ }
168
+
169
+ // Query 2: batch-fetch Site objects (caller controls which fields to fetch)
170
+ const { data: sites } = await this.batchGetByKeys(
171
+ siteIds.map((siteId) => ({ siteId })),
172
+ options,
173
+ );
174
+ return sites;
175
+ }
176
+
148
177
  async allByOrganizationIdAndProjectName(organizationId, projectName) {
149
178
  if (!hasText(organizationId)) {
150
179
  throw new DataAccessError('organizationId is required', this);
@@ -11,6 +11,7 @@
11
11
  */
12
12
 
13
13
  import BaseCollection from '../base/base.collection.js';
14
+ import DataAccessError from '../../errors/data-access.error.js';
14
15
 
15
16
  /**
16
17
  * SiteEnrollmentCollection - A class representing a collection of SiteEnrollment entities.
@@ -22,6 +23,30 @@ import BaseCollection from '../base/base.collection.js';
22
23
  class SiteEnrollmentCollection extends BaseCollection {
23
24
  static COLLECTION_NAME = 'SiteEnrollmentCollection';
24
25
 
26
+ /**
27
+ * Returns all site IDs enrolled in a given product code in a single JOIN query.
28
+ *
29
+ * @param {string} productCode - Product code to filter by (e.g. 'LLMO').
30
+ * @returns {Promise<string[]>} Array of siteId strings.
31
+ */
32
+ async allSiteIdsByProductCode(productCode) {
33
+ if (!productCode) {
34
+ throw new DataAccessError('productCode is required', { entityName: 'SiteEnrollment', tableName: 'site_enrollments' });
35
+ }
36
+
37
+ const { data, error } = await this.postgrestService
38
+ .from(this.tableName)
39
+ .select('site_id, entitlements!inner(product_code)')
40
+ .eq('entitlements.product_code', productCode);
41
+
42
+ if (error) {
43
+ this.log.error(`[SiteEnrollmentCollection] Failed to query site_enrollments by productCode - ${error.message}`, error);
44
+ throw new DataAccessError('Failed to query site_enrollments by productCode', { entityName: 'SiteEnrollment', tableName: 'site_enrollments' }, error);
45
+ }
46
+
47
+ return (data || []).map((row) => row.site_id);
48
+ }
49
+
25
50
  async create(item, options = {}) {
26
51
  if (item?.siteId && item?.entitlementId) {
27
52
  const existing = await this.findByIndexKeys({