mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 20:20:49 +00:00
Type check safe-chain package
This commit is contained in:
parent
d5dc801c00
commit
c88b1a624f
60 changed files with 1179 additions and 33 deletions
|
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* @param {string[]} args
|
||||
* @param {...string} commandArgs
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function matchesCommand(args, ...commandArgs) {
|
||||
if (args.length < commandArgs.length) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ import { ui } from "../../environment/userInteraction.js";
|
|||
import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
|
||||
/**
|
||||
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||
*/
|
||||
export function createBunPackageManager() {
|
||||
return {
|
||||
runCommand: (args) => runBunCommand("bun", args),
|
||||
|
|
@ -9,10 +12,13 @@ export function createBunPackageManager() {
|
|||
// For bun, we use the proxy-only approach to block package downloads,
|
||||
// so we don't need to analyze commands.
|
||||
isSupportedCommand: () => false,
|
||||
getDependencyUpdatesForCommand: () => [],
|
||||
getDependencyUpdatesForCommand: async () => [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||
*/
|
||||
export function createBunxPackageManager() {
|
||||
return {
|
||||
runCommand: (args) => runBunCommand("bunx", args),
|
||||
|
|
@ -20,18 +26,24 @@ export function createBunxPackageManager() {
|
|||
// For bunx, we use the proxy-only approach to block package downloads,
|
||||
// so we don't need to analyze commands.
|
||||
isSupportedCommand: () => false,
|
||||
getDependencyUpdatesForCommand: () => [],
|
||||
getDependencyUpdatesForCommand: async () => [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} command
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<{status: number}>}
|
||||
*/
|
||||
async function runBunCommand(command, args) {
|
||||
try {
|
||||
const result = await safeSpawn(command, args, {
|
||||
stdio: "inherit",
|
||||
// @ts-expect-error values of process.env can be string | undefined
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
});
|
||||
return { status: result.status };
|
||||
} catch (error) {
|
||||
} catch (/** @type any */ error) {
|
||||
if (error.status) {
|
||||
return { status: error.status };
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -10,10 +10,25 @@ import {
|
|||
} from "./pnpm/createPackageManager.js";
|
||||
import { createYarnPackageManager } from "./yarn/createPackageManager.js";
|
||||
|
||||
/**
|
||||
* @type {{packageManagerName: PackageManager | null}}
|
||||
*/
|
||||
const state = {
|
||||
packageManagerName: null,
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef PackageManager
|
||||
* @property {(args: string[]) => Promise<{ status: number }>} runCommand
|
||||
* @property {(args: string[]) => boolean} isSupportedCommand
|
||||
* @property {(args: string[]) => Promise<{name: string, version: string, type: string}[]>} getDependencyUpdatesForCommand
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} packageManagerName
|
||||
*
|
||||
* @return {PackageManager}
|
||||
*/
|
||||
export function initializePackageManager(packageManagerName) {
|
||||
if (packageManagerName === "npm") {
|
||||
state.packageManagerName = createNpmPackageManager();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,15 @@ import {
|
|||
npmExecCommand,
|
||||
} from "./utils/npmCommands.js";
|
||||
|
||||
/**
|
||||
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||
*/
|
||||
export function createNpmPackageManager() {
|
||||
/**
|
||||
* @param {string[]} args
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isSupportedCommand(args) {
|
||||
const scanner = findDependencyScannerForCommand(
|
||||
commandScannerMapping,
|
||||
|
|
@ -17,6 +25,11 @@ export function createNpmPackageManager() {
|
|||
return scanner.shouldScan(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
*
|
||||
* @returns {Promise<{name: string, version: string, type: string}[]>}
|
||||
*/
|
||||
function getDependencyUpdatesForCommand(args) {
|
||||
const scanner = findDependencyScannerForCommand(
|
||||
commandScannerMapping,
|
||||
|
|
@ -32,12 +45,22 @@ export function createNpmPackageManager() {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Record<string, import("./dependencyScanner/commandArgumentScanner.js").CommandArgumentScanner>}
|
||||
*/
|
||||
const commandScannerMapping = {
|
||||
[npmInstallCommand]: commandArgumentScanner(),
|
||||
[npmUpdateCommand]: commandArgumentScanner(),
|
||||
[npmExecCommand]: commandArgumentScanner({ ignoreDryRun: true }), // exec command doesn't support dry-run
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Record<string, import("./dependencyScanner/commandArgumentScanner.js").CommandArgumentScanner>} scanners
|
||||
* @param {string[]} args
|
||||
*
|
||||
* @returns {import("./dependencyScanner/commandArgumentScanner.js").CommandArgumentScanner}
|
||||
*/
|
||||
function findDependencyScannerForCommand(scanners, args) {
|
||||
const command = getNpmCommandForArgs(args);
|
||||
if (!command) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,29 @@ import { resolvePackageVersion } from "../../../api/npmApi.js";
|
|||
import { parsePackagesFromInstallArgs } from "../parsing/parsePackagesFromInstallArgs.js";
|
||||
import { hasDryRunArg } from "../utils/npmCommands.js";
|
||||
|
||||
/**
|
||||
* @typedef {Object} ScanResult
|
||||
* @property {string} name
|
||||
* @property {string} version
|
||||
* @property {string} type
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ScannerOptions
|
||||
* @property {boolean} [ignoreDryRun]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef CommandArgumentScanner
|
||||
* @property {(args: string[]) => Promise<ScanResult[]>} scan
|
||||
* @property {(args: string[]) => boolean} shouldScan
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {ScannerOptions} [opts]
|
||||
*
|
||||
* @returns {CommandArgumentScanner}
|
||||
*/
|
||||
export function commandArgumentScanner(opts) {
|
||||
const ignoreDryRun = opts?.ignoreDryRun ?? false;
|
||||
|
||||
|
|
@ -10,14 +33,28 @@ export function commandArgumentScanner(opts) {
|
|||
shouldScan: (args) => shouldScanDependencies(args, ignoreDryRun),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<ScanResult[]>}
|
||||
*/
|
||||
function scanDependencies(args) {
|
||||
return checkChangesFromArgs(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @param {boolean} ignoreDryRun
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function shouldScanDependencies(args, ignoreDryRun) {
|
||||
return ignoreDryRun || !hasDryRunArg(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<ScanResult[]>}
|
||||
*/
|
||||
export async function checkChangesFromArgs(args) {
|
||||
const changes = [];
|
||||
const packageUpdates = parsePackagesFromInstallArgs(args);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
/**
|
||||
* @returns {import("./commandArgumentScanner.js").CommandArgumentScanner}
|
||||
*/
|
||||
export function nullScanner() {
|
||||
return {
|
||||
scan: () => [],
|
||||
scan: async () => [],
|
||||
shouldScan: () => false,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,22 @@
|
|||
/**
|
||||
* @typedef {Object} PackageDetail
|
||||
* @property {string} name
|
||||
* @property {string} version
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} NpmOption
|
||||
* @property {string} name
|
||||
* @property {number} numberOfParameters
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {PackageDetail[]}
|
||||
*/
|
||||
export function parsePackagesFromInstallArgs(args) {
|
||||
const changes = [];
|
||||
/** @type {{name: string, version: string | null}[]} */
|
||||
const changes = [];
|
||||
let defaultTag = "latest";
|
||||
|
||||
// Skip first argument (install command)
|
||||
|
|
@ -32,9 +49,13 @@ export function parsePackagesFromInstallArgs(args) {
|
|||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
return /** @type {PackageDetail[]} */ (changes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {NpmOption | undefined}
|
||||
*/
|
||||
function getNpmOption(arg) {
|
||||
if (isNpmOptionWithParameter(arg)) {
|
||||
return {
|
||||
|
|
@ -54,6 +75,10 @@ function getNpmOption(arg) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isNpmOptionWithParameter(arg) {
|
||||
const optionsWithParameters = [
|
||||
"--access",
|
||||
|
|
@ -81,6 +106,10 @@ function isNpmOptionWithParameter(arg) {
|
|||
return optionsWithParameters.includes(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {{name: string, version: string | null}}
|
||||
*/
|
||||
function parsePackagename(arg) {
|
||||
arg = removeAlias(arg);
|
||||
const lastAtIndex = arg.lastIndexOf("@");
|
||||
|
|
@ -102,6 +131,10 @@ function parsePackagename(arg) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {string}
|
||||
*/
|
||||
function removeAlias(arg) {
|
||||
const aliasIndex = arg.indexOf("@npm:");
|
||||
if (aliasIndex !== -1) {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,20 @@ import { ui } from "../../environment/userInteraction.js";
|
|||
import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
*
|
||||
* @returns {Promise<{status: number}>}
|
||||
*/
|
||||
export async function runNpm(args) {
|
||||
try {
|
||||
const result = await safeSpawn("npm", args, {
|
||||
stdio: "inherit",
|
||||
// @ts-expect-error values of process.env can be string | undefined
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
});
|
||||
return { status: result.status };
|
||||
} catch (error) {
|
||||
} catch (/** @type any */ error) {
|
||||
if (error.status) {
|
||||
return { status: error.status };
|
||||
} else {
|
||||
|
|
@ -19,6 +25,10 @@ export async function runNpm(args) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<{status: number, output?: string}>}
|
||||
*/
|
||||
export async function dryRunNpmCommandAndOutput(args) {
|
||||
try {
|
||||
const result = await safeSpawn(
|
||||
|
|
@ -26,6 +36,7 @@ export async function dryRunNpmCommandAndOutput(args) {
|
|||
[...args, "--ignore-scripts", "--dry-run"],
|
||||
{
|
||||
stdio: "pipe",
|
||||
// @ts-expect-error values of process.env can be string | undefined
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
}
|
||||
);
|
||||
|
|
@ -33,7 +44,7 @@ export async function dryRunNpmCommandAndOutput(args) {
|
|||
status: result.status,
|
||||
output: result.status === 0 ? result.stdout : result.stderr,
|
||||
};
|
||||
} catch (error) {
|
||||
} catch (/** @type any */ error) {
|
||||
if (error.status) {
|
||||
const output =
|
||||
error.stdout?.toString() ??
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// This was ran with the abbrev package to generate the abbrevs object below
|
||||
// console.log(abbrev(commands.concat(Object.keys(aliases))));
|
||||
/** @type {Record<string, string>} */
|
||||
export const abbrevs = {
|
||||
ac: "access",
|
||||
acc: "access",
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ const commands = [
|
|||
];
|
||||
|
||||
// These must resolve to an entry in commands
|
||||
/** @type {Record<string, string>} */
|
||||
const aliases = {
|
||||
// aliases
|
||||
author: "owner",
|
||||
|
|
@ -138,6 +139,10 @@ const aliases = {
|
|||
"add-user": "adduser",
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} c
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
export function deref(c) {
|
||||
if (!c) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { deref } from "./cmd-list.js";
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {string | null}
|
||||
*/
|
||||
export function getNpmCommandForArgs(args) {
|
||||
if (args.length === 0) {
|
||||
return null;
|
||||
|
|
@ -13,6 +17,10 @@ export function getNpmCommandForArgs(args) {
|
|||
return argCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function hasDryRunArg(args) {
|
||||
return args.some((arg) => arg === "--dry-run");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { commandArgumentScanner } from "./dependencyScanner/commandArgumentScanner.js";
|
||||
import { runNpx } from "./runNpxCommand.js";
|
||||
|
||||
/**
|
||||
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||
*/
|
||||
export function createNpxPackageManager() {
|
||||
const scanner = commandArgumentScanner();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,28 @@
|
|||
import { resolvePackageVersion } from "../../../api/npmApi.js";
|
||||
import { parsePackagesFromArguments } from "../parsing/parsePackagesFromArguments.js";
|
||||
|
||||
/**
|
||||
* @returns {import("../../npm/dependencyScanner/commandArgumentScanner.js").CommandArgumentScanner}
|
||||
*/
|
||||
export function commandArgumentScanner() {
|
||||
return {
|
||||
scan: (args) => scanDependencies(args),
|
||||
shouldScan: () => true, // all npx commands need to be scanned, npx doesn't have dry-run
|
||||
shouldScan: (args) => true, // all npx commands need to be scanned, npx doesn't have dry-run
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<import("../../npm/dependencyScanner/commandArgumentScanner.js").ScanResult[]>}
|
||||
*/
|
||||
function scanDependencies(args) {
|
||||
return checkChangesFromArgs(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<import("../../npm/dependencyScanner/commandArgumentScanner.js").ScanResult[]>}
|
||||
*/
|
||||
export async function checkChangesFromArgs(args) {
|
||||
const changes = [];
|
||||
const packageUpdates = parsePackagesFromArguments(args);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
/**
|
||||
* @param {string[]} args
|
||||
*
|
||||
* @returns {{name: string, version: string}[]}
|
||||
*/
|
||||
export function parsePackagesFromArguments(args) {
|
||||
let defaultTag = "latest";
|
||||
|
||||
|
|
@ -21,6 +26,10 @@ export function parsePackagesFromArguments(args) {
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {{name: string, numberOfParameters: number} | undefined}
|
||||
*/
|
||||
function getOption(arg) {
|
||||
if (isOptionWithParameter(arg)) {
|
||||
return {
|
||||
|
|
@ -41,6 +50,10 @@ function getOption(arg) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isOptionWithParameter(arg) {
|
||||
const optionsWithParameters = [
|
||||
"--access",
|
||||
|
|
@ -68,6 +81,11 @@ function isOptionWithParameter(arg) {
|
|||
return optionsWithParameters.includes(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @param {string} defaultTag
|
||||
* @returns {{name: string, version: string}}
|
||||
*/
|
||||
function parsePackagename(arg, defaultTag) {
|
||||
// format can be --package=name@version
|
||||
// in that case, we need to remove the --package= part
|
||||
|
|
@ -97,6 +115,10 @@ function parsePackagename(arg, defaultTag) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {string}
|
||||
*/
|
||||
function removeAlias(arg) {
|
||||
// removes the alias.
|
||||
// Eg.: server@npm:http-server@latest becomes http-server@latest
|
||||
|
|
|
|||
|
|
@ -2,14 +2,20 @@ import { ui } from "../../environment/userInteraction.js";
|
|||
import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
*
|
||||
* @returns {Promise<{status: number}>}
|
||||
*/
|
||||
export async function runNpx(args) {
|
||||
try {
|
||||
const result = await safeSpawn("npx", args, {
|
||||
stdio: "inherit",
|
||||
// @ts-expect-error values of process.env can be string | undefined
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
});
|
||||
return { status: result.status };
|
||||
} catch (error) {
|
||||
} catch (/** @type any */ error) {
|
||||
if (error.status) {
|
||||
return { status: error.status };
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import { runPnpmCommand } from "./runPnpmCommand.js";
|
|||
|
||||
const scanner = commandArgumentScanner();
|
||||
|
||||
/**
|
||||
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||
*/
|
||||
export function createPnpmPackageManager() {
|
||||
return {
|
||||
runCommand: (args) => runPnpmCommand(args, "pnpm"),
|
||||
|
|
@ -23,6 +26,9 @@ export function createPnpmPackageManager() {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||
*/
|
||||
export function createPnpxPackageManager() {
|
||||
return {
|
||||
runCommand: (args) => runPnpmCommand(args, "pnpx"),
|
||||
|
|
@ -32,6 +38,11 @@ export function createPnpxPackageManager() {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @param {boolean} isPnpx
|
||||
* @returns {Promise<import("../npm/dependencyScanner/commandArgumentScanner.js").ScanResult[]>}
|
||||
*/
|
||||
function getDependencyUpdatesForCommand(args, isPnpx) {
|
||||
if (isPnpx) {
|
||||
return scanner.scan(args);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { resolvePackageVersion } from "../../../api/npmApi.js";
|
||||
import { parsePackagesFromArguments } from "../parsing/parsePackagesFromArguments.js";
|
||||
|
||||
/**
|
||||
* @returns {import("../../npm/dependencyScanner/commandArgumentScanner.js").CommandArgumentScanner}
|
||||
*/
|
||||
export function commandArgumentScanner() {
|
||||
return {
|
||||
scan: (args) => scanDependencies(args),
|
||||
|
|
@ -8,6 +11,10 @@ export function commandArgumentScanner() {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<import("../../npm/dependencyScanner/commandArgumentScanner.js").ScanResult[]>}
|
||||
*/
|
||||
async function scanDependencies(args) {
|
||||
const changes = [];
|
||||
const packageUpdates = parsePackagesFromArguments(args);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {{name: string, version: string}[]}
|
||||
*/
|
||||
export function parsePackagesFromArguments(args) {
|
||||
const changes = [];
|
||||
let defaultTag = "latest";
|
||||
|
|
@ -22,6 +26,10 @@ export function parsePackagesFromArguments(args) {
|
|||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {{name: string, numberOfParameters: number} | undefined}
|
||||
*/
|
||||
function getOption(arg) {
|
||||
if (isOptionWithParameter(arg)) {
|
||||
return {
|
||||
|
|
@ -42,12 +50,21 @@ function getOption(arg) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isOptionWithParameter(arg) {
|
||||
const optionsWithParameters = ["--C", "--dir"];
|
||||
|
||||
return optionsWithParameters.includes(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @param {string} defaultTag
|
||||
* @returns {{name: string, version: string}}
|
||||
*/
|
||||
function parsePackagename(arg, defaultTag) {
|
||||
// format can be --package=name@version
|
||||
// in that case, we need to remove the --package= part
|
||||
|
|
@ -77,6 +94,10 @@ function parsePackagename(arg, defaultTag) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {string}
|
||||
*/
|
||||
function removeAlias(arg) {
|
||||
// removes the alias.
|
||||
// Eg.: server@npm:http-server@latest becomes http-server@latest
|
||||
|
|
|
|||
|
|
@ -2,17 +2,24 @@ import { ui } from "../../environment/userInteraction.js";
|
|||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @param {string} [toolName]
|
||||
* @returns {Promise<{status: number}>}
|
||||
*/
|
||||
export async function runPnpmCommand(args, toolName = "pnpm") {
|
||||
try {
|
||||
let result;
|
||||
if (toolName === "pnpm") {
|
||||
result = await safeSpawn("pnpm", args, {
|
||||
stdio: "inherit",
|
||||
// @ts-expect-error values of process.env can be string | undefined
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
});
|
||||
} else if (toolName === "pnpx") {
|
||||
result = await safeSpawn("pnpx", args, {
|
||||
stdio: "inherit",
|
||||
// @ts-expect-error values of process.env can be string | undefined
|
||||
env: mergeSafeChainProxyEnvironmentVariables(process.env),
|
||||
});
|
||||
} else {
|
||||
|
|
@ -20,7 +27,7 @@ export async function runPnpmCommand(args, toolName = "pnpm") {
|
|||
}
|
||||
|
||||
return { status: result.status };
|
||||
} catch (error) {
|
||||
} catch (/** @type any */ error) {
|
||||
if (error.status) {
|
||||
return { status: error.status };
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@ import { runYarnCommand } from "./runYarnCommand.js";
|
|||
|
||||
const scanner = commandArgumentScanner();
|
||||
|
||||
/**
|
||||
* @returns {import("../currentPackageManager.js").PackageManager}
|
||||
*/
|
||||
export function createYarnPackageManager() {
|
||||
return {
|
||||
runCommand: runYarnCommand,
|
||||
|
|
@ -18,6 +21,11 @@ export function createYarnPackageManager() {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @param {...string} commandArgs
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function matchesCommand(args, ...commandArgs) {
|
||||
if (args.length < commandArgs.length) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { resolvePackageVersion } from "../../../api/npmApi.js";
|
||||
import { parsePackagesFromArguments } from "../parsing/parsePackagesFromArguments.js";
|
||||
|
||||
/**
|
||||
* @returns {import("../../npm/dependencyScanner/commandArgumentScanner.js").CommandArgumentScanner}
|
||||
*/
|
||||
export function commandArgumentScanner() {
|
||||
return {
|
||||
scan: (args) => scanDependencies(args),
|
||||
|
|
@ -8,6 +11,10 @@ export function commandArgumentScanner() {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {Promise<import("../../npm/dependencyScanner/commandArgumentScanner.js").ScanResult[]>}
|
||||
*/
|
||||
async function scanDependencies(args) {
|
||||
const changes = [];
|
||||
const packageUpdates = parsePackagesFromArguments(args);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
/**
|
||||
* @param {string[]} args
|
||||
* @returns {{name: string, version: string}[]}
|
||||
*/
|
||||
export function parsePackagesFromArguments(args) {
|
||||
const changes = [];
|
||||
let defaultTag = "latest";
|
||||
|
|
@ -22,6 +26,11 @@ export function parsePackagesFromArguments(args) {
|
|||
return changes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
*
|
||||
* @returns {{name: string, numberOfParameters: number} | undefined}
|
||||
*/
|
||||
function getOption(arg) {
|
||||
if (isOptionWithParameter(arg)) {
|
||||
return {
|
||||
|
|
@ -42,6 +51,11 @@ function getOption(arg) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isOptionWithParameter(arg) {
|
||||
const optionsWithParameters = [
|
||||
"--use-yarnrc",
|
||||
|
|
@ -64,6 +78,12 @@ function isOptionWithParameter(arg) {
|
|||
return optionsWithParameters.includes(arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @param {string} defaultTag
|
||||
*
|
||||
* @returns {{name: string, version: string}}
|
||||
*/
|
||||
function parsePackagename(arg, defaultTag) {
|
||||
// format can be --package=name@version
|
||||
// in that case, we need to remove the --package= part
|
||||
|
|
@ -93,6 +113,10 @@ function parsePackagename(arg, defaultTag) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} arg
|
||||
* @returns {string}
|
||||
*/
|
||||
function removeAlias(arg) {
|
||||
// removes the alias.
|
||||
// Eg.: server@npm:http-server@latest becomes http-server@latest
|
||||
|
|
|
|||
|
|
@ -2,8 +2,14 @@ import { ui } from "../../environment/userInteraction.js";
|
|||
import { safeSpawn } from "../../utils/safeSpawn.js";
|
||||
import { mergeSafeChainProxyEnvironmentVariables } from "../../registryProxy/registryProxy.js";
|
||||
|
||||
/**
|
||||
* @param {string[]} args
|
||||
*
|
||||
* @returns {Promise<{status: number}>}
|
||||
*/
|
||||
export async function runYarnCommand(args) {
|
||||
try {
|
||||
// @ts-expect-error values of process.env can be string | undefined
|
||||
const env = mergeSafeChainProxyEnvironmentVariables(process.env);
|
||||
await fixYarnProxyEnvironmentVariables(env);
|
||||
|
||||
|
|
@ -12,7 +18,7 @@ export async function runYarnCommand(args) {
|
|||
env,
|
||||
});
|
||||
return { status: result.status };
|
||||
} catch (error) {
|
||||
} catch (/** @type any */ error) {
|
||||
if (error.status) {
|
||||
return { status: error.status };
|
||||
} else {
|
||||
|
|
@ -22,6 +28,11 @@ export async function runYarnCommand(args) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Record<string, string>} env
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function fixYarnProxyEnvironmentVariables(env) {
|
||||
// Yarn ignores standard proxy environment variable HTTPS_PROXY
|
||||
// It does respect NODE_EXTRA_CA_CERTS for custom CA certificates though.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue