@intuned/runtime-dev 0.1.0-test.28 → 0.1.0-test.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/WebTemplate/controllers/async.ts +52 -50
- package/WebTemplate/controllers/authSessions/create.ts +1 -5
- package/package.json +1 -1
- package/InterfaceTemplate/index.js +0 -1
- package/WebTemplate/accessKeyHelpers.js +0 -20
- package/WebTemplate/api.js +0 -48
- package/WebTemplate/app.js +0 -13
- package/WebTemplate/controllers/async.js +0 -78
- package/WebTemplate/controllers/authSessions/check.js +0 -44
- package/WebTemplate/controllers/authSessions/create.js +0 -69
- package/WebTemplate/controllers/authSessions/index.js +0 -25
- package/WebTemplate/controllers/authSessions/killOperation.js +0 -26
- package/WebTemplate/controllers/authSessions/resumeOperation.js +0 -42
- package/WebTemplate/controllers/authSessions/store.js +0 -1
- package/WebTemplate/controllers/controllers.js +0 -30
- package/WebTemplate/controllers/runApi/helpers.js +0 -90
- package/WebTemplate/controllers/runApi/index.js +0 -45
- package/WebTemplate/controllers/runApi/types.js +0 -1
- package/WebTemplate/controllers/traces.js +0 -108
- package/WebTemplate/features.js +0 -6
- package/WebTemplate/headers.js +0 -6
- package/WebTemplate/index.playwright.js +0 -37
- package/WebTemplate/index.vanilla.js +0 -19
- package/WebTemplate/jobs.js +0 -259
- package/WebTemplate/shutdown.js +0 -51
- package/WebTemplate/utils.js +0 -189
- package/api/authed.js +0 -6
- package/api/test.js +0 -3
- package/api/test2.js +0 -17
- package/auth-sessions/check.js +0 -6
- package/auth-sessions/create.js +0 -20
|
@@ -40,59 +40,61 @@ export async function runEndpointAsync<_Parameters extends any[], _Result>(
|
|
|
40
40
|
} catch (e: any) {
|
|
41
41
|
console.error(`Error running ${requestId} in async mode:`, e);
|
|
42
42
|
({ status, body } = getErrorResponse(e));
|
|
43
|
-
} finally {
|
|
44
|
-
AsyncRunEndpointController.removeRequest(taskToken);
|
|
45
|
-
}
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
44
|
+
// report result
|
|
45
|
+
console.log("Reporting result for", requestId);
|
|
46
|
+
try {
|
|
47
|
+
// `retry` will keep retrying any errors unless they are thrown through calling `bail`
|
|
48
|
+
await retry(
|
|
49
|
+
async (bail: (e: Error) => void) => {
|
|
50
|
+
const response = await callBackendFunctionWithToken(
|
|
51
|
+
"run/reportResult",
|
|
52
|
+
{
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: {
|
|
55
|
+
"Content-Type": "application/json",
|
|
56
|
+
"fly-instance-id": process.env.FLY_ALLOC_ID ?? "",
|
|
57
|
+
},
|
|
58
|
+
body: JSON.stringify({
|
|
59
|
+
status,
|
|
60
|
+
body,
|
|
61
|
+
startTime,
|
|
62
|
+
taskToken,
|
|
63
|
+
}),
|
|
64
|
+
}
|
|
65
|
+
).catch((e) => {
|
|
66
|
+
const message = `Reporting result failed for ${requestId}, error: ${e.message}`;
|
|
67
|
+
console.error(message);
|
|
68
|
+
throw e;
|
|
69
|
+
});
|
|
70
|
+
if (!response.ok) {
|
|
71
|
+
// Do not retry unauthenticated, forbidden, not found or too large responses
|
|
72
|
+
if ([401, 403, 404, 413].includes(response.status)) {
|
|
73
|
+
const message = `Reporting result failed for ${requestId} (non-retryable), status ${response.status}`;
|
|
74
|
+
console.error(message);
|
|
75
|
+
bail(new Error(message));
|
|
76
|
+
}
|
|
77
|
+
// retry other errors (such as 502)
|
|
78
|
+
const message = `Reporting result failed for ${requestId}, status ${response.status}`;
|
|
79
|
+
console.error(message);
|
|
80
|
+
throw new Error(message);
|
|
67
81
|
}
|
|
68
|
-
);
|
|
69
|
-
if (!response.ok) {
|
|
70
|
-
// Do not retry unauthenticated, forbidden, not found or too large responses
|
|
71
|
-
if ([401, 403, 404, 413].includes(response.status)) {
|
|
72
|
-
bail(
|
|
73
|
-
new Error(
|
|
74
|
-
`Reporting result failed for ${requestId} (non-retryable), status ${response.status}`
|
|
75
|
-
)
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
// retry other errors (such as 502)
|
|
79
|
-
throw new Error(
|
|
80
|
-
`Reporting result failed for ${requestId}, status ${response.status}`
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
83
|
+
return response;
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
retries: 5,
|
|
87
|
+
factor: 2,
|
|
88
|
+
maxTimeout: 1000 * 60, // 1 minute
|
|
89
|
+
minTimeout: 1000 * 5, // 5 seconds
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
console.log("Reported result for", requestId);
|
|
93
|
+
} catch (e: any) {
|
|
94
|
+
// ignore
|
|
95
|
+
}
|
|
96
|
+
} finally {
|
|
97
|
+
AsyncRunEndpointController.removeRequest(taskToken);
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
await ShutdownController.instance.checkForShutdown();
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { authSessionsContextsStore } from "./store";
|
|
2
2
|
import { getTraceFilePath, isHeadless, importModule } from "../../utils";
|
|
3
3
|
import * as fs from "fs-extra";
|
|
4
|
-
import {
|
|
5
|
-
runApiGenerator,
|
|
6
|
-
type RunApiResult,
|
|
7
|
-
type RunApiResultWithSessionOk,
|
|
8
|
-
} from "@intuned/runtime/dist/common/runApi";
|
|
4
|
+
import { runApiGenerator } from "@intuned/runtime/dist/common/runApi";
|
|
9
5
|
import type { RequestMoreInfoDetails } from "@intuned/runtime/dist/runtime";
|
|
10
6
|
|
|
11
7
|
export async function createAuthSession({
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { createHash } from "crypto";
|
|
2
|
-
function hashToken(token) {
|
|
3
|
-
// This has to match the logic from the workflow that saves adds the token to fly io App.
|
|
4
|
-
return createHash("sha256").update(token).digest("hex");
|
|
5
|
-
}
|
|
6
|
-
export const accessKeyValidatorMiddleware = (req, res, next) => {
|
|
7
|
-
const authHeader = req.headers.authorization;
|
|
8
|
-
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
9
|
-
return res.status(401).send("Unauthorized");
|
|
10
|
-
}
|
|
11
|
-
const token = authHeader.split(" ")[1];
|
|
12
|
-
// Create a hash of the provided token
|
|
13
|
-
const hashedToken = hashToken(token);
|
|
14
|
-
const hashedTokenFromEnv = process.env.HASHED_ACCESS_KEY;
|
|
15
|
-
if (hashedToken !== hashedTokenFromEnv) {
|
|
16
|
-
console.log("Token mismatch", hashedToken, hashedTokenFromEnv);
|
|
17
|
-
return res.status(401).send("Unauthorized");
|
|
18
|
-
}
|
|
19
|
-
next();
|
|
20
|
-
};
|
package/WebTemplate/api.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { errorRetryMiddleware, proxyToUrl, isJobRunMachine, } from "./utils";
|
|
2
|
-
import { accessKeyValidatorMiddleware } from "./accessKeyHelpers";
|
|
3
|
-
import { runWithContext } from "@intuned/runtime";
|
|
4
|
-
import { createAuthSessionController, createAuthSessionAsyncController, resumeAuthSessionOperationController, resumeAuthSessionOperationAsyncController, killAuthSessionOperationController, checkAuthSessionController, checkAuthSessionAsyncController, } from "./controllers/authSessions";
|
|
5
|
-
import { app } from "./app";
|
|
6
|
-
import { getActiveAsyncEndpointController, runApiAsyncController, runApiController, } from "./controllers/runApi";
|
|
7
|
-
import { uploadTraceController, deleteTraceController, } from "./controllers/traces";
|
|
8
|
-
import { RUN_ID_HEADER, JOB_ID_HEADER, JOB_RUN_ID_HEADER, QUEUE_ID_HEADER, } from "./headers";
|
|
9
|
-
import { FEATURES } from "./features";
|
|
10
|
-
if (!isJobRunMachine()) {
|
|
11
|
-
app.use((req, _, next) => {
|
|
12
|
-
const runId = req.headers[RUN_ID_HEADER];
|
|
13
|
-
const jobId = req.headers[JOB_ID_HEADER];
|
|
14
|
-
const jobRunId = req.headers[JOB_RUN_ID_HEADER];
|
|
15
|
-
const queueId = req.headers[QUEUE_ID_HEADER];
|
|
16
|
-
const proxy = req?.body?.proxy
|
|
17
|
-
? proxyToUrl(req.body.proxy)
|
|
18
|
-
: undefined;
|
|
19
|
-
const contextData = {
|
|
20
|
-
runId: runId ?? "",
|
|
21
|
-
jobId,
|
|
22
|
-
jobRunId,
|
|
23
|
-
queueId,
|
|
24
|
-
proxy,
|
|
25
|
-
...(req?.body?.executionContext ?? {}),
|
|
26
|
-
};
|
|
27
|
-
runWithContext(contextData, next);
|
|
28
|
-
});
|
|
29
|
-
app.get("/api/protected/health", accessKeyValidatorMiddleware, async (req, res) => {
|
|
30
|
-
res.status(200).json({ status: "ok" });
|
|
31
|
-
});
|
|
32
|
-
app.post("/api/auth-session/create", accessKeyValidatorMiddleware, errorRetryMiddleware(createAuthSessionController));
|
|
33
|
-
app.post("/api/auth-session-async/create", accessKeyValidatorMiddleware, errorRetryMiddleware(createAuthSessionAsyncController));
|
|
34
|
-
app.post("/api/auth-session/check", accessKeyValidatorMiddleware, errorRetryMiddleware(checkAuthSessionController));
|
|
35
|
-
app.post("/api/auth-session-async/check", accessKeyValidatorMiddleware, errorRetryMiddleware(checkAuthSessionAsyncController));
|
|
36
|
-
app.post("/api/auth-session/kill", accessKeyValidatorMiddleware, errorRetryMiddleware(killAuthSessionOperationController));
|
|
37
|
-
app.post("/api/auth-session/resume", accessKeyValidatorMiddleware, errorRetryMiddleware(resumeAuthSessionOperationController));
|
|
38
|
-
app.post("/api/auth-session-async/resume", accessKeyValidatorMiddleware, errorRetryMiddleware(resumeAuthSessionOperationAsyncController));
|
|
39
|
-
app.post("/api/run/*", accessKeyValidatorMiddleware, errorRetryMiddleware(runApiController));
|
|
40
|
-
app.post("/api/run-async/start/*", accessKeyValidatorMiddleware, errorRetryMiddleware(runApiAsyncController) // todo: this probably needs changing
|
|
41
|
-
);
|
|
42
|
-
app.get("/api/run-async/count", accessKeyValidatorMiddleware, getActiveAsyncEndpointController);
|
|
43
|
-
app.post("/api/trace/upload/:runId", accessKeyValidatorMiddleware, uploadTraceController);
|
|
44
|
-
app.post("/api/trace/delete/:runId", accessKeyValidatorMiddleware, deleteTraceController);
|
|
45
|
-
}
|
|
46
|
-
app.get("/api/features", accessKeyValidatorMiddleware, async (_, res) => {
|
|
47
|
-
res.status(200).json({ features: FEATURES });
|
|
48
|
-
});
|
package/WebTemplate/app.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { App } from "@tinyhttp/app";
|
|
2
|
-
import { json as parser } from "milliparsec";
|
|
3
|
-
export const port = process.env.PORT ? parseInt(process.env.PORT) : 4000;
|
|
4
|
-
export const app = new App();
|
|
5
|
-
app.use("/", parser());
|
|
6
|
-
// add header with flyio instance id where the request is served from
|
|
7
|
-
app.use((_, res, next) => {
|
|
8
|
-
res.setHeader("fly-instance-id", process.env.FLY_ALLOC_ID ?? "");
|
|
9
|
-
next();
|
|
10
|
-
});
|
|
11
|
-
app.get("/api/health", async (req, res) => {
|
|
12
|
-
res.status(200).json({ status: "ok" });
|
|
13
|
-
});
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { AsyncRunEndpointController, getErrorResponse } from "../utils";
|
|
2
|
-
import { backendFunctionsTokenManager, callBackendFunctionWithToken, } from "@intuned/runtime/dist/common/jwtTokenManager";
|
|
3
|
-
import retry from "async-retry";
|
|
4
|
-
import { ShutdownController } from "../shutdown";
|
|
5
|
-
export async function runEndpointAsync(handler, parameters, endpointParameters) {
|
|
6
|
-
const { functionsToken, taskToken, startTime, requestId = "endpoint", } = endpointParameters;
|
|
7
|
-
AsyncRunEndpointController.addRequest(taskToken);
|
|
8
|
-
backendFunctionsTokenManager.token = functionsToken;
|
|
9
|
-
let status, body;
|
|
10
|
-
try {
|
|
11
|
-
console.log("Running", requestId, "in async mode");
|
|
12
|
-
({ status, body } = await handler(...parameters));
|
|
13
|
-
console.log("Finished running", requestId, "in async mode");
|
|
14
|
-
}
|
|
15
|
-
catch (e) {
|
|
16
|
-
console.error(`Error running ${requestId} in async mode:`, e);
|
|
17
|
-
({ status, body } = getErrorResponse(e));
|
|
18
|
-
}
|
|
19
|
-
finally {
|
|
20
|
-
AsyncRunEndpointController.removeRequest(taskToken);
|
|
21
|
-
}
|
|
22
|
-
// report result
|
|
23
|
-
console.log("Reporting result for", requestId);
|
|
24
|
-
try {
|
|
25
|
-
// `retry` will keep retrying any errors unless they are thrown through calling `bail`
|
|
26
|
-
await retry(async (bail) => {
|
|
27
|
-
const response = await callBackendFunctionWithToken("run/reportResult", {
|
|
28
|
-
method: "POST",
|
|
29
|
-
headers: {
|
|
30
|
-
"Content-Type": "application/json",
|
|
31
|
-
"fly-instance-id": process.env.FLY_ALLOC_ID ?? "",
|
|
32
|
-
},
|
|
33
|
-
body: JSON.stringify({
|
|
34
|
-
status,
|
|
35
|
-
body,
|
|
36
|
-
startTime,
|
|
37
|
-
taskToken,
|
|
38
|
-
}),
|
|
39
|
-
});
|
|
40
|
-
if (!response.ok) {
|
|
41
|
-
// Do not retry unauthenticated, forbidden, not found or too large responses
|
|
42
|
-
if ([401, 403, 404, 413].includes(response.status)) {
|
|
43
|
-
bail(new Error(`Reporting result failed for ${requestId} (non-retryable), status ${response.status}`));
|
|
44
|
-
}
|
|
45
|
-
// retry other errors (such as 502)
|
|
46
|
-
throw new Error(`Reporting result failed for ${requestId}, status ${response.status}`);
|
|
47
|
-
}
|
|
48
|
-
return response;
|
|
49
|
-
}, {
|
|
50
|
-
retries: 5,
|
|
51
|
-
factor: 2,
|
|
52
|
-
maxTimeout: 1000 * 60, // 1 minute
|
|
53
|
-
minTimeout: 1000 * 5, // 5 seconds
|
|
54
|
-
});
|
|
55
|
-
console.log("Reported result for", requestId);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
console.log(e?.message ?? `Reporting result failed for ${requestId}`);
|
|
59
|
-
}
|
|
60
|
-
await ShutdownController.instance.checkForShutdown();
|
|
61
|
-
return { status, body };
|
|
62
|
-
}
|
|
63
|
-
export function makeAsyncEndpointController({ requestId, handler, parameters, }) {
|
|
64
|
-
return async (req, res) => {
|
|
65
|
-
const { taskToken, startTime, functionsToken } = req.body;
|
|
66
|
-
if (AsyncRunEndpointController.isRunning(taskToken)) {
|
|
67
|
-
res.status(409).json({ error: "Already running" });
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
void runEndpointAsync(handler, typeof parameters === "function" ? parameters(req) : parameters, {
|
|
71
|
-
taskToken,
|
|
72
|
-
startTime,
|
|
73
|
-
functionsToken,
|
|
74
|
-
requestId: typeof requestId === "function" ? requestId(req) : requestId,
|
|
75
|
-
});
|
|
76
|
-
res.status(202).json({});
|
|
77
|
-
};
|
|
78
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { readJSON } from "fs-extra";
|
|
2
|
-
import { isHeadless } from "../../utils";
|
|
3
|
-
import { runApi } from "@intuned/runtime/dist/common/runApi";
|
|
4
|
-
import { importModule } from "../../utils";
|
|
5
|
-
export async function checkAuthSession({ proxy, session, }) {
|
|
6
|
-
const isAuthSessionEnabled = (await readJSON("./Intuned.json")).authSessions
|
|
7
|
-
?.enabled;
|
|
8
|
-
if (!isAuthSessionEnabled) {
|
|
9
|
-
return {
|
|
10
|
-
status: 400,
|
|
11
|
-
body: {
|
|
12
|
-
error: "Invalid Request",
|
|
13
|
-
message: "auth sessions are not enabled",
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
const result = await runApi({
|
|
18
|
-
automationFunction: {
|
|
19
|
-
name: "auth-sessions/check",
|
|
20
|
-
},
|
|
21
|
-
runOptions: {
|
|
22
|
-
environment: "deployed",
|
|
23
|
-
headless: isHeadless(),
|
|
24
|
-
proxy,
|
|
25
|
-
},
|
|
26
|
-
auth: {
|
|
27
|
-
session: {
|
|
28
|
-
type: "state",
|
|
29
|
-
state: session,
|
|
30
|
-
},
|
|
31
|
-
runCheck: false,
|
|
32
|
-
},
|
|
33
|
-
importFunction: importModule,
|
|
34
|
-
});
|
|
35
|
-
if (result.isErr()) {
|
|
36
|
-
return result.error.apiResponse;
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
status: 200,
|
|
40
|
-
body: {
|
|
41
|
-
result: result.value.result,
|
|
42
|
-
},
|
|
43
|
-
};
|
|
44
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { authSessionsContextsStore } from "./store";
|
|
2
|
-
import { getTraceFilePath, isHeadless, importModule } from "../../utils";
|
|
3
|
-
import * as fs from "fs-extra";
|
|
4
|
-
import { runApiGenerator, } from "@intuned/runtime/dist/common/runApi";
|
|
5
|
-
export async function createAuthSession({ parameters, operationId, proxy, saveTrace, }) {
|
|
6
|
-
const isAuthSessionEnabled = (await fs.readJSON("./Intuned.json"))
|
|
7
|
-
.authSessions?.enabled;
|
|
8
|
-
if (!isAuthSessionEnabled) {
|
|
9
|
-
return {
|
|
10
|
-
status: 400,
|
|
11
|
-
body: {
|
|
12
|
-
error: "Invalid Request",
|
|
13
|
-
message: "auth sessions are not enabled",
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
if (authSessionsContextsStore.has(operationId)) {
|
|
18
|
-
return {
|
|
19
|
-
status: 400,
|
|
20
|
-
body: {
|
|
21
|
-
error: "Invalid Request",
|
|
22
|
-
message: "operation id already exists, please use a different one, or kill the existing operation, and try again",
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
const headless = isHeadless();
|
|
27
|
-
const abortController = new AbortController();
|
|
28
|
-
const createGenerator = runApiGenerator({
|
|
29
|
-
automationFunction: {
|
|
30
|
-
name: "auth-sessions/create",
|
|
31
|
-
params: parameters,
|
|
32
|
-
},
|
|
33
|
-
tracing: saveTrace
|
|
34
|
-
? {
|
|
35
|
-
enabled: true,
|
|
36
|
-
filePath: getTraceFilePath(operationId),
|
|
37
|
-
}
|
|
38
|
-
: { enabled: false },
|
|
39
|
-
runOptions: {
|
|
40
|
-
environment: "deployed",
|
|
41
|
-
headless,
|
|
42
|
-
proxy,
|
|
43
|
-
},
|
|
44
|
-
abortSignal: abortController.signal,
|
|
45
|
-
retrieveSession: true,
|
|
46
|
-
importFunction: importModule,
|
|
47
|
-
});
|
|
48
|
-
const result = await createGenerator.next();
|
|
49
|
-
if (result.done === true) {
|
|
50
|
-
const r = result.value;
|
|
51
|
-
if (r.isErr()) {
|
|
52
|
-
return r.error.apiResponse;
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
status: 200,
|
|
56
|
-
body: { ...r.value.session, status: 200 },
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
authSessionsContextsStore.set(operationId, {
|
|
60
|
-
done: false,
|
|
61
|
-
generator: createGenerator,
|
|
62
|
-
requestInfo: result.value,
|
|
63
|
-
abortController,
|
|
64
|
-
});
|
|
65
|
-
return {
|
|
66
|
-
status: 200,
|
|
67
|
-
body: result.value,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { createAuthSession } from "./create";
|
|
2
|
-
import { makeEndpointControllers } from "../controllers";
|
|
3
|
-
import { checkAuthSession } from "./check";
|
|
4
|
-
import { killAuthSessionOperation } from "./killOperation";
|
|
5
|
-
import { resumeAuthSessionOperation } from "./resumeOperation";
|
|
6
|
-
export const { sync: createAuthSessionController, async: createAuthSessionAsyncController, } = makeEndpointControllers({
|
|
7
|
-
requestId: (req) => `createAuthSession ${req.body.operationId}`,
|
|
8
|
-
handler: createAuthSession,
|
|
9
|
-
parameters: (req) => [req.body],
|
|
10
|
-
});
|
|
11
|
-
export const { sync: checkAuthSessionController, async: checkAuthSessionAsyncController, } = makeEndpointControllers({
|
|
12
|
-
requestId: "checkAuthSession",
|
|
13
|
-
handler: checkAuthSession,
|
|
14
|
-
parameters: (req) => [req.body],
|
|
15
|
-
});
|
|
16
|
-
export const { sync: killAuthSessionOperationController, async: killAuthSessionOperationAsyncController, } = makeEndpointControllers({
|
|
17
|
-
requestId: (req) => `killAuthSessionOperation ${req.body.operationId}`,
|
|
18
|
-
handler: killAuthSessionOperation,
|
|
19
|
-
parameters: (req) => [req.body],
|
|
20
|
-
});
|
|
21
|
-
export const { sync: resumeAuthSessionOperationController, async: resumeAuthSessionOperationAsyncController, } = makeEndpointControllers({
|
|
22
|
-
requestId: (req) => `resumeAuthSessionOperation ${req.body.operationId}`,
|
|
23
|
-
handler: resumeAuthSessionOperation,
|
|
24
|
-
parameters: (req) => [req.body],
|
|
25
|
-
});
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { authSessionsContextsStore } from "./store";
|
|
2
|
-
export async function killAuthSessionOperation({ operationId, }) {
|
|
3
|
-
const operation = authSessionsContextsStore.get(operationId);
|
|
4
|
-
if (!operation) {
|
|
5
|
-
return {
|
|
6
|
-
status: 200,
|
|
7
|
-
body: {
|
|
8
|
-
done: true,
|
|
9
|
-
},
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
operation.abortController.abort();
|
|
14
|
-
authSessionsContextsStore.delete(operationId);
|
|
15
|
-
return { status: 200, body: { done: true } };
|
|
16
|
-
}
|
|
17
|
-
catch (error) {
|
|
18
|
-
return {
|
|
19
|
-
status: 500,
|
|
20
|
-
body: {
|
|
21
|
-
error,
|
|
22
|
-
message: "the server failed to kill the operation",
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { authSessionsContextsStore } from "./store";
|
|
2
|
-
export async function resumeAuthSessionOperation({ operationId, input, }) {
|
|
3
|
-
const operation = authSessionsContextsStore.get(operationId);
|
|
4
|
-
if (!operation) {
|
|
5
|
-
return {
|
|
6
|
-
status: 404,
|
|
7
|
-
body: {
|
|
8
|
-
error: "Invalid Request",
|
|
9
|
-
message: "operation not found",
|
|
10
|
-
},
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
if (operation.requestInfo.requestType === "multiple_choice" &&
|
|
14
|
-
!operation.requestInfo.choices.includes(input)) {
|
|
15
|
-
return {
|
|
16
|
-
status: 400,
|
|
17
|
-
body: {
|
|
18
|
-
error: "Invalid Request",
|
|
19
|
-
message: "input does not match any of the choices",
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
const result = await operation.generator.next(input);
|
|
24
|
-
if (result.done) {
|
|
25
|
-
authSessionsContextsStore.delete(operationId);
|
|
26
|
-
if (result.value.isErr()) {
|
|
27
|
-
return result.value.error.apiResponse;
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
status: 200,
|
|
31
|
-
body: result.value.value.session,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
authSessionsContextsStore.set(operationId, {
|
|
35
|
-
...operation,
|
|
36
|
-
requestInfo: result.value,
|
|
37
|
-
});
|
|
38
|
-
return {
|
|
39
|
-
status: 200,
|
|
40
|
-
body: result.value,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const authSessionsContextsStore = new Map();
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { AsyncRunEndpointController } from "../utils";
|
|
2
|
-
import { runEndpointAsync } from "./async";
|
|
3
|
-
export function makeSyncEndpointController({ handler, parameters, }) {
|
|
4
|
-
return async (req, res) => {
|
|
5
|
-
const { status, body } = await handler(...(typeof parameters === "function" ? parameters(req) : parameters));
|
|
6
|
-
res.status(status).json(body);
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
export function makeAsyncEndpointController({ requestId, handler, parameters, }) {
|
|
10
|
-
return async (req, res) => {
|
|
11
|
-
const { taskToken, startTime, functionsToken } = req.body;
|
|
12
|
-
if (AsyncRunEndpointController.isRunning(taskToken)) {
|
|
13
|
-
res.status(409).json({ error: "Already running" });
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
void runEndpointAsync(handler, typeof parameters === "function" ? parameters(req) : parameters, {
|
|
17
|
-
taskToken,
|
|
18
|
-
startTime,
|
|
19
|
-
functionsToken,
|
|
20
|
-
requestId: typeof requestId === "function" ? requestId(req) : requestId,
|
|
21
|
-
});
|
|
22
|
-
res.status(202).json({});
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export function makeEndpointControllers({ requestId, handler, parameters, }) {
|
|
26
|
-
return {
|
|
27
|
-
sync: makeSyncEndpointController({ handler, parameters }),
|
|
28
|
-
async: makeAsyncEndpointController({ requestId, handler, parameters }),
|
|
29
|
-
};
|
|
30
|
-
}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { getTraceFilePath, importModule, waitWithExtendableTimeout, } from "../../utils";
|
|
2
|
-
import * as fs from "fs-extra";
|
|
3
|
-
import { getExecutionContext } from "@intuned/runtime";
|
|
4
|
-
import { backendFunctionsTokenManager } from "@intuned/runtime/dist/common/jwtTokenManager";
|
|
5
|
-
import { runApi as runApiInternal } from "@intuned/runtime/dist/common/runApi";
|
|
6
|
-
export async function runApi({ session, params, proxy, functionsToken, runId, attemptNumber, functionName, shouldSaveTrace, headless = true, }) {
|
|
7
|
-
const isAuthSessionEnabled = (await fs.readJSON("./Intuned.json"))
|
|
8
|
-
.authSessions?.enabled;
|
|
9
|
-
if (!runId) {
|
|
10
|
-
return {
|
|
11
|
-
status: 400,
|
|
12
|
-
body: {
|
|
13
|
-
error: "runId header not provided",
|
|
14
|
-
message: "Please add provide run id to header",
|
|
15
|
-
},
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
backendFunctionsTokenManager.token = functionsToken;
|
|
19
|
-
// handle timeout
|
|
20
|
-
const requestTimeout = +(process.env.REQUEST_TIMEOUT ?? 600) * 1000;
|
|
21
|
-
getExecutionContext().timeoutInfo = {
|
|
22
|
-
...(getExecutionContext()?.timeoutInfo ?? {}),
|
|
23
|
-
timeoutDuration: requestTimeout,
|
|
24
|
-
};
|
|
25
|
-
async function handleTimeout() {
|
|
26
|
-
console.log("timeout triggered");
|
|
27
|
-
return {
|
|
28
|
-
status: 508,
|
|
29
|
-
body: {
|
|
30
|
-
error: "TimeoutError",
|
|
31
|
-
message: "The request timed out",
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
const abortController = new AbortController();
|
|
36
|
-
const resultWithTimeout = await waitWithExtendableTimeout({
|
|
37
|
-
promise: runApiInternal({
|
|
38
|
-
automationFunction: {
|
|
39
|
-
name: `api/${functionName}`,
|
|
40
|
-
params,
|
|
41
|
-
},
|
|
42
|
-
auth: isAuthSessionEnabled
|
|
43
|
-
? {
|
|
44
|
-
session: {
|
|
45
|
-
type: "state",
|
|
46
|
-
state: session,
|
|
47
|
-
},
|
|
48
|
-
runCheck: isAuthSessionEnabled,
|
|
49
|
-
}
|
|
50
|
-
: undefined,
|
|
51
|
-
runOptions: {
|
|
52
|
-
environment: "deployed",
|
|
53
|
-
headless,
|
|
54
|
-
proxy,
|
|
55
|
-
},
|
|
56
|
-
tracing: shouldSaveTrace
|
|
57
|
-
? {
|
|
58
|
-
enabled: true,
|
|
59
|
-
filePath: getTraceFilePath(runId, attemptNumber),
|
|
60
|
-
}
|
|
61
|
-
: { enabled: false },
|
|
62
|
-
functionsToken,
|
|
63
|
-
abortSignal: abortController.signal,
|
|
64
|
-
importFunction: importModule,
|
|
65
|
-
}),
|
|
66
|
-
initialTimeout: requestTimeout,
|
|
67
|
-
abortController,
|
|
68
|
-
});
|
|
69
|
-
if (resultWithTimeout.timedOut === true) {
|
|
70
|
-
return await handleTimeout();
|
|
71
|
-
}
|
|
72
|
-
const { result } = resultWithTimeout;
|
|
73
|
-
if (result.isErr()) {
|
|
74
|
-
if (result.error.code === "AbortedError") {
|
|
75
|
-
return await handleTimeout();
|
|
76
|
-
}
|
|
77
|
-
return result.error.apiResponse;
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
status: 200,
|
|
81
|
-
body: {
|
|
82
|
-
status: 200,
|
|
83
|
-
result: result.value.result,
|
|
84
|
-
payloadToAppend: result.value.extendedPayloads?.map(({ api, parameters }) => ({
|
|
85
|
-
apiName: api,
|
|
86
|
-
parameters,
|
|
87
|
-
})),
|
|
88
|
-
},
|
|
89
|
-
};
|
|
90
|
-
}
|