- Introduced a new contract for script returns, requiring an object with `output`, `context`, and `skipRemaining` fields. - Refactored existing scripts to align with the new return structure, ensuring compatibility with the updated context management. - Added utility functions for normalizing context and step results, improving the handling of script execution context. - Updated various scripts (e.g., fetch-binary, fetch-html, fetch-http) to return structured output and context, enhancing data flow and usability. - Improved error handling for script returns, ensuring clearer feedback when invalid structures are returned. This update significantly enhances the flexibility and clarity of script interactions within workflows.
392 lines
11 KiB
JavaScript
392 lines
11 KiB
JavaScript
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
import { api } from "./client.js";
|
|
|
|
export function useBootstrap() {
|
|
return useQuery({
|
|
queryKey: ["bootstrap"],
|
|
queryFn: async () => (await api.get("/auth/bootstrap")).data,
|
|
});
|
|
}
|
|
|
|
export function useMe() {
|
|
return useQuery({
|
|
queryKey: ["me"],
|
|
queryFn: async () => {
|
|
try {
|
|
return (await api.get("/auth/me")).data;
|
|
} catch (err) {
|
|
if (err.response?.status === 401) return { user: null };
|
|
throw err;
|
|
}
|
|
},
|
|
retry: false,
|
|
});
|
|
}
|
|
|
|
export function useLogin() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (body) => (await api.post("/auth/login", body)).data,
|
|
onSuccess: (data) => {
|
|
qc.setQueryData(["me"], data);
|
|
qc.invalidateQueries({ queryKey: ["bootstrap"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRegister() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (body) => (await api.post("/auth/register", body)).data,
|
|
onSuccess: (data) => {
|
|
qc.setQueryData(["me"], data);
|
|
qc.invalidateQueries({ queryKey: ["bootstrap"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useLogout() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async () => (await api.post("/auth/logout")).data,
|
|
onSuccess: () => {
|
|
qc.setQueryData(["me"], null);
|
|
qc.clear();
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDashboard() {
|
|
return useQuery({
|
|
queryKey: ["dashboard"],
|
|
queryFn: async () => (await api.get("/dashboard")).data,
|
|
refetchInterval: (query) =>
|
|
query.state.data?.running?.length ? 4000 : 15000,
|
|
});
|
|
}
|
|
|
|
export function useScripts() {
|
|
return useQuery({
|
|
queryKey: ["scripts"],
|
|
queryFn: async () => (await api.get("/scripts")).data.scripts,
|
|
});
|
|
}
|
|
|
|
export function useScript(name, enabled = true) {
|
|
return useQuery({
|
|
queryKey: ["scripts", name],
|
|
queryFn: async () => (await api.get(`/scripts/${encodeURIComponent(name)}`)).data,
|
|
enabled: Boolean(name) && enabled,
|
|
});
|
|
}
|
|
|
|
export function useSaveScript() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ name, content }) =>
|
|
(await api.put(`/scripts/${encodeURIComponent(name)}`, { content })).data,
|
|
onSuccess: (_data, vars) => {
|
|
qc.invalidateQueries({ queryKey: ["scripts"] });
|
|
qc.invalidateQueries({ queryKey: ["scripts", vars.name] });
|
|
qc.invalidateQueries({ queryKey: ["dashboard"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteScript() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (name) =>
|
|
(await api.delete(`/scripts/${encodeURIComponent(name)}`)).data,
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ["scripts"] });
|
|
qc.invalidateQueries({ queryKey: ["dashboard"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDryRunScript() {
|
|
return useMutation({
|
|
mutationFn: async ({ name, content, data, context, config, owner }) =>
|
|
(
|
|
await api.post(`/scripts/${encodeURIComponent(name)}/dry-run`, {
|
|
content,
|
|
data,
|
|
context,
|
|
config,
|
|
owner,
|
|
})
|
|
).data,
|
|
});
|
|
}
|
|
|
|
export function useWorkflows(owner) {
|
|
return useQuery({
|
|
queryKey: ["workflows", owner ?? "all"],
|
|
queryFn: async () => {
|
|
const params = owner ? { owner } : {};
|
|
return (await api.get("/workflows", { params })).data.workflows;
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useWorkflow(owner, file, enabled = true) {
|
|
return useQuery({
|
|
queryKey: ["workflows", owner, file],
|
|
queryFn: async () =>
|
|
(await api.get(`/workflows/${encodeURIComponent(owner)}/${encodeURIComponent(file)}`))
|
|
.data,
|
|
enabled: Boolean(owner && file) && enabled,
|
|
});
|
|
}
|
|
|
|
export function useOwners() {
|
|
return useQuery({
|
|
queryKey: ["owners"],
|
|
queryFn: async () => (await api.get("/owners")).data.owners,
|
|
});
|
|
}
|
|
|
|
export function useSaveWorkflow() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ owner, file, content }) =>
|
|
(
|
|
await api.put(
|
|
`/workflows/${encodeURIComponent(owner)}/${encodeURIComponent(file)}`,
|
|
{ content },
|
|
)
|
|
).data,
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ["workflows"] });
|
|
qc.invalidateQueries({ queryKey: ["owners"] });
|
|
qc.invalidateQueries({ queryKey: ["dashboard"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useSetWorkflowEnabled() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ owner, file, enabled }) =>
|
|
(
|
|
await api.patch(
|
|
`/workflows/${encodeURIComponent(owner)}/${encodeURIComponent(file)}`,
|
|
{ enabled },
|
|
)
|
|
).data,
|
|
onSuccess: (_data, vars) => {
|
|
qc.invalidateQueries({ queryKey: ["workflows"] });
|
|
qc.invalidateQueries({ queryKey: ["workflows", vars.owner, vars.file] });
|
|
qc.invalidateQueries({ queryKey: ["dashboard"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteWorkflow() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ owner, file }) =>
|
|
(
|
|
await api.delete(
|
|
`/workflows/${encodeURIComponent(owner)}/${encodeURIComponent(file)}`,
|
|
)
|
|
).data,
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ["workflows"] });
|
|
qc.invalidateQueries({ queryKey: ["dashboard"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRunWorkflow() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ owner, file, data }) =>
|
|
(
|
|
await api.post(
|
|
`/workflows/${encodeURIComponent(owner)}/${encodeURIComponent(file)}/run`,
|
|
data !== undefined ? { data } : {},
|
|
)
|
|
).data,
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ["workflows"] });
|
|
qc.invalidateQueries({ queryKey: ["runs"] });
|
|
qc.invalidateQueries({ queryKey: ["dashboard"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useReregisterWorkflows() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async () => (await api.post("/workflows/reregister")).data,
|
|
onSuccess: () => {
|
|
qc.invalidateQueries({ queryKey: ["workflows"] });
|
|
qc.invalidateQueries({ queryKey: ["scripts"] });
|
|
qc.invalidateQueries({ queryKey: ["owners"] });
|
|
qc.invalidateQueries({ queryKey: ["dashboard"] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRuns(filters = {}) {
|
|
const { owner, workflow, status, limit } = filters;
|
|
return useQuery({
|
|
queryKey: ["runs", { owner, workflow, status, limit }],
|
|
queryFn: async () => {
|
|
const params = {};
|
|
if (owner) params.owner = owner;
|
|
if (workflow) params.workflow = workflow;
|
|
if (status) params.status = status;
|
|
if (limit) params.limit = limit;
|
|
return (await api.get("/runs", { params })).data.runs;
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useRun(id) {
|
|
return useQuery({
|
|
queryKey: ["runs", id],
|
|
queryFn: async () => (await api.get(`/runs/${encodeURIComponent(id)}`)).data,
|
|
enabled: Boolean(id),
|
|
refetchInterval: (query) =>
|
|
query.state.data?.status === "running" ? 2000 : false,
|
|
});
|
|
}
|
|
|
|
export function useUsers() {
|
|
return useQuery({
|
|
queryKey: ["users"],
|
|
queryFn: async () => (await api.get("/users")).data.users,
|
|
});
|
|
}
|
|
|
|
export function useCreateUser() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (body) => (await api.post("/users", body)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
|
|
});
|
|
}
|
|
|
|
export function useUpdateUser() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async ({ id, ...body }) =>
|
|
(await api.patch(`/users/${encodeURIComponent(id)}`, body)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
|
|
});
|
|
}
|
|
|
|
export function useDeleteUser() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (id) =>
|
|
(await api.delete(`/users/${encodeURIComponent(id)}`)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["users"] }),
|
|
});
|
|
}
|
|
|
|
export function useSecrets(owner) {
|
|
return useQuery({
|
|
queryKey: ["secrets", owner ?? "all"],
|
|
queryFn: async () => {
|
|
const params = owner ? { owner } : {};
|
|
return (await api.get("/secrets", { params })).data.secrets;
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpsertSecret() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (body) => (await api.put("/secrets", body)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["secrets"] }),
|
|
});
|
|
}
|
|
|
|
export function useDeleteSecret() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (id) =>
|
|
(await api.delete(`/secrets/${encodeURIComponent(id)}`)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["secrets"] }),
|
|
});
|
|
}
|
|
|
|
export function useKvNamespaces() {
|
|
return useQuery({
|
|
queryKey: ["kv", "namespaces"],
|
|
queryFn: async () => (await api.get("/kv/namespaces")).data.namespaces,
|
|
});
|
|
}
|
|
|
|
export function useKv(filters = {}) {
|
|
const { namespace, q, limit, offset } = filters;
|
|
return useQuery({
|
|
queryKey: ["kv", { namespace, q, limit, offset }],
|
|
queryFn: async () => {
|
|
const params = {};
|
|
if (namespace) params.namespace = namespace;
|
|
if (q) params.q = q;
|
|
if (limit != null) params.limit = limit;
|
|
if (offset != null) params.offset = offset;
|
|
return (await api.get("/kv", { params })).data;
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useHttpPages() {
|
|
return useQuery({
|
|
queryKey: ["http-pages"],
|
|
queryFn: async () => (await api.get("/http-pages")).data.pages,
|
|
});
|
|
}
|
|
|
|
export function useUpsertHttpPage() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (body) => (await api.put("/http-pages", body)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["http-pages"] }),
|
|
});
|
|
}
|
|
|
|
export function useDeleteHttpPage() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (id) =>
|
|
(await api.delete(`/http-pages/${encodeURIComponent(id)}`)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["http-pages"] }),
|
|
});
|
|
}
|
|
|
|
export function useHttpAuths() {
|
|
return useQuery({
|
|
queryKey: ["http-auths"],
|
|
queryFn: async () => (await api.get("/http-auths")).data.auths,
|
|
});
|
|
}
|
|
|
|
export function useUpsertHttpAuth() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (body) => (await api.put("/http-auths", body)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["http-auths"] }),
|
|
});
|
|
}
|
|
|
|
export function useDeleteHttpAuth() {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: async (id) =>
|
|
(await api.delete(`/http-auths/${encodeURIComponent(id)}`)).data,
|
|
onSuccess: () => qc.invalidateQueries({ queryKey: ["http-auths"] }),
|
|
});
|
|
}
|
|
|
|
/** Fetch plaintext literals only (not encrypted secrets). */
|
|
export async function fetchHttpAuthLiterals(name) {
|
|
return (await api.get(`/http-auths/${encodeURIComponent(name)}/reveal`)).data;
|
|
}
|