feat(scanner): complete localized artifact quality checkpoint
This commit is contained in:
@@ -2,7 +2,12 @@ import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { StoredArtifactRecord } from "../../src/types/storage.js";
|
||||
import { isReviewOnlyArtifactSource, resolveStoredArtifactSource } from "../../src/lib/artifactStore.js";
|
||||
import type { ArtifactStoreLoadResult, ArtifactStoreRepositoryPort, ArtifactStoreSaveResult } from "./contracts.js";
|
||||
import type {
|
||||
ArtifactStoreLoadResult,
|
||||
ArtifactStoreRemoveResult,
|
||||
ArtifactStoreRepositoryPort,
|
||||
ArtifactStoreSaveResult,
|
||||
} from "./contracts.js";
|
||||
interface ArtifactStoreFile {
|
||||
version?: number;
|
||||
artifacts?: StoredArtifactRecord[];
|
||||
@@ -79,9 +84,26 @@ export class JsonArtifactStoreRepository implements ArtifactStoreRepositoryPort
|
||||
return { ok: true, added, updated, total: store.size, path: this.filePath };
|
||||
}
|
||||
|
||||
async removeByIds(ids: string[]): Promise<ArtifactStoreRemoveResult> {
|
||||
const requestedIds = new Set((ids ?? []).map((id) => String(id ?? "").trim()).filter(Boolean));
|
||||
const store = await this.loadMap();
|
||||
let removed = 0;
|
||||
for (const id of requestedIds) {
|
||||
if (store.delete(id)) removed += 1;
|
||||
}
|
||||
if (removed > 0) await this.writeRecords([...store.values()]);
|
||||
return { ok: true, removed, total: store.size, path: this.filePath };
|
||||
}
|
||||
|
||||
private async writeRecords(records: StoredArtifactRecord[]) {
|
||||
await fs.mkdir(path.dirname(this.filePath), { recursive: true });
|
||||
await fs.writeFile(this.filePath, JSON.stringify({ version: 1, artifacts: records }, null, 2), "utf8");
|
||||
const temporaryPath = `${this.filePath}.tmp-${process.pid}-${Date.now()}`;
|
||||
try {
|
||||
await fs.writeFile(temporaryPath, JSON.stringify({ version: 1, artifacts: records }, null, 2), "utf8");
|
||||
await fs.rename(temporaryPath, this.filePath);
|
||||
} finally {
|
||||
await fs.rm(temporaryPath, { force: true }).catch(() => undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
CaptureSourceInfo,
|
||||
ClickResult,
|
||||
ArtifactStoreLoadResult,
|
||||
ArtifactStoreRemoveResult,
|
||||
ArtifactStoreSaveResult,
|
||||
ReviewSampleListResult,
|
||||
ReviewSamplePayload,
|
||||
@@ -23,6 +24,7 @@ import type { AppSnapshot } from "../../src/types/domain.js";
|
||||
|
||||
export type {
|
||||
ArtifactStoreLoadResult,
|
||||
ArtifactStoreRemoveResult,
|
||||
ArtifactStoreSaveResult,
|
||||
ReviewSampleListResult,
|
||||
ReviewSamplePayload,
|
||||
@@ -34,6 +36,7 @@ export interface ArtifactStoreRepositoryPort {
|
||||
loadAll(): Promise<ArtifactStoreLoadResult>;
|
||||
loadMap(): Promise<Map<string, StoredArtifactRecord>>;
|
||||
saveMany(records: StoredArtifactRecord[]): Promise<ArtifactStoreSaveResult>;
|
||||
removeByIds(ids: string[]): Promise<ArtifactStoreRemoveResult>;
|
||||
}
|
||||
|
||||
export interface ReviewSamplesRepositoryPort {
|
||||
|
||||
Reference in New Issue
Block a user