mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 21:48:18 +00:00
feat(freight-api): enrich canonical request log line
Emit the request line as raw JSON on stdout (level/time/logger as fields) instead of through Nest's console logger, whose prefix made it unparsable. Collect data points via logCtx at the flow chokepoints: BaseRepository writes (status changes, creates, deletes), invoice transitions, payment intent lifecycle + outbound payment-service calls, booking/contract entry state, review-note reasons, signatures and OTP verify outcomes.
This commit is contained in:
@@ -7,9 +7,16 @@ import {
|
||||
Repository,
|
||||
} from "typeorm";
|
||||
|
||||
import { logCtx } from "../logging/request-context";
|
||||
|
||||
export abstract class BaseRepository<T extends ObjectLiteral> {
|
||||
protected constructor(protected readonly repository: Repository<T>) {}
|
||||
|
||||
/** Table name, for the write trail on the canonical request log line. */
|
||||
private get table(): string {
|
||||
return this.repository.metadata.tableName;
|
||||
}
|
||||
|
||||
/** Find a single entity by its primary key. */
|
||||
async findById(
|
||||
id: string,
|
||||
@@ -34,22 +41,43 @@ export abstract class BaseRepository<T extends ObjectLiteral> {
|
||||
/** Create and persist a new entity. */
|
||||
async create(data: DeepPartial<T>): Promise<T> {
|
||||
const entity = this.repository.create(data);
|
||||
return this.repository.save(entity);
|
||||
const saved = await this.repository.save(entity);
|
||||
logCtx(1, { path: `db.created.${this.table}`, mode: "count" });
|
||||
return saved;
|
||||
}
|
||||
|
||||
/** Patch an entity in place and return the reloaded row. */
|
||||
/**
|
||||
* Patch an entity in place and return the reloaded row.
|
||||
*
|
||||
* Every domain status machine in this app (booking, contract, wagon,
|
||||
* warehouse, transfer request…) lands here, so this is the one place that can
|
||||
* record "what state did this request actually move" without every service
|
||||
* remembering to log it.
|
||||
*/
|
||||
async update(id: string, data: DeepPartial<T>): Promise<T | null> {
|
||||
await this.repository.update(id, data as never);
|
||||
logCtx(1, { path: `db.updated.${this.table}`, mode: "count" });
|
||||
if (data && typeof data === "object" && "status" in data) {
|
||||
logCtx(
|
||||
{ entity: this.table, id, status: (data as { status: unknown }).status },
|
||||
{ path: "statusChanges", mode: "push" },
|
||||
);
|
||||
}
|
||||
return this.findById(id);
|
||||
}
|
||||
|
||||
/** Soft-delete an entity by primary key (sets deleted_at). */
|
||||
async softDelete(id: string): Promise<void> {
|
||||
await this.repository.softDelete(id);
|
||||
logCtx({ entity: this.table, id }, { path: "deleted", mode: "push" });
|
||||
}
|
||||
|
||||
/** Permanently delete an entity. Avoid in domain code; prefer softDelete. */
|
||||
async hardDelete(id: string): Promise<void> {
|
||||
await this.repository.delete(id);
|
||||
logCtx(
|
||||
{ entity: this.table, id, hard: true },
|
||||
{ path: "deleted", mode: "push" },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user