Decouple runtime domain services
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import { CircuitDeviceRowRepository } from "../../db/repositories/circuit-device-row.repository.js";
|
||||
import { ProjectDeviceRepository } from "../../db/repositories/project-device.repository.js";
|
||||
import {
|
||||
createProjectDeviceRowSyncProjectCommand,
|
||||
projectDeviceSyncRowSnapshotFields,
|
||||
@@ -20,15 +18,44 @@ export {
|
||||
serializeOverriddenFields,
|
||||
} from "./project-device-overrides.js";
|
||||
|
||||
type ProjectDevice = NonNullable<Awaited<ReturnType<ProjectDeviceRepository["findById"]>>>;
|
||||
type LinkedRow = Awaited<ReturnType<CircuitDeviceRowRepository["listLinkedByProjectDevice"]>>[number];
|
||||
export type ProjectDeviceSyncSource = {
|
||||
id: string;
|
||||
} & Pick<ProjectDeviceSyncRowSnapshot, ProjectDeviceSyncField>;
|
||||
|
||||
type SyncDependencies = {
|
||||
projectDeviceRepository: Pick<ProjectDeviceRepository, "findById">;
|
||||
deviceRowRepository: Pick<CircuitDeviceRowRepository, "listLinkedByProjectDevice">;
|
||||
export type LinkedProjectDeviceRow = ProjectDeviceSyncRowSnapshot & {
|
||||
id: string;
|
||||
circuitId: string;
|
||||
equipmentIdentifier: string;
|
||||
circuitDisplayName: string | null;
|
||||
circuitListId: string;
|
||||
circuitListName: string;
|
||||
distributionBoardId: string;
|
||||
distributionBoardName: string;
|
||||
};
|
||||
|
||||
function sourceValue(projectDevice: ProjectDevice, field: ProjectDeviceSyncField) {
|
||||
export interface ProjectDeviceSyncSourceReader {
|
||||
findById(
|
||||
projectId: string,
|
||||
projectDeviceId: string
|
||||
): Promise<ProjectDeviceSyncSource | null>;
|
||||
}
|
||||
|
||||
export interface LinkedProjectDeviceRowReader {
|
||||
listLinkedByProjectDevice(
|
||||
projectId: string,
|
||||
projectDeviceId: string
|
||||
): Promise<LinkedProjectDeviceRow[]>;
|
||||
}
|
||||
|
||||
export interface ProjectDeviceSyncDependencies {
|
||||
projectDeviceRepository: ProjectDeviceSyncSourceReader;
|
||||
deviceRowRepository: LinkedProjectDeviceRowReader;
|
||||
}
|
||||
|
||||
function sourceValue(
|
||||
projectDevice: ProjectDeviceSyncSource,
|
||||
field: ProjectDeviceSyncField
|
||||
) {
|
||||
return projectDevice[field];
|
||||
}
|
||||
|
||||
@@ -36,7 +63,10 @@ function valuesEqual(left: unknown, right: unknown) {
|
||||
return (left ?? null) === (right ?? null);
|
||||
}
|
||||
|
||||
function buildDifferences(projectDevice: ProjectDevice, row: LinkedRow) {
|
||||
function buildDifferences(
|
||||
projectDevice: ProjectDeviceSyncSource,
|
||||
row: LinkedProjectDeviceRow
|
||||
) {
|
||||
return projectDeviceSyncFields
|
||||
.filter((field) => !valuesEqual(row[field], sourceValue(projectDevice, field)))
|
||||
.map((field) => ({
|
||||
@@ -48,12 +78,12 @@ function buildDifferences(projectDevice: ProjectDevice, row: LinkedRow) {
|
||||
}
|
||||
|
||||
export class ProjectDeviceSyncService {
|
||||
private readonly projectDeviceRepository: SyncDependencies["projectDeviceRepository"];
|
||||
private readonly deviceRowRepository: SyncDependencies["deviceRowRepository"];
|
||||
private readonly projectDeviceRepository: ProjectDeviceSyncSourceReader;
|
||||
private readonly deviceRowRepository: LinkedProjectDeviceRowReader;
|
||||
|
||||
constructor(deps?: Partial<SyncDependencies>) {
|
||||
this.projectDeviceRepository = deps?.projectDeviceRepository ?? new ProjectDeviceRepository();
|
||||
this.deviceRowRepository = deps?.deviceRowRepository ?? new CircuitDeviceRowRepository();
|
||||
constructor(deps: ProjectDeviceSyncDependencies) {
|
||||
this.projectDeviceRepository = deps.projectDeviceRepository;
|
||||
this.deviceRowRepository = deps.deviceRowRepository;
|
||||
}
|
||||
|
||||
async getPreview(projectId: string, projectDeviceId: string) {
|
||||
@@ -154,10 +184,15 @@ export class ProjectDeviceSyncService {
|
||||
);
|
||||
}
|
||||
|
||||
private resolveSelectedRows(linkedRows: LinkedRow[], rowIds: string[]) {
|
||||
private resolveSelectedRows(
|
||||
linkedRows: LinkedProjectDeviceRow[],
|
||||
rowIds: string[]
|
||||
) {
|
||||
const uniqueRowIds = [...new Set(rowIds)];
|
||||
const byId = new Map(linkedRows.map((row) => [row.id, row]));
|
||||
const selectedRows = uniqueRowIds.map((rowId) => byId.get(rowId)).filter(Boolean) as LinkedRow[];
|
||||
const selectedRows = uniqueRowIds
|
||||
.map((rowId) => byId.get(rowId))
|
||||
.filter(Boolean) as LinkedProjectDeviceRow[];
|
||||
if (selectedRows.length !== uniqueRowIds.length) {
|
||||
throw new Error("One or more rows are not linked to this project device.");
|
||||
}
|
||||
@@ -166,7 +201,9 @@ export class ProjectDeviceSyncService {
|
||||
|
||||
}
|
||||
|
||||
function toSyncSnapshot(row: LinkedRow): ProjectDeviceSyncRowSnapshot {
|
||||
function toSyncSnapshot(
|
||||
row: LinkedProjectDeviceRow
|
||||
): ProjectDeviceSyncRowSnapshot {
|
||||
return {
|
||||
linkedProjectDeviceId: row.linkedProjectDeviceId,
|
||||
name: row.name,
|
||||
|
||||
Reference in New Issue
Block a user