diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c44b4b4d..cd8833a4 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -42,6 +42,8 @@ jobs: - name: Build run: npm run bundle + env: + NODE_OPTIONS: '--max_old_space_size=4096' - name: Set up Node.js uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 @@ -62,7 +64,7 @@ jobs: - name: Run tests shell: bash if: ${{ matrix.node != '20' }} - run: npm run test + run: npm run test:no-build # Gating job for branch protection. test-success: diff --git a/package.json b/package.json index 86a1aad0..dbd5d780 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "main": "index.js", "scripts": { "clean": "node -e \"require('fs').rmSync('build', {recursive: true, force: true})\"", - "bundle": "npm run clean && npm run build && rollup -c rollup.config.mjs", + "bundle": "npm run clean && npm run build && rollup -c rollup.config.mjs && node -e \"require('fs').rmSync('build/node_modules', {recursive: true, force: true})\"", "build": "tsc && node --experimental-strip-types --no-warnings=ExperimentalWarning scripts/post-build.ts", "typecheck": "tsc --noEmit", "format": "eslint --cache --fix . && prettier --write --cache .", @@ -16,11 +16,12 @@ "docs:generate": "node --experimental-strip-types scripts/generate-docs.ts", "start": "npm run build && node build/src/index.js", "start-debug": "DEBUG=mcp:* DEBUG_COLORS=false npm run build && node build/src/index.js", - "test:node20": "node --require ./build/tests/setup.js --test-reporter spec --test-force-exit --test build/tests", - "test": "npm run build && node --require ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-reporter spec --test-force-exit --test \"build/tests/**/*.test.js\"", - "test:only": "npm run build && node --require ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-reporter spec --test-force-exit --test --test-only \"build/tests/**/*.test.js\"", - "test:only:no-build": "node --require ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-reporter spec --test-force-exit --test --test-only \"build/tests/**/*.test.js\"", - "test:update-snapshots": "npm run build && node --require ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-force-exit --test --test-update-snapshots \"build/tests/**/*.test.js\"", + "test:node20": "node --import ./build/tests/setup.js --test-reporter spec --test-force-exit --test build/tests", + "test:no-build": "node --import ./build/tests/setup.js --no-warnings=ExperimentalWarning --experimental-print-required-tla --test-reporter spec --test-force-exit --test \"build/tests/**/*.test.js\"", + "test": "npm run build && npm run test:no-build", + "test:only": "npm run build && node --import ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-reporter spec --test-force-exit --test --test-only \"build/tests/**/*.test.js\"", + "test:only:no-build": "node --import ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-reporter spec --test-force-exit --test --test-only \"build/tests/**/*.test.js\"", + "test:update-snapshots": "npm run build && node --import ./build/tests/setup.js --no-warnings=ExperimentalWarning --test-force-exit --test --test-update-snapshots \"build/tests/**/*.test.js\"", "prepare": "node --experimental-strip-types scripts/prepare.ts", "verify-server-json-version": "node --experimental-strip-types scripts/verify-server-json-version.ts" }, diff --git a/rollup.config.mjs b/rollup.config.mjs index 0fdfc944..957952de 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -19,6 +19,7 @@ * and modified to specific requirement. */ +import fs from 'node:fs'; import path from 'node:path'; import commonjs from '@rollup/plugin-commonjs'; @@ -79,7 +80,7 @@ const bundleDependency = ( 'THIRD_PARTY_NOTICES', ), template(dependencies) { - const stringified_dependencies = dependencies.map(dependency => { + const stringifiedDependencies = dependencies.map(dependency => { let arr = []; arr.push(`Name: ${dependency.name ?? 'N/A'}`); let url = dependency.homepage ?? dependency.repository; @@ -95,9 +96,60 @@ const bundleDependency = ( } return arr.join('\n'); }); + + // Manual license handling for chrome-devtools-frontend third_party + const tsConfig = JSON.parse( + fs.readFileSync( + path.join(process.cwd(), 'tsconfig.json'), + 'utf-8', + ), + ); + const thirdPartyDirectories = tsConfig.include.filter(location => + location.includes( + 'node_modules/chrome-devtools-frontend/front_end/third_party', + ), + ); + + const manualLicenses = []; + // Add chrome-devtools-frontend main license + const cdtfLicensePath = path.join( + process.cwd(), + 'node_modules/chrome-devtools-frontend/LICENSE', + ); + if (fs.existsSync(cdtfLicensePath)) { + manualLicenses.push( + [ + 'Name: chrome-devtools-frontend', + 'License: Apache-2.0', + '', + fs.readFileSync(cdtfLicensePath, 'utf-8'), + ].join('\n'), + ); + } + + for (const thirdPartyDir of thirdPartyDirectories) { + const fullPath = path.join(process.cwd(), thirdPartyDir); + const licenseFile = path.join(fullPath, 'LICENSE'); + if (fs.existsSync(licenseFile)) { + const name = path.basename(thirdPartyDir); + manualLicenses.push( + [ + `Name: ${name}`, + `License:`, + '', + fs.readFileSync(licenseFile, 'utf-8').replaceAll('\r', ''), + ].join('\n'), + ); + } + } + + if (manualLicenses.length > 0) { + stringifiedDependencies.push(...manualLicenses); + } + const divider = '\n\n-------------------- DEPENDENCY DIVIDER --------------------\n\n'; - return stringified_dependencies.join(divider); + return stringifiedDependencies.join(divider); }, }, }, diff --git a/scripts/post-build.ts b/scripts/post-build.ts index 011b71aa..db702801 100644 --- a/scripts/post-build.ts +++ b/scripts/post-build.ts @@ -7,8 +7,6 @@ import * as fs from 'node:fs'; import * as path from 'node:path'; -import tsConfig from '../tsconfig.json' with {type: 'json'}; - import {sed} from './sed.ts'; const BUILD_DIR = path.join(process.cwd(), 'build'); @@ -22,29 +20,6 @@ function writeFile(filePath: string, content: string): void { fs.writeFileSync(filePath, content, 'utf-8'); } -/** - * Ensures that licenses for third party files we use gets copied into the build/ dir. - */ -function copyThirdPartyLicenseFiles() { - const thirdPartyDirectories = tsConfig.include.filter(location => { - return location.includes( - 'node_modules/chrome-devtools-frontend/front_end/third_party', - ); - }); - - for (const thirdPartyDir of thirdPartyDirectories) { - const fullPath = path.join(process.cwd(), thirdPartyDir); - const licenseFile = path.join(fullPath, 'LICENSE'); - if (!fs.existsSync(licenseFile)) { - console.error('No LICENSE for', path.basename(thirdPartyDir)); - } - - const destinationDir = path.join(BUILD_DIR, thirdPartyDir); - const destinationFile = path.join(destinationDir, 'LICENSE'); - fs.copyFileSync(licenseFile, destinationFile); - } -} - function main(): void { const devtoolsThirdPartyPath = 'node_modules/chrome-devtools-frontend/front_end/third_party'; @@ -113,22 +88,6 @@ export const experiments = { sed(clientFile, globalAssignment, ''); sed(clientFile, registerCommands, ''); - const devtoolsLicensePath = path.join( - 'node_modules', - 'chrome-devtools-frontend', - 'LICENSE', - ); - const devtoolsLicenseFileSource = path.join( - process.cwd(), - devtoolsLicensePath, - ); - const devtoolsLicenseFileDestination = path.join( - BUILD_DIR, - devtoolsLicensePath, - ); - fs.copyFileSync(devtoolsLicenseFileSource, devtoolsLicenseFileDestination); - - copyThirdPartyLicenseFiles(); copyDevToolsDescriptionFiles(); } @@ -136,7 +95,12 @@ function copyDevToolsDescriptionFiles() { const devtoolsIssuesDescriptionPath = 'node_modules/chrome-devtools-frontend/front_end/models/issues_manager/descriptions'; const sourceDir = path.join(process.cwd(), devtoolsIssuesDescriptionPath); - const destDir = path.join(BUILD_DIR, devtoolsIssuesDescriptionPath); + const destDir = path.join( + BUILD_DIR, + 'src', + 'third_party', + 'issue-descriptions', + ); fs.cpSync(sourceDir, destDir, {recursive: true}); } diff --git a/src/DevToolsConnectionAdapter.ts b/src/DevToolsConnectionAdapter.ts index 2d628742..a8316799 100644 --- a/src/DevToolsConnectionAdapter.ts +++ b/src/DevToolsConnectionAdapter.ts @@ -4,8 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type {CDPConnection as devtools} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; - +import type {CDPConnection as devtools} from './third_party/index.js'; import type * as puppeteer from './third_party/index.js'; import {CDPSessionEvent} from './third_party/index.js'; diff --git a/src/DevtoolsUtils.ts b/src/DevtoolsUtils.ts index 05a145e9..1b60e6f1 100644 --- a/src/DevtoolsUtils.ts +++ b/src/DevtoolsUtils.ts @@ -4,11 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {PuppeteerDevToolsConnection} from './DevToolsConnectionAdapter.js'; +import {ISSUE_UTILS} from './issue-descriptions.js'; +import {logger} from './logger.js'; +import {Mutex} from './Mutex.js'; import { type Issue, type AggregatedIssue, type IssuesManagerEventTypes, - type Target, + type SDKTarget as Target, DebuggerModel, Foundation, TargetManager, @@ -17,12 +21,7 @@ import { ProtocolClient, Common, I18n, -} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; - -import {PuppeteerDevToolsConnection} from './DevToolsConnectionAdapter.js'; -import {ISSUE_UTILS} from './issue-descriptions.js'; -import {logger} from './logger.js'; -import {Mutex} from './Mutex.js'; +} from './third_party/index.js'; import type { Browser, Page, diff --git a/src/McpContext.ts b/src/McpContext.ts index f35bbbc7..9bc760cf 100644 --- a/src/McpContext.ts +++ b/src/McpContext.ts @@ -8,11 +8,10 @@ import fs from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; -import {type AggregatedIssue} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; - import {extractUrlLikeFromDevToolsTitle, urlsEqual} from './DevtoolsUtils.js'; import type {ListenerMap} from './PageCollector.js'; import {NetworkCollector, ConsoleCollector} from './PageCollector.js'; +import {type AggregatedIssue} from './third_party/index.js'; import {Locator} from './third_party/index.js'; import type { Browser, diff --git a/src/McpResponse.ts b/src/McpResponse.ts index af7c8b51..0b8c8cee 100644 --- a/src/McpResponse.ts +++ b/src/McpResponse.ts @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {AggregatedIssue} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; - import {mapIssueToMessageObject} from './DevtoolsUtils.js'; import type {ConsoleMessageData} from './formatters/consoleFormatter.js'; import { @@ -21,6 +19,7 @@ import { } from './formatters/networkFormatter.js'; import {formatSnapshotNode} from './formatters/snapshotFormatter.js'; import type {McpContext} from './McpContext.js'; +import {AggregatedIssue} from './third_party/index.js'; import type { ConsoleMessage, ImageContent, diff --git a/src/PageCollector.ts b/src/PageCollector.ts index 22b3dc6d..28f1edc4 100644 --- a/src/PageCollector.ts +++ b/src/PageCollector.ts @@ -4,17 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type { - AggregatedIssue, - Common, -} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; -import { - IssueAggregatorEvents, - IssuesManagerEvents, - createIssuesFromProtocolIssue, - IssueAggregator, -} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; - import {FakeIssuesManager} from './DevtoolsUtils.js'; import {logger} from './logger.js'; import type { @@ -22,6 +11,14 @@ import type { ConsoleMessage, Protocol, Target, + Common, +} from './third_party/index.js'; +import { + type AggregatedIssue, + IssueAggregatorEvents, + IssuesManagerEvents, + createIssuesFromProtocolIssue, + IssueAggregator, } from './third_party/index.js'; import { type Browser, diff --git a/src/formatters/consoleFormatter.ts b/src/formatters/consoleFormatter.ts index d5bc828e..86222ba2 100644 --- a/src/formatters/consoleFormatter.ts +++ b/src/formatters/consoleFormatter.ts @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import type {AggregatedIssue} from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import type {McpContext} from '../McpContext.js'; +import {type AggregatedIssue} from '../third_party/index.js'; export interface ConsoleMessageData { consoleMessageStableId: number; diff --git a/src/issue-descriptions.ts b/src/issue-descriptions.ts index c13e405e..ab0ea788 100644 --- a/src/issue-descriptions.ts +++ b/src/issue-descriptions.ts @@ -9,7 +9,7 @@ import * as path from 'node:path'; const DESCRIPTIONS_PATH = path.join( import.meta.dirname, - '../node_modules/chrome-devtools-frontend/front_end/models/issues_manager/descriptions', + 'third_party/issue-descriptions', ); let issueDescriptions: Record = {}; diff --git a/src/third_party/index.ts b/src/third_party/index.ts index fc589fcc..8239f1cf 100644 --- a/src/third_party/index.ts +++ b/src/third_party/index.ts @@ -35,3 +35,27 @@ export { Browser as BrowserEnum, type ChromeReleaseChannel as BrowsersChromeReleaseChannel, } from '@puppeteer/browsers'; + +export { + AgentFocus, + TraceEngine, + PerformanceTraceFormatter, + PerformanceInsightFormatter, + AggregatedIssue, + type Issue, + type IssuesManagerEventTypes, + type Target as SDKTarget, + type CDPConnection, + DebuggerModel, + Foundation, + TargetManager, + MarkdownIssueDescription, + Marked, + ProtocolClient, + Common, + I18n, + IssueAggregatorEvents, + IssuesManagerEvents, + createIssuesFromProtocolIssue, + IssueAggregator, +} from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js'; diff --git a/src/trace-processing/parse.ts b/src/trace-processing/parse.ts index cbd79462..25c969b7 100644 --- a/src/trace-processing/parse.ts +++ b/src/trace-processing/parse.ts @@ -4,13 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +import {logger} from '../logger.js'; import { AgentFocus, TraceEngine, PerformanceTraceFormatter, PerformanceInsightFormatter, -} from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js'; -import {logger} from '../logger.js'; +} from '../third_party/index.js'; const engine = TraceEngine.TraceModel.Model.createWithAllHandlers(); diff --git a/tests/DevtoolsUtils.test.ts b/tests/DevtoolsUtils.test.ts index 84b028b2..2e602a95 100644 --- a/tests/DevtoolsUtils.test.ts +++ b/tests/DevtoolsUtils.test.ts @@ -9,10 +9,6 @@ import {afterEach, describe, it} from 'node:test'; import sinon from 'sinon'; -import { - AggregatedIssue, - DebuggerModel, -} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import { extractUrlLikeFromDevToolsTitle, urlsEqual, @@ -20,6 +16,7 @@ import { UniverseManager, } from '../src/DevtoolsUtils.js'; import {ISSUE_UTILS} from '../src/issue-descriptions.js'; +import {AggregatedIssue, DebuggerModel} from '../src/third_party/index.js'; import type {Browser, Target} from '../src/third_party/index.js'; import { diff --git a/tests/PageCollector.test.ts b/tests/PageCollector.test.ts index 267a6daa..4ec44799 100644 --- a/tests/PageCollector.test.ts +++ b/tests/PageCollector.test.ts @@ -10,13 +10,13 @@ import {beforeEach, describe, it} from 'node:test'; import type {Frame, HTTPRequest, Target, Protocol} from 'puppeteer-core'; import sinon from 'sinon'; -import {AggregatedIssue} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import type {ListenerMap} from '../src/PageCollector.js'; import { ConsoleCollector, NetworkCollector, PageCollector, } from '../src/PageCollector.js'; +import {AggregatedIssue} from '../src/third_party/index.js'; import {getMockRequest, getMockBrowser} from './utils.js'; diff --git a/tests/setup.ts b/tests/setup.ts index f79b8735..d48cc49d 100644 --- a/tests/setup.ts +++ b/tests/setup.ts @@ -20,7 +20,7 @@ if (!it.snapshot) { }; } -// This is run by Node when we execute the tests via the --require flag. +// This is run by Node when we execute the tests via the --import flag. it.snapshot.setResolveSnapshotPath(testPath => { // By default the snapshots go into the build directory, but we want them // in the tests/ directory. diff --git a/tests/tools/console.test.ts b/tests/tools/console.test.ts index 2597b873..8f32ec36 100644 --- a/tests/tools/console.test.ts +++ b/tests/tools/console.test.ts @@ -7,9 +7,9 @@ import assert from 'node:assert'; import {before, describe, it} from 'node:test'; -import {AggregatedIssue} from '../../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import {loadIssueDescriptions} from '../../src/issue-descriptions.js'; import {McpResponse} from '../../src/McpResponse.js'; +import {AggregatedIssue} from '../../src/third_party/index.js'; import { getConsoleMessage, listConsoleMessages, diff --git a/tests/utils.ts b/tests/utils.ts index 5043dd23..84d2b8b6 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -17,10 +17,10 @@ import type { } from 'puppeteer-core'; import sinon from 'sinon'; -import {AggregatedIssue} from '../node_modules/chrome-devtools-frontend/mcp/mcp.js'; import {McpContext} from '../src/McpContext.js'; import {McpResponse} from '../src/McpResponse.js'; import {stableIdSymbol} from '../src/PageCollector.js'; +import {AggregatedIssue} from '../src/third_party/index.js'; export function getTextContent( content: CallToolResult['content'][number],