333 lines
9.8 KiB
JavaScript
333 lines
9.8 KiB
JavaScript
/**
|
|
* Copyright 2021 Google LLC.
|
|
* Copyright (c) Microsoft Corporation.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview taken from {@link https://github.com/GoogleChromeLabs/chromium-bidi/blob/main/rollup.config.mjs | chromium-bidi}
|
|
* and modified to specific requirement.
|
|
*/
|
|
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
import commonjs from '@rollup/plugin-commonjs';
|
|
import json from '@rollup/plugin-json';
|
|
import {nodeResolve} from '@rollup/plugin-node-resolve';
|
|
import cleanup from 'rollup-plugin-cleanup';
|
|
import license from 'rollup-plugin-license';
|
|
|
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
|
|
const allowedLicenses = [
|
|
'MIT',
|
|
'Apache 2.0',
|
|
'Apache-2.0',
|
|
'BSD-3-Clause',
|
|
'BSD-2-Clause',
|
|
'ISC',
|
|
'0BSD',
|
|
];
|
|
|
|
const thirdPartyDir = './build/src/third_party';
|
|
|
|
const {devDependencies = {}} = JSON.parse(
|
|
fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'),
|
|
);
|
|
|
|
// special case for puppeteer, from which we only bundle puppeteer-core
|
|
devDependencies['puppeteer-core'] = devDependencies['puppeteer'];
|
|
|
|
const packageLock = JSON.parse(
|
|
fs.readFileSync(path.join(process.cwd(), 'package-lock.json'), 'utf-8'),
|
|
);
|
|
|
|
function getResolvedVersion(packageName) {
|
|
const packageEntry = packageLock.packages?.[`node_modules/${packageName}`];
|
|
return packageEntry?.version || null;
|
|
}
|
|
|
|
const aggregatedStats = {
|
|
bundlesProcessed: 0,
|
|
totalBundles: 0,
|
|
bundledPackages: new Set(),
|
|
};
|
|
|
|
const projectNodeModulesPath =
|
|
path.join(process.cwd(), 'node_modules') + path.sep;
|
|
|
|
function getPackageName(modulePath) {
|
|
// Handle rollup's virtual module paths (paths starting with 0x00)
|
|
const absolutePathStart = modulePath.indexOf(projectNodeModulesPath);
|
|
if (absolutePathStart < 0) {
|
|
return null;
|
|
}
|
|
|
|
const relativePath = modulePath.slice(
|
|
projectNodeModulesPath.length + absolutePathStart,
|
|
);
|
|
const segments = relativePath.split(path.sep);
|
|
|
|
// handle scoped packages
|
|
if (segments[0].startsWith('@') && segments[1]) {
|
|
return `${segments[0]}/${segments[1]}`;
|
|
}
|
|
return segments[0];
|
|
}
|
|
|
|
/**
|
|
* @returns {import('rollup').Plugin}
|
|
*/
|
|
function listBundledDeps() {
|
|
aggregatedStats.totalBundles++;
|
|
return {
|
|
name: 'gather-bundled-dependencies',
|
|
generateBundle(options, bundle) {
|
|
for (const chunk of Object.values(bundle)) {
|
|
if (chunk.type === 'chunk' && chunk.modules) {
|
|
// chunk.modules is an object where keys are the absolute file paths
|
|
Object.keys(chunk.modules).forEach(modulePath => {
|
|
const packageName = getPackageName(modulePath);
|
|
if (packageName) {
|
|
aggregatedStats.bundledPackages.add(packageName);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
aggregatedStats.bundlesProcessed++;
|
|
|
|
// Only write the file when the last bundle is finished
|
|
if (aggregatedStats.bundlesProcessed === aggregatedStats.totalBundles) {
|
|
const outputPath = path.join(thirdPartyDir, 'bundled-packages.json');
|
|
|
|
const bundledDevDeps = {};
|
|
for (const [name, versionRange] of Object.entries(devDependencies)) {
|
|
if (
|
|
aggregatedStats.bundledPackages.has(name) ||
|
|
name === 'chrome-devtools-frontend' ||
|
|
name === 'lighthouse'
|
|
) {
|
|
const resolvedVersion = getResolvedVersion(name);
|
|
bundledDevDeps[name] = resolvedVersion || versionRange;
|
|
}
|
|
}
|
|
|
|
fs.writeFileSync(outputPath, JSON.stringify(bundledDevDeps, null, 2));
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
const seenDependencies = new Map();
|
|
|
|
/**
|
|
* @param {string} wrapperIndexName
|
|
* @param {import('rollup').OutputOptions} [extraOutputOptions={}]
|
|
* @param {import('rollup').ExternalOption} [external=[]]
|
|
* @returns {import('rollup').RollupOptions}
|
|
*/
|
|
const bundleDependency = (
|
|
wrapperIndexName,
|
|
extraOutputOptions = {},
|
|
external = [],
|
|
) => ({
|
|
input: path.join(thirdPartyDir, wrapperIndexName),
|
|
output: {
|
|
...extraOutputOptions,
|
|
file: path.join(thirdPartyDir, wrapperIndexName),
|
|
sourcemap: !isProduction,
|
|
format: 'esm',
|
|
},
|
|
plugins: [
|
|
cleanup({
|
|
// Keep license comments. Other comments are removed due to
|
|
// http://b/390559299 and
|
|
// https://github.com/microsoft/TypeScript/issues/60811.
|
|
comments: [/Copyright/i],
|
|
}),
|
|
license({
|
|
thirdParty: {
|
|
allow: {
|
|
test: dependency => {
|
|
return allowedLicenses.includes(dependency.license);
|
|
},
|
|
failOnUnlicensed: true,
|
|
failOnViolation: true,
|
|
},
|
|
output: {
|
|
file: path.join(thirdPartyDir, 'THIRD_PARTY_NOTICES'),
|
|
template(dependencies) {
|
|
for (const dependency of dependencies) {
|
|
const key = `${dependency.name}:${dependency.version}`;
|
|
seenDependencies.set(key, dependency);
|
|
}
|
|
|
|
const stringifiedDependencies = Array.from(
|
|
seenDependencies.values(),
|
|
).map(dependency => {
|
|
let arr = [];
|
|
arr.push(`Name: ${dependency.name ?? 'N/A'}`);
|
|
let url = dependency.homepage ?? dependency.repository;
|
|
if (url !== null && typeof url !== 'string') {
|
|
url = url.url;
|
|
}
|
|
arr.push(`URL: ${url ?? 'N/A'}`);
|
|
arr.push(`Version: ${dependency.version ?? 'N/A'}`);
|
|
arr.push(`License: ${dependency.license ?? 'N/A'}`);
|
|
if (dependency.licenseText !== null) {
|
|
arr.push('');
|
|
arr.push(dependency.licenseText.replaceAll('\r', ''));
|
|
}
|
|
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'),
|
|
);
|
|
}
|
|
|
|
// Add chrome-devtools-frontend main license
|
|
const lighthouseLicensePath = path.join(
|
|
process.cwd(),
|
|
'node_modules/lighthouse/LICENSE',
|
|
);
|
|
if (fs.existsSync(lighthouseLicensePath)) {
|
|
manualLicenses.push(
|
|
[
|
|
'Name: lighthouse',
|
|
'License: Apache-2.0',
|
|
'',
|
|
fs.readFileSync(lighthouseLicensePath, '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 stringifiedDependencies.join(divider);
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
listBundledDeps(),
|
|
commonjs(),
|
|
json(),
|
|
nodeResolve(),
|
|
],
|
|
external,
|
|
});
|
|
|
|
export default [
|
|
bundleDependency(
|
|
'index.js',
|
|
{
|
|
inlineDynamicImports: true,
|
|
},
|
|
(source, importer, _isResolved) => {
|
|
if (
|
|
source === 'yargs' &&
|
|
importer &&
|
|
importer.includes('puppeteer-core')
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
if (
|
|
source === '@toon-format/toon' ||
|
|
source.startsWith('@toon-format/toon/')
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
if (
|
|
source === '@blackwell-systems/gcf' ||
|
|
source.startsWith('@blackwell-systems/gcf/')
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
const existingExternals = [
|
|
'./bidi.js',
|
|
'../bidi/bidi.js',
|
|
'./lighthouse-devtools-mcp-bundle.js',
|
|
];
|
|
|
|
if (existingExternals.includes(source)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
),
|
|
bundleDependency(
|
|
'devtools-formatter-worker.js',
|
|
{
|
|
inlineDynamicImports: true,
|
|
},
|
|
(_source, _importer, _isResolved) => false,
|
|
),
|
|
bundleDependency(
|
|
'devtools-heap-snapshot-worker.js',
|
|
{
|
|
inlineDynamicImports: true,
|
|
},
|
|
(_source, _importer, _isResolved) => false,
|
|
),
|
|
];
|