381 lines
11 KiB
TypeScript
381 lines
11 KiB
TypeScript
import { apiFetch, apiPath, type ApiSettings } from "@govoplan/core-webui";
|
|
|
|
|
|
export type FilePlanNode = {
|
|
node_id: string;
|
|
revision: number;
|
|
parent_node_id?: string | null;
|
|
code: string;
|
|
label: string;
|
|
description?: string | null;
|
|
active: boolean;
|
|
valid_from?: string | null;
|
|
valid_to?: string | null;
|
|
recorded_at: string;
|
|
closed_at?: string | null;
|
|
retention_started_at?: string | null;
|
|
retention_due_at?: string | null;
|
|
retention_rule: Record<string, unknown>;
|
|
appraisal_state?: string | null;
|
|
appraisal: Record<string, unknown>;
|
|
institutional_context: Record<string, unknown>;
|
|
};
|
|
|
|
export type RecordClass = {
|
|
class_id: string;
|
|
revision: number;
|
|
file_plan_node_id: string;
|
|
key: string;
|
|
label: string;
|
|
description?: string | null;
|
|
metadata_requirements: string[];
|
|
allowed_source_types: string[];
|
|
retention_period_days?: number | null;
|
|
closure_trigger?: string | null;
|
|
access_mode: "tenant" | "restricted";
|
|
active: boolean;
|
|
};
|
|
|
|
export type RecordCatalog = {
|
|
file_plan: FilePlanNode[];
|
|
classes: RecordClass[];
|
|
};
|
|
|
|
export type RecordEntry = {
|
|
record_id: string;
|
|
record_number: string;
|
|
revision: number;
|
|
class_id: string;
|
|
file_plan_node_id: string;
|
|
title: string;
|
|
description?: string | null;
|
|
state: "planned" | "open" | string;
|
|
source_authority_mode: string;
|
|
access_mode: "tenant" | "restricted";
|
|
purpose: string;
|
|
classification?: string | null;
|
|
responsible_unit_id?: string | null;
|
|
responsible_function_id?: string | null;
|
|
external_reference: Record<string, unknown>;
|
|
institutional_context: Record<string, unknown>;
|
|
valid_from?: string | null;
|
|
valid_to?: string | null;
|
|
recorded_at: string;
|
|
};
|
|
|
|
export type RecordVolume = {
|
|
volume_id: string;
|
|
sequence: number;
|
|
label: string;
|
|
state: string;
|
|
recorded_at: string;
|
|
};
|
|
|
|
export type RecordItem = {
|
|
item_id: string;
|
|
sequence: number;
|
|
volume_id?: string | null;
|
|
source: {
|
|
source_module: string;
|
|
resource_type: string;
|
|
resource_id: string;
|
|
source_revision: string;
|
|
};
|
|
label: string;
|
|
relationship: string;
|
|
filing_reason: string;
|
|
purpose: string;
|
|
authority_mode: string;
|
|
content_sha256?: string | null;
|
|
content_type?: string | null;
|
|
size_bytes?: number | null;
|
|
source_valid_from?: string | null;
|
|
source_valid_to?: string | null;
|
|
source_recorded_at?: string | null;
|
|
launch_url?: string | null;
|
|
filed_at: string;
|
|
filed_by?: string | null;
|
|
institutional_context: Record<string, unknown>;
|
|
source_metadata: Record<string, unknown>;
|
|
filing_metadata: Record<string, unknown>;
|
|
};
|
|
|
|
export type RecordChronology = {
|
|
event_id: string;
|
|
event_type: string;
|
|
record_revision: number;
|
|
summary: string;
|
|
occurred_at: string;
|
|
actor_id?: string | null;
|
|
purpose: string;
|
|
payload: Record<string, unknown>;
|
|
};
|
|
|
|
export type RecordHold = {
|
|
hold_id: string;
|
|
record_id: string;
|
|
revision: number;
|
|
status: string;
|
|
reason: string;
|
|
authority: string;
|
|
scope: Record<string, unknown>;
|
|
effective_from: string;
|
|
effective_to?: string | null;
|
|
released_at?: string | null;
|
|
policy_refs: string[];
|
|
recorded_at: string;
|
|
};
|
|
|
|
export type RecordDisposition = {
|
|
disposition_id: string;
|
|
record_id: string;
|
|
revision: number;
|
|
action: "retain" | "transfer" | "destroy" | "reclassify";
|
|
status: string;
|
|
reason: string;
|
|
subject_revision: number;
|
|
subject_sha256: string;
|
|
consequence_preview: Record<string, unknown>;
|
|
policy_refs: string[];
|
|
approval_request_id?: string | null;
|
|
proposed_by?: string | null;
|
|
reviewed_by?: string | null;
|
|
reviewed_at?: string | null;
|
|
recorded_at: string;
|
|
};
|
|
|
|
export type RecordTransferPackage = {
|
|
package_id: string;
|
|
record_id: string;
|
|
disposition_id: string;
|
|
revision: number;
|
|
record_revision: number;
|
|
provider_id: string;
|
|
profile: string;
|
|
status: string;
|
|
authority_mode: string;
|
|
manifest: Record<string, unknown>;
|
|
manifest_sha256: string;
|
|
receipt: Record<string, unknown>;
|
|
receipt_sha256?: string | null;
|
|
external_reference?: string | null;
|
|
recovery_operation_id?: string | null;
|
|
simulated: boolean;
|
|
institutional_context: Record<string, unknown>;
|
|
recorded_at: string;
|
|
};
|
|
|
|
export type RecordDetail = {
|
|
record: RecordEntry;
|
|
volumes: RecordVolume[];
|
|
items: RecordItem[];
|
|
chronology: RecordChronology[];
|
|
holds: RecordHold[];
|
|
dispositions: RecordDisposition[];
|
|
transfer_packages: RecordTransferPackage[];
|
|
access_explanation: {
|
|
decision: string;
|
|
reason: string;
|
|
purpose: string;
|
|
current_authorization: boolean;
|
|
access_mode: string;
|
|
limitations: string[];
|
|
};
|
|
};
|
|
|
|
export type RecordSourceProvider = {
|
|
id: string;
|
|
source_module: string;
|
|
resource_types: string[];
|
|
};
|
|
|
|
export type RecordArchiveProvider = {
|
|
id: string;
|
|
label: string;
|
|
profiles: string[];
|
|
authority_modes: string[];
|
|
healthy: boolean;
|
|
checked_at: string;
|
|
last_success_at?: string | null;
|
|
freshness_seconds?: number | null;
|
|
limitations: string[];
|
|
simulated: boolean;
|
|
};
|
|
|
|
export function listRecords(
|
|
settings: ApiSettings,
|
|
options: {
|
|
query?: string;
|
|
state?: string;
|
|
classId?: string;
|
|
filePlanNodeId?: string;
|
|
offset?: number;
|
|
limit?: number;
|
|
},
|
|
signal?: AbortSignal
|
|
): Promise<{ records: RecordEntry[]; total: number; offset: number; limit: number }> {
|
|
return apiFetch(settings, apiPath("/api/v1/records", {
|
|
query: options.query,
|
|
state: options.state,
|
|
class_id: options.classId,
|
|
file_plan_node_id: options.filePlanNodeId,
|
|
offset: options.offset,
|
|
limit: options.limit ?? 50
|
|
}), { signal });
|
|
}
|
|
|
|
export function getRecord(settings: ApiSettings, recordId: string, signal?: AbortSignal): Promise<RecordDetail> {
|
|
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}`, { signal });
|
|
}
|
|
|
|
export function getRecordCatalog(settings: ApiSettings, signal?: AbortSignal): Promise<RecordCatalog> {
|
|
return apiFetch(settings, "/api/v1/records/catalog", { signal });
|
|
}
|
|
|
|
export function getRecordSources(settings: ApiSettings, signal?: AbortSignal): Promise<{ providers: RecordSourceProvider[] }> {
|
|
return apiFetch(settings, "/api/v1/records/sources", { signal });
|
|
}
|
|
|
|
export function getRecordArchiveProviders(settings: ApiSettings, signal?: AbortSignal): Promise<{ providers: RecordArchiveProvider[] }> {
|
|
return apiFetch(settings, "/api/v1/records/archive-providers", { signal });
|
|
}
|
|
|
|
export function writeFilePlanNode(settings: ApiSettings, payload: Record<string, unknown>): Promise<FilePlanNode> {
|
|
return apiFetch(settings, "/api/v1/records/catalog/file-plan", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export function writeRecordClass(settings: ApiSettings, payload: Record<string, unknown>): Promise<RecordClass> {
|
|
return apiFetch(settings, "/api/v1/records/catalog/classes", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export function createRecord(settings: ApiSettings, payload: Record<string, unknown>): Promise<RecordEntry> {
|
|
return apiFetch(settings, "/api/v1/records", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export function updateRecord(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<RecordEntry> {
|
|
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export function fileRecordItem(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<Record<string, unknown>> {
|
|
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}/items`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|
|
|
|
export function createRecordVolume(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<RecordVolume> {
|
|
return recordMutation(settings, recordId, "volumes", payload);
|
|
}
|
|
|
|
export function closeRecord(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordEntry> {
|
|
return recordMutation(settings, recordId, "close", payload);
|
|
}
|
|
|
|
export function reopenRecord(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordEntry> {
|
|
return recordMutation(settings, recordId, "reopen", payload);
|
|
}
|
|
|
|
export function appraiseRecord(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordEntry> {
|
|
return recordMutation(settings, recordId, "appraise", payload);
|
|
}
|
|
|
|
export function applyRecordHold(settings: ApiSettings, recordId: string, payload: Record<string, unknown>): Promise<RecordHold> {
|
|
return recordMutation(settings, recordId, "holds", payload);
|
|
}
|
|
|
|
export function releaseRecordHold(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
holdId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<RecordHold> {
|
|
return recordMutation(settings, recordId, `holds/${encodeURIComponent(holdId)}/release`, payload);
|
|
}
|
|
|
|
export function proposeRecordDisposition(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<RecordDisposition> {
|
|
return recordMutation(settings, recordId, "dispositions", payload);
|
|
}
|
|
|
|
export function finalizeRecordDisposition(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
dispositionId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<{ disposition: RecordDisposition; record: RecordEntry }> {
|
|
return recordMutation(settings, recordId, `dispositions/${encodeURIComponent(dispositionId)}/finalize`, payload);
|
|
}
|
|
|
|
export function withdrawRecordDisposition(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
dispositionId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<RecordDisposition> {
|
|
return recordMutation(settings, recordId, `dispositions/${encodeURIComponent(dispositionId)}/withdraw`, payload);
|
|
}
|
|
|
|
export function prepareRecordTransfer(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<RecordTransferPackage> {
|
|
return recordMutation(settings, recordId, "transfer-packages", payload);
|
|
}
|
|
|
|
export function dispatchRecordTransfer(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
packageId: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<RecordTransferPackage> {
|
|
return recordMutation(settings, recordId, `transfer-packages/${encodeURIComponent(packageId)}/dispatch`, payload);
|
|
}
|
|
|
|
export function getRecordRecoveryStatus(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
signal?: AbortSignal
|
|
): Promise<Record<string, unknown>> {
|
|
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}/recovery`, { signal });
|
|
}
|
|
|
|
function recordMutation<T>(
|
|
settings: ApiSettings,
|
|
recordId: string,
|
|
path: string,
|
|
payload: Record<string, unknown>
|
|
): Promise<T> {
|
|
return apiFetch(settings, `/api/v1/records/${encodeURIComponent(recordId)}/${path}`, {
|
|
method: "POST",
|
|
body: JSON.stringify(payload)
|
|
});
|
|
}
|