@cyclonedx/cyclonedx-esbuild
Version:
Creates CycloneDX Software Bill of Materials (SBoM) from esbuild projects
185 lines (180 loc) • 6.95 kB
JavaScript
;
/*!
This file is part of CycloneDX generator for esbuild.
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.
SPDX-License-Identifier: Apache-2.0
Copyright (c) OWASP Foundation. All Rights Reserved.
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PACKAGE_MANIFEST_FILENAME = exports.ValidationError = void 0;
exports.loadJsonFile = loadJsonFile;
exports.writeAllSync = writeAllSync;
exports.isString = isString;
exports.normalizePackageManifest = normalizePackageManifest;
exports.isNonNullable = isNonNullable;
exports.makeToolCs = makeToolCs;
exports.getPackageDescription = getPackageDescription;
exports.isValidPackageJSON = isValidPackageJSON;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const CDX = __importStar(require("@cyclonedx/cyclonedx-library"));
const normalize_package_data_1 = __importDefault(require("normalize-package-data"));
const logger_1 = require("./logger");
function loadJsonFile(path) {
return JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
}
async function writeAllSync(fd, data) {
const b = Buffer.from(data);
const l = b.byteLength;
let w = 0;
while (w < l) {
try {
w += (0, node_fs_1.writeSync)(fd, b, w);
}
catch (error) {
if (error.code !== 'EAGAIN') {
throw error;
}
await new Promise((resolve) => {
setTimeout(resolve, 100);
});
}
}
return w;
}
function isString(v) {
return typeof v === 'string';
}
function normalizePackageManifest(data, warn) {
const oVersion = data.version;
(0, normalize_package_data_1.default)(data, warn);
if (isString(oVersion)) {
data.version = oVersion.trim();
}
}
function isNonNullable(value) {
return value !== null && value !== undefined;
}
function* makeToolCs(selfCTyp, builder, logger) {
const packageJsonPaths = [
[(0, node_path_1.resolve)(module.path, '..', 'package.json'), selfCTyp]
];
const libs = [
'@cyclonedx/cyclonedx-library'
].map(s => s.split('/', 2));
const nodeModulePaths = require.resolve.paths('__some_none-native_package__') ?? [];
libsLoop: for (const lib of libs) {
for (const nodeModulePath of nodeModulePaths) {
const packageJsonPath = (0, node_path_1.resolve)(nodeModulePath, ...lib, 'package.json');
if ((0, node_fs_1.existsSync)(packageJsonPath)) {
packageJsonPaths.push([packageJsonPath, CDX.Enums.ComponentType.Library]);
continue libsLoop;
}
}
}
for (const [packageJsonPath, cType] of packageJsonPaths) {
logger.info(logger_1.LogPrefixes.INFO, 'try to build new Tool from PkgPath', packageJsonPath);
const packageJson = loadJsonFile(packageJsonPath) ?? {};
normalizePackageManifest(packageJson, w => {
logger.debug(logger_1.LogPrefixes.DEBUG, 'normalizePackageJson from PkgPath', packageJsonPath, 'caused:', w);
});
const tool = builder.makeComponent(packageJson, cType);
if (tool !== undefined) {
yield tool;
}
}
}
class ValidationError extends Error {
details;
constructor(message, details) {
super(message);
this.details = details;
}
}
exports.ValidationError = ValidationError;
exports.PACKAGE_MANIFEST_FILENAME = 'package.json';
function getPackageDescription(ppath) {
if (!(0, node_fs_1.existsSync)(ppath)) {
return undefined;
}
const isSubDirOfNodeModules = isSubDirectoryOfNodeModulesFolder(ppath);
while ((0, node_path_1.isAbsolute)(ppath)) {
const pathToPackageJson = (0, node_path_1.join)(ppath, exports.PACKAGE_MANIFEST_FILENAME);
if ((0, node_fs_1.existsSync)(pathToPackageJson)) {
try {
const contentOfPackageJson = loadJsonFile(pathToPackageJson) ?? {};
if (!isSubDirOfNodeModules || isValidPackageJSON(contentOfPackageJson)) {
return {
path: pathToPackageJson,
packageJson: contentOfPackageJson
};
}
}
catch {
return undefined;
}
}
const nextPath = (0, node_path_1.dirname)(ppath);
if (nextPath === ppath || isNodeModulesFolder(nextPath)) {
return undefined;
}
ppath = nextPath;
}
return undefined;
}
const NODE_MODULES_FOLDERNAME = 'node_modules';
function isNodeModulesFolder(path) {
return path.endsWith(`${node_path_1.sep}${NODE_MODULES_FOLDERNAME}`);
}
function isSubDirectoryOfNodeModulesFolder(path) {
return path.includes(`${node_path_1.sep}${NODE_MODULES_FOLDERNAME}${node_path_1.sep}`);
}
function isValidPackageJSON(pkg) {
return isNonNullable(pkg)
&& typeof pkg.name === 'string'
&& typeof pkg.version === 'string';
}