Skip to content

Commit

Permalink
feat: latest audit entity (#503)
Browse files Browse the repository at this point in the history
Co-authored-by: Damian Zehnder <16799758+dzehnder@users.noreply.github.com>
  • Loading branch information
solaris007 and dzehnder authored Dec 23, 2024
1 parent 57c2859 commit 2d01b09
Show file tree
Hide file tree
Showing 69 changed files with 12,812 additions and 22,922 deletions.
33,465 changes: 11,038 additions & 22,427 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/spacecat-shared-ahrefs-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"dependencies": {
"@adobe/fetch": "4.1.11",
"@adobe/helix-universal": "5.0.8",
"@adobe/spacecat-shared-utils": "1.22.4"
"@adobe/spacecat-shared-utils": "1.24.1"
},
"devDependencies": {
"chai": "5.1.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/spacecat-shared-content-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@
},
"dependencies": {
"@adobe/helix-universal": "5.0.8",
"@adobe/spacecat-shared-data-access": "1.50.0",
"@adobe/spacecat-shared-data-access": "1.60.3",
"@adobe/spacecat-helix-content-sdk": "1.3.16",
"@adobe/spacecat-shared-utils": "1.22.4",
"@adobe/spacecat-shared-utils": "1.24.1",
"graph-data-structure": "4.3.0"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/spacecat-shared-data-access/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
"access": "public"
},
"dependencies": {
"@adobe/spacecat-shared-dynamo": "1.4.0",
"@adobe/spacecat-shared-utils": "1.23.1",
"@adobe/spacecat-shared-dynamo": "1.4.2",
"@adobe/spacecat-shared-utils": "1.24.1",
"@aws-sdk/client-dynamodb": "3.716.0",
"@aws-sdk/lib-dynamodb": "3.716.0",
"@types/joi": "17.2.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

export default class DataAccessError extends Error {
constructor(message, details = {}, cause = null) {
super(message);
this.name = this.constructor.name;
this.details = details;
this.cause = cause;

if (cause?.stack) {
this.stack += `\nCaused by: ${cause.stack}`;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@
* governing permissions and limitations under the License.
*/

export type ValidationError = Error
export type DataAccessError = Error
export type SchemaBuilderError = DataAccessError
export type SchemaError = DataAccessError
export type SchemaValidationError = DataAccessError
export type ValidationError = DataAccessError
12 changes: 11 additions & 1 deletion packages/spacecat-shared-data-access/src/v2/errors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@
* governing permissions and limitations under the License.
*/

import DataAccessError from './data-access.error.js';
import SchemaBuilderError from './schema.builder.error.js';
import SchemaError from './schema.error.js';
import SchemaValidationError from './schema-validation.error.js';
import ValidationError from './validation.error.js';

export { ValidationError };
export {
DataAccessError,
SchemaBuilderError,
SchemaError,
SchemaValidationError,
ValidationError,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import DataAccessError from './data-access.error.js';

export default class ReferenceError extends DataAccessError {
constructor(reference, message, cause) {
const { type, target } = reference;
const prefix = type && target ? `[${type} -> ${target}] ` : '';

super(`${prefix}${message}`, { reference }, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
export const INDEX_TYPES = {
PRIMARY: 'primary',
ALL: 'all',
BELONGS_TO: 'belongs_to',
OTHER: 'other',
};

import DataAccessError from './data-access.error.js';

export default class SchemaValidationError extends DataAccessError {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import { hasText } from '@adobe/spacecat-shared-utils';

import DataAccessError from './data-access.error.js';

export default class SchemaBuilderError extends DataAccessError {
constructor(builder, message, cause) {
const { serviceName, entityName } = builder;
const prefix = hasText(serviceName) && hasText(entityName)
? `[${serviceName} -> ${entityName}] `
: '';

super(`${prefix}${message}`, { builder }, cause);
this.name = this.constructor.name;
}
}
19 changes: 19 additions & 0 deletions packages/spacecat-shared-data-access/src/v2/errors/schema.error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright 2024 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import DataAccessError from './data-access.error.js';

export default class SchemaError extends DataAccessError {
constructor(schema, message, cause) {
super(`[${schema.getModelName()}] ${message}`, { schema }, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@
* governing permissions and limitations under the License.
*/

export default class ValidationError extends Error {}
import DataAccessError from './data-access.error.js';

export default class ValidationError extends DataAccessError {}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import type { BaseCollection, BaseModel } from '../base';

export interface ApiKey extends BaseModel {
getApiKeyId(): string;
getDeletedAt(): string | undefined;
getExpiresAt(): string | undefined;
getHashedApiKey(): string;
Expand All @@ -32,6 +33,18 @@ export interface ApiKey extends BaseModel {
}

export interface ApiKeyCollection extends BaseCollection<ApiKey> {
allByImsOrgIdAndImsUserId: (imsUserId: string, imsOrgId: string) => Promise<ApiKey[]>;
findByHashedApiKey: (hashedApiKey: string) => Promise<ApiKey | null>;
allByHashedApiKey(hashedApiKey: string): Promise<ApiKey[]>;
allByHashedApiKeyAndUpdatedAt(hashedApiKey: string, updatedAt: string): Promise<ApiKey[]>;
allByImsOrgId(imsOrgId: string): Promise<ApiKey[]>;
allByImsOrgIdAndImsUserId(imsOrgId: string, imsUserId: string): Promise<ApiKey[]>;
allByImsOrgIdAndImsUserIdAndUpdatedAt(
imsOrgId: string, imsUserId: string, updatedAt: string
): Promise<ApiKey[]>;
findByHashedApiKey(hashedApiKey: string): Promise<ApiKey | null>;
findByHashedApiKeyAndUpdatedAt(hashedApiKey: string, updatedAt: string): Promise<ApiKey | null>;
findByImsOrgId(imsOrgId: string): Promise<ApiKey | null>;
findByImsOrgIdAndImsUserId(imsOrgId: string, imsUserId: string): Promise<ApiKey | null>;
findByImsOrgIdAndImsUserIdAndUpdatedAt(
imsOrgId: string, imsUserId: string, updatedAt: string
): Promise<ApiKey | null>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,31 @@ import BaseCollection from '../base/base.collection.js';
* @extends BaseCollection
*/
class AuditCollection extends BaseCollection {
// add custom methods here
// create a copy of the audit as a LatestAudit entity
async _onCreate(item) {
const collection = this.entityRegistry.getCollection('LatestAuditCollection');
await collection.create(item.toJSON());
}

// of the created audits, find the latest per site and auditType
// and create a LatestAudit copy for each
async _onCreateMany(items) {
const collection = this.entityRegistry.getCollection('LatestAuditCollection');
const latestAudits = items.createdItems.reduce((acc, audit) => {
const siteId = audit.getSiteId();
const auditType = audit.getAuditType();
const auditedAt = audit.getAuditedAt();
const key = `${siteId}-${auditType}`;

if (!acc[key] || acc[key].getAuditedAt() < auditedAt) {
acc[key] = audit;
}

return acc;
}, {});

await collection.createMany(Object.values(latestAudits).map((audit) => audit.toJSON()));
}
}

export default AuditCollection;
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ Indexes Doc: https://electrodb.dev/en/modeling/indexes/

const schema = new SchemaBuilder(Audit, AuditCollection)
.addReference('belongs_to', 'Site', ['auditType', 'auditedAt'])
.addReference('has_one', 'LatestAudit', ['auditType'], { required: false })
.addReference('has_many', 'Opportunities')
.allowUpdates(false)
.allowRemove(false)
.addAttribute('auditResult', {
type: 'any',
required: true,
Expand Down
27 changes: 16 additions & 11 deletions packages/spacecat-shared-data-access/src/v2/models/audit/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,35 @@
*/

import type {
BaseCollection, BaseModel, Opportunity, Site,
BaseCollection, BaseModel, LatestAudit, Opportunity, Site,
} from '../index';

export interface Audit extends BaseModel {
getAuditedAt(): number;
getAuditId(): string;
getAuditResult(): object;
getAuditType(): string;
getAuditedAt(): number;
getFullAuditRef(): string;
getIsError(): boolean;
getIsLive(): boolean;
getLatestAudit(): Promise<LatestAudit | null>;
getLatestAuditByAuditType(auditType: string): Promise<LatestAudit | null>;
getOpportunities(): Promise<Opportunity[]>;
getOpportunitiesByUpdatedAt(updatedAt: string): Promise<Opportunity[]>;
getScores(): object | undefined;
getSite(): Promise<Site>;
getSiteId(): string;
setAuditResult(auditResult: object): Audit;
setAuditType(auditType: string): Audit;
setAuditedAt(auditedAt: number): Audit;
setFullAuditRef(fullAuditRef: string): Audit;
setIsError(isError: boolean): Audit;
setIsLive(isLive: boolean): Audit;
setSiteId(siteId: string): Audit;
toggleLive(): Audit;
}

export interface AuditCollection extends BaseCollection<Audit> {
allBySiteId(siteId: string): Promise<Audit[]>;
allBySiteAndType(siteId: string, auditType: string): Promise<Audit[]>;
allBySiteIdAndAuditType(siteId: string, auditType: string): Promise<Audit[]>;
allBySiteIdAndAuditTypeAndAuditedAt(
siteId: string, auditType: string, auditedAt: string
): Promise<Audit[]>;
findBySiteId(siteId: string): Promise<Audit | null>;
findBySiteIdAndAuditType(siteId: string, auditType: string): Promise<Audit | null>;
findBySiteIdAndAuditTypeAndAuditedAt(
siteId: string, auditType: string, auditedAt: string
): Promise<Audit | null>;
}
Loading

0 comments on commit 2d01b09

Please sign in to comment.