mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 00:52:50 +00:00
125 lines
3.1 KiB
TypeScript
125 lines
3.1 KiB
TypeScript
import {
|
|
UseQueryOptions,
|
|
UseMutationOptions
|
|
} from "@tanstack/react-query";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// React Query shared types
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type QueryConfig<T> = Omit<
|
|
UseQueryOptions<T, Error, T, readonly unknown[]>,
|
|
"queryKey" | "queryFn"
|
|
>;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Endpoint interfaces
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface EndpointWithInput<TInput, TResponse> {
|
|
call(input: TInput): Promise<TResponse>;
|
|
queryKey(input: TInput): readonly unknown[];
|
|
queryOptions(
|
|
config: { input: TInput } & QueryConfig<TResponse>,
|
|
): UseQueryOptions<TResponse, Error, TResponse, readonly unknown[]>;
|
|
}
|
|
|
|
export interface EndpointWithoutInput<TResponse> {
|
|
call(): Promise<TResponse>;
|
|
queryKey(): readonly unknown[];
|
|
queryOptions(
|
|
config?: QueryConfig<TResponse>,
|
|
): UseQueryOptions<TResponse, Error, TResponse, readonly unknown[]>;
|
|
}
|
|
|
|
export type Endpoint<TInput, TResponse> = TInput extends void
|
|
? EndpointWithoutInput<TResponse>
|
|
: EndpointWithInput<TInput, TResponse>;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Endpoint builder
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export function endpoint<TInput, TResponse>(
|
|
service: string,
|
|
action: string,
|
|
execute: (input: TInput) => Promise<TResponse>,
|
|
queryKeyBuilder?: (input: TInput) => readonly unknown[],
|
|
) {
|
|
const buildKey = (input?: TInput): readonly unknown[] => {
|
|
if (queryKeyBuilder && input !== undefined) {
|
|
return queryKeyBuilder(input as TInput);
|
|
}
|
|
return input === undefined
|
|
? [service, action]
|
|
: [service, action, input];
|
|
};
|
|
|
|
const call = (input: TInput) => execute(input);
|
|
|
|
const queryKey = (input?: TInput) => buildKey(input);
|
|
|
|
const queryOptions = (
|
|
config?: { input?: TInput } & QueryConfig<TResponse>,
|
|
): UseQueryOptions<
|
|
TResponse,
|
|
Error,
|
|
TResponse,
|
|
readonly unknown[]
|
|
> => {
|
|
const { input, ...rest } = config ?? {};
|
|
|
|
return {
|
|
...rest,
|
|
queryKey: buildKey(input),
|
|
queryFn: () => execute(input as TInput),
|
|
};
|
|
};
|
|
|
|
const mutationOptions = (
|
|
config?: Omit<
|
|
UseMutationOptions<
|
|
TResponse,
|
|
Error,
|
|
TInput
|
|
>,
|
|
"mutationFn"
|
|
>,
|
|
): UseMutationOptions<
|
|
TResponse,
|
|
Error,
|
|
TInput
|
|
> => {
|
|
return {
|
|
...config,
|
|
mutationFn: (
|
|
variables: TInput,
|
|
): Promise<TResponse> =>
|
|
execute(variables),
|
|
};
|
|
};
|
|
|
|
return {
|
|
call,
|
|
queryKey,
|
|
queryOptions,
|
|
mutationOptions
|
|
};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helper utilities
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export function unwrap<T>(response: { data: T } | T): T {
|
|
if (
|
|
response &&
|
|
typeof response === "object" &&
|
|
"data" in (response as object)
|
|
) {
|
|
return (response as { data: T }).data;
|
|
}
|
|
|
|
return response as T;
|
|
}
|