@adobe/spacecat-shared-data-access 2.88.2 → 2.88.3

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 (36) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +1 -1
  3. package/src/models/api-key/api-key.collection.js +2 -0
  4. package/src/models/async-job/async-job.collection.js +2 -0
  5. package/src/models/audit/audit.collection.js +2 -0
  6. package/src/models/base/base.collection.js +8 -0
  7. package/src/models/base/entity.registry.js +1 -1
  8. package/src/models/base/schema.builder.js +4 -0
  9. package/src/models/base/schema.js +2 -2
  10. package/src/models/configuration/configuration.collection.js +2 -0
  11. package/src/models/entitlement/entitlement.collection.js +2 -0
  12. package/src/models/experiment/experiment.collection.js +2 -0
  13. package/src/models/fix-entity/fix-entity.collection.js +2 -0
  14. package/src/models/fix-entity-suggestion/fix-entity-suggestion.collection.js +2 -0
  15. package/src/models/import-job/import-job.collection.js +2 -0
  16. package/src/models/import-url/import-url.collection.js +2 -0
  17. package/src/models/key-event/key-event.collection.js +2 -0
  18. package/src/models/latest-audit/latest-audit.collection.js +2 -0
  19. package/src/models/opportunity/opportunity.collection.js +2 -0
  20. package/src/models/organization/organization.collection.js +2 -0
  21. package/src/models/page-citability/page-citability.collection.js +2 -0
  22. package/src/models/page-intent/page-intent.collection.js +2 -0
  23. package/src/models/project/project.collection.js +1 -0
  24. package/src/models/report/report.collection.js +2 -0
  25. package/src/models/scrape-job/scrape-job.collection.js +2 -0
  26. package/src/models/scrape-url/scrape-url.collection.js +2 -0
  27. package/src/models/site/site.collection.js +2 -0
  28. package/src/models/site-candidate/site-candidate.collection.js +2 -0
  29. package/src/models/site-enrollment/site-enrollment.collection.js +2 -0
  30. package/src/models/site-top-form/site-top-form.collection.js +2 -0
  31. package/src/models/site-top-page/site-top-page.collection.js +2 -0
  32. package/src/models/suggestion/suggestion.collection.js +2 -0
  33. package/src/models/trial-user/trial-user.collection.js +2 -0
  34. package/src/models/trial-user-activity/trial-user-activity.collection.js +2 -0
  35. package/src/readme.md +15 -4
  36. package/src/util/util.js +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [@adobe/spacecat-shared-data-access-v2.88.3](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v2.88.2...@adobe/spacecat-shared-data-access-v2.88.3) (2025-11-26)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Bundler-Agnostic Explicit COLLECTION_NAME ([#1174](https://github.com/adobe/spacecat-shared/issues/1174)) ([d08b4b8](https://github.com/adobe/spacecat-shared/commit/d08b4b82521da524dd37e64fa85258451dc4a3fa)), closes [#1173](https://github.com/adobe/spacecat-shared/issues/1173) [#1173](https://github.com/adobe/spacecat-shared/issues/1173) [#1173](https://github.com/adobe/spacecat-shared/issues/1173) [#1173](https://github.com/adobe/spacecat-shared/issues/1173)
7
+
1
8
  # [@adobe/spacecat-shared-data-access-v2.88.2](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v2.88.1...@adobe/spacecat-shared-data-access-v2.88.2) (2025-11-26)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-data-access",
3
- "version": "2.88.2",
3
+ "version": "2.88.3",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "engines": {
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class ApiKeyCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'ApiKeyCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class AsyncJobCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'AsyncJobCollection';
24
+
23
25
  // Add custom methods or overrides here if needed
24
26
  }
25
27
 
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class AuditCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'AuditCollection';
24
+
23
25
  // create a copy of the audit as a LatestAudit entity
24
26
  async _onCreate(item) {
25
27
  const collection = this.entityRegistry.getCollection('LatestAuditCollection');
@@ -47,6 +47,14 @@ function isValidParent(parent, child) {
47
47
  * @abstract
48
48
  */
49
49
  class BaseCollection {
50
+ /**
51
+ * The collection name for this collection. Must be overridden by subclasses.
52
+ * This ensures the collection name is explicit and not dependent on class names
53
+ * which can be mangled by bundlers.
54
+ * @type {string}
55
+ */
56
+ static COLLECTION_NAME = undefined;
57
+
50
58
  /**
51
59
  * Constructs an instance of BaseCollection.
52
60
  * @constructor
@@ -101,7 +101,7 @@ class EntityRegistry {
101
101
  #initialize() {
102
102
  Object.values(EntityRegistry.entities).forEach(({ collection: Collection, schema }) => {
103
103
  const collection = new Collection(this.service, this, schema, this.log);
104
- this.collections.set(Collection.name, collection);
104
+ this.collections.set(Collection.COLLECTION_NAME, collection);
105
105
  });
106
106
  }
107
107
 
@@ -115,6 +115,10 @@ class SchemaBuilder {
115
115
  throw new SchemaBuilderError(this, `Model class ${modelClass.name} must define a static ENTITY_NAME property.`);
116
116
  }
117
117
 
118
+ if (!hasText(collectionClass.COLLECTION_NAME)) {
119
+ throw new SchemaBuilderError(this, `Collection class ${collectionClass.name} must define a static COLLECTION_NAME property.`);
120
+ }
121
+
118
122
  this.modelClass = modelClass;
119
123
  this.collectionClass = collectionClass;
120
124
  this.schemaVersion = schemaVersion;
@@ -116,7 +116,7 @@ class Schema {
116
116
  }
117
117
 
118
118
  getCollectionName() {
119
- return this.collectionClass.name;
119
+ return this.collectionClass.COLLECTION_NAME;
120
120
  }
121
121
 
122
122
  getEntityName() {
@@ -257,7 +257,7 @@ class Schema {
257
257
  }
258
258
 
259
259
  getModelName() {
260
- return this.modelClass.name;
260
+ return this.modelClass.ENTITY_NAME;
261
261
  }
262
262
 
263
263
  /**
@@ -22,6 +22,8 @@ import BaseCollection from '../base/base.collection.js';
22
22
  * @extends BaseCollection
23
23
  */
24
24
  class ConfigurationCollection extends BaseCollection {
25
+ static COLLECTION_NAME = 'ConfigurationCollection';
26
+
25
27
  async create(data) {
26
28
  const latestConfiguration = await this.findLatest();
27
29
  const version = latestConfiguration ? incrementVersion(latestConfiguration.getVersion()) : 1;
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class EntitlementCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'EntitlementCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class ExperimentCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'ExperimentCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -28,6 +28,8 @@ import { resolveUpdates } from '../../util/util.js';
28
28
  * @extends BaseCollection
29
29
  */
30
30
  class FixEntityCollection extends BaseCollection {
31
+ static COLLECTION_NAME = 'FixEntityCollection';
32
+
31
33
  /**
32
34
  * Gets all suggestions associated with a specific FixEntity.
33
35
  *
@@ -26,6 +26,8 @@ import BaseCollection from '../base/base.collection.js';
26
26
  * @extends BaseCollection
27
27
  */
28
28
  class FixEntitySuggestionCollection extends BaseCollection {
29
+ static COLLECTION_NAME = 'FixEntitySuggestionCollection';
30
+
29
31
  /**
30
32
  * Gets all junction records associated with a specific Suggestion.
31
33
  *
@@ -23,6 +23,8 @@ import BaseCollection from '../base/base.collection.js';
23
23
  * @extends BaseCollection
24
24
  */
25
25
  class ImportJobCollection extends BaseCollection {
26
+ static COLLECTION_NAME = 'ImportJobCollection';
27
+
26
28
  async allByDateRange(startDate, endDate) {
27
29
  if (!isIsoDate(startDate)) {
28
30
  throw new ValidationError(`Invalid start date: ${startDate}`);
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class ImportUrlCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'ImportUrlCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class KeyEventCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'KeyEventCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -21,6 +21,8 @@ import { guardId, guardString } from '../../util/index.js';
21
21
  * @extends AuditCollection
22
22
  */
23
23
  class LatestAuditCollection extends BaseCollection {
24
+ static COLLECTION_NAME = 'LatestAuditCollection';
25
+
24
26
  async create(item) {
25
27
  return super.create(item, { upsert: true });
26
28
  }
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class OpportunityCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'OpportunityCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class OrganizationCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'OrganizationCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -19,6 +19,8 @@ import BaseCollection from '../base/base.collection.js';
19
19
  * @extends BaseCollection
20
20
  */
21
21
  class PageCitabilityCollection extends BaseCollection {
22
+ static COLLECTION_NAME = 'PageCitabilityCollection';
23
+
22
24
  // add custom collection-level methods here, if needed
23
25
  }
24
26
 
@@ -19,6 +19,8 @@ import BaseCollection from '../base/base.collection.js';
19
19
  * @extends BaseCollection
20
20
  */
21
21
  class PageIntentCollection extends BaseCollection {
22
+ static COLLECTION_NAME = 'PageIntentCollection';
23
+
22
24
  // add custom collection-level methods here, if needed
23
25
  }
24
26
 
@@ -20,6 +20,7 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class ProjectCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'ProjectCollection';
23
24
  }
24
25
 
25
26
  export default ProjectCollection;
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class ReportCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'ReportCollection';
24
+
23
25
  async create(item) {
24
26
  const report = await super.create(item, { upsert: true });
25
27
 
@@ -23,6 +23,8 @@ import BaseCollection from '../base/base.collection.js';
23
23
  * @extends BaseCollection
24
24
  */
25
25
  class ScrapeJobCollection extends BaseCollection {
26
+ static COLLECTION_NAME = 'ScrapeJobCollection';
27
+
26
28
  async allByDateRange(startDate, endDate) {
27
29
  if (!isIsoDate(startDate)) {
28
30
  throw new ValidationError(`Invalid start date: ${startDate}`);
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class ScrapeUrlCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'ScrapeUrlCollection';
24
+
23
25
  async allRecentByUrlAndProcessingType(url, processingType, maxAgeInHours = 168) {
24
26
  const now = new Date();
25
27
  const pastDate = new Date(now.getTime() - maxAgeInHours * 60 * 60 * 1000);
@@ -25,6 +25,8 @@ import Site, { AEM_CS_HOST, getAuthoringType } from './site.model.js';
25
25
  * @extends BaseCollection
26
26
  */
27
27
  class SiteCollection extends BaseCollection {
28
+ static COLLECTION_NAME = 'SiteCollection';
29
+
28
30
  async allSitesToAudit() {
29
31
  return (await this.all({}, { attributes: ['siteId'] })).map((site) => site.getId());
30
32
  }
@@ -21,6 +21,8 @@ import BaseCollection from '../base/base.collection.js';
21
21
  * @extends BaseCollection
22
22
  */
23
23
  class SiteCandidateCollection extends BaseCollection {
24
+ static COLLECTION_NAME = 'SiteCandidateCollection';
25
+
24
26
  // add custom methods here
25
27
  }
26
28
 
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class SiteEnrollmentCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'SiteEnrollmentCollection';
24
+
23
25
  // add your custom collection methods here
24
26
  }
25
27
 
@@ -22,6 +22,8 @@ import BaseCollection from '../base/base.collection.js';
22
22
  * @extends BaseCollection
23
23
  */
24
24
  class SiteTopFormCollection extends BaseCollection {
25
+ static COLLECTION_NAME = 'SiteTopFormCollection';
26
+
25
27
  /**
26
28
  * Override create method to validate URL presence and handle optional formSource
27
29
  * @param {Object} item - The data for the entity to be created
@@ -22,6 +22,8 @@ import BaseCollection from '../base/base.collection.js';
22
22
  * @extends BaseCollection
23
23
  */
24
24
  class SiteTopPageCollection extends BaseCollection {
25
+ static COLLECTION_NAME = 'SiteTopPageCollection';
26
+
25
27
  async removeForSiteId(siteId, source, geo) {
26
28
  if (!hasText(siteId)) {
27
29
  throw new Error('SiteId is required');
@@ -28,6 +28,8 @@ import { guardId } from '../../util/guards.js';
28
28
  * @extends BaseCollection
29
29
  */
30
30
  class SuggestionCollection extends BaseCollection {
31
+ static COLLECTION_NAME = 'SuggestionCollection';
32
+
31
33
  /**
32
34
  * Updates the status of multiple given suggestions. The given status must conform
33
35
  * to the status enum defined in the Suggestion schema.
@@ -20,6 +20,8 @@ import BaseCollection from '../base/base.collection.js';
20
20
  * @extends BaseCollection
21
21
  */
22
22
  class TrialUserCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'TrialUserCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -22,6 +22,8 @@ import BaseCollection from '../base/base.collection.js';
22
22
  * @extends BaseCollection
23
23
  */
24
24
  class TrialUserActivityCollection extends BaseCollection {
25
+ static COLLECTION_NAME = 'TrialUserActivityCollection';
26
+
25
27
  // add custom methods here
26
28
  }
27
29
 
package/src/readme.md CHANGED
@@ -31,6 +31,8 @@ A *Collection* operates on sets of entities. While `Model` focuses on individual
31
31
 
32
32
  Collections extend `BaseCollection`, which generates query methods at runtime based on your schema definitions.
33
33
 
34
+ **Required:** All collection classes must define a `static COLLECTION_NAME` property to ensure bundler-agnostic operation.
35
+
34
36
  ### Schema Builder
35
37
  The `SchemaBuilder` is a fluent API to define an entity’s schema:
36
38
 
@@ -42,20 +44,25 @@ The `SchemaBuilder` enforces naming conventions and sets defaults, reducing repe
42
44
 
43
45
  **Note on Indexes:** Add indexes thoughtfully. Every extra index adds cost and complexity. Only create indexes for well-understood, frequently-needed query patterns.
44
46
 
45
- ### Entity Naming (ENTITY_NAME)
47
+ ### Entity and Collection Naming
46
48
 
47
- All model classes **must** define a static `ENTITY_NAME` property:
49
+ All model and collection classes **must** define explicit static name properties:
48
50
 
49
51
  ```js
50
52
  class User extends BaseModel {
51
53
  static ENTITY_NAME = 'User';
52
54
  // ...
53
55
  }
56
+
57
+ class UserCollection extends BaseCollection {
58
+ static COLLECTION_NAME = 'UserCollection';
59
+ // ...
60
+ }
54
61
  ```
55
62
 
56
- This requirement ensures entity names remain consistent regardless of build tool transformations. Modern JavaScript bundlers (webpack, esbuild) may mangle class names during the build process (e.g., `Configuration` → `_Configuration`), which would break ElectroDB's key generation. By explicitly declaring the entity name, the framework operates correctly in all bundling scenarios.
63
+ This requirement ensures names remain consistent regardless of build tool transformations. Modern JavaScript bundlers (webpack, esbuild) may mangle class names during the build process (e.g., `Configuration` → `_Configuration`), which would break ElectroDB's key generation and internal lookups. By explicitly declaring both entity and collection names, the framework operates correctly in all bundling scenarios.
57
64
 
58
- The `SchemaBuilder` validates that `ENTITY_NAME` is defined and will throw a descriptive error if it's missing.
65
+ The `SchemaBuilder` validates that both `ENTITY_NAME` and `COLLECTION_NAME` are defined and will throw descriptive errors if either is missing.
59
66
 
60
67
  ### Entity Registry
61
68
  The `EntityRegistry` aggregates all entities, their schemas, and their collections. It ensures consistent lookup and retrieval of any registered entity’s collection. When you add a new entity, you must register it with the `EntityRegistry` so the rest of the application can discover it.
@@ -383,6 +390,8 @@ Create `user.collection.js`:
383
390
  import BaseCollection from '../base/base.collection.js';
384
391
 
385
392
  class UserCollection extends BaseCollection {
393
+ static COLLECTION_NAME = 'UserCollection';
394
+
386
395
  // Additional domain logic collection methods can be added here if needed.
387
396
  async findByEmail(email) {
388
397
  return this.findByIndexKeys({ email });
@@ -392,6 +401,8 @@ class UserCollection extends BaseCollection {
392
401
  export default UserCollection;
393
402
  ```
394
403
 
404
+ **Important:** Every collection class **must** define a `static COLLECTION_NAME` property for the same bundler-related reasons as `ENTITY_NAME`.
405
+
395
406
  ### 4. Register the Entity
396
407
  In `entity.registry.js` (or equivalent):
397
408
 
package/src/util/util.js CHANGED
@@ -35,7 +35,7 @@ const referenceToBaseMethodName = (reference) => {
35
35
  return `get${baseName}`;
36
36
  };
37
37
 
38
- const entityNameToAllPKValue = (entityName) => `ALL_${pluralize.plural(entityName.toUpperCase())}`;
38
+ const entityNameToAllPKValue = (entityName) => `all_${pluralize.plural(entityName.toLowerCase())}`;
39
39
 
40
40
  const idNameToEntityName = (idName) => {
41
41
  let result = idName;