@intuned/runtime-dev 0.1.0-test.14 → 0.1.0-test.16

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.
Files changed (114) hide show
  1. package/.babelrc +1 -2
  2. package/WebTemplate/api.ts +90 -92
  3. package/WebTemplate/controllers/authSessions/create.ts +2 -2
  4. package/WebTemplate/controllers/authSessions/store.ts +1 -1
  5. package/WebTemplate/controllers/runApi/helpers.ts +14 -12
  6. package/WebTemplate/index.playwright.ts +32 -42
  7. package/WebTemplate/jobs.ts +13 -2
  8. package/WebTemplate/utils.ts +53 -1
  9. package/api/test2.ts +6 -1
  10. package/auth-sessions/check.ts +3 -1
  11. package/auth-sessions/create.ts +10 -10
  12. package/bin/intuned-api-run +1 -1
  13. package/bin/intuned-auth-session-check +1 -1
  14. package/bin/intuned-auth-session-create +1 -1
  15. package/bin/intuned-auth-session-load +1 -1
  16. package/bin/intuned-auth-session-refresh +1 -1
  17. package/bin/intuned-browser-save-state +1 -1
  18. package/bin/intuned-browser-start +1 -1
  19. package/bin/intuned-build +1 -1
  20. package/bin/intuned-ts-check +1 -1
  21. package/dist/commands/api/run.js +109 -170
  22. package/dist/commands/auth-sessions/load.js +28 -26
  23. package/dist/commands/auth-sessions/run-check.js +54 -53
  24. package/dist/commands/auth-sessions/run-create.js +93 -96
  25. package/dist/commands/browser/save-state.js +14 -16
  26. package/dist/commands/browser/start-browser.js +11 -11
  27. package/dist/commands/build.js +79 -109
  28. package/dist/commands/common/browserUtils.js +53 -51
  29. package/dist/commands/common/getFirstLineNumber.js +93 -93
  30. package/dist/commands/common/{getFirstLineNumber.test.ts → getFirstLineNumber.test.js} +53 -48
  31. package/dist/commands/common/sendMessageToClient.js +9 -4
  32. package/dist/commands/common/tsNodeImport.d.ts +1 -0
  33. package/dist/commands/common/tsNodeImport.js +18 -0
  34. package/dist/commands/common/utils/fileUtils.js +32 -22
  35. package/dist/commands/common/utils/settings.js +27 -19
  36. package/dist/commands/common/utils/unixSocket.js +43 -43
  37. package/dist/commands/common/utils/webTemplate.js +30 -28
  38. package/dist/commands/interface/run.js +162 -139
  39. package/dist/commands/ts-check.js +50 -50
  40. package/dist/common/Logger/Logger/index.js +55 -42
  41. package/dist/common/Logger/Logger/types.js +5 -1
  42. package/dist/common/Logger/index.js +55 -42
  43. package/dist/common/Logger/types.js +5 -1
  44. package/dist/common/asyncLocalStorage/index.js +16 -8
  45. package/dist/common/cleanEnvironmentVariables.js +16 -12
  46. package/dist/common/constants.js +7 -1
  47. package/dist/common/contextStorageStateHelpers.js +47 -38
  48. package/dist/common/getPlaywrightConstructs.js +178 -197
  49. package/dist/common/jwtTokenManager.js +76 -79
  50. package/dist/common/runApi/errors.js +159 -150
  51. package/dist/common/runApi/index.js +240 -232
  52. package/dist/common/runApi/types.d.ts +19 -5
  53. package/dist/common/runApi/types.js +53 -56
  54. package/dist/common/settingsSchema.js +15 -10
  55. package/dist/common/telemetry.js +28 -30
  56. package/dist/index.js +69 -4
  57. package/dist/runtime/RunError.js +18 -11
  58. package/dist/runtime/downloadDirectory.js +19 -13
  59. package/dist/runtime/enums.d.js +5 -0
  60. package/dist/runtime/enums.d.ts +11 -1
  61. package/dist/runtime/enums.js +18 -12
  62. package/dist/runtime/executionHelpers.test.js +53 -0
  63. package/dist/runtime/export.d.js +5 -0
  64. package/dist/runtime/export.d.ts +202 -1
  65. package/dist/runtime/extendPayload.js +21 -15
  66. package/dist/runtime/extendTimeout.js +28 -21
  67. package/dist/runtime/index.js +53 -6
  68. package/dist/runtime/requestMoreInfo.js +23 -16
  69. package/dist/runtime/runInfo.js +21 -14
  70. package/package.json +4 -7
  71. package/dist/commands/api/run.ts +0 -105
  72. package/dist/commands/auth-sessions/load.ts +0 -30
  73. package/dist/commands/auth-sessions/run-check.ts +0 -51
  74. package/dist/commands/auth-sessions/run-create.ts +0 -91
  75. package/dist/commands/browser/save-state.ts +0 -14
  76. package/dist/commands/browser/start-browser.ts +0 -11
  77. package/dist/commands/build.ts +0 -79
  78. package/dist/commands/common/browserUtils.ts +0 -45
  79. package/dist/commands/common/getDefaultExportFromFile.d.ts +0 -1
  80. package/dist/commands/common/getDefaultExportFromFile.js +0 -12
  81. package/dist/commands/common/getDefaultExportFromFile.ts +0 -11
  82. package/dist/commands/common/getFirstLineNumber.ts +0 -96
  83. package/dist/commands/common/sendMessageToClient.ts +0 -3
  84. package/dist/commands/common/utils/fileUtils.ts +0 -23
  85. package/dist/commands/common/utils/settings.ts +0 -22
  86. package/dist/commands/common/utils/unixSocket.ts +0 -38
  87. package/dist/commands/common/utils/webTemplate.ts +0 -23
  88. package/dist/commands/interface/run.ts +0 -156
  89. package/dist/commands/ts-check.ts +0 -51
  90. package/dist/common/Logger/Logger/index.ts +0 -53
  91. package/dist/common/Logger/Logger/types.ts +0 -1
  92. package/dist/common/Logger/index.ts +0 -53
  93. package/dist/common/Logger/types.ts +0 -1
  94. package/dist/common/asyncLocalStorage/index.ts +0 -9
  95. package/dist/common/cleanEnvironmentVariables.ts +0 -10
  96. package/dist/common/constants.ts +0 -1
  97. package/dist/common/contextStorageStateHelpers.ts +0 -43
  98. package/dist/common/getPlaywrightConstructs.ts +0 -182
  99. package/dist/common/jwtTokenManager.ts +0 -71
  100. package/dist/common/runApi/errors.ts +0 -154
  101. package/dist/common/runApi/index.ts +0 -253
  102. package/dist/common/runApi/types.ts +0 -43
  103. package/dist/common/settingsSchema.ts +0 -9
  104. package/dist/common/telemetry.ts +0 -23
  105. package/dist/index.ts +0 -4
  106. package/dist/runtime/RunError.ts +0 -12
  107. package/dist/runtime/downloadDirectory.ts +0 -13
  108. package/dist/runtime/enums.ts +0 -12
  109. package/dist/runtime/executionHelpers.test.ts +0 -51
  110. package/dist/runtime/extendPayload.ts +0 -15
  111. package/dist/runtime/extendTimeout.ts +0 -24
  112. package/dist/runtime/index.ts +0 -6
  113. package/dist/runtime/requestMoreInfo.ts +0 -18
  114. package/dist/runtime/runInfo.ts +0 -15
