mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-03 13:52:09 +03:00
`kieExecutor.createTask()` returns `JsonObject` (`Record<string, unknown>`), so `createData.data` is `unknown` and the `createData?.data?.taskId` read that image, video and music generation each duplicated could not compile. The same three-line expression appeared verbatim in all three handlers. `open-sse/utils/kieTask.ts` already holds two helpers with exactly this shape — `normalizeKieTaskState()` and `parseKieResultJson()` both take `unknown`, guard with `isJsonObject()` and return a declared type. `getKieTaskId()` follows them, so the three handlers now share one guarded read instead of three unguarded ones. `getKieCallbackUrl()` took `KieCallbackBody`, a weak type (all properties optional). Passing a request body whose declared keys are `prompt` / `timeout_ms` / `poll_interval_ms` tripped TS2559 "no properties in common" at both music call sites. It receives arbitrary upstream request bodies, so it now takes `unknown` and guards the same way its neighbours do; `KieCallbackBody` had no other reference and is gone. Behaviour is unchanged. `isJsonObject()` rejects arrays and null exactly where optional chaining already yielded `undefined`, and the callers' `String(taskId)` coercion moved inside the helper, so a numeric id still reaches `pollTask()` as a string and a falsy id still takes the 502 branch. Fixes 5 of the 208 `tsc -p open-sse/tsconfig.json` diagnostics with no new ones: 3 x TS2339 `taskId` on `unknown`, 2 x TS2559 on `KieCallbackBody`. Refs #8484
130 lines
3.7 KiB
TypeScript
130 lines
3.7 KiB
TypeScript
export type JsonObject = Record<string, unknown>;
|
|
|
|
export type KieTaskState = "success" | "failed" | "pending";
|
|
|
|
const FALLBACK_KIE_CALLBACK_URL = "https://omniroute.local/api/kie/callback";
|
|
|
|
export function isJsonObject(value: unknown): value is JsonObject {
|
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
}
|
|
|
|
function callbackUrlFromBaseUrl(baseUrl: string | undefined): string | null {
|
|
if (!baseUrl || baseUrl.trim().length === 0) return null;
|
|
|
|
try {
|
|
const url = new URL(baseUrl);
|
|
url.pathname = "/api/kie/callback";
|
|
url.search = "";
|
|
url.hash = "";
|
|
return url.toString();
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getConfiguredKieCallbackUrl(): string {
|
|
const explicit =
|
|
process.env.KIE_CALLBACK_URL?.trim() || process.env.OMNIROUTE_KIE_CALLBACK_URL?.trim();
|
|
if (explicit) return explicit;
|
|
|
|
return (
|
|
callbackUrlFromBaseUrl(process.env.OMNIROUTE_PUBLIC_URL) ||
|
|
callbackUrlFromBaseUrl(process.env.NEXT_PUBLIC_APP_URL) ||
|
|
callbackUrlFromBaseUrl(process.env.APP_URL) ||
|
|
callbackUrlFromBaseUrl(process.env.PUBLIC_URL) ||
|
|
FALLBACK_KIE_CALLBACK_URL
|
|
);
|
|
}
|
|
|
|
export function getKieCallbackUrl(body: unknown = {}): string {
|
|
const record = isJsonObject(body) ? body : {};
|
|
const callbackUrl = record.callBackUrl ?? record.callback_url ?? record.callbackUrl;
|
|
return typeof callbackUrl === "string" && callbackUrl.trim().length > 0
|
|
? callbackUrl
|
|
: getConfiguredKieCallbackUrl();
|
|
}
|
|
|
|
export function parseKieResultJson(recordData: unknown): JsonObject {
|
|
const data = isJsonObject(recordData) && isJsonObject(recordData.data) ? recordData.data : {};
|
|
const resultJson = data.resultJson;
|
|
|
|
if (typeof resultJson === "string") {
|
|
try {
|
|
const parsed = JSON.parse(resultJson) as unknown;
|
|
return isJsonObject(parsed) ? parsed : {};
|
|
} catch {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
return isJsonObject(resultJson) ? resultJson : {};
|
|
}
|
|
|
|
export function getKieTaskId(createData: unknown): string | null {
|
|
const record = isJsonObject(createData) ? createData : {};
|
|
const data = isJsonObject(record.data) ? record.data : {};
|
|
const taskId = data.taskId || record.taskId;
|
|
return taskId ? String(taskId) : null;
|
|
}
|
|
|
|
export function normalizeKieTaskState(recordData: unknown): KieTaskState {
|
|
const record = isJsonObject(recordData) ? recordData : {};
|
|
const data = isJsonObject(record.data) ? record.data : {};
|
|
const state = String(
|
|
data.status ?? data.state ?? data.successFlag ?? record.msg ?? "PENDING"
|
|
).toUpperCase();
|
|
|
|
if (
|
|
state === "SUCCESS" ||
|
|
state === "1" ||
|
|
state === "FINISHED" ||
|
|
state === "COMPLETE" ||
|
|
state === "COMPLETED" ||
|
|
state === "FIRST_SUCCESS" ||
|
|
state === "ALL_SUCCESS" ||
|
|
state.includes("SUCCESS")
|
|
) {
|
|
return "success";
|
|
}
|
|
|
|
if (
|
|
state === "FAIL" ||
|
|
state === "FAILED" ||
|
|
state === "ERROR" ||
|
|
state === "2" ||
|
|
state === "3" ||
|
|
state.includes("FAIL") ||
|
|
state.includes("ERROR") ||
|
|
state === "CREATE_TASK_FAILED" ||
|
|
state === "GENERATE_FAILED" ||
|
|
state === "GENERATE_AUDIO_FAILED"
|
|
) {
|
|
return "failed";
|
|
}
|
|
|
|
return "pending";
|
|
}
|
|
|
|
export function getKieErrorStatus(error: unknown, fallback = 502): number {
|
|
if (isJsonObject(error)) {
|
|
const status = Number(error.status);
|
|
if (Number.isFinite(status) && status > 0) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return fallback;
|
|
}
|
|
|
|
export function getKieErrorMessage(error: unknown, fallback: string): string {
|
|
if (error instanceof Error && error.message) {
|
|
return error.message;
|
|
}
|
|
|
|
if (isJsonObject(error) && typeof error.message === "string" && error.message.length > 0) {
|
|
return error.message;
|
|
}
|
|
|
|
return typeof error === "string" && error.length > 0 ? error : fallback;
|
|
}
|