@adobe/spacecat-shared-data-access 1.59.2 → 1.60.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +2 -2
  3. package/src/models/site/config.js +1 -1
  4. package/src/service/audits/accessPatterns.js +7 -7
  5. package/src/service/experiments/accessPatterns.js +2 -2
  6. package/src/service/import-job/accessPatterns.js +1 -1
  7. package/src/service/import-url/accessPatterns.js +2 -2
  8. package/src/service/index.js +10 -18
  9. package/src/service/key-events/accessPatterns.js +3 -3
  10. package/src/service/organizations/accessPatterns.js +3 -3
  11. package/src/service/site-candidates/accessPatterns.js +1 -1
  12. package/src/service/sites/accessPatterns.js +11 -11
  13. package/src/v2/models/api-key/api-key.collection.js +26 -0
  14. package/src/v2/models/api-key/api-key.model.js +59 -0
  15. package/src/v2/models/api-key/api-key.schema.js +82 -0
  16. package/src/v2/models/api-key/index.d.ts +37 -0
  17. package/src/v2/models/api-key/index.js +19 -0
  18. package/src/v2/models/audit/audit.collection.js +26 -0
  19. package/src/v2/models/audit/audit.model.js +89 -0
  20. package/src/v2/models/audit/audit.schema.js +66 -0
  21. package/src/v2/models/audit/index.d.ts +40 -0
  22. package/src/v2/models/audit/index.js +19 -0
  23. package/src/v2/models/base/base.collection.js +450 -0
  24. package/src/v2/models/{base.model.js → base/base.model.js} +109 -89
  25. package/src/v2/models/base/constants.js +17 -0
  26. package/src/v2/models/base/entity.registry.js +137 -0
  27. package/src/v2/models/base/index.d.ts +83 -0
  28. package/src/v2/models/base/index.js +27 -0
  29. package/src/v2/models/base/reference.js +159 -0
  30. package/src/v2/models/base/schema.builder.js +420 -0
  31. package/src/v2/models/base/schema.js +283 -0
  32. package/src/v2/models/configuration/configuration.collection.js +39 -0
  33. package/src/v2/models/configuration/configuration.model.js +160 -0
  34. package/src/v2/models/configuration/configuration.schema.js +103 -0
  35. package/src/v2/models/configuration/index.d.ts +111 -0
  36. package/src/v2/models/configuration/index.js +19 -0
  37. package/src/v2/models/experiment/experiment.collection.js +26 -0
  38. package/src/v2/models/experiment/experiment.model.js +28 -0
  39. package/src/v2/models/experiment/experiment.schema.js +70 -0
  40. package/src/v2/models/experiment/index.d.ts +49 -0
  41. package/src/v2/models/experiment/index.js +19 -0
  42. package/src/v2/models/import-job/import-job.collection.js +45 -0
  43. package/src/v2/models/import-job/import-job.model.js +55 -0
  44. package/src/v2/models/import-job/import-job.schema.js +152 -0
  45. package/src/v2/models/import-job/index.d.ts +51 -0
  46. package/src/v2/models/import-job/index.js +19 -0
  47. package/src/v2/models/import-url/import-url.collection.js +26 -0
  48. package/src/v2/models/import-url/import-url.model.js +28 -0
  49. package/src/v2/models/import-url/import-url.schema.js +59 -0
  50. package/src/v2/models/import-url/index.d.ts +35 -0
  51. package/src/v2/models/import-url/index.js +19 -0
  52. package/src/v2/models/index.d.ts +11 -99
  53. package/src/v2/models/index.js +14 -15
  54. package/src/v2/models/key-event/index.d.ts +28 -0
  55. package/src/v2/models/key-event/index.js +19 -0
  56. package/src/v2/models/key-event/key-event.collection.js +26 -0
  57. package/src/v2/models/key-event/key-event.model.js +37 -0
  58. package/src/v2/models/key-event/key-event.schema.js +45 -0
  59. package/src/v2/models/opportunity/index.d.ts +46 -0
  60. package/src/v2/models/opportunity/index.js +19 -0
  61. package/src/v2/models/opportunity/opportunity.collection.js +26 -0
  62. package/src/v2/models/{opportunity.model.js → opportunity/opportunity.model.js} +15 -2
  63. package/src/v2/models/opportunity/opportunity.schema.js +69 -0
  64. package/src/v2/models/organization/index.d.ts +28 -0
  65. package/src/v2/models/organization/index.js +19 -0
  66. package/src/v2/models/organization/organization.collection.js +26 -0
  67. package/src/v2/models/organization/organization.model.js +31 -0
  68. package/src/v2/models/organization/organization.schema.js +51 -0
  69. package/src/v2/models/site/index.d.ts +43 -0
  70. package/src/v2/models/site/index.js +20 -0
  71. package/src/v2/models/site/site.collection.js +28 -0
  72. package/src/v2/models/site/site.model.js +47 -0
  73. package/src/v2/models/site/site.schema.js +91 -0
  74. package/src/v2/models/site-candidate/index.d.ts +38 -0
  75. package/src/v2/models/site-candidate/index.js +19 -0
  76. package/src/v2/models/site-candidate/site-candidate.collection.js +27 -0
  77. package/src/v2/models/site-candidate/site-candidate.model.js +41 -0
  78. package/src/v2/models/site-candidate/site-candidate.schema.js +59 -0
  79. package/src/v2/models/site-top-page/index.d.ts +35 -0
  80. package/src/v2/models/site-top-page/index.js +19 -0
  81. package/src/v2/models/site-top-page/site-top-page.collection.js +44 -0
  82. package/src/v2/models/site-top-page/site-top-page.model.js +28 -0
  83. package/src/v2/models/site-top-page/site-top-page.schema.js +65 -0
  84. package/src/v2/models/suggestion/index.d.ts +34 -0
  85. package/src/v2/models/suggestion/index.js +19 -0
  86. package/src/v2/models/suggestion/suggestion.collection.js +55 -0
  87. package/src/v2/models/{suggestion.model.js → suggestion/suggestion.model.js} +16 -1
  88. package/src/v2/models/suggestion/suggestion.schema.js +53 -0
  89. package/src/v2/readme.md +201 -256
  90. package/src/v2/util/accessor.utils.js +158 -0
  91. package/src/v2/util/guards.d.ts +7 -0
  92. package/src/v2/util/guards.js +21 -4
  93. package/src/v2/util/index.js +1 -0
  94. package/src/v2/util/patcher.js +54 -25
  95. package/src/v2/util/util.js +84 -0
  96. package/src/v2/models/base.collection.js +0 -275
  97. package/src/v2/models/model.factory.js +0 -74
  98. package/src/v2/models/opportunity.collection.js +0 -74
  99. package/src/v2/models/suggestion.collection.js +0 -104
  100. package/src/v2/schema/opportunity.schema.js +0 -159
  101. package/src/v2/schema/suggestion.schema.js +0 -132
  102. package/src/v2/util/reference.js +0 -41
