@airplane/views
Version:
A React library for building Airplane views. Views components are optimized in style and functionality to produce internal apps that are easy to build and maintain.
197 lines (196 loc) • 7.05 kB
JavaScript
import { useMutation } from "@tanstack/react-query";
import { useState, useContext, useEffect } from "react";
import { PERMISSIONS_GET } from "../../client/endpoints.js";
import { executeRunbook, isExecuteRunbookError } from "../../client/executeRunbook.js";
import { executeTaskBackground, executeTask, isExecuteTaskError } from "../../client/executeTask.js";
import { Fetcher } from "../../client/fetcher.js";
import { getSlug } from "../../components/query.js";
import { RequestDialogContext } from "../../components/requestDialog/RequestDialogProvider.js";
import { MISSING_EXECUTE_PERMISSIONS_ERROR_PREFIX } from "../../errors/formatErrors.js";
import { useRefetchTasks } from "./useRefetchTask.js";
import { RunnerScaleSignalContext } from "../context/RunnerScaleSignalProvider.js";
const useTaskOrRunbookMutation = (mutation) => {
const [executedRunID, setExecutedRunID] = useState();
const slug = getTaskOrRunbookSlug(mutation);
const {
params,
refetchTasks: refetchQuery
} = mutation.mutation;
const refetchTasks = useRefetchTasks();
const requestDialogContext = useContext(RequestDialogContext);
const {
createScaleSignal
} = useContext(RunnerScaleSignalContext);
useEffect(() => {
async function warmupTask() {
if (mutation.type !== "TASK") {
return;
}
await createScaleSignal({
signalKey: "views_warmup",
expirationDurationSeconds: 300,
taskSlug: slug
});
}
warmupTask();
}, [slug, mutation.type, createScaleSignal]);
const {
data,
error,
isLoading,
mutate
} = useMutation(async (opts) => {
switch (mutation.type) {
case "TASK": {
setExecutedRunID(void 0);
const runID = await executeTaskBackground(slug, "mutation", (opts == null ? void 0 : opts.params) ?? params);
if (typeof runID === "object") {
throw runID;
}
setExecutedRunID(runID);
const r = await executeTask(slug, "mutation", (opts == null ? void 0 : opts.params) ?? params, runID);
if (isExecuteTaskError(r)) {
throw r;
}
return r;
}
case "RUNBOOK": {
const r = await executeRunbook(slug, "mutation", (opts == null ? void 0 : opts.params) ?? params);
if (isExecuteRunbookError(r)) {
throw r;
}
return r;
}
default:
throw new Error("invalid mutation type");
}
}, {
onSuccess: (result, opts) => {
var _a, _b;
switch (mutation.type) {
case "TASK": {
result = result;
const taskOnSuccess = (opts == null ? void 0 : opts.onSuccess) ?? ((_a = mutation.mutation) == null ? void 0 : _a.onSuccess);
taskOnSuccess == null ? void 0 : taskOnSuccess(result.output, result.runID);
break;
}
case "RUNBOOK": {
result = result;
const runbookOnSuccess = (opts == null ? void 0 : opts.onSuccess) ?? ((_b = mutation.mutation) == null ? void 0 : _b.onSuccess);
runbookOnSuccess == null ? void 0 : runbookOnSuccess(result.sessionID);
break;
}
default:
throw new Error("invalid mutation type");
}
const refetch = (opts == null ? void 0 : opts.refetchTasks) ?? refetchQuery;
if (refetch) {
refetchTasks(refetch);
}
},
onError: async (e, opts) => {
var _a, _b;
if (e.error.type === "AIRPLANE_INTERNAL" && e.error.message.startsWith(MISSING_EXECUTE_PERMISSIONS_ERROR_PREFIX)) {
try {
const showRequestDialog = await shouldShowRequestDialog(slug, mutation.type);
if (showRequestDialog) {
requestDialogContext.setState({
params: (opts == null ? void 0 : opts.params) ?? params ?? {},
taskSlug: mutation.type === "TASK" ? slug : void 0,
runbookSlug: mutation.type === "RUNBOOK" ? slug : void 0,
opened: true
});
return;
}
} catch (shouldShowReqErr) {
if (shouldShowReqErr instanceof Error) {
e.error.message = `${e.error.message} (error checking request permissions: ${shouldShowReqErr.message})`;
} else {
e.error.message = `${e.error.message} (error checking request permissions: ${shouldShowReqErr})`;
}
}
}
switch (mutation.type) {
case "TASK": {
const taskOnError = (opts == null ? void 0 : opts.onError) ?? ((_a = mutation.mutation) == null ? void 0 : _a.onError);
const err = e;
taskOnError == null ? void 0 : taskOnError(err.output, err.error, err.runID);
return e;
}
case "RUNBOOK": {
const runbookOnError = (opts == null ? void 0 : opts.onError) ?? ((_b = mutation.mutation) == null ? void 0 : _b.onError);
const err = e;
runbookOnError == null ? void 0 : runbookOnError(err.error, err.sessionID);
return e;
}
default:
throw new Error("invalid mutation type");
}
}
});
switch (mutation.type) {
case "TASK": {
const taskData = data;
const taskError = error;
return {
type: mutation.type,
result: {
output: (taskData == null ? void 0 : taskData.output) ?? (taskError == null ? void 0 : taskError.output),
runID: executedRunID ?? (taskData == null ? void 0 : taskData.runID) ?? (taskError == null ? void 0 : taskError.runID),
loading: isLoading,
mutate,
error: taskError == null ? void 0 : taskError.error
}
};
}
case "RUNBOOK": {
const sessionData = data;
const sessionError = error;
return {
type: mutation.type,
result: {
sessionID: (sessionData == null ? void 0 : sessionData.sessionID) ?? (sessionError == null ? void 0 : sessionError.sessionID),
loading: isLoading,
mutate,
error: sessionError == null ? void 0 : sessionError.error
}
};
}
}
};
const shouldShowRequestDialog = async (slug, mutationType) => {
if (mutationType === "TASK") {
const fetcher = new Fetcher();
const result = await fetcher.get(PERMISSIONS_GET, {
task_slug: slug,
actions: ["tasks.request_run"]
});
if (result.resource["tasks.request_run"]) {
return true;
}
} else if (mutationType === "RUNBOOK") {
const fetcher = new Fetcher();
const result = await fetcher.get(PERMISSIONS_GET, {
runbook_slug: slug,
actions: ["trigger_requests.create"]
});
if (result.resource["trigger_requests.create"]) {
return true;
}
}
return false;
};
const getTaskOrRunbookSlug = (mutation) => {
switch (mutation.type) {
case "TASK":
return getSlug(mutation.mutation);
case "RUNBOOK":
return mutation.mutation.slug;
default:
throw new Error("invalid mutation type");
}
};
export {
useTaskOrRunbookMutation
};
//# sourceMappingURL=useTaskOrRunbookMutation.js.map