UNPKG

@angular/cli

Version:
234 lines • 7.99 kB
"use strict"; /** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ Object.defineProperty(exports, "__esModule", { value: true }); exports.parseNpmLikeDependencies = parseNpmLikeDependencies; exports.parseYarnClassicDependencies = parseYarnClassicDependencies; exports.parseYarnModernDependencies = parseYarnModernDependencies; exports.parseNpmLikeManifest = parseNpmLikeManifest; exports.parseNpmLikeMetadata = parseNpmLikeMetadata; exports.parseYarnLegacyManifest = parseYarnLegacyManifest; const MAX_LOG_LENGTH = 1024; function logStdout(stdout, logger) { if (!logger) { return; } let output = stdout; if (output.length > MAX_LOG_LENGTH) { output = `${output.slice(0, MAX_LOG_LENGTH)}... (truncated)`; } logger.debug(` stdout:\n${output}`); } /** * Parses the output of `npm list` or a compatible command. * * The expected JSON structure is: * ```json * { * "dependencies": { * "@angular/cli": { * "version": "18.0.0", * "path": "/path/to/project/node_modules/@angular/cli", // path is optional * ... (other package.json properties) * } * } * } * ``` * * @param stdout The standard output of the command. * @param logger An optional logger instance. * @returns A map of package names to their installed package details. */ function parseNpmLikeDependencies(stdout, logger) { logger?.debug(`Parsing npm-like dependency list...`); logStdout(stdout, logger); const dependencies = new Map(); if (!stdout) { logger?.debug(' stdout is empty. No dependencies found.'); return dependencies; } let data = JSON.parse(stdout); if (Array.isArray(data)) { // pnpm returns an array of projects. data = data[0]; } const dependencyMaps = [data.dependencies, data.devDependencies, data.unsavedDependencies].filter((d) => !!d); if (dependencyMaps.length === 0) { logger?.debug(' `dependencies` property not found. No dependencies found.'); return dependencies; } for (const dependencyMap of dependencyMaps) { for (const [name, info] of Object.entries(dependencyMap)) { dependencies.set(name, { name, version: info.version, path: info.path, }); } } logger?.debug(` Found ${dependencies.size} dependencies.`); return dependencies; } /** * Parses the output of `yarn list` (classic). * * The expected output is a JSON stream (JSONL), where each line is a JSON object. * The relevant object has a `type` of `'tree'`. * Yarn classic does not provide a path, so the `path` property will be `undefined`. * * ```json * {"type":"tree","data":{"trees":[{"name":"@angular/cli@18.0.0","children":[]}]}} * ``` * * @param stdout The standard output of the command. * @param logger An optional logger instance. * @returns A map of package names to their installed package details. */ function parseYarnClassicDependencies(stdout, logger) { logger?.debug(`Parsing yarn classic dependency list...`); logStdout(stdout, logger); const dependencies = new Map(); if (!stdout) { logger?.debug(' stdout is empty. No dependencies found.'); return dependencies; } for (const line of stdout.split('\n')) { if (!line) { continue; } const json = JSON.parse(line); if (json.type === 'tree' && json.data?.trees) { for (const info of json.data.trees) { const name = info.name.split('@')[0]; const version = info.name.split('@').pop(); dependencies.set(name, { name, version, }); } } } logger?.debug(` Found ${dependencies.size} dependencies.`); return dependencies; } /** * Parses the output of `yarn list` (modern). * * The expected JSON structure is a single object. * Yarn modern does not provide a path, so the `path` property will be `undefined`. * * ```json * { * "trees": [ * { "name": "@angular/cli@18.0.0", "children": [] } * ] * } * ``` * * @param stdout The standard output of the command. * @param logger An optional logger instance. * @returns A map of package names to their installed package details. */ function parseYarnModernDependencies(stdout, logger) { logger?.debug(`Parsing yarn modern dependency list...`); logStdout(stdout, logger); const dependencies = new Map(); if (!stdout) { logger?.debug(' stdout is empty. No dependencies found.'); return dependencies; } // Modern yarn `list` command outputs a single JSON object with a `trees` property. // Each line is not a separate JSON object. try { const data = JSON.parse(stdout); for (const info of data.trees) { const name = info.name.split('@')[0]; const version = info.name.split('@').pop(); dependencies.set(name, { name, version, }); } } catch (e) { logger?.debug(` Failed to parse as single JSON object: ${e}. Falling back to line-by-line parsing.`); // Fallback for older versions of yarn berry that might still output json lines for (const line of stdout.split('\n')) { if (!line) { continue; } try { const json = JSON.parse(line); if (json.type === 'tree' && json.data?.trees) { for (const info of json.data.trees) { const name = info.name.split('@')[0]; const version = info.name.split('@').pop(); dependencies.set(name, { name, version, }); } } } catch (innerError) { logger?.debug(` Ignoring non-JSON line: ${innerError}`); // Ignore lines that are not valid JSON. } } } logger?.debug(` Found ${dependencies.size} dependencies.`); return dependencies; } /** * Parses the output of `npm view` or a compatible command to get a package manifest. * @param stdout The standard output of the command. * @param logger An optional logger instance. * @returns The package manifest object. */ function parseNpmLikeManifest(stdout, logger) { logger?.debug(`Parsing npm-like manifest...`); logStdout(stdout, logger); if (!stdout) { logger?.debug(' stdout is empty. No manifest found.'); return null; } return JSON.parse(stdout); } /** * Parses the output of `npm view` or a compatible command to get package metadata. * @param stdout The standard output of the command. * @param logger An optional logger instance. * @returns The package metadata object. */ function parseNpmLikeMetadata(stdout, logger) { logger?.debug(`Parsing npm-like metadata...`); logStdout(stdout, logger); if (!stdout) { logger?.debug(' stdout is empty. No metadata found.'); return null; } return JSON.parse(stdout); } /** * Parses the output of `yarn info` (classic). * @param stdout The standard output of the command. * @param logger An optional logger instance. * @returns The package manifest object. */ function parseYarnLegacyManifest(stdout, logger) { logger?.debug(`Parsing yarn classic manifest...`); logStdout(stdout, logger); if (!stdout) { logger?.debug(' stdout is empty. No manifest found.'); return null; } const data = JSON.parse(stdout); // Yarn classic wraps the manifest in a `data` property. return data.data ?? data; } //# sourceMappingURL=parsers.js.map