@@ -12,13 +12,16 @@
12
12
 
13
13
  import { isNonEmptyObject } from '@adobe/spacecat-shared-utils';
14
14
 
15
- import Patcher from '../util/patcher.js';
15
+ import { createAccessors } from '../../util/accessor.utils.js';
16
+ import Patcher from '../../util/patcher.js';
16
17
  import {
17
18
  capitalize,
18
- entityNameToCollectionName,
19
19
  entityNameToIdName,
20
- entityNameToReferenceMethodName, idNameToEntityName,
21
- } from '../util/reference.js';
20
+ idNameToEntityName,
21
+ isNonEmptyArray,
22
+ } from '../../util/util.js';
23
+
24
+ import Reference from './reference.js';
22
25
 
23
26
  /**
24
27
  * Base - A base class for representing individual entities in the application.
@@ -40,20 +43,28 @@ class BaseModel {
40
43
  * Constructs an instance of BaseModel.
41
44
  * @constructor
42
45
  * @param {Object} electroService - The ElectroDB service used for managing entities.
43
- * @param {Object} modelFactory - A factory for creating model instances.
46
+ * @param {EntityRegistry} entityRegistry - The registry holding entities, their schema
47
+ * and collection.
48
+ * @param {Schema} schema - The schema for the entity.
44
49
  * @param {Object} record - The initial data for the entity instance.
45
- * @param {Object} log - A logger for capturing logging information.
50
+ * @param {Object} log - A log for capturing logging information.
46
51
  */
