@adobe/spacecat-shared-data-access 2.88.1 → 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 (65) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +1 -1
  3. package/src/models/api-key/api-key.collection.js +2 -0
  4. package/src/models/api-key/api-key.model.js +2 -0
  5. package/src/models/async-job/async-job.collection.js +2 -0
  6. package/src/models/async-job/async-job.model.js +2 -0
  7. package/src/models/audit/audit.collection.js +2 -0
  8. package/src/models/audit/audit.model.js +2 -0
  9. package/src/models/base/base.collection.js +8 -0
  10. package/src/models/base/base.model.js +8 -0
  11. package/src/models/base/entity.registry.js +1 -1
  12. package/src/models/base/schema.builder.js +9 -1
  13. package/src/models/base/schema.js +2 -2
  14. package/src/models/configuration/configuration.collection.js +2 -0
  15. package/src/models/configuration/configuration.model.js +2 -0
  16. package/src/models/entitlement/entitlement.collection.js +2 -0
  17. package/src/models/entitlement/entitlement.model.js +2 -0
  18. package/src/models/experiment/experiment.collection.js +2 -0
  19. package/src/models/experiment/experiment.model.js +2 -0
  20. package/src/models/fix-entity/fix-entity.collection.js +2 -0
  21. package/src/models/fix-entity/fix-entity.model.js +2 -0
  22. package/src/models/fix-entity-suggestion/fix-entity-suggestion.collection.js +2 -0
  23. package/src/models/fix-entity-suggestion/fix-entity-suggestion.model.js +2 -0
  24. package/src/models/import-job/import-job.collection.js +2 -0
  25. package/src/models/import-job/import-job.model.js +2 -0
  26. package/src/models/import-url/import-url.collection.js +2 -0
  27. package/src/models/import-url/import-url.model.js +2 -0
  28. package/src/models/key-event/key-event.collection.js +2 -0
  29. package/src/models/key-event/key-event.model.js +2 -0
  30. package/src/models/latest-audit/latest-audit.collection.js +2 -0
  31. package/src/models/latest-audit/latest-audit.model.js +2 -0
  32. package/src/models/opportunity/opportunity.collection.js +2 -0
  33. package/src/models/opportunity/opportunity.model.js +2 -0
  34. package/src/models/organization/organization.collection.js +2 -0
  35. package/src/models/organization/organization.model.js +2 -0
  36. package/src/models/page-citability/page-citability.collection.js +2 -0
  37. package/src/models/page-citability/page-citability.model.js +2 -0
  38. package/src/models/page-intent/page-intent.collection.js +2 -0
  39. package/src/models/page-intent/page-intent.model.js +2 -0
  40. package/src/models/project/project.collection.js +1 -0
  41. package/src/models/project/project.model.js +2 -0
  42. package/src/models/report/report.collection.js +2 -0
  43. package/src/models/report/report.model.js +2 -0
  44. package/src/models/scrape-job/scrape-job.collection.js +2 -0
  45. package/src/models/scrape-job/scrape-job.model.js +2 -0
  46. package/src/models/scrape-url/scrape-url.collection.js +2 -0
  47. package/src/models/scrape-url/scrape-url.model.js +2 -0
  48. package/src/models/site/site.collection.js +2 -0
  49. package/src/models/site/site.model.js +2 -0
  50. package/src/models/site-candidate/site-candidate.collection.js +2 -0
  51. package/src/models/site-candidate/site-candidate.model.js +2 -0
  52. package/src/models/site-enrollment/site-enrollment.collection.js +2 -0
  53. package/src/models/site-enrollment/site-enrollment.model.js +2 -0
  54. package/src/models/site-top-form/site-top-form.collection.js +2 -0
  55. package/src/models/site-top-form/site-top-form.model.js +2 -0
  56. package/src/models/site-top-page/site-top-page.collection.js +2 -0
  57. package/src/models/site-top-page/site-top-page.model.js +2 -0
  58. package/src/models/suggestion/suggestion.collection.js +2 -0
  59. package/src/models/suggestion/suggestion.model.js +2 -0
  60. package/src/models/trial-user/trial-user.collection.js +2 -0
  61. package/src/models/trial-user/trial-user.model.js +2 -0
  62. package/src/models/trial-user-activity/trial-user-activity.collection.js +2 -0
  63. package/src/models/trial-user-activity/trial-user-activity.model.js +2 -0
  64. package/src/readme.md +34 -4
  65. package/src/util/util.js +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
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
+
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)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Make Entity Naming Bundler-Agnostic with Explicit ENTITY_NAME ([#1173](https://github.com/adobe/spacecat-shared/issues/1173)) ([c6cb69c](https://github.com/adobe/spacecat-shared/commit/c6cb69c6114db686f911afafe8d477b4556d9d49))
14
+
1
15
  # [@adobe/spacecat-shared-data-access-v2.88.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v2.88.0...@adobe/spacecat-shared-data-access-v2.88.1) (2025-11-24)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-data-access",
3
- "version": "2.88.1",
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
 
@@ -22,6 +22,8 @@ import BaseModel from '../base/base.model.js';
22
22
  * @extends BaseModel
23
23
  */
24
24
  class ApiKey extends BaseModel {
25
+ static ENTITY_NAME = 'ApiKey';
26
+
25
27
  static SCOPE_NAMES = [
26
28
  'sites.read_all',
27
29
  'sites.write_all',
@@ -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 BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class AsyncJob extends BaseModel {
23
+ static ENTITY_NAME = 'AsyncJob';
24
+
23
25
  /**
24
26
  * Async Job Status types.
25
27
  * Any changes to this object needs to be reflected in the index.d.ts file as well.
@@ -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');
@@ -28,6 +28,8 @@ import BaseModel from '../base/base.model.js';
28
28
  * @extends BaseModel
29
29
  */
30
30
  class Audit extends BaseModel {
31
+ static ENTITY_NAME = 'Audit';
32
+
31
33
  static AUDIT_TYPES = {
32
34
  APEX: 'apex',
33
35
  CWV: 'cwv',
@@ -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
@@ -39,6 +39,14 @@ import Reference from './reference.js';
39
39
  * @class BaseModel
40
40
  */
41
41
  class BaseModel {
42
+ /**
43
+ * The entity name for this model. Must be overridden by subclasses.
44
+ * This ensures the entity name is explicit and not dependent on class names
45
+ * which can be mangled by bundlers.
46
+ * @type {string}
47
+ */
48
+ static ENTITY_NAME = undefined;
49
+
42
50
  /**
43
51
  * Constructs an instance of BaseModel.
44
52
  * @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
 
@@ -111,10 +111,18 @@ class SchemaBuilder {
111
111
  throw new SchemaBuilderError(this, 'schemaVersion is required and must be a positive integer.');
112
112
  }
113
113
 
114
+ if (!hasText(modelClass.ENTITY_NAME)) {
115
+ throw new SchemaBuilderError(this, `Model class ${modelClass.name} must define a static ENTITY_NAME property.`);
116
+ }
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
+
114
122
  this.modelClass = modelClass;
115
123
  this.collectionClass = collectionClass;
116
124
  this.schemaVersion = schemaVersion;
117
- this.entityName = modelClass.name;
125
+ this.entityName = modelClass.ENTITY_NAME;
118
126
  this.serviceName = DEFAULT_SERVICE_NAME;
119
127
 
120
128
  this.idName = entityNameToIdName(this.entityName);
@@ -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;
@@ -24,6 +24,8 @@ import { Entitlement } from '../entitlement/index.js';
24
24
  * @extends BaseModel
25
25
  */
26
26
  class Configuration extends BaseModel {
27
+ static ENTITY_NAME = 'Configuration';
28
+
27
29
  static JOB_GROUPS = {
28
30
  AUDITS: 'audits',
29
31
  IMPORTS: 'imports',
@@ -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 BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class Entitlement extends BaseModel {
23
+ static ENTITY_NAME = 'Entitlement';
24
+
23
25
  static TIERS = {
24
26
  FREE_TRIAL: 'FREE_TRIAL',
25
27
  PAID: 'PAID',
@@ -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
 
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class Experiment extends BaseModel {
23
+ static ENTITY_NAME = 'Experiment';
24
+
23
25
  static DEFAULT_UPDATED_BY = 'spacecat';
24
26
 
25
27
  // add your custom methods or overrides here
@@ -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
  *
@@ -19,6 +19,8 @@ import BaseModel from '../base/base.model.js';
19
19
  * @extends BaseModel
20
20
  */
21
21
  class FixEntity extends BaseModel {
22
+ static ENTITY_NAME = 'FixEntity';
23
+
22
24
  static DEFAULT_UPDATED_BY = 'spacecat';
23
25
 
24
26
  static STATUSES = {
@@ -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
  *
@@ -21,6 +21,8 @@ import BaseModel from '../base/base.model.js';
21
21
  * @extends BaseModel
22
22
  */
23
23
  class FixEntitySuggestion extends BaseModel {
24
+ static ENTITY_NAME = 'FixEntitySuggestion';
25
+
24
26
  static DEFAULT_UPDATED_BY = 'spacecat';
25
27
 
26
28
  /**
@@ -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 BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class ImportJob extends BaseModel {
23
+ static ENTITY_NAME = 'ImportJob';
24
+
23
25
  /**
24
26
  * Import Job Status types.
25
27
  * Any changes to this object needs to be reflected in the index.d.ts file as well.
@@ -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 BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class ImportUrl extends BaseModel {
23
+ static ENTITY_NAME = 'ImportUrl';
24
+
23
25
  static IMPORT_URL_EXPIRES_IN_DAYS = 30;
24
26
 
25
27
  // add your custom methods or overrides here
@@ -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
 
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class KeyEvent extends BaseModel {
23
+ static ENTITY_NAME = 'KeyEvent';
24
+
23
25
  static KEY_EVENT_TYPES = {
24
26
  PERFORMANCE: 'PERFORMANCE',
25
27
  SEO: 'SEO',
@@ -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 Audit from '../audit/audit.model.js';
20
20
  * @extends Audit
21
21
  */
22
22
  class LatestAudit extends Audit {
23
+ static ENTITY_NAME = 'LatestAudit';
24
+
23
25
  // add your custom methods or overrides 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 OpportunityCollection extends BaseCollection {
23
+ static COLLECTION_NAME = 'OpportunityCollection';
24
+
23
25
  // add custom methods here
24
26
  }
25
27
 
@@ -22,6 +22,8 @@ import BaseModel from '../base/base.model.js';
22
22
  */
23
23
 
24
24
  class Opportunity extends BaseModel {
25
+ static ENTITY_NAME = 'Opportunity';
26
+
25
27
  static ORIGINS = {
26
28
  ESS_OPS: 'ESS_OPS',
27
29
  AI: 'AI',
@@ -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
 
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class Organization extends BaseModel {
23
+ static ENTITY_NAME = 'Organization';
24
+
23
25
  static IMS_ORG_ID_REGEX = /[a-z0-9]{24}@AdobeOrg/i;
24
26
 
25
27
  // add your custom methods or overrides here
@@ -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 BaseModel from '../base/base.model.js';
19
19
  * @extends BaseModel
20
20
  */
21
21
  class PageCitability extends BaseModel {
22
+ static ENTITY_NAME = 'PageCitability';
23
+
22
24
  static DEFAULT_UPDATED_BY = 'spacecat';
23
25
 
24
26
  // add any custom methods or overrides here
@@ -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
 
@@ -19,6 +19,8 @@ import BaseModel from '../base/base.model.js';
19
19
  * @extends BaseModel
20
20
  */
21
21
  class PageIntent extends BaseModel {
22
+ static ENTITY_NAME = 'PageIntent';
23
+
22
24
  static DEFAULT_UPDATED_BY = 'spacecat';
23
25
 
24
26
  static PAGE_INTENTS = {
@@ -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 BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class Project extends BaseModel {
23
+ static ENTITY_NAME = 'Project';
24
+
23
25
  async getPrimaryLocaleSites() {
24
26
  const sites = await this.getSites();
25
27
  return sites.filter((site) => site.getIsPrimaryLocale());
@@ -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
 
@@ -13,6 +13,8 @@
13
13
  import BaseModel from '../base/base.model.js';
14
14
 
15
15
  class Report extends BaseModel {
16
+ static ENTITY_NAME = 'Report';
17
+
16
18
  static STATUSES = {
17
19
  PROCESSING: 'processing',
18
20
  SUCCESS: 'success',
@@ -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 BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class ScrapeJob extends BaseModel {
23
+ static ENTITY_NAME = 'ScrapeJob';
24
+
23
25
  static SCRAPE_JOB_EXPIRES_IN_DAYS = 120;
24
26
 
25
27
  /**
@@ -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);
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class ScrapeUrl extends BaseModel {
23
+ static ENTITY_NAME = 'ScrapeUrl';
24
+
23
25
  static SCRAPE_URL_EXPIRES_IN_DAYS = 120;
24
26
 
25
27
  // add your custom methods or overrides here
@@ -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
  }
@@ -70,6 +70,8 @@ export const getAuthoringType = (hostname, authoringTypes) => {
70
70
  * @extends BaseModel
71
71
  */
72
72
  class Site extends BaseModel {
73
+ static ENTITY_NAME = 'Site';
74
+
73
75
  static DELIVERY_TYPES = DELIVERY_TYPES;
74
76
 
75
77
  static DEFAULT_DELIVERY_TYPE = DELIVERY_TYPES.AEM_EDGE;
@@ -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 BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class SiteCandidate extends BaseModel {
23
+ static ENTITY_NAME = 'SiteCandidate';
24
+
23
25
  static DEFAULT_UPDATED_BY = 'spacecat';
24
26
 
25
27
  static SITE_CANDIDATE_SOURCES = {
@@ -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
 
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class SiteEnrollment extends BaseModel {
23
+ static ENTITY_NAME = 'SiteEnrollment';
24
+
23
25
  // add your custom methods or overrides 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
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class SiteTopForm extends BaseModel {
23
+ static ENTITY_NAME = 'SiteTopForm';
24
+
23
25
  // add your custom methods or overrides 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 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');
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class SiteTopPage extends BaseModel {
23
+ static ENTITY_NAME = 'SiteTopPage';
24
+
23
25
  static DEFAULT_GEO = 'global';
24
26
 
25
27
  // add your custom methods or overrides here
@@ -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.
@@ -21,6 +21,8 @@ import BaseModel from '../base/base.model.js';
21
21
  * @extends BaseModel
22
22
  */
23
23
  class Suggestion extends BaseModel {
24
+ static ENTITY_NAME = 'Suggestion';
25
+
24
26
  static STATUSES = {
25
27
  NEW: 'NEW',
26
28
  APPROVED: 'APPROVED',
@@ -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
 
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class TrialUser extends BaseModel {
23
+ static ENTITY_NAME = 'TrialUser';
24
+
23
25
  /**
24
26
  * Trial user status types.
25
27
  * Any change to this object needs to be reflected in the index.d.ts file as well.
@@ -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
 
@@ -20,6 +20,8 @@ import BaseModel from '../base/base.model.js';
20
20
  * @extends BaseModel
21
21
  */
22
22
  class TrialUserActivity extends BaseModel {
23
+ static ENTITY_NAME = 'TrialUserActivity';
24
+
23
25
  /**
24
26
  * Trial user activity types.
25
27
  * Any change to this object needs to be reflected in the index.d.ts file as well.
package/src/readme.md CHANGED
@@ -20,6 +20,8 @@ A *Model* is a class representing a single instance of an entity. It provides:
20
20
 
21
21
  Models extend `BaseModel`, which handles most of the common logic.
22
22
 
23
+ **Required:** All model classes must define a `static ENTITY_NAME` property to ensure bundler-agnostic operation.
24
+
23
25
  ### Collections
24
26
  A *Collection* operates on sets of entities. While `Model` focuses on individual records, `Collection` is for batch and query-level operations:
25
27
 
@@ -29,6 +31,8 @@ A *Collection* operates on sets of entities. While `Model` focuses on individual
29
31
 
30
32
  Collections extend `BaseCollection`, which generates query methods at runtime based on your schema definitions.
31
33
 
34
+ **Required:** All collection classes must define a `static COLLECTION_NAME` property to ensure bundler-agnostic operation.
35
+
32
36
  ### Schema Builder
33
37
  The `SchemaBuilder` is a fluent API to define an entity’s schema:
34
38
 
@@ -40,6 +44,26 @@ The `SchemaBuilder` enforces naming conventions and sets defaults, reducing repe
40
44
 
41
45
  **Note on Indexes:** Add indexes thoughtfully. Every extra index adds cost and complexity. Only create indexes for well-understood, frequently-needed query patterns.
42
46
 
47
+ ### Entity and Collection Naming
48
+
49
+ All model and collection classes **must** define explicit static name properties:
50
+
51
+ ```js
52
+ class User extends BaseModel {
53
+ static ENTITY_NAME = 'User';
54
+ // ...
55
+ }
56
+
57
+ class UserCollection extends BaseCollection {
58
+ static COLLECTION_NAME = 'UserCollection';
59
+ // ...
60
+ }
61
+ ```
62
+
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.
64
+
65
+ The `SchemaBuilder` validates that both `ENTITY_NAME` and `COLLECTION_NAME` are defined and will throw descriptive errors if either is missing.
66
+
43
67
  ### Entity Registry
44
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.
45
69
 
@@ -348,22 +372,26 @@ Create `user.model.js`:
348
372
  ```js
349
373
  import BaseModel from '../base/base.model.js';
350
374
 
351
- class UserModel extends BaseModel {
375
+ class User extends BaseModel {
376
+ static ENTITY_NAME = 'User';
377
+
352
378
  // Additional domain logic methods can be added here if needed.
353
379
  }
354
380
 
355
- export default UserModel;
381
+ export default User;
356
382
  ```
357
383
 
384
+ **Important:** Every model class **must** define a `static ENTITY_NAME` property. This ensures the entity name is explicit and not affected by bundler transformations (like class name mangling in webpack/esbuild). The `SchemaBuilder` will throw an error if this property is missing.
385
+
358
386
  ### 3. Implement the Collection
359
387
  Create `user.collection.js`:
360
388
 
361
389
  ```js
362
390
  import BaseCollection from '../base/base.collection.js';
363
- import UserModel from './user.model.js';
364
- import userSchema from './user.schema.js';
365
391
 
366
392
  class UserCollection extends BaseCollection {
393
+ static COLLECTION_NAME = 'UserCollection';
394
+
367
395
  // Additional domain logic collection methods can be added here if needed.
368
396
  async findByEmail(email) {
369
397
  return this.findByIndexKeys({ email });
@@ -373,6 +401,8 @@ class UserCollection extends BaseCollection {
373
401
  export default UserCollection;
374
402
  ```
375
403
 
404
+ **Important:** Every collection class **must** define a `static COLLECTION_NAME` property for the same bundler-related reasons as `ENTITY_NAME`.
405
+
376
406
  ### 4. Register the Entity
377
407
  In `entity.registry.js` (or equivalent):
378
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;