Add multi-user automation features and per-user error tracking. - Database migrations: add workflow_configs/workflow_runs (004), app_errors (005), pipeline_configs/pipeline_runs (006), and add user_token_hash to app_errors (007). - Backend: introduce per-request token handling (X-API-Token) via app.api.deps and update many API routes (auth, automations, bank, characters, dashboard, events, exchange, logs) to use user-scoped Artifacts client and character scoping. Auth endpoints no longer store tokens server-side (validate-only); clear is a no-op on server. - New Errors API and services: endpoint to list, filter, resolve, and report errors scoped to the requesting user; add error models, schemas, middleware/error handler and error_service for recording/hashing tokens. - Pipelines & Workflows: add API routers, models, schemas and engine modules (pipeline/worker/coordinator, workflow runner/conditions) and action_executor updates to support workflow/pipeline execution. - Logs: logs endpoint now prefers fetching recent action logs from the game API (with fallback to local DB), supports paging and filtering, and scopes results to the user. - Frontend: add pipeline/workflow builders, lists, progress components and hooks (use-errors, use-pipelines, use-workflows), sentry client config, and updates to API client/constants/types. - Misc: add middleware error handler, various engine strategy tweaks, tests adjusted. Overall this change enables per-user API tokens, scopes DB queries to each user, introduces pipelines/workflows runtime support, and centralizes application error tracking.
140 lines
3.2 KiB
TypeScript
140 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import {
|
|
getPipelines,
|
|
getPipeline,
|
|
getPipelineStatuses,
|
|
getPipelineLogs,
|
|
createPipeline,
|
|
updatePipeline,
|
|
deletePipeline,
|
|
startPipeline,
|
|
stopPipeline,
|
|
pausePipeline,
|
|
resumePipeline,
|
|
} from "@/lib/api-client";
|
|
import type {
|
|
PipelineConfig,
|
|
PipelineRun,
|
|
PipelineStatus,
|
|
AutomationLog,
|
|
} from "@/lib/types";
|
|
|
|
export function usePipelines() {
|
|
return useQuery<PipelineConfig[]>({
|
|
queryKey: ["pipelines"],
|
|
queryFn: getPipelines,
|
|
refetchInterval: 5000,
|
|
});
|
|
}
|
|
|
|
export function usePipeline(id: number) {
|
|
return useQuery<{ config: PipelineConfig; runs: PipelineRun[] }>({
|
|
queryKey: ["pipeline", id],
|
|
queryFn: () => getPipeline(id),
|
|
refetchInterval: 5000,
|
|
enabled: id > 0,
|
|
});
|
|
}
|
|
|
|
export function usePipelineStatuses() {
|
|
return useQuery<PipelineStatus[]>({
|
|
queryKey: ["pipelineStatuses"],
|
|
queryFn: getPipelineStatuses,
|
|
refetchInterval: 3000,
|
|
});
|
|
}
|
|
|
|
export function usePipelineLogs(id: number) {
|
|
return useQuery<AutomationLog[]>({
|
|
queryKey: ["pipelineLogs", id],
|
|
queryFn: () => getPipelineLogs(id),
|
|
refetchInterval: 3000,
|
|
enabled: id > 0,
|
|
});
|
|
}
|
|
|
|
export function useCreatePipeline() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (data: {
|
|
name: string;
|
|
description?: string;
|
|
stages: Record<string, unknown>[];
|
|
loop?: boolean;
|
|
max_loops?: number;
|
|
}) => createPipeline(data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ["pipelines"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdatePipeline() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: ({
|
|
id,
|
|
data,
|
|
}: {
|
|
id: number;
|
|
data: Partial<PipelineConfig>;
|
|
}) => updatePipeline(id, data),
|
|
onSuccess: (_data, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: ["pipelines"] });
|
|
queryClient.invalidateQueries({
|
|
queryKey: ["pipeline", variables.id],
|
|
});
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeletePipeline() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: (id: number) => deletePipeline(id),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ["pipelines"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useControlPipeline() {
|
|
const queryClient = useQueryClient();
|
|
|
|
return useMutation({
|
|
mutationFn: async ({
|
|
id,
|
|
action,
|
|
}: {
|
|
id: number;
|
|
action: "start" | "stop" | "pause" | "resume";
|
|
}) => {
|
|
switch (action) {
|
|
case "start":
|
|
await startPipeline(id);
|
|
return;
|
|
case "stop":
|
|
return stopPipeline(id);
|
|
case "pause":
|
|
return pausePipeline(id);
|
|
case "resume":
|
|
return resumePipeline(id);
|
|
}
|
|
},
|
|
onSuccess: (_data, variables) => {
|
|
queryClient.invalidateQueries({ queryKey: ["pipelines"] });
|
|
queryClient.invalidateQueries({
|
|
queryKey: ["pipeline", variables.id],
|
|
});
|
|
queryClient.invalidateQueries({ queryKey: ["pipelineStatuses"] });
|
|
queryClient.invalidateQueries({
|
|
queryKey: ["pipelineLogs", variables.id],
|
|
});
|
|
},
|
|
});
|
|
}
|