Files
govoplan-docs/webui/src/api/docs.ts
T

395 lines
11 KiB
TypeScript

import { apiFetch, type ApiSettings } from "@govoplan/core-webui";
export type DocsModuleArchitecture = {
contract_version: string;
layer: string;
kind: string;
maturity: string;
evidence: Array<{ kind: string; reference: string; summary: string }>;
known_limits: string[];
supported_authority_modes: string[];
owned_concepts: string[];
non_owned_concepts: string[];
reference_packages: string[];
target_tested_providers: string[];
documentation: Record<string, string[]>;
};
export type DocsExternalProvider = {
id: string;
module_id: string;
label: string;
maturity: string;
operations: string[];
authority_modes: string[];
behavior?: Record<string, unknown>;
known_outage_behavior?: string | null;
runtime_state?: {
configured?: boolean;
active?: boolean;
authority_mode?: string | null;
authority_modes?: string[];
health?: string;
freshness?: string;
conflict?: string;
recovery?: string;
observed_at?: string;
} | null;
};
export type DocsModule = {
id: string;
name: string;
version: string;
dependencies: string[];
optional_dependencies: string[];
permission_count: number;
role_template_count: number;
nav_count: number;
route_count: number;
frontend_package?: string | null;
backend_route_contributed: boolean;
migration_module_id?: string | null;
capabilities: string[];
documentation_count: number;
documentation_provider_count: number;
architecture?: DocsModuleArchitecture | null;
external_provider_count: number;
external_providers: DocsExternalProvider[];
};
export type DocsRoute = {
module_id: string;
path: string;
label: string;
icon?: string | null;
section?: string | null;
source: string;
component?: string | null;
required_all: string[];
required_any: string[];
order: number;
visible: boolean;
reason: string;
};
export type DocsPermission = {
scope: string;
label: string;
description: string;
category: string;
level: "system" | "tenant";
module_id: string;
resource: string;
action: string;
deprecated: boolean;
granted: boolean;
};
export type DocsOptionalModuleEvidence = {
module_id: string;
source_module_id: string;
status: "installed" | "not_installed" | string;
reason: string;
};
export type DocsSource = {
id: string;
kind: string;
owner_module_id: string;
label: string;
state: "configured" | "disabled" | "unavailable";
state_reason?: string | null;
inspection_url: string;
provenance: {
source: string;
version?: string | null;
revision?: string | null;
published_at?: string | null;
checksum?: string | null;
};
};
export type DocsSourceDetail = DocsSource & {
visibility: {
documentation_types: string[];
required_modules: string[];
any_modules: string[];
missing_modules: string[];
required_capabilities: string[];
required_scopes: string[];
any_scopes: string[];
configuration_keys: string[];
};
inspection: Record<string, unknown>;
};
export type DocsDocumentationCondition = {
required_modules: string[];
any_modules: string[];
missing_modules: string[];
required_capabilities: string[];
required_scopes: string[];
any_scopes: string[];
configuration_keys: string[];
};
export type DocsDocumentationLink = {
label: string;
href: string;
kind: string;
};
export type DocsTopicKind = "workflow" | "reference" | "pattern" | "system" | string;
export type DocsDocumentationTopic = {
id: string;
source_module_id: string;
kind: DocsTopicKind;
anchor_id: string;
title: string;
summary: string;
body: string;
layer: "always" | "configured" | "available" | "evidence" | string;
target_layer: string;
documentation_types: Array<"admin" | "user" | string>;
active: boolean;
reason: string;
blockers: {
modules: string[];
capabilities: string[];
scopes: string[];
configuration: string[];
};
audience: string[];
order: number;
i18n_key: string;
locale: string;
translation_locale: string;
structured_translation_locale: string;
structured_translation_version?: string | null;
version: {
resolved: string;
minimum?: string | null;
maximum_exclusive?: string | null;
range: string;
fallback: "unversioned" | "matching_range" | string;
};
conditions: DocsDocumentationCondition[];
links: DocsDocumentationLink[];
related_modules: string[];
unlocks: string[];
configuration_keys: string[];
configuration_states: Array<{
key: string;
state: "enabled" | "disabled" | "inherited" | "unavailable";
source?: string | null;
reason?: string | null;
}>;
metadata: Record<string, unknown>;
};
export type DocsContext = {
versions: {
mode: "installed" | "selected";
selected_version?: string | null;
status: "installed" | "stable" | "older_supported" | "unsupported" | string;
latest_version?: string | null;
stable_version?: string | null;
supported_versions: string[];
installed_versions: Record<string, string>;
fallback_policy: string;
};
actor: {
tenant_id?: string;
user_id?: string;
scope_count?: number;
documentation_type: "admin" | "user";
locale: string;
available_documentation_types: Array<"admin" | "user">;
};
summary: {
module_count: number;
architecture_declared_module_count: number;
external_provider_count: number;
visible_route_count: number;
available_route_count: number;
permission_count: number;
granted_permission_count: number;
optional_module_count: number;
documentation_topic_count: number;
configured_documentation_topic_count: number;
workflow_topic_count: number;
reference_topic_count: number;
pattern_topic_count: number;
system_topic_count: number;
};
topic_groups: {
workflow: DocsDocumentationTopic[];
reference: DocsDocumentationTopic[];
pattern: DocsDocumentationTopic[];
system: DocsDocumentationTopic[];
[kind: string]: DocsDocumentationTopic[];
};
layers: {
always: {
documentation: DocsDocumentationTopic[];
};
configured: {
modules: DocsModule[];
routes: DocsRoute[];
permissions: DocsPermission[];
documentation: DocsDocumentationTopic[];
};
available: {
routes: DocsRoute[];
permissions: DocsPermission[];
documentation: DocsDocumentationTopic[];
};
evidence: {
optional_modules: DocsOptionalModuleEvidence[];
sources: DocsSource[];
documentation: DocsDocumentationTopic[];
};
};
};
export function fetchDocsContext(settings: ApiSettings, options: { documentationType?: "admin" | "user"; locale?: string; version?: string | null } = {}): Promise<DocsContext> {
const params = new URLSearchParams();
if (options.documentationType) params.set("type", options.documentationType);
if (options.locale) params.set("locale", options.locale);
if (options.version) params.set("version", options.version);
const query = params.toString();
return apiFetch(settings, `/api/v1/docs/context${query ? `?${query}` : ""}`);
}
export function fetchDocsSource(
settings: ApiSettings,
sourceId: string,
options: { documentationType?: "admin" | "user"; locale?: string } = {}
): Promise<DocsSourceDetail> {
const params = new URLSearchParams();
if (options.documentationType) params.set("type", options.documentationType);
if (options.locale) params.set("locale", options.locale);
const query = params.toString();
return apiFetch(
settings,
`/api/v1/docs/sources/${encodeURIComponent(sourceId)}${query ? `?${query}` : ""}`
);
}
export type SemanticSubjectReference = {
module_id: string;
tenant_id: string;
subject_kind: string;
subject_id: string;
anchor?: { kind: string; id: string } | null;
observed_revision?: string | null;
observed_fingerprint?: string | null;
};
export type SemanticSubjectDescriptor = {
reference: SemanticSubjectReference;
labels: Record<string, string>;
descriptions: Record<string, string>;
route?: string | null;
route_anchor?: string | null;
};
export type SemanticContent = {
title: string;
summary: string;
body: string;
meaning: string;
intended_use: string;
non_intended_use: string;
examples: string[];
owner_account_id: string | null;
steward_account_id: string | null;
audience: string[];
classification: "internal" | "restricted";
links: Array<{ label: string; href: string }>;
};
export type SemanticEntry = {
id: string;
subject: SemanticSubjectReference;
subject_resolution: {
availability: "available" | "changed" | "superseded" | "missing" | "temporarily_unavailable";
reason_code?: string | null;
};
locale: string;
requested_locale: string;
locale_fallback: boolean;
lifecycle_state: "draft" | "published" | "superseded" | "retired";
pending_draft: boolean;
current_revision: number;
published_revision?: number | null;
content: SemanticContent;
content_redacted: boolean;
updated_at: string;
};
export async function fetchSemanticSubjects(
settings: ApiSettings,
query = ""
): Promise<SemanticSubjectDescriptor[]> {
const params = new URLSearchParams({ query });
const response = await apiFetch<{ providers: Array<{ subjects: SemanticSubjectDescriptor[] }> }>(
settings,
`/api/v1/docs/semantic/subjects?${params}`
);
return response.providers.flatMap((provider) => provider.subjects);
}
export async function fetchSemanticEntries(
settings: ApiSettings,
locale: string,
includeDrafts = true
): Promise<SemanticEntry[]> {
const params = new URLSearchParams({ locale, include_drafts: String(includeDrafts) });
const response = await apiFetch<{ items: SemanticEntry[] }>(
settings,
`/api/v1/docs/semantic/entries?${params}`
);
return response.items;
}
export function createSemanticEntry(
settings: ApiSettings,
payload: { subject: SemanticSubjectReference; locale: string; content: SemanticContent; change_reason: string }
): Promise<SemanticEntry> {
return apiFetch(settings, "/api/v1/docs/semantic/entries", {
method: "POST",
body: JSON.stringify(payload)
});
}
export function updateSemanticEntry(
settings: ApiSettings,
entryId: string,
payload: { expected_revision: number; content: SemanticContent; change_reason: string }
): Promise<SemanticEntry> {
return apiFetch(settings, `/api/v1/docs/semantic/entries/${encodeURIComponent(entryId)}`, {
method: "PUT",
body: JSON.stringify(payload)
});
}
export function transitionSemanticEntry(
settings: ApiSettings,
entryId: string,
transition: "publish" | "retire",
expectedRevision: number,
changeReason: string
): Promise<SemanticEntry> {
return apiFetch(
settings,
`/api/v1/docs/semantic/entries/${encodeURIComponent(entryId)}/${transition}`,
{
method: "POST",
body: JSON.stringify({ expected_revision: expectedRevision, change_reason: changeReason })
}
);
}