273 lines
8.0 KiB
TypeScript
273 lines
8.0 KiB
TypeScript
import { apiFetch, apiPath, type ApiSettings } from "@govoplan/core-webui";
|
|
|
|
|
|
export type InstitutionalReference = {
|
|
kind: string;
|
|
owner_module: string;
|
|
object_id: string;
|
|
tenant_id: string;
|
|
version?: string | null;
|
|
valid_at?: string | null;
|
|
label?: string | null;
|
|
};
|
|
|
|
export type EvidenceReference = {
|
|
kind: string;
|
|
owner_module: string;
|
|
evidence_id: string;
|
|
tenant_id: string;
|
|
version?: string | null;
|
|
};
|
|
|
|
export type FormCondition =
|
|
| { kind: "predicate"; field_key: string; operator: string; value?: unknown }
|
|
| { kind: "all" | "any" | "not"; conditions: FormCondition[] };
|
|
|
|
export type FormFieldDefinition = {
|
|
key: string;
|
|
label: string;
|
|
value_type: "text" | "multiline_text" | "integer" | "number" | "boolean" | "date" | "datetime" | "email" | "choice" | "multi_choice" | "object" | "list";
|
|
required: boolean;
|
|
help_text?: string | null;
|
|
options: string[];
|
|
constraints: Record<string, unknown>;
|
|
default_value?: unknown;
|
|
visibility_condition?: FormCondition | null;
|
|
};
|
|
|
|
export type FormDefinition = {
|
|
reference: InstitutionalReference;
|
|
key: string;
|
|
temporal: { revision: string; recorded_at?: string | null };
|
|
title: string;
|
|
description?: string | null;
|
|
fields: FormFieldDefinition[];
|
|
publication_state: "draft" | "published" | "retired";
|
|
allow_drafts: boolean;
|
|
max_attachments: number;
|
|
signature_requirement: "none" | "optional" | "required";
|
|
policy_refs: string[];
|
|
handoff_kinds: string[];
|
|
pages?: Array<{
|
|
key: string;
|
|
title: string;
|
|
description?: string | null;
|
|
visibility_condition?: FormCondition | null;
|
|
sections: Array<{
|
|
key: string;
|
|
title: string;
|
|
description?: string | null;
|
|
field_keys: string[];
|
|
visibility_condition?: FormCondition | null;
|
|
}>;
|
|
}>;
|
|
fallback_locale?: string | null;
|
|
localizations?: Array<{
|
|
locale: string;
|
|
title?: string | null;
|
|
description?: string | null;
|
|
field_labels: Record<string, string>;
|
|
field_help_texts: Record<string, string>;
|
|
option_labels: Record<string, Record<string, string>>;
|
|
page_titles: Record<string, string>;
|
|
section_titles: Record<string, string>;
|
|
}>;
|
|
};
|
|
|
|
export type ValidationResult = {
|
|
field?: string | null;
|
|
severity: "warning" | "error";
|
|
code: string;
|
|
message: string;
|
|
};
|
|
|
|
export type FormInstance = {
|
|
reference: InstitutionalReference;
|
|
tenant_id: string;
|
|
instance_id: string;
|
|
revision: number;
|
|
status: string;
|
|
definition_ref: InstitutionalReference;
|
|
values: Record<string, unknown>;
|
|
validation_results: ValidationResult[];
|
|
attachment_refs: EvidenceReference[];
|
|
signature_refs: EvidenceReference[];
|
|
handoff_refs: InstitutionalReference[];
|
|
service_ref?: InstitutionalReference | null;
|
|
receipt_id?: string | null;
|
|
recorded_at: string;
|
|
change_reason: string;
|
|
created_by: string;
|
|
changed_by: string;
|
|
replayed: boolean;
|
|
};
|
|
|
|
export type FormInstanceEvent = {
|
|
event_id: string;
|
|
event_type: string;
|
|
instance_revision: number;
|
|
status: string;
|
|
occurred_at: string;
|
|
actor_id: string;
|
|
payload: Record<string, unknown>;
|
|
};
|
|
|
|
export type FormHandoff = {
|
|
effect_id: string;
|
|
instance_id: string;
|
|
instance_revision: number;
|
|
binding_kind: "case" | "workflow";
|
|
binding_reference: string;
|
|
provider_capability: string;
|
|
state: "requested" | "accepted" | "rejected" | "outcome_unknown" | "reconciled" | "compensated";
|
|
attempt_count: number;
|
|
requested_at: string;
|
|
resolved_at?: string | null;
|
|
target_ref?: InstitutionalReference | null;
|
|
href?: string | null;
|
|
evidence: EvidenceReference[];
|
|
last_error?: string | null;
|
|
metadata: Record<string, unknown>;
|
|
};
|
|
|
|
export function listFormInstances(
|
|
settings: ApiSettings,
|
|
options: { statuses?: string[]; definitionId?: string; offset?: number; limit?: number } = {},
|
|
signal?: AbortSignal
|
|
): Promise<{ instances: FormInstance[]; total: number; offset: number; limit: number }> {
|
|
return apiFetch(settings, apiPath("/api/v1/forms-runtime/instances", {
|
|
status: options.statuses,
|
|
definition_id: options.definitionId,
|
|
offset: options.offset ?? 0,
|
|
limit: options.limit ?? 100
|
|
}), { signal });
|
|
}
|
|
|
|
export function getFormInstance(
|
|
settings: ApiSettings,
|
|
instanceId: string,
|
|
signal?: AbortSignal
|
|
): Promise<FormInstance> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instanceId)}`, { signal });
|
|
}
|
|
|
|
export function getFormDefinition(
|
|
settings: ApiSettings,
|
|
instanceId: string,
|
|
signal?: AbortSignal
|
|
): Promise<FormDefinition> {
|
|
return apiFetch(
|
|
settings,
|
|
`/api/v1/forms-runtime/instances/${encodeURIComponent(instanceId)}/definition`,
|
|
{ signal }
|
|
);
|
|
}
|
|
|
|
export function getFormInstanceHistory(
|
|
settings: ApiSettings,
|
|
instanceId: string,
|
|
signal?: AbortSignal
|
|
): Promise<{ revisions: FormInstance[] }> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instanceId)}/history`, { signal });
|
|
}
|
|
|
|
export function getFormInstanceEvents(
|
|
settings: ApiSettings,
|
|
instanceId: string,
|
|
signal?: AbortSignal
|
|
): Promise<{ events: FormInstanceEvent[] }> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instanceId)}/events`, { signal });
|
|
}
|
|
|
|
export function saveFormDraft(
|
|
settings: ApiSettings,
|
|
instance: FormInstance,
|
|
values: Record<string, unknown>,
|
|
changeReason: string
|
|
): Promise<FormInstance> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instance.instance_id)}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify({
|
|
expected_revision: instance.revision,
|
|
values,
|
|
attachment_refs: instance.attachment_refs,
|
|
signature_refs: instance.signature_refs,
|
|
idempotency_key: crypto.randomUUID(),
|
|
recorded_at: new Date().toISOString(),
|
|
change_reason: changeReason
|
|
})
|
|
});
|
|
}
|
|
|
|
export function submitFormInstance(
|
|
settings: ApiSettings,
|
|
instance: FormInstance,
|
|
values: Record<string, unknown>
|
|
): Promise<FormInstance> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instance.instance_id)}/submit`, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
expected_revision: instance.revision,
|
|
values,
|
|
attachment_refs: instance.attachment_refs,
|
|
signature_refs: instance.signature_refs,
|
|
idempotency_key: crypto.randomUUID(),
|
|
recorded_at: new Date().toISOString()
|
|
})
|
|
});
|
|
}
|
|
|
|
export function listFormHandoffs(
|
|
settings: ApiSettings,
|
|
instanceId: string,
|
|
signal?: AbortSignal
|
|
): Promise<{ handoffs: FormHandoff[] }> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instanceId)}/handoffs`, { signal });
|
|
}
|
|
|
|
export function startFormHandoff(
|
|
settings: ApiSettings,
|
|
instance: FormInstance,
|
|
bindingKind: "case" | "workflow",
|
|
bindingReference?: string
|
|
): Promise<{ handoff: FormHandoff; instance?: FormInstance | null }> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instance.instance_id)}/handoffs/native`, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
expected_revision: instance.revision,
|
|
binding_kind: bindingKind,
|
|
binding_reference: bindingReference?.trim() || null,
|
|
idempotency_key: crypto.randomUUID(),
|
|
requested_at: new Date().toISOString()
|
|
})
|
|
});
|
|
}
|
|
|
|
export function actOnFormHandoff(
|
|
settings: ApiSettings,
|
|
instanceId: string,
|
|
effectId: string,
|
|
action: "retry" | "reconcile"
|
|
): Promise<{ handoff: FormHandoff; instance?: FormInstance | null }> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instanceId)}/handoffs/${encodeURIComponent(effectId)}/${action}`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ recorded_at: new Date().toISOString() })
|
|
});
|
|
}
|
|
|
|
export function compensateFormHandoff(
|
|
settings: ApiSettings,
|
|
instanceId: string,
|
|
effectId: string,
|
|
changeReason: string
|
|
): Promise<{ handoff: FormHandoff }> {
|
|
return apiFetch(settings, `/api/v1/forms-runtime/instances/${encodeURIComponent(instanceId)}/handoffs/${encodeURIComponent(effectId)}/compensate`, {
|
|
method: "POST",
|
|
body: JSON.stringify({
|
|
recorded_at: new Date().toISOString(),
|
|
confirmed_absent: true,
|
|
change_reason: changeReason
|
|
})
|
|
});
|
|
}
|