@adobe/spacecat-shared-data-access 1.0.2 → 1.1.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,10 @@
1
+ # [@adobe/spacecat-shared-data-access-v1.1.0](https://github.com/adobe-rnd/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v1.0.2...@adobe/spacecat-shared-data-access-v1.1.0) (2023-12-02)
2
+
3
+
4
+ ### Features
5
+
6
+ * allow configuration from ctx / add missing fields ([#24](https://github.com/adobe-rnd/spacecat-shared/issues/24)) ([6959f89](https://github.com/adobe-rnd/spacecat-shared/commit/6959f895ed9b167f421b201f856ef871bd2a335c))
7
+
1
8
  # [@adobe/spacecat-shared-data-access-v1.0.2](https://github.com/adobe-rnd/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v1.0.1...@adobe/spacecat-shared-data-access-v1.0.2) (2023-12-02)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/spacecat-shared-data-access",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Shared modules of the Spacecat Services - Data Access",
5
5
  "type": "module",
6
6
  "main": "src/service/index.js",
@@ -29,7 +29,7 @@
29
29
  "access": "public"
30
30
  },
31
31
  "dependencies": {
32
- "@adobe/spacecat-shared-dynamo": "1.1.4",
32
+ "@adobe/spacecat-shared-dynamo": "1.2.3",
33
33
  "@adobe/spacecat-shared-utils": "1.2.0",
34
34
  "@aws-sdk/client-dynamodb": "3.465.0",
35
35
  "@aws-sdk/lib-dynamodb": "3.465.0",
package/src/dto/audit.js CHANGED
@@ -44,6 +44,7 @@ export const AuditDto = {
44
44
  auditType: audit.getAuditType(),
45
45
  expiresAt: convertDateToEpochSeconds(audit.getExpiresAt()),
46
46
  fullAuditRef: audit.getFullAuditRef(),
47
+ isLive: audit.isLive(),
47
48
  SK: `${audit.getAuditType()}#${audit.getAuditedAt()}`,
48
49
  ...latestAuditProps,
49
50
  };
@@ -62,6 +63,7 @@ export const AuditDto = {
62
63
  auditType: dynamoItem.auditType,
63
64
  expiresAt: parseEpochToDate(dynamoItem.expiresAt),
64
65
  fullAuditRef: dynamoItem.fullAuditRef,
66
+ isLive: dynamoItem.isLive,
65
67
  };
66
68
 
67
69
  return createAudit(auditData);
package/src/dto/site.js CHANGED
@@ -24,7 +24,9 @@ export const SiteDto = {
24
24
  toDynamoItem: (site) => ({
25
25
  id: site.getId(),
26
26
  baseURL: site.getBaseURL(),
27
+ gitHubURL: site.getGitHubURL(),
27
28
  imsOrgId: site.getImsOrgId(),
29
+ isLive: site.isLive(),
28
30
  createdAt: site.getCreatedAt(),
29
31
  updatedAt: site.getUpdatedAt(),
30
32
  GSI1PK: 'ALL_SITES',
@@ -39,7 +41,9 @@ export const SiteDto = {
39
41
  const siteData = {
40
42
  id: dynamoItem.id,
41
43
  baseURL: dynamoItem.baseURL,
44
+ gitHubURL: dynamoItem.gitHubURL,
42
45
  imsOrgId: dynamoItem.imsOrgId,
46
+ isLive: dynamoItem.isLive,
43
47
  createdAt: dynamoItem.createdAt,
44
48
  updatedAt: dynamoItem.updatedAt,
45
49
  };
package/src/index.d.ts CHANGED
@@ -19,18 +19,22 @@ export interface Audit {
19
19
  getAuditType: () => object;
20
20
  getExpiresAt: () => Date;
21
21
  getFullAuditRef: () => string;
22
+ isLive: () => boolean;
22
23
  getScores: () => object;
23
24
  }
24
25
 
25
26
  export interface Site {
26
27
  getId: () => string;
27
28
  getBaseURL: () => string;
29
+ getGitHubURL: () => string;
28
30
  getImsOrgId: () => string;
29
31
  getCreatedAt: () => string;
30
32
  getUpdatedAt: () => string;
31
33
  getAudits: () => Audit[];
32
- updateImsOrgId: (imsOrgId: string) => Site;
34
+ isLive: () => boolean;
33
35
  setAudits: (audits: Audit[]) => Site;
36
+ toggleLive: () => Site;
37
+ updateImsOrgId: (imsOrgId: string) => Site;
34
38
  }
35
39
 
36
40
  export interface DataAccess {
@@ -49,6 +53,12 @@ export interface DataAccess {
49
53
  getLatestAuditsForSite: (
50
54
  siteId: string,
51
55
  ) => Promise<Audit[]>;
56
+ addAudit: (
57
+ auditData: object,
58
+ ) => Promise<Audit>;
59
+ removeAuditsForSite: (
60
+ siteId: string,
61
+ ) => Promise<void>;
52
62
  getSites: () => Promise<Site[]>;
53
63
  getSitesToAudit: () => Promise<string[]>;
54
64
  getSitesWithLatestAudit: (
@@ -82,6 +92,17 @@ export interface DataAccess {
82
92
  ) => Promise<void>;
83
93
  }
84
94
 
95
+ interface DataAccessConfig {
96
+ tableNameAudits: string;
97
+ tableNameLatestAudits: string;
98
+ tableNameSites: string;
99
+ indexNameAllSites: string;
100
+ indexNameAllLatestAuditScores: string;
101
+ pkAllSites: string;
102
+ pkAllLatestAudits: string;
103
+ }
104
+
85
105
  export function createDataAccess(
106
+ config: DataAccessConfig,
86
107
  logger: object,
87
108
  ): DataAccess;
package/src/index.js CHANGED
@@ -12,11 +12,38 @@
12
12
 
13
13
  import { createDataAccess } from './service/index.js';
14
14
 
15
+ const TABLE_NAME_AUDITS = 'spacecat-services-audits';
16
+ const TABLE_NAME_LATEST_AUDITS = 'spacecat-services-latest-audits';
17
+ const TABLE_NAME_SITES = 'spacecat-services-sites';
18
+
19
+ const INDEX_NAME_ALL_SITES = 'spacecat-services-all-sites';
20
+ const INDEX_NAME_ALL_LATEST_AUDIT_SCORES = 'spacecat-services-all-latest-audit-scores';
21
+
22
+ const PK_ALL_SITES = 'ALL_SITES';
23
+ const PK_ALL_LATEST_AUDITS = 'ALL_LATEST_AUDITS';
24
+
15
25
  export default function dataAccessWrapper(fn) {
16
26
  return async (request, context) => {
17
27
  if (!context.dataAccess) {
18
28
  const { log } = context;
19
- context.dataAccess = createDataAccess(log);
29
+
30
+ const {
31
+ DYNAMO_TABLE_NAME_AUDITS = TABLE_NAME_AUDITS,
32
+ DYNAMO_TABLE_NAME_LATEST_AUDITS = TABLE_NAME_LATEST_AUDITS,
33
+ DYNAMO_TABLE_NAME_SITES = TABLE_NAME_SITES,
34
+ DYNAMO_INDEX_NAME_ALL_SITES = INDEX_NAME_ALL_SITES,
35
+ DYNAMO_INDEX_NAME_ALL_LATEST_AUDIT_SCORES = INDEX_NAME_ALL_LATEST_AUDIT_SCORES,
36
+ } = context.env;
37
+
38
+ context.dataAccess = createDataAccess({
39
+ tableNameAudits: DYNAMO_TABLE_NAME_AUDITS,
40
+ tableNameLatestAudits: DYNAMO_TABLE_NAME_LATEST_AUDITS,
41
+ tableNameSites: DYNAMO_TABLE_NAME_SITES,
42
+ indexNameAllSites: DYNAMO_INDEX_NAME_ALL_SITES,
43
+ indexNameAllLatestAuditScores: DYNAMO_INDEX_NAME_ALL_LATEST_AUDIT_SCORES,
44
+ pkAllSites: PK_ALL_SITES,
45
+ pkAllLatestAudits: PK_ALL_LATEST_AUDITS,
46
+ }, log);
20
47
  }
21
48
 
22
49
  return fn(request, context);
@@ -58,6 +58,7 @@ const Audit = (data = {}) => {
58
58
  self.getAuditType = () => self.state.auditType.toLowerCase();
59
59
  self.getExpiresAt = () => self.state.expiresAt;
60
60
  self.getFullAuditRef = () => self.state.fullAuditRef;
61
+ self.isLive = () => self.state.isLive;
61
62
  self.getScores = () => self.getAuditResult();
62
63
 
63
64
  return Object.freeze(self);
@@ -99,5 +100,9 @@ export const createAudit = (data) => {
99
100
  newState.expiresAt.setDate(newState.expiresAt.getDate() + EXPIRES_IN_DAYS);
100
101
  }
101
102
 
103
+ if (!Object.prototype.hasOwnProperty.call(newState, 'isLive')) {
104
+ newState.isLive = false;
105
+ }
106
+
102
107
  return Audit(newState);
103
108
  };
@@ -24,7 +24,9 @@ const Site = (data = {}) => {
24
24
 
25
25
  self.getAudits = () => self.state.audits;
26
26
  self.getBaseURL = () => self.state.baseURL;
27
+ self.getGitHubURL = () => self.state.gitHubURL;
27
28
  self.getImsOrgId = () => self.state.imsOrgId;
29
+ self.isLive = () => self.state.isLive;
28
30
 
29
31
  // TODO: updating the baseURL is not supported yet, it will require a transact write
30
32
  // on dynamodb (put then delete) since baseURL is part of the primary key, something like:
@@ -79,6 +81,11 @@ const Site = (data = {}) => {
79
81
  return self;
80
82
  };
81
83
 
84
+ self.toggleLive = () => {
85
+ self.state.isLive = !self.state.isLive;
86
+ return self;
87
+ };
88
+
82
89
  return Object.freeze(self);
83
90
  };
84
91
 
@@ -95,6 +102,10 @@ export const createSite = (data) => {
95
102
  throw new Error('Base URL must be a valid URL');
96
103
  }
97
104
 
105
+ if (!Object.prototype.hasOwnProperty.call(newState, 'isLive')) {
106
+ newState.isLive = false;
107
+ }
108
+
98
109
  if (!Array.isArray(newState.audits)) {
99
110
  newState.audits = [];
100
111
  }
@@ -15,25 +15,21 @@ import { isObject } from '@adobe/spacecat-shared-utils';
15
15
  import { AuditDto } from '../../dto/audit.js';
16
16
  import { createAudit } from '../../models/audit.js';
17
17
 
18
- const TABLE_NAME_AUDITS = 'audits';
19
- const TABLE_NAME_LATEST_AUDITS = 'latest_audits';
20
- const INDEX_NAME_ALL_LATEST_AUDIT_SCORES = 'all_latest_audit_scores';
21
- const PK_ALL_LATEST_AUDITS = 'ALL_LATEST_AUDITS';
22
-
23
18
  /**
24
19
  * Retrieves audits for a specified site. If an audit type is provided,
25
20
  * it returns only audits of that type.
26
21
  *
27
22
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
23
+ * @param {DataAccessConfig} config - The data access config.
28
24
  * @param {Logger} log - The logger.
29
25
  * @param {string} siteId - The ID of the site for which audits are being retrieved.
30
26
  * @param {string} [auditType] - Optional. The type of audits to retrieve.
31
27
  * @returns {Promise<Readonly<Audit>[]>} A promise that resolves to an array of audits
32
28
  * for the specified site.
33
29
  */
34
- export const getAuditsForSite = async (dynamoClient, log, siteId, auditType) => {
30
+ export const getAuditsForSite = async (dynamoClient, config, log, siteId, auditType) => {
35
31
  const queryParams = {
36
- TableName: TABLE_NAME_AUDITS,
32
+ TableName: config.tableNameAudits,
37
33
  KeyConditionExpression: 'siteId = :siteId',
38
34
  ExpressionAttributeValues: {
39
35
  ':siteId': siteId,
@@ -54,6 +50,7 @@ export const getAuditsForSite = async (dynamoClient, log, siteId, auditType) =>
54
50
  * Retrieves a specific audit for a specified site.
55
51
  *
56
52
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
53
+ * @param {DataAccessConfig} config - The data access config.
57
54
  * @param {Logger} log - The logger.
58
55
  * @param {string} siteId - The ID of the site for which to retrieve the audit.
59
56
  * @param {string} auditType - The type of audit to retrieve.
@@ -62,13 +59,14 @@ export const getAuditsForSite = async (dynamoClient, log, siteId, auditType) =>
62
59
  */
63
60
  export const getAuditForSite = async (
64
61
  dynamoClient,
62
+ config,
65
63
  log,
66
64
  siteId,
67
65
  auditType,
68
66
  auditedAt,
69
67
  ) => {
70
68
  const audit = await dynamoClient.query({
71
- TableName: TABLE_NAME_AUDITS,
69
+ TableName: config.tableNameAudits,
72
70
  KeyConditionExpression: 'siteId = :siteId AND SK = :sk',
73
71
  ExpressionAttributeValues: {
74
72
  ':siteId': siteId,
@@ -84,6 +82,7 @@ export const getAuditForSite = async (
84
82
  * Retrieves the latest audits of a specific type across all sites.
85
83
  *
86
84
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
85
+ * @param {DataAccessConfig} config - The data access config.
87
86
  * @param {Logger} log - The logger.
88
87
  * @param {string} auditType - The type of audits to retrieve.
89
88
  * @param {boolean} ascending - Determines if the audits should be sorted ascending
@@ -93,16 +92,17 @@ export const getAuditForSite = async (
93
92
  */
94
93
  export const getLatestAudits = async (
95
94
  dynamoClient,
95
+ config,
96
96
  log,
97
97
  auditType,
98
98
  ascending = true,
99
99
  ) => {
100
100
  const dynamoItems = await dynamoClient.query({
101
- TableName: TABLE_NAME_LATEST_AUDITS,
102
- IndexName: INDEX_NAME_ALL_LATEST_AUDIT_SCORES,
101
+ TableName: config.tableNameLatestAudits,
102
+ IndexName: config.indexNameAllLatestAuditScores,
103
103
  KeyConditionExpression: 'GSI1PK = :gsi1pk AND begins_with(GSI1SK, :auditType)',
104
104
  ExpressionAttributeValues: {
105
- ':gsi1pk': PK_ALL_LATEST_AUDITS,
105
+ ':gsi1pk': config.pkAllLatestAudits,
106
106
  ':auditType': `${auditType}#`,
107
107
  },
108
108
  ScanIndexForward: ascending, // Sorts ascending if true, descending if false
@@ -115,14 +115,20 @@ export const getLatestAudits = async (
115
115
  * Retrieves latest audits for a specified site.
116
116
  *
117
117
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
118
+ * @param {DataAccessConfig} config - The data access config.
118
119
  * @param {Logger} log - The logger.
119
120
  * @param {string} siteId - The ID of the site for which audits are being retrieved.
120
121
  * @returns {Promise<Readonly<Audit>[]>} A promise that resolves to an array of latest audits
121
122
  * for the specified site.
122
123
  */
123
- export const getLatestAuditsForSite = async (dynamoClient, log, siteId) => {
124
+ export const getLatestAuditsForSite = async (
125
+ dynamoClient,
126
+ config,
127
+ log,
128
+ siteId,
129
+ ) => {
124
130
  const queryParams = {
125
- TableName: TABLE_NAME_LATEST_AUDITS,
131
+ TableName: config.tableNameLatestAudits,
126
132
  KeyConditionExpression: 'siteId = :siteId',
127
133
  ExpressionAttributeValues: { ':siteId': siteId },
128
134
  };
@@ -136,6 +142,7 @@ export const getLatestAuditsForSite = async (dynamoClient, log, siteId) => {
136
142
  * Retrieves the latest audit for a specified site and audit type.
137
143
  *
138
144
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
145
+ * @param {DataAccessConfig} config - The data access config.
139
146
  * @param {Logger} log - The logger.
140
147
  * @param {string} siteId - The ID of the site for which the latest audit is being retrieved.
141
148
  * @param {string} auditType - The type of audit to retrieve the latest instance of.
@@ -144,12 +151,13 @@ export const getLatestAuditsForSite = async (dynamoClient, log, siteId) => {
144
151
  */
145
152
  export const getLatestAuditForSite = async (
146
153
  dynamoClient,
154
+ config,
147
155
  log,
148
156
  siteId,
149
157
  auditType,
150
158
  ) => {
151
159
  const latestAudit = await dynamoClient.query({
152
- TableName: TABLE_NAME_LATEST_AUDITS,
160
+ TableName: config.tableNameLatestAudits,
153
161
  KeyConditionExpression: 'siteId = :siteId AND begins_with(SK, :auditType)',
154
162
  ExpressionAttributeValues: {
155
163
  ':siteId': siteId,
@@ -165,14 +173,21 @@ export const getLatestAuditForSite = async (
165
173
  * Adds an audit.
166
174
  *
167
175
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
176
+ * @param {DataAccessConfig} config - The data access config.
168
177
  * @param {Logger} log - The logger.
169
178
  * @param {object} auditData - The audit data.
170
179
  * @returns {Promise<Readonly<Audit>>}
171
180
  */
172
- export const addAudit = async (dynamoClient, log, auditData) => {
181
+ export const addAudit = async (
182
+ dynamoClient,
183
+ config,
184
+ log,
185
+ auditData,
186
+ ) => {
173
187
  const audit = createAudit(auditData);
174
188
  const existingAudit = await getAuditForSite(
175
189
  dynamoClient,
190
+ config,
176
191
  log,
177
192
  audit.getSiteId(),
178
193
  audit.getAuditType(),
@@ -184,8 +199,8 @@ export const addAudit = async (dynamoClient, log, auditData) => {
184
199
  }
185
200
 
186
201
  // TODO: Add transaction support
187
- await dynamoClient.putItem('audits', AuditDto.toDynamoItem(audit));
188
- await dynamoClient.putItem('latest_audits', AuditDto.toDynamoItem(audit, true));
202
+ await dynamoClient.putItem(config.tableNameAudits, AuditDto.toDynamoItem(audit));
203
+ await dynamoClient.putItem(config.tableNameLatestAudits, AuditDto.toDynamoItem(audit, true));
189
204
 
190
205
  return audit;
191
206
  };
@@ -193,18 +208,26 @@ export const addAudit = async (dynamoClient, log, auditData) => {
193
208
  /**
194
209
  * Removes audits from the database.
195
210
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
196
- * @param {Logger} log - The logger.
211
+ * @param {DataAccessConfig} config - The data access config.
197
212
  * @param audits
198
213
  * @param latest
199
214
  * @returns {Promise<void>}
200
215
  */
201
- async function removeAudits(dynamoClient, audits, latest = false) {
202
- const tableName = latest ? TABLE_NAME_LATEST_AUDITS : TABLE_NAME_AUDITS;
216
+ async function removeAudits(
217
+ dynamoClient,
218
+ config,
219
+ audits,
220
+ latest = false,
221
+ ) {
222
+ const tableName = latest ? config.tableNameLatestAudits : config.tableNameAudits;
203
223
  // TODO: use batch-remove (needs dynamo client update)
204
- const removeAuditPromises = audits.map((audit) => dynamoClient.removeItem(tableName, {
205
- siteId: audit.getSiteId(),
206
- SK: `${audit.getAuditType()}#${audit.getAuditedAt()}`,
207
- }));
224
+ const removeAuditPromises = audits.map((audit) => dynamoClient.removeItem(
225
+ tableName,
226
+ {
227
+ siteId: audit.getSiteId(),
228
+ SK: `${audit.getAuditType()}#${audit.getAuditedAt()}`,
229
+ },
230
+ ));
208
231
 
209
232
  await Promise.all(removeAuditPromises);
210
233
  }
@@ -213,17 +236,23 @@ async function removeAudits(dynamoClient, audits, latest = false) {
213
236
  * Removes all audits for a specified site and the latest audit entry.
214
237
  *
215
238
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
239
+ * @param {DataAccessConfig} config - The data access config.
216
240
  * @param {Logger} log - The logger.
217
241
  * @param {string} siteId - The ID of the site for which audits are being removed.
218
242
  * @returns {Promise<void>}
219
243
  */
220
- export const removeAuditsForSite = async (dynamoClient, log, siteId) => {
244
+ export const removeAuditsForSite = async (
245
+ dynamoClient,
246
+ config,
247
+ log,
248
+ siteId,
249
+ ) => {
221
250
  try {
222
- const audits = await getAuditsForSite(dynamoClient, log, siteId);
223
- const latestAudits = await getLatestAuditsForSite(dynamoClient, log, siteId);
251
+ const audits = await getAuditsForSite(dynamoClient, config, log, siteId);
252
+ const latestAudits = await getLatestAuditsForSite(dynamoClient, config, log, siteId);
224
253
 
225
- await removeAudits(dynamoClient, audits);
226
- await removeAudits(dynamoClient, latestAudits, true);
254
+ await removeAudits(dynamoClient, config, audits);
255
+ await removeAudits(dynamoClient, config, latestAudits, true);
227
256
  } catch (error) {
228
257
  log.error(`Error removing audits for site ${siteId}: ${error.message}`);
229
258
  throw error;
@@ -18,9 +18,10 @@ import {
18
18
  removeAuditsForSite,
19
19
  } from './accessPatterns.js';
20
20
 
21
- export const auditFunctions = (dynamoClient, log) => ({
21
+ export const auditFunctions = (dynamoClient, config, log) => ({
22
22
  getAuditForSite: (siteId, auditType, auditedAt) => getAuditForSite(
23
23
  dynamoClient,
24
+ config,
24
25
  log,
25
26
  siteId,
26
27
  auditType,
@@ -28,29 +29,34 @@ export const auditFunctions = (dynamoClient, log) => ({
28
29
  ),
29
30
  getAuditsForSite: (siteId, auditType) => getAuditsForSite(
30
31
  dynamoClient,
32
+ config,
31
33
  log,
32
34
  siteId,
33
35
  auditType,
34
36
  ),
35
37
  getLatestAudits: (auditType, ascending) => getLatestAudits(
36
38
  dynamoClient,
39
+ config,
37
40
  log,
38
41
  auditType,
39
42
  ascending,
40
43
  ),
41
44
  getLatestAuditForSite: (siteId, auditType) => getLatestAuditForSite(
42
45
  dynamoClient,
46
+ config,
43
47
  log,
44
48
  siteId,
45
49
  auditType,
46
50
  ),
47
51
  addAudit: (auditData) => addAudit(
48
52
  dynamoClient,
53
+ config,
49
54
  log,
50
55
  auditData,
51
56
  ),
52
57
  removeAuditsForSite: (siteId) => removeAuditsForSite(
53
58
  dynamoClient,
59
+ config,
54
60
  log,
55
61
  siteId,
56
62
  ),
@@ -17,14 +17,15 @@ import { siteFunctions } from './sites/index.js';
17
17
  /**
18
18
  * Creates a data access object.
19
19
  *
20
+ * @param {DataAccessConfig} config configuration
20
21
  * @param {Logger} log logger
21
22
  * @returns {object} data access object
22
23
  */
23
- export const createDataAccess = (log = console) => {
24
+ export const createDataAccess = (config, log = console) => {
24
25
  const dynamoClient = createClient(log);
25
26
 
26
- const auditFuncs = auditFunctions(dynamoClient, log);
27
- const siteFuncs = siteFunctions(dynamoClient, log);
27
+ const auditFuncs = auditFunctions(dynamoClient, config, log);
28
+ const siteFuncs = siteFunctions(dynamoClient, config, log);
28
29
 
29
30
  return {
30
31
  ...auditFuncs,
@@ -21,23 +21,20 @@ import {
21
21
  import { createSite } from '../../models/site.js';
22
22
  import { SiteDto } from '../../dto/site.js';
23
23
 
24
- const INDEX_NAME_ALL_SITES = 'all_sites';
25
- const PK_ALL_SITES = 'ALL_SITES';
26
- const TABLE_NAME_SITES = 'sites';
27
-
28
24
  /**
29
25
  * Retrieves all sites.
30
26
  *
31
27
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
28
+ * @param {DataAccessConfig} config - The data access config.
32
29
  * @returns {Promise<Readonly<Site>[]>} A promise that resolves to an array of all sites.
33
30
  */
34
- export const getSites = async (dynamoClient) => {
31
+ export const getSites = async (dynamoClient, config) => {
35
32
  const dynamoItems = await dynamoClient.query({
36
- TableName: TABLE_NAME_SITES,
37
- IndexName: INDEX_NAME_ALL_SITES, // GSI name
33
+ TableName: config.tableNameSites,
34
+ IndexName: config.indexNameAllSites,
38
35
  KeyConditionExpression: 'GSI1PK = :gsi1pk',
39
36
  ExpressionAttributeValues: {
40
- ':gsi1pk': PK_ALL_SITES,
37
+ ':gsi1pk': config.pkAllSites,
41
38
  },
42
39
  });
43
40
 
@@ -48,10 +45,11 @@ export const getSites = async (dynamoClient) => {
48
45
  * Retrieves a list of base URLs for all sites.
49
46
  *
50
47
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
48
+ * @param {DataAccessConfig} config - The data access config.
51
49
  * @returns {Promise<Array<string>>} A promise that resolves to an array of base URLs for all sites.
52
50
  */
53
- export const getSitesToAudit = async (dynamoClient) => {
54
- const sites = await getSites(dynamoClient);
51
+ export const getSitesToAudit = async (dynamoClient, config) => {
52
+ const sites = await getSites(dynamoClient, config);
55
53
 
56
54
  return sites.map((site) => site.getBaseURL());
57
55
  };
@@ -60,6 +58,7 @@ export const getSitesToAudit = async (dynamoClient) => {
60
58
  * Retrieves sites with their latest audit of a specified type.
61
59
  *
62
60
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
61
+ * @param {DataAccessConfig} config - The data access config.
63
62
  * @param {Logger} log - The logger.
64
63
  * @param {string} auditType - The type of the latest audits to retrieve for each site.
65
64
  * @param {boolean} [sortAuditsAscending] - Optional. Determines if the audits
@@ -69,13 +68,14 @@ export const getSitesToAudit = async (dynamoClient) => {
69
68
  */
70
69
  export const getSitesWithLatestAudit = async (
71
70
  dynamoClient,
71
+ config,
72
72
  log,
73
73
  auditType,
74
74
  sortAuditsAscending = true,
75
75
  ) => {
76
76
  const [sites, latestAudits] = await Promise.all([
77
- getSites(dynamoClient),
78
- getLatestAudits(dynamoClient, log, auditType, sortAuditsAscending),
77
+ getSites(dynamoClient, config),
78
+ getLatestAudits(dynamoClient, config, log, auditType, sortAuditsAscending),
79
79
  ]);
80
80
 
81
81
  const sitesMap = new Map(sites.map((site) => [site.getId(), site]));
@@ -94,6 +94,7 @@ export const getSitesWithLatestAudit = async (
94
94
  * Retrieves a site by its base URL.
95
95
  *
96
96
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
97
+ * @param {DataAccessConfig} config - The data access config.
97
98
  * @param {Logger} log - The logger.
98
99
  * @param {string} baseURL - The base URL of the site to retrieve.
99
100
  * @returns {Promise<Readonly<Site>|null>} A promise that resolves to the site object if found,
@@ -101,15 +102,16 @@ export const getSitesWithLatestAudit = async (
101
102
  */
102
103
  export const getSiteByBaseURL = async (
103
104
  dynamoClient,
105
+ config,
104
106
  log,
105
107
  baseURL,
106
108
  ) => {
107
109
  const dynamoItems = await dynamoClient.query({
108
- TableName: TABLE_NAME_SITES,
109
- IndexName: INDEX_NAME_ALL_SITES,
110
+ TableName: config.tableNameSites,
111
+ IndexName: config.indexNameAllSites,
110
112
  KeyConditionExpression: 'GSI1PK = :gsi1pk AND baseURL = :baseURL',
111
113
  ExpressionAttributeValues: {
112
- ':gsi1pk': PK_ALL_SITES,
114
+ ':gsi1pk': config.pkAllSites,
113
115
  ':baseURL': baseURL,
114
116
  },
115
117
  Limit: 1,
@@ -126,6 +128,7 @@ export const getSiteByBaseURL = async (
126
128
  * Retrieves a site by its base URL, along with associated audit information.
127
129
  *
128
130
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
131
+ * @param {DataAccessConfig} config - The data access config.
129
132
  * @param {Logger} log - The logger.
130
133
  * @param {string} baseUrl - The base URL of the site to retrieve.
131
134
  * @param {string} auditType - The type of audits to retrieve for the site.
@@ -135,12 +138,13 @@ export const getSiteByBaseURL = async (
135
138
  */
136
139
  export const getSiteByBaseURLWithAuditInfo = async (
137
140
  dynamoClient,
141
+ config,
138
142
  log,
139
143
  baseUrl,
140
144
  auditType,
141
145
  latestOnly = false,
142
146
  ) => {
143
- const site = await getSiteByBaseURL(dynamoClient, log, baseUrl);
147
+ const site = await getSiteByBaseURL(dynamoClient, config, log, baseUrl);
144
148
 
145
149
  if (!isObject(site)) {
146
150
  return null;
@@ -149,12 +153,14 @@ export const getSiteByBaseURLWithAuditInfo = async (
149
153
  const audits = latestOnly
150
154
  ? [await getLatestAuditForSite(
151
155
  dynamoClient,
156
+ config,
152
157
  log,
153
158
  site.getId(),
154
159
  auditType,
155
160
  )].filter((audit) => audit != null)
156
161
  : await getAuditsForSite(
157
162
  dynamoClient,
163
+ config,
158
164
  log,
159
165
  site.getId(),
160
166
  auditType,
@@ -169,6 +175,7 @@ export const getSiteByBaseURLWithAuditInfo = async (
169
175
  * Retrieves a site by its base URL, including all its audits.
170
176
  *
171
177
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
178
+ * @param {DataAccessConfig} config - The data access config.
172
179
  * @param {Logger} log - The logger.
173
180
  * @param {string} baseUrl - The base URL of the site to retrieve.
174
181
  * @param {string} auditType - The type of audits to retrieve for the site.
@@ -177,15 +184,17 @@ export const getSiteByBaseURLWithAuditInfo = async (
177
184
  */
178
185
  export const getSiteByBaseURLWithAudits = async (
179
186
  dynamoClient,
187
+ config,
180
188
  log,
181
189
  baseUrl,
182
190
  auditType,
183
- ) => getSiteByBaseURLWithAuditInfo(dynamoClient, log, baseUrl, auditType, false);
191
+ ) => getSiteByBaseURLWithAuditInfo(dynamoClient, config, log, baseUrl, auditType, false);
184
192
 
185
193
  /**
186
194
  * Retrieves a site by its base URL, including only its latest audit.
187
195
  *
188
196
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
197
+ * @param {DataAccessConfig} config - The data access config.
189
198
  * @param {Logger} log - The logger.
190
199
  * @param {string} baseUrl - The base URL of the site to retrieve.
191
200
  * @param {string} auditType - The type of the latest audit to retrieve for the site.
@@ -194,23 +203,31 @@ export const getSiteByBaseURLWithAudits = async (
194
203
  */
195
204
  export const getSiteByBaseURLWithLatestAudit = async (
196
205
  dynamoClient,
206
+ config,
197
207
  log,
198
208
  baseUrl,
199
209
  auditType,
200
- ) => getSiteByBaseURLWithAuditInfo(dynamoClient, log, baseUrl, auditType, true);
210
+ ) => getSiteByBaseURLWithAuditInfo(dynamoClient, config, log, baseUrl, auditType, true);
201
211
 
202
212
  /**
203
213
  * Adds a site.
204
214
  *
205
215
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
216
+ * @param {DataAccessConfig} config - The data access config.
206
217
  * @param {Logger} log - The logger.
207
218
  * @param {object} siteData - The site data.
208
219
  * @returns {Promise<Readonly<Site>>}
209
220
  */
210
- export const addSite = async (dynamoClient, log, siteData) => {
221
+ export const addSite = async (
222
+ dynamoClient,
223
+ config,
224
+ log,
225
+ siteData,
226
+ ) => {
211
227
  const site = createSite(siteData);
212
228
  const existingSite = await getSiteByBaseURL(
213
229
  dynamoClient,
230
+ config,
214
231
  log,
215
232
  site.getBaseURL(),
216
233
  );
@@ -219,7 +236,7 @@ export const addSite = async (dynamoClient, log, siteData) => {
219
236
  throw new Error('Site already exists');
220
237
  }
221
238
 
222
- await dynamoClient.putItem(TABLE_NAME_SITES, SiteDto.toDynamoItem(site));
239
+ await dynamoClient.putItem(config.tableNameSites, SiteDto.toDynamoItem(site));
223
240
 
224
241
  return site;
225
242
  };
@@ -228,18 +245,24 @@ export const addSite = async (dynamoClient, log, siteData) => {
228
245
  * Updates a site.
229
246
  *
230
247
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
248
+ * @param {DataAccessConfig} config - The data access config.
231
249
  * @param {Logger} log - The logger.
232
250
  * @param {Site} site - The site.
233
251
  * @returns {Promise<Readonly<Site>>} - The updated site.
234
252
  */
235
- export const updateSite = async (dynamoClient, log, site) => {
236
- const existingSite = await getSiteByBaseURL(dynamoClient, log, site.getBaseURL());
253
+ export const updateSite = async (
254
+ dynamoClient,
255
+ config,
256
+ log,
257
+ site,
258
+ ) => {
259
+ const existingSite = await getSiteByBaseURL(dynamoClient, config, log, site.getBaseURL());
237
260
 
238
261
  if (!isObject(existingSite)) {
239
262
  throw new Error('Site not found');
240
263
  }
241
264
 
242
- await dynamoClient.putItem(TABLE_NAME_SITES, SiteDto.toDynamoItem(site));
265
+ await dynamoClient.putItem(config.tableNameSites, SiteDto.toDynamoItem(site));
243
266
 
244
267
  return site;
245
268
  };
@@ -248,16 +271,22 @@ export const updateSite = async (dynamoClient, log, site) => {
248
271
  * Removes a site and its related audits.
249
272
  *
250
273
  * @param {DynamoDbClient} dynamoClient - The DynamoDB client.
274
+ * @param {DataAccessConfig} config - The data access config.
251
275
  * @param {Logger} log - The logger.
252
276
  * @param {string} siteId - The ID of the site to remove.
253
277
  * @returns {Promise<void>}
254
278
  */
255
- export const removeSite = async (dynamoClient, log, siteId) => {
279
+ export const removeSite = async (
280
+ dynamoClient,
281
+ config,
282
+ log,
283
+ siteId,
284
+ ) => {
256
285
  try {
257
286
  // TODO: Add transaction support
258
- await removeAuditsForSite(dynamoClient, log, siteId);
287
+ await removeAuditsForSite(dynamoClient, config, log, siteId);
259
288
 
260
- await dynamoClient.removeItem(TABLE_NAME_SITES, { id: siteId });
289
+ await dynamoClient.removeItem(config.tableNameSites, { id: siteId });
261
290
  } catch (error) {
262
291
  log.error(`Error removing site: ${error.message}`);
263
292
  throw error;
@@ -22,26 +22,31 @@ import {
22
22
  updateSite,
23
23
  } from './accessPatterns.js';
24
24
 
25
- export const siteFunctions = (dynamoClient, log) => ({
25
+ export const siteFunctions = (dynamoClient, config, log) => ({
26
26
  getSites: () => getSites(
27
27
  dynamoClient,
28
+ config,
28
29
  ),
29
30
  getSitesToAudit: () => getSitesToAudit(
30
31
  dynamoClient,
32
+ config,
31
33
  ),
32
34
  getSitesWithLatestAudit: (auditType, sortAuditsAscending) => getSitesWithLatestAudit(
33
35
  dynamoClient,
36
+ config,
34
37
  log,
35
38
  auditType,
36
39
  sortAuditsAscending,
37
40
  ),
38
41
  getSiteByBaseURL: (baseUrl) => getSiteByBaseURL(
39
42
  dynamoClient,
43
+ config,
40
44
  log,
41
45
  baseUrl,
42
46
  ),
43
47
  getSiteByBaseURLWithAuditInfo: (baseUrl, auditType, latestOnly) => getSiteByBaseURLWithAuditInfo(
44
48
  dynamoClient,
49
+ config,
45
50
  log,
46
51
  baseUrl,
47
52
  auditType,
@@ -49,17 +54,19 @@ export const siteFunctions = (dynamoClient, log) => ({
49
54
  ),
50
55
  getSiteByBaseURLWithAudits: (baseUrl, auditType) => getSiteByBaseURLWithAudits(
51
56
  dynamoClient,
57
+ config,
52
58
  log,
53
59
  baseUrl,
54
60
  auditType,
55
61
  ),
56
62
  getSiteByBaseURLWithLatestAudit: (baseUrl, auditType) => getSiteByBaseURLWithLatestAudit(
57
63
  dynamoClient,
64
+ config,
58
65
  log,
59
66
  baseUrl,
60
67
  auditType,
61
68
  ),
62
- addSite: (siteData) => addSite(dynamoClient, log, siteData),
63
- updateSite: (site) => updateSite(dynamoClient, log, site),
64
- removeSite: (siteId) => removeSite(dynamoClient, log, siteId),
69
+ addSite: (siteData) => addSite(dynamoClient, config, log, siteData),
70
+ updateSite: (site) => updateSite(dynamoClient, config, log, site),
71
+ removeSite: (siteId) => removeSite(dynamoClient, config, log, siteId),
65
72
  });