Initial commit: establish deterministic rod-string solver stack.
Set up the C solver core, Node API orchestration, TS GUI workflow, and engineering documentation with cleaned repo hygiene for private Git hosting. Made-with: Cursor
This commit is contained in:
86
gui-ts/src/api/client.ts
Normal file
86
gui-ts/src/api/client.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
import type { ParsedCase, SolveResponse } from "../types";
|
||||
|
||||
const API_BASE =
|
||||
(import.meta as unknown as { env?: { VITE_API_BASE?: string } }).env?.VITE_API_BASE ||
|
||||
"http://localhost:4400";
|
||||
|
||||
export type SolverModel = "fdm" | "fea" | "both";
|
||||
export type Workflow = "predictive" | "diagnostic";
|
||||
|
||||
export type SurfaceCard = {
|
||||
position: number[];
|
||||
load: number[];
|
||||
time?: number[];
|
||||
};
|
||||
|
||||
async function handleJson<T>(resp: Response): Promise<T> {
|
||||
const body = await resp.json().catch(() => ({}));
|
||||
if (!resp.ok) {
|
||||
const message =
|
||||
(body && typeof body === "object" && "error" in body && typeof body.error === "string"
|
||||
? body.error
|
||||
: null) || `Request failed: HTTP ${resp.status}`;
|
||||
throw new Error(message);
|
||||
}
|
||||
return body as T;
|
||||
}
|
||||
|
||||
export async function fetchDefaultCase(signal?: AbortSignal): Promise<ParsedCase> {
|
||||
const resp = await fetch(`${API_BASE}/case/default`, { signal });
|
||||
return handleJson<ParsedCase>(resp);
|
||||
}
|
||||
|
||||
export async function parseCaseXmlApi(xml: string, signal?: AbortSignal): Promise<ParsedCase> {
|
||||
const resp = await fetch(`${API_BASE}/case/parse`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ xml }),
|
||||
signal
|
||||
});
|
||||
return handleJson<ParsedCase>(resp);
|
||||
}
|
||||
|
||||
export type SolveArgs = {
|
||||
xml: string;
|
||||
solverModel: SolverModel;
|
||||
workflow?: Workflow;
|
||||
surfaceCard?: SurfaceCard;
|
||||
options?: {
|
||||
enableProfiles?: boolean;
|
||||
enableDiagnosticsDetail?: boolean;
|
||||
enableFourierBaseline?: boolean;
|
||||
fourierHarmonics?: number;
|
||||
};
|
||||
};
|
||||
|
||||
export async function solveCase(args: SolveArgs, signal?: AbortSignal): Promise<SolveResponse> {
|
||||
const body: Record<string, unknown> = {
|
||||
xml: args.xml,
|
||||
solverModel: args.solverModel
|
||||
};
|
||||
if (args.workflow) body.workflow = args.workflow;
|
||||
if (args.surfaceCard) body.surfaceCard = args.surfaceCard;
|
||||
if (args.options) body.options = args.options;
|
||||
const resp = await fetch(`${API_BASE}/solve`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(body),
|
||||
signal
|
||||
});
|
||||
return handleJson<SolveResponse>(resp);
|
||||
}
|
||||
|
||||
export async function validateSurfaceCard(
|
||||
surfaceCard: SurfaceCard,
|
||||
signal?: AbortSignal
|
||||
): Promise<{ ok: boolean; qa: Record<string, unknown>; schemaVersion: number }> {
|
||||
const resp = await fetch(`${API_BASE}/solve/validate-card`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ surfaceCard }),
|
||||
signal
|
||||
});
|
||||
return handleJson(resp);
|
||||
}
|
||||
|
||||
export { API_BASE };
|
||||
Reference in New Issue
Block a user