@midscene/core 0.21.0 → 0.21.1-beta-20250705095012.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"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","names":["readFileSync","writeFileSync"],"ignoreList":[],"sources":["../../src/utils.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport * as path from 'node:path';\nimport { dirname } from 'node:path';\nimport {\n defaultRunDirName,\n getMidsceneRunSubDir,\n} from '@midscene/shared/common';\nimport {\n MIDSCENE_DEBUG_MODE,\n MIDSCENE_OPENAI_INIT_CONFIG_JSON,\n getAIConfig,\n getAIConfigInJson,\n} from '@midscene/shared/env';\nimport { getRunningPkgInfo } from '@midscene/shared/fs';\nimport { assert, logMsg } from '@midscene/shared/utils';\nimport { escapeScriptTag, ifInBrowser, uuid } from '@midscene/shared/utils';\nimport type { Rect, ReportDumpWithAttributes } from './types';\n\nlet logEnvReady = false;\n\nexport const groupedActionDumpFileExt = 'web-dump.json';\n\nconst reportInitializedMap = new Map<string, boolean>();\nconst writingFiles = new Set<string>();\n\nfunction getReportTpl() {\n const reportTpl = 'REPLACE_ME_WITH_REPORT_HTML';\n\n return reportTpl;\n}\n\n/**\n * high performance, insert script before </html> in HTML file\n * only truncate and append, no temporary file\n * with file-system based locking to prevent concurrent writes across processes\n */\nexport function insertScriptBeforeClosingHtml(\n filePath: string,\n scriptContent: string,\n): void {\n const lockFile = `${filePath}.lock`;\n const maxRetries = 100; // max retries\n const retryDelay = 100; // retry delay (ms)\n\n // process-level locking\n if (writingFiles.has(filePath)) {\n throw new Error(`File ${filePath} is being written by current process`);\n }\n\n for (let i = 0; i < maxRetries; i++) {\n try {\n // try to create lock file (atomic operation)\n fs.writeFileSync(lockFile, process.pid.toString(), { flag: 'wx' });\n\n // get process-level lock\n writingFiles.add(filePath);\n\n try {\n const htmlEndTag = '</html>';\n const stat = fs.statSync(filePath);\n const readSize = 65536; // 64KB\n const start = Math.max(0, stat.size - readSize);\n const buffer = Buffer.alloc(stat.size - start);\n const fd = fs.openSync(filePath, 'r');\n fs.readSync(fd, buffer, 0, buffer.length, start);\n fs.closeSync(fd);\n\n const tailStr = buffer.toString('utf8');\n const htmlEndIdx = tailStr.lastIndexOf(htmlEndTag);\n if (htmlEndIdx === -1) {\n throw new Error('No </html> found');\n }\n\n const htmlEndPos = start + htmlEndIdx;\n // atomic operation: truncate and append\n fs.truncateSync(filePath, htmlEndPos);\n fs.appendFileSync(filePath, `${scriptContent}\\n${htmlEndTag}\\n`);\n return; // success, exit\n } finally {\n // release lock\n writingFiles.delete(filePath);\n try {\n fs.unlinkSync(lockFile);\n } catch (e) {\n // ignore error when deleting lock file\n }\n }\n } catch (error: any) {\n if (error.code === 'EEXIST') {\n // lock file exists, check if it is a dead lock\n try {\n const lockContent = fs.readFileSync(lockFile, 'utf8');\n const lockPid = Number.parseInt(lockContent, 10);\n\n // check if the process still exists\n try {\n process.kill(lockPid, 0); // will not actually kill the process, just check if it exists\n } catch (killError: any) {\n if (killError.code === 'ESRCH') {\n // process does not exist, delete dead lock file\n try {\n fs.unlinkSync(lockFile);\n continue; // retry\n } catch (unlinkError) {\n // ignore error when deleting lock file\n }\n }\n }\n } catch (readError) {\n // cannot read lock file, maybe format problem, try to delete\n try {\n fs.unlinkSync(lockFile);\n continue; // retry\n } catch (unlinkError) {\n // ignore error when deleting lock file\n }\n }\n\n // wait for a while and retry\n const now = Date.now();\n while (Date.now() - now < retryDelay) {\n // busy wait\n }\n } else {\n throw error;\n }\n }\n }\n\n throw new Error(\n `Failed to write to file ${filePath} after ${maxRetries} retries - file is locked`,\n );\n}\n\nexport function reportHTMLContent(\n dumpData: string | ReportDumpWithAttributes,\n reportPath?: string,\n appendReport?: boolean,\n): string {\n const tpl = getReportTpl();\n\n if (!tpl) {\n console.warn('reportTpl is not set, will not write report');\n return '';\n }\n\n // if reportPath is set, it means we are in write to file mode\n const writeToFile = reportPath && !ifInBrowser;\n let dumpContent = '';\n\n if (typeof dumpData === 'string') {\n // do not use template string here, will cause bundle error\n dumpContent =\n // biome-ignore lint/style/useTemplate: <explanation>\n '<script type=\"midscene_web_dump\" type=\"application/json\">\\n' +\n escapeScriptTag(dumpData) +\n '\\n</script>';\n } else {\n const { dumpString, attributes } = dumpData;\n const attributesArr = Object.keys(attributes || {}).map((key) => {\n return `${key}=\"${encodeURIComponent(attributes![key])}\"`;\n });\n\n dumpContent =\n // do not use template string here, will cause bundle error\n // biome-ignore lint/style/useTemplate: <explanation>\n '<script type=\"midscene_web_dump\" type=\"application/json\" ' +\n attributesArr.join(' ') +\n '>\\n' +\n escapeScriptTag(dumpString) +\n '\\n</script>';\n }\n\n if (writeToFile) {\n if (!appendReport) {\n writeFileSync(reportPath!, tpl + dumpContent, { flag: 'w' });\n return reportPath!;\n }\n\n if (!reportInitializedMap.get(reportPath!)) {\n writeFileSync(reportPath!, tpl, { flag: 'w' });\n reportInitializedMap.set(reportPath!, true);\n }\n\n insertScriptBeforeClosingHtml(reportPath!, dumpContent);\n return reportPath!;\n }\n\n return tpl + dumpContent;\n}\n\nexport function writeDumpReport(\n fileName: string,\n dumpData: string | ReportDumpWithAttributes,\n appendReport?: boolean,\n): string | null {\n if (ifInBrowser) {\n console.log('will not write report in browser');\n return null;\n }\n\n const __dirname = dirname(__filename);\n const midscenePkgInfo = getRunningPkgInfo(__dirname);\n if (!midscenePkgInfo) {\n console.warn('midscenePkgInfo not found, will not write report');\n return null;\n }\n\n const reportPath = path.join(\n getMidsceneRunSubDir('report'),\n `${fileName}.html`,\n );\n\n reportHTMLContent(dumpData, reportPath, appendReport);\n\n if (process.env.MIDSCENE_DEBUG_LOG_JSON) {\n const jsonPath = `${reportPath}.json`;\n let data;\n\n if (typeof dumpData === 'string') {\n data = JSON.parse(dumpData) as ReportDumpWithAttributes;\n } else {\n data = dumpData;\n }\n\n writeFileSync(jsonPath, JSON.stringify(data, null, 2), {\n flag: appendReport ? 'a' : 'w',\n });\n\n logMsg(`Midscene - dump file written: ${jsonPath}`);\n }\n\n return reportPath;\n}\n\nexport function writeLogFile(opts: {\n fileName: string;\n fileExt: string;\n fileContent: string;\n type: 'dump' | 'cache' | 'report' | 'tmp';\n generateReport?: boolean;\n appendReport?: boolean;\n}) {\n if (ifInBrowser) {\n return '/mock/report.html';\n }\n const { fileName, fileExt, fileContent, type = 'dump' } = opts;\n const targetDir = getMidsceneRunSubDir(type);\n // Ensure directory exists\n if (!logEnvReady) {\n assert(targetDir, 'logDir should be set before writing dump file');\n\n // gitIgnore in the parent directory\n const gitIgnorePath = path.join(targetDir, '../../.gitignore');\n const gitPath = path.join(targetDir, '../../.git');\n let gitIgnoreContent = '';\n\n if (existsSync(gitPath)) {\n // if the git path exists, we need to add the log folder to the git ignore file\n if (existsSync(gitIgnorePath)) {\n gitIgnoreContent = readFileSync(gitIgnorePath, 'utf-8');\n }\n\n // ignore the log folder\n if (!gitIgnoreContent.includes(`${defaultRunDirName}/`)) {\n writeFileSync(\n gitIgnorePath,\n `${gitIgnoreContent}\\n# Midscene.js dump files\\n${defaultRunDirName}/dump\\n${defaultRunDirName}/report\\n${defaultRunDirName}/tmp\\n${defaultRunDirName}/log\\n`,\n 'utf-8',\n );\n }\n }\n\n logEnvReady = true;\n }\n\n const filePath = path.join(targetDir, `${fileName}.${fileExt}`);\n\n if (type !== 'dump') {\n // do not write dump file any more\n writeFileSync(filePath, fileContent);\n }\n\n if (opts?.generateReport) {\n return writeDumpReport(fileName, fileContent, opts.appendReport);\n }\n\n return filePath;\n}\n\nexport function getTmpDir(): string | null {\n try {\n const runningPkgInfo = getRunningPkgInfo();\n if (!runningPkgInfo) {\n return null;\n }\n const { name } = runningPkgInfo;\n const tmpPath = path.join(tmpdir(), name);\n mkdirSync(tmpPath, { recursive: true });\n return tmpPath;\n } catch (e) {\n return null;\n }\n}\n\nexport function getTmpFile(fileExtWithoutDot: string): string | null {\n if (ifInBrowser) {\n return null;\n }\n const tmpDir = getTmpDir();\n const filename = `${uuid()}.${fileExtWithoutDot}`;\n return path.join(tmpDir!, filename);\n}\n\nexport function overlapped(container: Rect, target: Rect) {\n // container and the target have some part overlapped\n return (\n container.left < target.left + target.width &&\n container.left + container.width > target.left &&\n container.top < target.top + target.height &&\n container.top + container.height > target.top\n );\n}\n\nexport async function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function replacerForPageObject(key: string, value: any) {\n if (value && value.constructor?.name === 'Page') {\n return '[Page object]';\n }\n if (value && value.constructor?.name === 'Browser') {\n return '[Browser object]';\n }\n return value;\n}\n\nexport function stringifyDumpData(data: any, indents?: number) {\n return JSON.stringify(data, replacerForPageObject, indents);\n}\n\ndeclare const __VERSION__: string;\n\nexport function getVersion() {\n return __VERSION__;\n}\n\nfunction debugLog(...message: any[]) {\n const debugMode = getAIConfig(MIDSCENE_DEBUG_MODE);\n if (debugMode) {\n console.log('[Midscene]', ...message);\n }\n}\n\nlet lastReportedRepoUrl = '';\nexport function uploadTestInfoToServer({ testUrl }: { testUrl: string }) {\n let repoUrl = '';\n let userEmail = '';\n\n const extraConfig = getAIConfigInJson(MIDSCENE_OPENAI_INIT_CONFIG_JSON);\n const serverUrl = extraConfig?.REPORT_SERVER_URL;\n\n try {\n repoUrl = execSync('git config --get remote.origin.url').toString().trim();\n userEmail = execSync('git config --get user.email').toString().trim();\n } catch (error) {\n debugLog('Failed to get git info:', error);\n }\n\n // Only upload test info if:\n // 1. Server URL is configured AND\n // 2. Either:\n // - We have a repo URL that's different from last reported one (to avoid duplicate reports)\n // - OR we don't have a repo URL but have a test URL (for non-git environments)\n if (\n serverUrl &&\n ((repoUrl && repoUrl !== lastReportedRepoUrl) || (!repoUrl && testUrl))\n ) {\n debugLog('Uploading test info to server', {\n serverUrl,\n repoUrl,\n testUrl,\n userEmail,\n });\n\n fetch(serverUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n repo_url: repoUrl,\n test_url: testUrl,\n user_email: userEmail,\n }),\n })\n .then((response) => response.json())\n .then((data) => {\n debugLog('Successfully uploaded test info to server:', data);\n })\n .catch((error) =>\n debugLog('Failed to upload test info to server:', error),\n );\n lastReportedRepoUrl = repoUrl;\n }\n}\n"]}
package/dist/es/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getVersion
3
- } from "./chunk-VLQRL65C.js";
3
+ } from "./chunk-HYDONOYT.js";
4
4
  import {
5
5
  AiAssert,
6
6
  AiExtractElementInfo,
@@ -7,6 +7,7 @@ declare const groupedActionDumpFileExt = "web-dump.json";
7
7
  /**
8
8
  * high performance, insert script before </html> in HTML file
9
9
  * only truncate and append, no temporary file
10
+ * with file-system based locking to prevent concurrent writes across processes
10
11
  */
11
12
  declare function insertScriptBeforeClosingHtml(filePath: string, scriptContent: string): void;
12
13
  declare function reportHTMLContent(dumpData: string | ReportDumpWithAttributes, reportPath?: string, appendReport?: boolean): string;
package/dist/es/utils.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  uploadTestInfoToServer,
13
13
  writeDumpReport,
14
14
  writeLogFile
15
- } from "./chunk-VLQRL65C.js";
15
+ } from "./chunk-HYDONOYT.js";
16
16
  export {
17
17
  getTmpDir,
18
18
  getTmpFile,