@@ -1,182 +0,0 @@
1
- import * as playwright from "@intuned/playwright-core";
2
- import { existsSync, mkdir, mkdtemp, rm, writeFile, readFile } from "fs-extra";
3
- import { setContextStorageState } from "./contextStorageStateHelpers.js";
4
- import { join } from "path";
5
- import path from "path";
6
- import * as fs from "fs-extra";
7
- import { getFullPathInProject } from "../commands/common/utils/fileUtils";
8
- import waitOn from "wait-on";
9
- import { getDownloadDirectoryPath } from "../runtime";
10
- import { fileURLToPath } from "url";
11
- async function createUserDirWithPreferences() {
12
- const playwrightTempDir = await mkdtemp("/tmp/pw-");
13
- const userDir = join(playwrightTempDir, "userdir");
14
- const defaultDir = join(userDir, "Default");
15
- await mkdir(defaultDir, {
16
- recursive: true
17
- });
18
- const preferences = {
19
- plugins: {
20
- always_open_pdf_externally: true
21
- }
22
- };
23
- await writeFile(join(defaultDir, "Preferences"), JSON.stringify(preferences));
24
- return userDir;
25
- }
26
- export async function getProductionPlaywrightConstructs({
27
- proxy,
28
- headless = true,
29
- storageState,
30
- downloadsPath
31
- }) {
32
- const extraArgs = ["--no-first-run", "--disable-sync", "--disable-translate", "--disable-features=TranslateUI", "--disable-features=NetworkService", "--lang=en"];
33
- if (headless) {
34
- extraArgs.push("--headless=new");
35
- }
36
- const executablePath = playwright.chromium.executablePath();
37
- const chromium127Path = executablePath.replace("chromium-1117", "chromium-1124");
38
- const isChrome127There = existsSync(chromium127Path);
39
- const userAgent = `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${isChrome127There ? 127 : 125}.0.0.0 Safari/537.36`;
40
- const userDataDir = await createUserDirWithPreferences();
41
- const context = await playwright.chromium.launchPersistentContext(userDataDir, {
42
- headless,
43
- ignoreDefaultArgs: [...getChromiumLaunchArgsToIgnore(), "--headless"],
44
- proxy,
45
- executablePath: isChrome127There ? chromium127Path : executablePath,
46
- args: extraArgs,
47
- downloadsPath,
48
- userAgent
49
- });
50
- context.once("close", async () => {
51
- try {
52
- await rm(userDataDir, {
53
- recursive: true,
54
- force: true,
55
- retryDelay: 1000,
56
- maxRetries: 5
57
- });
58
- } catch (error) {
59
- console.error("Failed to remove user data dir", error);
60
- }
61
- });
62
- if (storageState) {
63
- await loadSessionToContext({
64
- context,
65
- session: storageState
66
- });
67
- }
68
- const assetsFile = path.join(path.dirname(fileURLToPath(import.meta.url)), "./assets/browser_scripts.js");
69
- await context.addInitScript({
70
- path: assetsFile
71
- });
72
- let page = context.pages().at(0);
73
- if (page) {
74
- const scriptString = await readFile(assetsFile, "utf8");
75
- await page.evaluate(scriptString);
76
- } else {
77
- page = await context.newPage();
78
- }
79
- return {
80
- page,
81
- context
82
- };
83
- }
84
- const getChromiumLaunchArgsToIgnore = () => ["--disable-field-trial-config", "--disable-background-networking", "--enable-features=NetworkService,NetworkServiceInProcess", "--disable-background-timer-throttling", "--disable-backgrounding-occluded-windows", "--disable-back-forward-cache", "--disable-breakpad", "--disable-client-side-phishing-detection", "--disable-component-extensions-with-background-pages", "--disable-component-update", "--no-default-browser-check", "--disable-default-apps", "--disable-dev-shm-usage", "--disable-extensions", "--disable-features=ImprovedCookieControls,LazyFrameLoading,GlobalMediaControls,DestroyProfileOnBrowserClose,MediaRouter,DialMediaRouteProvider,AcceptCHFrame,AutoExpandDetailsElement,CertificateTransparencyComponentUpdater,AvoidUnnecessaryBeforeUnloadCheckSync,Translate,TranslateUI", "--allow-pre-commit-input", "--disable-hang-monitor", "--disable-ipc-flooding-protection", "--disable-prompt-on-repost", "--disable-renderer-backgrounding", "--force-color-profile=srgb", "--metrics-recording-only", "--no-first-run", "--enable-automation", "--password-store=basic", "--use-mock-keychain", "--no-service-autorun", "--export-tagged-pdf", "--enable-use-zoom-for-dsf=false"];
85
- export async function getPlaywrightConstructsForMode(mode, cdpAddress, authSession) {
86
- if (mode == "playwright-standalone") {
87
- if (!cdpAddress) {
88
- throw new Error("cdpAddress is required");
89
- }
90
- const {
91
- context
92
- } = await getRemotePlaywrightContext(cdpAddress);
93
- if (!context) {
94
- throw new Error("no context found");
95
- }
96
- const assetsFile = path.join(path.dirname(fileURLToPath(import.meta.url)), "./assets/browser_scripts.js");
97
- await context.addInitScript({
98
- path: assetsFile
99
- });
100
- const pages = await context.pages();
101
- let page = null;
102
- if (pages.length > 0) {
103
- page = pages[0];
104
- const scriptString = await fs.readFile(assetsFile, "utf8");
105
- await page.evaluate(scriptString);
106
- } else {
107
- page = await context.newPage();
108
- }
109
- if (authSession) {
110
- await loadSessionToContext({
111
- context,
112
- session: authSession
113
- });
114
- }
115
- return {
116
- page,
117
- context
118
- };
119
- }
120
- const downloadsPath = getDownloadDirectoryPath();
121
- if (mode === "playwright" || mode === "playwright-headless") {
122
- const productionConstructs = await getProductionPlaywrightConstructs({
123
- headless: mode === "playwright-headless",
124
- downloadsPath
125
- });
126
- if (authSession) {
127
- await loadSessionToContext({
128
- context: productionConstructs.context,
129
- session: authSession
130
- });
131
- }
132
- return {
133
- ...productionConstructs
134
- };
135
- }
136
- throw "invalid mode";
137
- }
138
- export async function loadSessionToContext({
139
- context,
140
- session
141
- }) {
142
- let sessionToLoad;
143
- if (session.type === "state") {
144
- sessionToLoad = session.state;
145
- } else {
146
- const fullPath = getFullPathInProject(session.path);
147
- sessionToLoad = await fs.readJson(fullPath);
148
- }
149
- await setContextStorageState(context, sessionToLoad);
150
- }
151
- export async function getRemotePlaywrightContext(cdpAddress) {
152
- const playwright = await import("@intuned/playwright-core");
153
- let browser = null;
154
- if (!cdpAddress) {
155
- throw new Error("cdpAddress is required");
156
- }
157
- const cdpAddressWithoutProtocol = cdpAddress.replace("http://", "").replace("https://", "").replace("localhost", "127.0.0.1");
158
- try {
159
- await waitOn({
160
- resources: [`http-get://${cdpAddressWithoutProtocol}/json/version`],
161
- delay: 100,
162
- interval: 100,
163
- timeout: 5000,
164
- tcpTimeout: 1000,
165
- window: 1000
166
- });
167
- } catch (error) {
168
- console.error("Failed to connect to the browser");
169
- process.exit(128 + 9);
170
- }
171
- try {
172
- browser = await playwright.chromium.connectOverCDP(cdpAddress);
173
- } catch (e) {
174
- console.log(e);
175
- throw new Error("failed to connect to the browser");
176
- }
177
- const context = browser.contexts()[0];
178
- return {
179
- browser,
180
- context
181
- };
182
- }
@@ -1,71 +0,0 @@
1
- import fetch from "cross-fetch";
2
- import * as jwt from "jsonwebtoken";
3
- import { err, ResultAsync } from "neverthrow";
4
- class JwtTokenManager {
5
- constructor(refreshTokenPath) {
6
- this.refreshTokenPath = refreshTokenPath;
7
- this._token = undefined;
8
- }
9
- get token() {
10
- return this._token;
11
- }
12
- set token(newToken) {
13
- if (this._token != newToken) {
14
- this._token = newToken;
15
- void this.scheduleTokenRefresh();
16
- }
17
- }
18
- get timeToRefresh() {
19
- if (!this._token) return;
20
- const payload = jwt.decode(this._token);
21
- if (!payload || typeof payload == "string") return;
22
- const expiry = payload.expiry;
23
- if (!expiry || typeof expiry !== "number") return;
24
- const timeWindow = 60 * 1000;
25
- const timeToRefresh = expiry - Date.now() - timeWindow;
26
- return Math.max(timeToRefresh, timeWindow);
27
- }
28
- async scheduleTokenRefresh() {
29
- var _process$env$RUN_ENVI;
30
- if (((_process$env$RUN_ENVI = process.env.RUN_ENVIRONMENT) === null || _process$env$RUN_ENVI === void 0 ? void 0 : _process$env$RUN_ENVI.toLowerCase()) !== "authoring") return;
31
- const timeToRefresh = this.timeToRefresh;
32
- if (timeToRefresh === undefined) return;
33
- if (this.tokenRefreshTimeout) clearTimeout(this.tokenRefreshTimeout);
34
- this.tokenRefreshTimeout = setTimeout(async () => {
35
- const result = await this.refreshToken();
36
- if (result && result.isErr()) {
37
- console.error(`[Internal Error] ${result.error}`);
38
- return;
39
- }
40
- await this.scheduleTokenRefresh();
41
- }, timeToRefresh);
42
- }
43
- async refreshToken() {
44
- var _process$env$RUN_ENVI2;
45
- if (((_process$env$RUN_ENVI2 = process.env.RUN_ENVIRONMENT) === null || _process$env$RUN_ENVI2 === void 0 ? void 0 : _process$env$RUN_ENVI2.toLowerCase()) !== "authoring") return;
46
- const res = await this.fetchWithToken(this.refreshTokenPath, {
47
- method: "GET"
48
- });
49
- if (res.status === 401) {
50
- return err("Unauthorized");
51
- }
52
- const jsonResult = await ResultAsync.fromPromise(res.json(), () => "not json");
53
- if (jsonResult.isErr()) return;
54
- const newToken = jsonResult.value.token;
55
- if (newToken) this._token = newToken;
56
- }
57
- fetchWithToken(...[input, init]) {
58
- const headers = new Headers(init === null || init === void 0 ? void 0 : init.headers);
59
- headers.set("Authorization", `Bearer ${this.token}`);
60
- return fetch(input, {
61
- ...init,
62
- headers
63
- });
64
- }
65
- }
66
- const backendFunctionsPath = `${process.env.FUNCTIONS_DOMAIN}/api/${process.env.INTUNED_WORKSPACE_ID}/functions/${process.env.INTUNED_INTEGRATION_ID}`;
67
- export const backendFunctionsTokenManager = new JwtTokenManager(`${backendFunctionsPath}/refreshBackendFunctionsToken`);
68
- backendFunctionsTokenManager.token = process.env.INTUNED_AUTHORING_SESSION_BACKEND_FUNCTIONS_TOKEN;
69
- export function callBackendFunctionWithToken(path, init) {
70
- return backendFunctionsTokenManager.fetchWithToken(`${backendFunctionsPath}/${path}`, init);
71
- }
@@ -1,154 +0,0 @@
1
- import { RunError } from "../../runtime";
2
- import * as playwright from "@intuned/playwright-core";
3
- export const apiNotFoundErrorCode = "APINotFoundError";
4
- export const invalidApiErrorCode = "InvalidAPIError";
5
- export const invalidCheckErrorCode = "InvalidCheckError";
6
- export const abortedErrorCode = "AbortedError";
7
- export const authRequiredErrorCode = "AuthRequiredError";
8
- export const authCheckNotFoundErrorCode = "AuthCheckNotFoundError";
9
- export const authCheckFailedErrorCode = "AuthCheckFailedError";
10
- export const maxLevelsExceededErrorCode = "MaxLevelsExceededError";
11
- export const automationError = "AutomationError";
12
- export const runAutomationErrorCodes = [apiNotFoundErrorCode, invalidApiErrorCode, invalidCheckErrorCode, abortedErrorCode, authRequiredErrorCode, authCheckNotFoundErrorCode, authCheckFailedErrorCode, maxLevelsExceededErrorCode, automationError];
13
- export class RunAutomationError {
14
- wrapped = false;
15
- get apiResponse() {
16
- if (this.wrapped) {
17
- return {
18
- status: 200,
19
- body: {
20
- status: this.statusCode,
21
- error: this.code,
22
- message: this.message
23
- }
24
- };
25
- }
26
- return {
27
- status: this.statusCode,
28
- body: {
29
- error: this.code,
30
- message: this.message
31
- }
32
- };
33
- }
34
- get json() {
35
- var _this$cause;
36
- return {
37
- code: this.code,
38
- details: this.details,
39
- cause: (_this$cause = this.cause) === null || _this$cause === void 0 ? void 0 : _this$cause.json
40
- };
41
- }
42
- }
43
- export class ApiNotFoundError extends RunAutomationError {
44
- constructor(apiName) {
45
- super();
46
- this.code = apiNotFoundErrorCode;
47
- this.statusCode = 404;
48
- this.message = `API ${apiName} not found`;
49
- }
50
- }
51
- export class InvalidApiError extends RunAutomationError {
52
- constructor(message) {
53
- super();
54
- this.code = invalidApiErrorCode;
55
- this.statusCode = 400;
56
- this.message = `API is invalid: ${message}`;
57
- }
58
- }
59
- export class InvalidCheckError extends RunAutomationError {
60
- constructor(message, cause) {
61
- super();
62
- this.code = invalidCheckErrorCode;
63
- this.statusCode = 400;
64
- this.message = message;
65
- this.cause = cause;
66
- }
67
- }
68
- export class AbortedError extends RunAutomationError {
69
- constructor() {
70
- super();
71
- this.code = abortedErrorCode;
72
- this.statusCode = 200;
73
- this.message = "Operation was aborted";
74
- }
75
- }
76
- export class AuthRequiredError extends RunAutomationError {
77
- constructor() {
78
- super();
79
- this.code = authRequiredErrorCode;
80
- this.statusCode = 401;
81
- this.message = "Authentication is required";
82
- }
83
- }
84
- export class AuthCheckNotFoundError extends RunAutomationError {
85
- constructor() {
86
- super();
87
- this.code = authCheckNotFoundErrorCode;
88
- this.statusCode = 404;
89
- this.message = "Auth check not found";
90
- }
91
- }
92
- export class AuthCheckFailedError extends RunAutomationError {
93
- constructor() {
94
- super();
95
- this.code = authCheckFailedErrorCode;
96
- this.statusCode = 401;
97
- this.message = "auth session check failed";
98
- }
99
- get apiResponse() {
100
- return {
101
- status: 200,
102
- body: {
103
- status: this.statusCode,
104
- error: "AUTH_SESSION_CHECK_FAILED",
105
- message: this.message
106
- }
107
- };
108
- }
109
- }
110
- export class MaxLevelsExceededError extends RunAutomationError {
111
- constructor(levels) {
112
- super();
113
- this.code = maxLevelsExceededErrorCode;
114
- this.statusCode = 400;
115
- this.message = `Max levels exceeded. Only ${levels} levels are supported`;
116
- this.details = {
117
- levels
118
- };
119
- }
120
- }
121
- export class AutomationError extends RunAutomationError {
122
- constructor(error) {
123
- super();
124
- this.error = error;
125
- this.code = automationError;
126
- if (error instanceof playwright.errors.TimeoutError) {
127
- this.statusCode = 500;
128
- this.message = `[${error.name}] ${error.message}`;
129
- this.details = {
130
- name: error.name,
131
- message: error.message
132
- };
133
- return;
134
- }
135
- if (error instanceof RunError) {
136
- this.wrapped = true;
137
- this.statusCode = error.options.status_code ?? 500;
138
- this.message = `[${error.options.error_code ?? error.name}] ${error.message}`;
139
- this.details = {
140
- name: error.name,
141
- statusCode: error.options.status_code,
142
- errorCode: error.options.error_code,
143
- message: error.message,
144
- options: error.options
145
- };
146
- }
147
- this.statusCode = 500;
148
- this.message = `[${(error === null || error === void 0 ? void 0 : error.name) ?? error}] ${error === null || error === void 0 ? void 0 : error.message}`;
149
- this.details = {
150
- name: error === null || error === void 0 ? void 0 : error.name,
151
- message: error === null || error === void 0 ? void 0 : error.message
152
- };
153
- }
154
- }
@@ -1,253 +0,0 @@
1
- import { getDownloadDirectoryPath } from "../../runtime/downloadDirectory";
2
- import { getExecutionContext } from "../asyncLocalStorage";
3
- import * as fs from "fs-extra";
4
- import { backendFunctionsTokenManager } from "../jwtTokenManager";
5
- import { getContextStorageState, setContextStorageState } from "../contextStorageStateHelpers";
6
- import { remove } from "fs-extra";
7
- import { ok, err } from "neverthrow";
8
- import { AbortedError, ApiNotFoundError, AutomationError, InvalidApiError, InvalidCheckError, MaxLevelsExceededError } from "./errors.js";
9
- import { AUTH_SESSIONS_FOLDER_NAME } from "../constants";
10
- import { getPlaywrightConstructsForMode, getProductionPlaywrightConstructs } from "../getPlaywrightConstructs";
11
- import { runApiParametersSchema } from "./types.js";
12
- export * from "./types.js";
13
- export * from "./errors.js";
14
- export async function* runApiGenerator({
15
- retrieveSession = false,
16
- abortSignal,
17
- ...input
18
- }) {
19
- let traceStarted = false;
20
- const {
21
- automationFunction,
22
- runOptions,
23
- tracing,
24
- auth,
25
- functionsToken
26
- } = runApiParametersSchema.parse(input);
27
- backendFunctionsTokenManager.token = functionsToken;
28
- const downloadsPath = getDownloadDirectoryPath();
29
- let page;
30
- let context;
31
- if (runOptions.environment === "deployed") {
32
- const {
33
- headless,
34
- proxy
35
- } = runOptions;
36
- ({
37
- page,
38
- context
39
- } = await getProductionPlaywrightConstructs({
40
- headless,
41
- proxy,
42
- downloadsPath,
43
- storageState: auth === null || auth === void 0 ? void 0 : auth.session
44
- }));
45
- } else {
46
- const {
47
- mode,
48
- cdpAddress
49
- } = runOptions;
50
- ({
51
- page,
52
- context
53
- } = await getPlaywrightConstructsForMode(mode, cdpAddress, auth === null || auth === void 0 ? void 0 : auth.session));
54
- }
55
- const executionContext = getExecutionContext();
56
- if (!executionContext) {
57
- throw "";
58
- }
59
- async function saveTraceIfNeeded({
60
- errorMessage
61
- }) {
62
- if (!tracing.enabled || !traceStarted) {
63
- return;
64
- }
65
- try {
66
- await context.tracing.stop({
67
- path: tracing.filePath
68
- });
69
- } catch (error) {
70
- console.log(errorMessage, error === null || error === void 0 ? void 0 : error.message);
71
- await remove(tracing.filePath);
72
- }
73
- }
74
- if (tracing.enabled) {
75
- await context.tracing.start({
76
- screenshots: true,
77
- snapshots: true,
78
- sources: true
79
- });
80
- traceStarted = true;
81
- }
82
- const abortSymbol = Symbol("abort");
83
- const abortPromise = new Promise(resolve => {
84
- if (!abortSignal) return;
85
- abortSignal.addEventListener("abort", () => {
86
- resolve(abortSymbol);
87
- });
88
- });
89
- if (auth && auth.session.type === "state") {
90
- await setContextStorageState(context, auth.session.state);
91
- }
92
- async function* runAutomation() {
93
- var _getExecutionContext;
94
- if (auth !== null && auth !== void 0 && auth.runCheck) {
95
- if (!auth.session) {
96
- return err({
97
- code: "AuthRequiredError"
98
- });
99
- }
100
- console.log("Running auth check");
101
- const authCheckResult = await checkAuthSessionWithRetries(page, context, 2);
102
- if (authCheckResult.isErr()) {
103
- const error = authCheckResult.error;
104
- if (["APINotFoundError", "InvalidAPIError"].includes(error.code)) {
105
- return err(new InvalidCheckError(`Auth session check function failed`, error));
106
- }
107
- return authCheckResult;
108
- }
109
- if (!authCheckResult.value) {
110
- return err({
111
- code: "AuthCheckFailedError"
112
- });
113
- }
114
- }
115
- console.log("Running function", automationFunction.name);
116
- const args = [...(automationFunction.params ? [automationFunction.params] : []), page, context];
117
- const importResult = await importFunction(automationFunction.name);
118
- if (importResult.isErr()) {
119
- return importResult;
120
- }
121
- let result;
122
- if (importResult.value.type === "async-generator") {
123
- const generator = importResult.value.generator(...args);
124
- let next = undefined;
125
- while (true) {
126
- const generatorResult = await generator.next(...(next ? [next] : []));
127
- if (!generatorResult.done) {
128
- next = yield generatorResult.value;
129
- continue;
130
- }
131
- result = generatorResult.value;
132
- break;
133
- }
134
- } else {
135
- result = await importResult.value.func(...args);
136
- }
137
- return ok({
138
- result,
139
- extendedPayloads: (_getExecutionContext = getExecutionContext()) === null || _getExecutionContext === void 0 ? void 0 : _getExecutionContext.extendedPayloads,
140
- session: retrieveSession ? await getContextStorageState(context) : undefined
141
- });
142
- }
143
- try {
144
- const generator = runAutomation();
145
- let next = undefined;
146
- while (true) {
147
- const result = await Promise.race([generator.next(await next), abortPromise]);
148
- if (result === abortSymbol) {
149
- return err(new AbortedError());
150
- }
151
- if (!result.done) {
152
- next = yield result.value;
153
- continue;
154
- }
155
- return result.value;
156
- }
157
- } catch (error) {
158
- console.log("run errored", error);
159
- return err(new AutomationError(error));
160
- } finally {
161
- await saveTraceIfNeeded({
162
- errorMessage: "failed to save trace"
163
- });
164
- await context.close();
165
- await fs.remove(downloadsPath);
166
- }
167
- }
168
- export async function runApi(params) {
169
- const generator = runApiGenerator(params);
170
- const {
171
- value,
172
- done
173
- } = await generator.next();
174
- if (done) {
175
- return value;
176
- }
177
- return err(new InvalidApiError("Expected API to be async function, got async generator"));
178
- }
179
- export async function checkAuthSessionWithRetries(page, context, retries = 3) {
180
- if (retries === 0) {
181
- return ok(false);
182
- }
183
- let tryNumber = 0;
184
- console.log("Checking auth session with retries", `${AUTH_SESSIONS_FOLDER_NAME}/check`);
185
- const importResult = await importFunction(`${AUTH_SESSIONS_FOLDER_NAME}/check`);
186
- if (importResult.isErr()) {
187
- return err(importResult.error);
188
- }
189
- if (importResult.value.type !== "async") {
190
- return err(new InvalidCheckError("Check function is not an async function"));
191
- }
192
- const check = importResult.value.func;
193
- while (retries > tryNumber) {
194
- const result = await check(page, context);
195
- if (result) return ok(true);
196
- tryNumber++;
197
- }
198
- return ok(false);
199
- }
200
- async function importFunction(path) {
201
- const functionNameParts = path.split("/");
202
- const functionNameDepth = functionNameParts.length;
203
- try {
204
- let imported = undefined;
205
- switch (functionNameDepth) {
206
- case 1:
207
- imported = await import(`../../../${functionNameParts[0]}.ts`);
208
- break;
209
- case 2:
210
- imported = await import(`../../../${functionNameParts[0]}/${functionNameParts[1]}.ts`);
211
- break;
212
- case 3:
213
- imported = await import(`../../../${functionNameParts[0]}/${functionNameParts[1]}/${functionNameParts[2]}.ts`);
214
- break;
215
- case 4:
216
- imported = await import(`../../../${functionNameParts[0]}/${functionNameParts[1]}/${functionNameParts[2]}/${functionNameParts[3]}.ts`);
217
- break;
218
- case 5:
219
- imported = await import(`../../../${functionNameParts[0]}/${functionNameParts[1]}/${functionNameParts[2]}/${functionNameParts[3]}/${functionNameParts[4]}.ts`);
220
- break;
221
- case 6:
222
- imported = await import(`../../../${functionNameParts[0]}/${functionNameParts[1]}/${functionNameParts[2]}/${functionNameParts[3]}/${functionNameParts[4]}/${functionNameParts[5]}.ts`);
223
- break;
224
- default:
225
- return err(new MaxLevelsExceededError(5));
226
- }
227
- if (!imported || !imported.default || !imported.default.constructor) {
228
- return err(new InvalidApiError("API file path does not have a default export"));
229
- }
230
- if (imported.default.constructor.name === "AsyncGeneratorFunction") {
231
- return ok({
232
- type: "async-generator",
233
- generator: imported.default
234
- });
235
- }
236
- if (imported.default.constructor.name === "AsyncFunction") {
237
- return ok({
238
- type: "async",
239
- func: imported.default
240
- });
241
- }
242
- return err(new InvalidApiError("API file path does not have a default async function/generator export"));
243
- } catch (error) {
244
- if (error.message.includes("Unknown variable dynamic import")) {
245
- return err(new ApiNotFoundError(path));
246
- }
247
- if ((error === null || error === void 0 ? void 0 : error.code) === "ERR_MODULE_NOT_FOUND") {
248
- console.log("API not found", error);
249
- return err(new ApiNotFoundError(path));
250
- }
251
- throw error;
252
- }
253
- }
@@ -1,43 +0,0 @@
1
- import z from "zod";
2
- export const runApiSessionSchema = z.discriminatedUnion("type", [z.object({
3
- type: z.literal("file"),
4
- path: z.string()
5
- }), z.object({
6
- type: z.literal("state"),
7
- state: z.custom(v => v)
8
- })]);
9
- export const runApiParametersSchema = z.object({
10
- functionsToken: z.string().optional(),
11
- automationFunction: z.object({
12
- name: z.string(),
13
- params: z.any().optional()
14
- }),
15
- tracing: z.discriminatedUnion("enabled", [z.object({
16
- enabled: z.literal(false)
17
- }), z.object({
18
- enabled: z.literal(true),
19
- filePath: z.string()
20
- })]).optional().default({
21
- enabled: false
22
- }),
23
- auth: z.object({
24
- session: runApiSessionSchema,
25
- runCheck: z.boolean().default(false)
26
- }).optional(),
27
- runOptions: z.discriminatedUnion("environment", [z.object({
28
- environment: z.literal("deployed"),
29
- headless: z.boolean().default(true),
30
- proxy: z.object({
31
- server: z.string(),
32
- username: z.string(),
33
- password: z.string()
34
- }).optional()
35
- }), z.object({
36
- environment: z.literal("ide"),
37
- cdpAddress: z.string(),
38
- mode: z.union([z.literal("vanilla"), z.literal("playwright"), z.literal("playwright-standalone"), z.literal("playwright-headless")])
39
- })]).default({
40
- environment: "deployed"
41
- }),
42
- retrieveSession: z.boolean().default(false)
43
- });