@adobe/spacecat-shared-data-access 1.4.3 → 1.5.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,17 @@
1
+ # [@adobe/spacecat-shared-data-access-v1.5.0](https://github.com/adobe-rnd/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v1.4.4...@adobe/spacecat-shared-data-access-v1.5.0) (2023-12-26)
2
+
3
+
4
+ ### Features
5
+
6
+ * store previous latest audit result ([#74](https://github.com/adobe-rnd/spacecat-shared/issues/74)) ([4663c43](https://github.com/adobe-rnd/spacecat-shared/commit/4663c4344e260f85c4e64691e0685260d36629e5))
7
+
8
+ # [@adobe/spacecat-shared-data-access-v1.4.4](https://github.com/adobe-rnd/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v1.4.3...@adobe/spacecat-shared-data-access-v1.4.4) (2023-12-25)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * add missing pattern to interface ([#72](https://github.com/adobe-rnd/spacecat-shared/issues/72)) ([0eacbff](https://github.com/adobe-rnd/spacecat-shared/commit/0eacbff39dbc12d604e40ae94285533f7804ca0a))
14
+
1
15
  # [@adobe/spacecat-shared-data-access-v1.4.3](https://github.com/adobe-rnd/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v1.4.2...@adobe/spacecat-shared-data-access-v1.4.3) (2023-12-23)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-data-access",
3
- "version": "1.4.3",
3
+ "version": "1.5.0",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/dto/audit.js CHANGED
@@ -10,6 +10,8 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
+ import { isObject } from '@adobe/spacecat-shared-utils';
14
+
13
15
  import { createAudit } from '../models/audit.js';
14
16
 
15
17
  function parseEpochToDate(epochInSeconds) {
@@ -28,10 +30,10 @@ export const AuditDto = {
28
30
  /**
29
31
  * Converts an Audit object into a DynamoDB item.
30
32
  * @param {Readonly<Audit>} audit - Audit object.
31
- * @param {boolean} latestAudit - If true, returns the latest audit flavor.
33
+ * @param {boolean} isLatestAudit - If true, returns the latest audit flavor.
32
34
  * @returns {{siteId, auditedAt, auditResult, auditType, expiresAt, fullAuditRef, SK: string}}
33
35
  */
34
- toDynamoItem: (audit, latestAudit = false) => {
36
+ toDynamoItem: (audit, isLatestAudit = false) => {
35
37
  const GSI1PK = 'ALL_LATEST_AUDITS';
36
38
  let GSI1SK;
37
39
 
@@ -41,7 +43,12 @@ export const AuditDto = {
41
43
  GSI1SK = `${audit.getAuditType()}#${Object.values(audit.getScores()).join('#')}`;
42
44
  }
43
45
 
44
- const latestAuditProps = latestAudit ? { GSI1PK, GSI1SK } : {};
46
+ const latestAuditProps = isLatestAudit ? {
47
+ GSI1PK,
48
+ GSI1SK,
49
+ ...(isObject(audit.getPreviousAuditResult())
50
+ && { previousAuditResult: audit.getPreviousAuditResult() }),
51
+ } : {};
45
52
 
46
53
  return {
47
54
  siteId: audit.getSiteId(),
@@ -70,6 +77,8 @@ export const AuditDto = {
70
77
  expiresAt: parseEpochToDate(dynamoItem.expiresAt),
71
78
  fullAuditRef: dynamoItem.fullAuditRef,
72
79
  isLive: dynamoItem.isLive,
80
+ ...(isObject(dynamoItem.previousAuditResult)
81
+ && { previousAuditResult: dynamoItem.previousAuditResult }),
73
82
  };
74
83
 
75
84
  return createAudit(auditData);
package/src/index.d.ts CHANGED
@@ -34,6 +34,19 @@ export interface Audit {
34
34
  */
35
35
  getAuditResult: () => object;
36
36
 
37
+ /**
38
+ * Retrieves the result of the previous audit.
39
+ * This serves for comparison purposes.
40
+ * @returns {object|null} The parsed audit result.
41
+ */
42
+ getPreviousAuditResult: () => object | null;
43
+
44
+ /**
45
+ * Sets the result of the previous audit.
46
+ * @param {object} result The parsed audit result.
47
+ */
48
+ setPreviousAuditResult: (result: object) => void;
49
+
37
50
  /**
38
51
  * Retrieves the type of the audit.
39
52
  * @returns {object} The audit type.
@@ -195,6 +208,11 @@ export interface Site {
195
208
  }
196
209
 
197
210
  export interface DataAccess {
211
+ getAuditForSite: (
212
+ sitedId: string,
213
+ auditType: string,
214
+ auditedAt: string,
215
+ ) => Promise<Audit | null>;
198
216
  getAuditsForSite: (
199
217
  siteId: string,
200
218
  auditType?: string,
@@ -36,6 +36,10 @@ const validateScores = (auditResult, auditType) => {
36
36
  return true;
37
37
  }
38
38
 
39
+ if (!isObject(auditResult.scores)) {
40
+ throw new Error(`Missing scores property for audit type '${auditType}'`);
41
+ }
42
+
39
43
  const expectedProperties = AUDIT_TYPE_PROPERTIES[auditType];
40
44
  if (!expectedProperties) {
41
45
  throw new Error(`Unknown audit type: ${auditType}`);
@@ -66,6 +70,11 @@ const Audit = (data = {}) => {
66
70
  self.getFullAuditRef = () => self.state.fullAuditRef;
67
71
  self.isLive = () => self.state.isLive;
68
72
  self.isError = () => hasText(self.getAuditResult().runtimeError?.code);
73
+ self.getPreviousAuditResult = () => self.state.previousAuditResult;
74
+ self.setPreviousAuditResult = (previousAuditResult) => {
75
+ validateScores(previousAuditResult, self.getAuditType());
76
+ self.state.previousAuditResult = previousAuditResult;
77
+ };
69
78
  self.getScores = () => self.getAuditResult().scores;
70
79
 
71
80
  return Object.freeze(self);
@@ -98,6 +107,14 @@ export const createAudit = (data) => {
98
107
 
99
108
  validateScores(data.auditResult, data.auditType);
100
109
 
110
+ if (data.previousAuditResult && !isObject(data.previousAuditResult)) {
111
+ throw new Error('Previous audit result must be an object');
112
+ }
113
+
114
+ if (data.previousAuditResult) {
115
+ validateScores(data.previousAuditResult, data.auditType);
116
+ }
117
+
101
118
  if (!hasText(newState.fullAuditRef)) {
102
119
  throw new Error('Full audit ref must be provided');
103
120
  }
@@ -184,25 +184,40 @@ export const addAudit = async (
184
184
  log,
185
185
  auditData,
186
186
  ) => {
187
- const audit = createAudit(auditData);
187
+ const newAudit = createAudit(auditData);
188
188
  const existingAudit = await getAuditForSite(
189
189
  dynamoClient,
190
190
  config,
191
191
  log,
192
- audit.getSiteId(),
193
- audit.getAuditType(),
194
- audit.getAuditedAt(),
192
+ newAudit.getSiteId(),
193
+ newAudit.getAuditType(),
194
+ newAudit.getAuditedAt(),
195
195
  );
196
196
 
197
197
  if (isObject(existingAudit)) {
198
198
  throw new Error('Audit already exists');
199
199
  }
200
200
 
201
+ const latestAudit = await getLatestAuditForSite(
202
+ dynamoClient,
203
+ config,
204
+ log,
205
+ newAudit.getSiteId(),
206
+ newAudit.getAuditType(),
207
+ );
208
+
209
+ if (isObject(latestAudit)) {
210
+ newAudit.setPreviousAuditResult(latestAudit.getAuditResult());
211
+ }
212
+
201
213
  // TODO: Add transaction support
202
- await dynamoClient.putItem(config.tableNameAudits, AuditDto.toDynamoItem(audit));
203
- await dynamoClient.putItem(config.tableNameLatestAudits, AuditDto.toDynamoItem(audit, true));
214
+ await dynamoClient.putItem(config.tableNameAudits, AuditDto.toDynamoItem(newAudit));
215
+ await dynamoClient.putItem(
216
+ config.tableNameLatestAudits,
217
+ AuditDto.toDynamoItem(newAudit, true),
218
+ );
204
219
 
205
- return audit;
220
+ return newAudit;
206
221
  };
207
222
 
208
223
  /**