47
- constructor(electroService, modelFactory, record, log) {
48
- this.modelFactory = modelFactory;
52
+ constructor(electroService, entityRegistry, schema, record, log) {
53
+ this.electroService = electroService;
54
+ this.entityRegistry = entityRegistry;
55
+ this.schema = schema;
49
56
  this.record = record;
50
- this.entityName = this.constructor.name.toLowerCase();
51
- this.entity = electroService.entities[this.entityName];
52
- this.idName = `${this.entityName}Id`;
53
57
  this.log = log;
54
- this.referencesCache = {};
55
58
 
56
- this.patcher = new Patcher(this.entity, this.record);
59
+ this.entityName = schema.getEntityName();
60
+ this.idName = entityNameToIdName(this.entityName);
61
+
62
+ this.collection = entityRegistry.getCollection(schema.getCollectionName());
63
+ this.entity = electroService.entities[this.entityName];
64
+
65
+ this.patcher = new Patcher(this.entity, this.schema, this.record);
66
+
67
+ this._accessorCache = {};
57
68
 
58
69
  this.#initializeReferences();
59
70
  this.#initializeAttributes();
@@ -66,23 +77,16 @@ class BaseModel {
66
77
  * @private
67
78
  */
68
79
  #initializeReferences() {
69
- const { references } = this.entity.model.original;
70
- if (!isNonEmptyObject(references)) {
71
- return;
72
- }
73
-
74
- for (const [type, refs] of Object.entries(references)) {
75
- refs.forEach((ref) => {
76
- const { target } = ref;
77
- const methodName = entityNameToReferenceMethodName(target, type);
80
+ const references = this.schema.getReferences();
78
81
 
79
- this[methodName] = async () => this._fetchReference(type, target);
80
- });
81
- }
82
+ references.forEach((reference) => {
83
+ const accessorConfigs = reference.toAccessorConfigs(this.entityRegistry, this);
84
+ createAccessors(accessorConfigs, this.log);
85
+ });
82
86
  }
83
87
 
84
88
  #initializeAttributes() {
85
- const { attributes } = this.entity.model.schema;
89
+ const attributes = this.schema.getAttributes();
86
90
 
87
91
  if (!isNonEmptyObject(attributes)) {
88
92
  return;
@@ -92,8 +96,9 @@ class BaseModel {
92
96
  const capitalized = capitalize(name);
93
97
  const getterMethodName = `get${capitalized}`;
94
98
  const setterMethodName = `set${capitalized}`;
95
- const isReference = this.entity.model.original
96
- .references?.belongs_to?.some((ref) => ref.target === idNameToEntityName(name));
99
+ const isReference = this.schema
100
+ .getReferencesByType(Reference.TYPES.BELONGS_TO)
101
+ .some((ref) => ref.getTarget() === idNameToEntityName(name));
97
102
 
98
103
  if (!this[getterMethodName] || name === this.idName) {
99
104
  this[getterMethodName] = () => this.record[name];
@@ -108,64 +113,43 @@ class BaseModel {
108
113
  }
109
114
  }
110
115
 
111
- /**
112
- * Gets a cached reference for the specified entity.
113
- * @param {string} targetName - The name of the entity to fetch.
114
- * @return {*}
115
- */
116
- #getCachedReference(targetName) {
117
- return this.referencesCache[targetName];
118
- }
119
-
120
- /**
121
- * Caches a reference for the specified entity. This method is used to store
122
- * fetched references to avoid redundant database queries.
123
- * @param {string} targetName - The name of the entity to cache.
124
- * @param {*} reference - The reference to cache.
125
- * @private
126
- */
127
- _cacheReference(targetName, reference) {
128
- this.referencesCache[targetName] = reference;
116
+ #invalidateCache() {
117
+ this._accessorCache = {};
129
118
  }
130
119
 
131
- /**
132
- * Fetches a reference for the specified entity. This method is used to fetch
133
- * associated entities based on the type of relationship (belongs_to, has_one, has_many).
134
- * The fetched references are cached to avoid redundant database queries. If the reference
135
- * is already cached, it will be returned directly.
136
- * References are defined in the entity model and are used to fetch associated entities.
137
- * @async
138
- * @param {string} type - The type of relationship (belongs_to, has_one, has_many).
139
- * @param {string} targetName - The name of the entity to fetch.
140
- * @return {Promise<*|null>} - A promise that resolves to the fetched reference or null if
141
- * not found.
142
- * @private
143
- */
144
- async _fetchReference(type, targetName) { /* eslint-disable no-underscore-dangle */
145
- let result = this.#getCachedReference(targetName);
146
- if (result) {
147
- return result;
148
- }
149
-
150
- const collectionName = entityNameToCollectionName(targetName);
151
- const targetCollection = this.modelFactory.getCollection(collectionName);
152
-
153
- if (type === 'belongs_to' || type === 'has_one') {
154
- const foreignKey = entityNameToIdName(targetName);
155
- const id = this.record[foreignKey];
156
- if (!id) return null;
157
-
158
- result = await targetCollection.findById(id);
159
- } else if (type === 'has_many') {
160
- const foreignKey = entityNameToIdName(this.entityName);
161
- result = await targetCollection.findByIndexKeys({ [foreignKey]: this.getId() });
162
- }
120
+ async #fetchDependents() {
121
+ const promises = [];
122
+
123
+ const relationshipTypes = [
124
+ Reference.TYPES.HAS_MANY,
125
+ Reference.TYPES.HAS_ONE,
126
+ ];
127
+
128
+ relationshipTypes.forEach((type) => {
129
+ const references = this.schema.getReferencesByType(type);
130
+ const targets = references.filter((reference) => reference.isRemoveDependents());
131
+
132
+ targets.forEach((reference) => {
133
+ const accessors = reference.toAccessorConfigs(this.entityRegistry, this);
134
+ const methodName = accessors[0].name;
135
+ promises.push(
136
+ this[methodName]()
137
+ .then((dependent) => {
138
+ if (isNonEmptyArray(dependent)) {
139
+ return dependent;
140
+ } else if (isNonEmptyObject(dependent)) {
141
+ return [dependent];
142
+ }
143
+
144
+ return null;
145
+ }),
146
+ );
147
+ });
148
+ });
163
149
 
164
- if (result) {
165
- await this._cacheReference(targetName, result);
166
- }
150
+ const results = await Promise.all(promises);
167
151
 
168
- return result;
152
+ return results.flat().filter((dependent) => dependent !== null);
169
153
  }
170
154
 
171
155
  /**
@@ -181,7 +165,7 @@ class BaseModel {
181
165
  * @returns {string} - The ISO string representing when the entity was created.
182
166
  */
183
167
  getCreatedAt() {
184
- return new Date(this.record.createdAt).toISOString();
168
+ return this.record.createdAt;
185
169
  }
186
170
 
187
171
  /**
@@ -189,20 +173,37 @@ class BaseModel {
189
173
  * @returns {string} - The ISO string representing when the entity was last updated.
190
174
  */
191
175
  getUpdatedAt() {
192
- return new Date(this.record.updatedAt).toISOString();
176
+ return this.record.updatedAt;
193
177
  }
194
178
 
195
179
  /**
196
- * Removes the current entity from the database.
180
+ * Removes the current entity from the database. This method also removes any dependent
181
+ * entities associated with the current entity. For example, if the current entity has
182
+ * a has_many relationship with another entity, the dependent entity will be removed.
183
+ * When adding a reference to an entity, the dependent entity will be removed if the
184
+ * removeDependentss flag is set to true in the reference definition.
185
+ *
186
+ * Dependents are removed by calling the remove method on each dependent entity, which in turn
187
+ * will also remove any dependent entities associated with the dependent entity. This may result
188
+ * in a cascade effect where multiple entities are removed. Consider the destructive
189
+ * and performance implications before using this method.
197
190
  * @async
198
191
  * @returns {Promise<BaseModel>} - A promise that resolves to the current instance of the entity
199
- * after it has been removed.
192
+ * after it and its dependents have been removed.
200
193
  * @throws {Error} - Throws an error if the removal fails.
201
194
  */
202
195
  async remove() {
203
196
  try {
204
- // todo: remove dependents (child associations)
205
- await this.entity.remove({ [this.idName]: this.getId() }).go();
197
+ const dependents = await this.#fetchDependents();
198
+ const removePromises = dependents.map((dependent) => dependent.remove());
199
+ removePromises.push(this.entity.remove({ [this.idName]: this.getId() }).go());
200
+
201
+ this.log.info(`Removing entity ${this.entityName} with ID ${this.getId()} and ${dependents.length} dependents`);
202
+
203
+ await Promise.all(removePromises);
204
+
205
+ this.#invalidateCache();
206
+
206
207
  return this;
207
208
  } catch (error) {
208
209
  this.log.error('Failed to remove record', error);
@@ -221,14 +222,33 @@ class BaseModel {
221
222
  async save() {
222
223
  // todo: validate associations
223
224
  try {
225
+ this.log.info(`Saving entity ${this.entityName} with ID ${this.getId()}`);
226
+
224
227
  await this.patcher.save();
225
- // todo: in case references are updated, clear or refresh references cache
228
+ this.#invalidateCache();
229
+
226
230
  return this;
227
231
  } catch (error) {
228
232
  this.log.error('Failed to save record', error);
229
233
  throw error;
230
234
  }
231
235
  }
236
+
237
+ /**
238
+ * Converts the entity attributes to a JSON object.
239
+ * @returns {Object} - A JSON representation of the entity attributes.
240
+ */
241
+ toJSON() {
242
+ const attributes = this.schema.getAttributes();
243
+
244
+ return Object.keys(attributes).reduce((json, key) => {
245
+ if (this.record[key] !== undefined) {
246
+ // eslint-disable-next-line no-param-reassign
247
+ json[key] = this.record[key];
248
+ }
249
+ return json;
250
+ }, {});
251
+ }
232
252
  }
233
253
 
234
254
  export default BaseModel;
@@ -0,0 +1,17 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+ export const INDEX_TYPES = {
13
+ PRIMARY: 'primary',
14
+ ALL: 'all',
15
+ BELONGS_TO: 'belongs_to',
16
+ OTHER: 'other',
17
+ };
@@ -0,0 +1,137 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import { collectionNameToEntityName, decapitalize } from '../../util/util.js';
14
+
15
+ import ApiKeyCollection from '../api-key/api-key.collection.js';
16
+ import AuditCollection from '../audit/audit.collection.js';
17
+ import ConfigurationCollection from '../configuration/configuration.collection.js';
18
+ import ExperimentCollection from '../experiment/experiment.collection.js';
19
+ import ImportJobCollection from '../import-job/import-job.collection.js';
20
+ import ImportUrlCollection from '../import-url/import-url.collection.js';
21
+ import KeyEventCollection from '../key-event/key-event.collection.js';
22
+ import OpportunityCollection from '../opportunity/opportunity.collection.js';
23
+ import OrganizationCollection from '../organization/organization.collection.js';
24
+ import SiteCandidateCollection from '../site-candidate/site-candidate.collection.js';
25
+ import SiteCollection from '../site/site.collection.js';
26
+ import SiteTopPageCollection from '../site-top-page/site-top-page.collection.js';
27
+ import SuggestionCollection from '../suggestion/suggestion.collection.js';
28
+
29
+ import ApiKeySchema from '../api-key/api-key.schema.js';
30
+ import AuditSchema from '../audit/audit.schema.js';
31
+ import ConfigurationSchema from '../configuration/configuration.schema.js';
32
+ import ExperimentSchema from '../experiment/experiment.schema.js';
33
+ import ImportJobSchema from '../import-job/import-job.schema.js';
34
+ import ImportUrlSchema from '../import-url/import-url.schema.js';
35
+ import KeyEventSchema from '../key-event/key-event.schema.js';
36
+ import OpportunitySchema from '../opportunity/opportunity.schema.js';
37
+ import OrganizationSchema from '../organization/organization.schema.js';
38
+ import SiteSchema from '../site/site.schema.js';
39
+ import SiteCandidateSchema from '../site-candidate/site-candidate.schema.js';
40
+ import SiteTopPageSchema from '../site-top-page/site-top-page.schema.js';
41
+ import SuggestionSchema from '../suggestion/suggestion.schema.js';
42
+
43
+ /**
44
+ * EntityRegistry - A registry class responsible for managing entities, their schema and collection.
45
+ *
46
+ * @class EntityRegistry
47
+ */
48
+ class EntityRegistry {
49
+ static entities = {};
50
+
51
+ /**
52
+ * Constructs an instance of EntityRegistry.
53
+ * @constructor
54
+ * @param {Object} service - The ElectroDB service instance used to manage entities.
55
+ * @param {Object} log - A logger for capturing and logging information.
56
+ */
57
+ constructor(service, log) {
58
+ this.service = service;
59
+ this.log = log;
60
+ this.collections = new Map();
61
+
62
+ this.#initialize();
63
+ }
64
+
65
+ /**
66
+ * Initializes the collections managed by the EntityRegistry.
67
+ * This method creates instances of each collection and stores them in an internal map.
68
+ * @private
69
+ */
70
+ #initialize() {
71
+ Object.values(EntityRegistry.entities).forEach(({ collection: Collection, schema }) => {
72
+ const collection = new Collection(this.service, this, schema, this.log);
73
+ this.collections.set(Collection.name, collection);
74
+ });
75
+
76
+ this.#logIndexes();
77
+ }
78
+
79
+ #logIndexes() {
80
+ // reduce collection schema indexes into object
81
+ const indexes = Object.values(EntityRegistry.entities).reduce((acc, { schema }) => {
82
+ acc[schema.getEntityName()] = schema.indexes;
83
+ return acc;
84
+ }, {});
85
+
86
+ this.log.debug('Indexes:', JSON.stringify(indexes, null, 2));
87
+ }
88
+
89
+ /**
90
+ * Gets a collection instance by its name.
91
+ * @param {string} collectionName - The name of the collection to retrieve.
92
+ * @returns {Object} - The requested collection instance.
93
+ * @throws {Error} - Throws an error if the collection with the specified name is not found.
94
+ */
95
+ getCollection(collectionName) {
96
+ const collection = this.collections.get(collectionName);
97
+ if (!collection) {
98
+ throw new Error(`Collection ${collectionName} not found`);
99
+ }
100
+ return collection;
101
+ }
102
+
103
+ getCollections() {
104
+ const collections = {};
105
+ for (const [key, value] of this.collections) {
106
+ collections[collectionNameToEntityName(key)] = value;
107
+ }
108
+ return collections;
109
+ }
110
+
111
+ static getEntities() {
112
+ return Object.keys(this.entities).reduce((acc, key) => {
113
+ acc[key] = this.entities[key].schema.toElectroDBSchema();
114
+ return acc;
115
+ }, {});
116
+ }
117
+
118
+ static registerEntity(schema, collection) {
119
+ this.entities[decapitalize(schema.getEntityName())] = { schema, collection };
120
+ }
121
+ }
122
+
123
+ EntityRegistry.registerEntity(ApiKeySchema, ApiKeyCollection);
124
+ EntityRegistry.registerEntity(AuditSchema, AuditCollection);
125
+ EntityRegistry.registerEntity(ConfigurationSchema, ConfigurationCollection);
126
+ EntityRegistry.registerEntity(ExperimentSchema, ExperimentCollection);
127
+ EntityRegistry.registerEntity(ImportJobSchema, ImportJobCollection);
128
+ EntityRegistry.registerEntity(ImportUrlSchema, ImportUrlCollection);
129
+ EntityRegistry.registerEntity(KeyEventSchema, KeyEventCollection);
130
+ EntityRegistry.registerEntity(OpportunitySchema, OpportunityCollection);
131
+ EntityRegistry.registerEntity(OrganizationSchema, OrganizationCollection);
132
+ EntityRegistry.registerEntity(SiteSchema, SiteCollection);
133
+ EntityRegistry.registerEntity(SiteCandidateSchema, SiteCandidateCollection);
134
+ EntityRegistry.registerEntity(SiteTopPageSchema, SiteTopPageCollection);
135
+ EntityRegistry.registerEntity(SuggestionSchema, SuggestionCollection);
136
+
137
+ export default EntityRegistry;
@@ -0,0 +1,83 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import type { ValidationError } from '../../errors';
14
+
15
+ export interface BaseModel {
16
+ getCreatedAt(): string;
17
+ getId(): string;
18
+ getUpdatedAt(): string;
19
+ remove(): Promise<this>;
20
+ save(): Promise<this>;
21
+ toJSON(): object;
22
+ }
23
+
24
+ export interface MultiStatusCreateResult<T> {
25
+ createdItems: T[],
26
+ errorItems: { item: object, error: ValidationError }[],
27
+ }
28
+
29
+ export interface QueryOptions {
30
+ index?: string;
31
+ limit?: number;
32
+ sort?: string;
33
+ attributes?: string[];
34
+ }
35
+
36
+ export interface BaseCollection<T extends BaseModel> {
37
+ all(sortKeys?: object, options?: QueryOptions): Promise<T[]>;
38
+ allByIndexKeys(keys: object, options?: QueryOptions): Promise<T[]>;
39
+ create(item: object): Promise<T>;
40
+ createMany(items: object[]): Promise<MultiStatusCreateResult<T>>;
41
+ findByAll(sortKeys?: object, options?: QueryOptions): Promise<T>;
42
+ findById(id: string): Promise<T>;
43
+ findByIndexKeys(indexKeys: object): Promise<T>;
44
+ removeByIds(ids: string[]): Promise<void>;
45
+ }
46
+
47
+ export interface EntityRegistry {
48
+ getCollection<T extends BaseModel>(collectionName: string): BaseCollection<T>;
49
+ getCollections(): BaseCollection<BaseModel>[];
50
+ getEntities(): object;
51
+ registerEntity(schema: object, collection: BaseCollection<BaseModel>): void;
52
+ }
53
+
54
+ export interface Reference {
55
+ getSortKeys(): string[];
56
+ getTarget(): string;
57
+ getType(): string;
58
+ isRemoveDependents(): boolean;
59
+ }
60
+
61
+ export interface Schema {
62
+ getAttribute(name: string): object;
63
+ getAttributes(): object;
64
+ getCollectionName(): string;
65
+ getEntityName(): string;
66
+ getIdName(): string;
67
+ getIndexes(): object;
68
+ getIndexKeys(indexName: string): string[];
69
+ getModelClass(): object;
70
+ getModelName(): string;
71
+ getReferences(): Reference[];
72
+ getReferencesByType(referenceType: string): Reference[];
73
+ getReferenceByTypeAndTarget(referenceType: string, target: string): Reference | undefined;
74
+ }
75
+
76
+ export interface SchemaBuilder {
77
+ addAttribute(name: string, data: object): SchemaBuilder;
78
+ addAllIndexWithComposite(...attributeNames: string[]): SchemaBuilder
79
+ addAllIndexWithTemplateField(fieldName: string, template: string): SchemaBuilder;
80
+ addIndex(name: string, partitionKey: object, sortKey: object): SchemaBuilder;
81
+ addReference(referenceType: string, entityName: string, sortKeys?: string[]): SchemaBuilder;
82
+ build(): Schema;
83
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright 2024 Adobe. All rights reserved.
3
+ * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License. You may obtain a copy
5
+ * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ *
7
+ * Unless required by applicable law or agreed to in writing, software distributed under
8
+ * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ * OF ANY KIND, either express or implied. See the License for the specific language
10
+ * governing permissions and limitations under the License.
11
+ */
12
+
13
+ import BaseModel from './base.model.js';
14
+ import BaseCollection from './base.collection.js';
15
+ import EntityRegistry from './entity.registry.js';
16
+ import Reference from './reference.js';
17
+ import Schema from './schema.js';
18
+ import SchemaBuilder from './schema.builder.js';
19
+
20
+ export {
21
+ BaseModel,
22
+ BaseCollection,
23
+ EntityRegistry,
24
+ Reference,
25
+ Schema,
26
+ SchemaBuilder,
27
+ };