beachball
Advanced tools
Comparing version 2.32.4 to 2.33.0
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.gatherBumpInfo = void 0; | ||
const getPackageChangeTypes_1 = require("../changefile/getPackageChangeTypes"); | ||
const changeTypes_1 = require("../changefile/changeTypes"); | ||
const readChangeFiles_1 = require("../changefile/readChangeFiles"); | ||
const bumpInPlace_1 = require("./bumpInPlace"); | ||
const getScopedPackages_1 = require("../monorepo/getScopedPackages"); | ||
function gatherPreBumpInfo(options, packageInfos) { | ||
function gatherBumpInfo(options, packageInfos) { | ||
// Collate the changes per package | ||
const changes = readChangeFiles_1.readChangeFiles(options, packageInfos); | ||
// const dependentChangeTypes: BumpInfo['dependentChangeTypes'] = {}; | ||
const groupOptions = {}; | ||
// Clear non-existent packages from changefiles infos | ||
const calculatedChangeTypes = getPackageChangeTypes_1.initializePackageChangeInfo(changes); | ||
const calculatedChangeTypes = changeTypes_1.initializePackageChangeTypes(changes); | ||
Object.keys(calculatedChangeTypes).forEach(packageName => { | ||
@@ -20,3 +18,3 @@ if (!packageInfos[packageName]) { | ||
}); | ||
return { | ||
const bumpInfo = { | ||
calculatedChangeTypes, | ||
@@ -30,8 +28,5 @@ packageInfos, | ||
dependentChangedBy: {}, | ||
groupOptions, | ||
groupOptions: {}, | ||
dependents: {}, | ||
}; | ||
} | ||
function gatherBumpInfo(options, packageInfos) { | ||
const bumpInfo = gatherPreBumpInfo(options, packageInfos); | ||
bumpInPlace_1.bumpInPlace(bumpInfo, options); | ||
@@ -38,0 +33,0 @@ return bumpInfo; |
@@ -88,8 +88,5 @@ "use strict"; | ||
const packageInfo = bumpInfo.packageInfos[packageName]; | ||
const hookRet = hook(path_1.default.dirname(packageInfo.packageJsonPath), packageName, packageInfo.version); | ||
if (hookRet instanceof Promise) { | ||
await hookRet; | ||
} | ||
await hook(path_1.default.dirname(packageInfo.packageJsonPath), packageName, packageInfo.version); | ||
} | ||
} | ||
//# sourceMappingURL=performBump.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.updateRelatedChangeType = void 0; | ||
const getPackageChangeTypes_1 = require("../changefile/getPackageChangeTypes"); | ||
const changeTypes_1 = require("../changefile/changeTypes"); | ||
/** | ||
@@ -41,4 +41,4 @@ * This is the core of the bumpInfo dependency bumping logic - done once per change file | ||
} | ||
let updatedChangeType = getPackageChangeTypes_1.getMaxChangeType(dependentChangeType, getPackageChangeTypes_1.MinChangeType, []); | ||
const queue = [{ subjectPackage: entryPointPackageName, changeType: getPackageChangeTypes_1.MinChangeType }]; | ||
let updatedChangeType = changeTypes_1.getMaxChangeType(dependentChangeType, changeTypes_1.MinChangeType, []); | ||
const queue = [{ subjectPackage: entryPointPackageName, changeType: changeTypes_1.MinChangeType }]; | ||
// visited is a set of package names that already has been seen by this algorithm - this allows the algo to scale | ||
@@ -89,3 +89,3 @@ const visited = new Set(); | ||
function updateChangeType(pkg, changeType, disallowedChangeTypes) { | ||
const newChangeType = getPackageChangeTypes_1.getMaxChangeType(calculatedChangeTypes[pkg], changeType, disallowedChangeTypes); | ||
const newChangeType = changeTypes_1.getMaxChangeType(calculatedChangeTypes[pkg], changeType, disallowedChangeTypes); | ||
calculatedChangeTypes[pkg] = newChangeType; | ||
@@ -92,0 +92,0 @@ return newChangeType; |
@@ -13,77 +13,4 @@ "use strict"; | ||
const getScopedPackages_1 = require("../monorepo/getScopedPackages"); | ||
const ensureSharedHistory_1 = require("../git/ensureSharedHistory"); | ||
const count = (count, str) => `${count} ${str}${count === 1 ? '' : 's'}`; | ||
/** | ||
* Ensure that adequate history is available to check for changes between HEAD and `options.branch`. | ||
* Otherwise attempting to get changes will fail with an error "no merge base". | ||
*/ | ||
function ensureHistory(options) { | ||
const { fetch, path: cwd, branch } = options; | ||
const { remote, remoteBranch } = workspace_tools_1.parseRemoteBranch(branch); | ||
const fetchMitigationSteps = `- Omit the "--no-fetch" / "--fetch=false" option from the command line | ||
- Remove "fetch: false" from the beachball config | ||
- If this is a CI build, ensure that adequate history is being fetched | ||
- For GitHub Actions (actions/checkout), add the option "fetch-depth: 0" in the checkout step`; | ||
if (fetch) { | ||
// Fetch the latest from the remote branch for comparison | ||
console.log(`fetching latest from remotes "${remote}/${remoteBranch}"`); | ||
workspace_tools_1.fetchRemoteBranch(remote, remoteBranch, cwd); | ||
} | ||
else { | ||
// If fetching is disabled, ensure that the target branch is available for comparison locally | ||
const hasTargetBranch = workspace_tools_1.git(['rev-parse', '--verify', branch], { cwd }).success; | ||
if (!hasTargetBranch) { | ||
// This is most likely to happen in a CI build which does a shallow checkout (github actions/checkout | ||
// does this by default) and for some reason also disables beachball fetching. | ||
const mainError = `Target branch "${branch}" does not exist locally, and fetching is disabled.`; | ||
console.error(` | ||
${mainError} Some possible fixes: | ||
- Fetch the branch manually: git fetch ${remote} ${remoteBranch} | ||
${fetchMitigationSteps} | ||
`); | ||
throw new Error(mainError); | ||
} | ||
} | ||
// Verify that HEAD and the target branch share history | ||
const hasCommonCommit = workspace_tools_1.git(['merge-base', branch, 'HEAD'], { cwd }).success; | ||
if (!hasCommonCommit) { | ||
// This might be a shallow repo, and it's necessary to unshallow the head branch for comparison | ||
const isShallow = workspace_tools_1.git(['rev-parse', '--is-shallow-repository'], { cwd }).stdout.trim() === 'true'; | ||
if (isShallow) { | ||
if (fetch) { | ||
// Fetch more history (if needed, this could be optimized later to only deepen by e.g. 100 commits at a time) | ||
// TODO switch to this after workspace-tools update | ||
// try { | ||
// console.log('This is a shallow clone. Unshallowing to check for changes...'); | ||
// git(['fetch', '--unshallow'], { cwd, throwOnError: true }); | ||
// } catch (err) { | ||
// throw new GitError(`Failed to fetch more history for branch "${branch}"`, err); | ||
// } | ||
console.log('This is a shallow clone. Unshallowing to check for changes...'); | ||
const result = workspace_tools_1.git(['fetch', '--unshallow'], { cwd }); | ||
if (!result.success) { | ||
throw new Error(`Failed to fetch more history for branch "${branch}":\n${result.stderr}`); | ||
} | ||
} | ||
else { | ||
console.error(` | ||
This repo is a shallow clone, fetching is disabled, and not enough history is available to connect HEAD to "${branch}". | ||
Some possible fixes: | ||
- Verify that you're using the correct target branch | ||
- Unshallow or deepen the clone manually | ||
${fetchMitigationSteps} | ||
`); | ||
throw new Error(`Inadequate history available for HEAD to connect it to target branch "${branch}".`); | ||
} | ||
} | ||
else { | ||
// Not a shallow repo, so it's probably using the wrong target branch | ||
throw new Error(`HEAD does not appear to share history with "${branch}" -- are you using the correct target branch?`); | ||
} | ||
} | ||
} | ||
function getMatchingPackageInfo(file, cwd, packageInfosByPath) { | ||
@@ -166,3 +93,3 @@ // Normalize all the paths before comparing (the packageInfosByPath entries should also be normalized) | ||
const changePath = paths_1.getChangePath(cwd); | ||
ensureHistory(options); | ||
ensureSharedHistory_1.ensureSharedHistory(options); | ||
const changedPackages = getAllChangedPackages(options, packageInfos); | ||
@@ -169,0 +96,0 @@ const changeFilesResult = workspace_tools_1.git(['diff', '--name-only', '--relative', '--no-renames', '--diff-filter=A', `${branch}...`], { cwd }); |
@@ -10,3 +10,2 @@ "use strict"; | ||
const prompts_1 = __importDefault(require("prompts")); | ||
const getPackageChangeTypes_1 = require("../changefile/getPackageChangeTypes"); | ||
const readChangeFiles_1 = require("../changefile/readChangeFiles"); | ||
@@ -22,4 +21,3 @@ const bumpAndPush_1 = require("../publish/bumpAndPush"); | ||
const changes = readChangeFiles_1.readChangeFiles(options, oldPackageInfos); | ||
const packageChangeTypes = getPackageChangeTypes_1.initializePackageChangeInfo(changes); | ||
if (Object.keys(packageChangeTypes).length === 0) { | ||
if (!changes.length) { | ||
console.log('Nothing to bump, skipping publish!'); | ||
@@ -26,0 +24,0 @@ return; |
@@ -10,28 +10,33 @@ "use strict"; | ||
function getPackageGroups(packageInfos, root, groups) { | ||
var _a; | ||
if (!groups?.length) { | ||
return {}; | ||
} | ||
const packageGroups = {}; | ||
const packageNameToGroup = {}; | ||
if (groups && groups.length) { | ||
// Check every package to see which group it belongs to | ||
for (const [pkgName, info] of Object.entries(packageInfos)) { | ||
const packagePath = path_1.default.dirname(info.packageJsonPath); | ||
const relativePath = path_1.default.relative(root, packagePath); | ||
for (const groupOption of groups) { | ||
if (isPathIncluded_1.isPathIncluded(relativePath, groupOption.include, groupOption.exclude)) { | ||
const groupName = groupOption.name; | ||
if (packageNameToGroup[pkgName]) { | ||
console.error(`Error: ${pkgName} cannot belong to multiple groups: [${groupName}, ${packageNameToGroup[pkgName]}]!`); | ||
process.exit(1); | ||
} | ||
packageNameToGroup[pkgName] = groupName; | ||
if (!packageGroups[groupName]) { | ||
packageGroups[groupName] = { | ||
packageNames: [], | ||
disallowedChangeTypes: groupOption.disallowedChangeTypes, | ||
}; | ||
} | ||
packageGroups[groupName].packageNames.push(pkgName); | ||
} | ||
} | ||
let hasError = false; | ||
// Check every package to see which group it belongs to | ||
for (const [pkgName, info] of Object.entries(packageInfos)) { | ||
const packagePath = path_1.default.dirname(info.packageJsonPath); | ||
const relativePath = path_1.default.relative(root, packagePath); | ||
const groupsForPkg = groups.filter(group => isPathIncluded_1.isPathIncluded(relativePath, group.include, group.exclude)); | ||
if (groupsForPkg.length > 1) { | ||
// Keep going after this error to ensure we report all errors | ||
console.error(`ERROR: "${pkgName}" cannot belong to multiple groups: [${groupsForPkg.map(g => g.name).join(', ')}]`); | ||
hasError = true; | ||
} | ||
else if (groupsForPkg.length === 1) { | ||
const group = groupsForPkg[0]; | ||
packageNameToGroup[pkgName] = group.name; | ||
packageGroups[_a = group.name] ?? (packageGroups[_a] = { | ||
packageNames: [], | ||
disallowedChangeTypes: group.disallowedChangeTypes, | ||
}); | ||
packageGroups[group.name].packageNames.push(pkgName); | ||
} | ||
} | ||
if (hasError) { | ||
// TODO: probably more appropriate to throw here and let the caller handle it? | ||
process.exit(1); | ||
} | ||
return packageGroups; | ||
@@ -38,0 +43,0 @@ } |
@@ -25,20 +25,6 @@ "use strict"; | ||
function getPackageInfosFromWorkspace(projectRoot) { | ||
let workspacePackages; | ||
try { | ||
const packageInfos = {}; | ||
// first try using the workspace provided packages (if available) | ||
const workspaceInfo = workspace_tools_1.getWorkspaces(projectRoot); | ||
if (workspaceInfo && workspaceInfo.length > 0) { | ||
workspaceInfo.forEach(info => { | ||
const { path: packagePath, packageJson } = info; | ||
const packageJsonPath = path_1.default.join(packagePath, 'package.json'); | ||
try { | ||
packageInfos[packageJson.name] = infoFromPackageJson_1.infoFromPackageJson(packageJson, packageJsonPath); | ||
} | ||
catch (e) { | ||
// Pass, the package.json is invalid | ||
console.warn(`Invalid package.json file detected ${packageJsonPath}: `, e); | ||
} | ||
}); | ||
return packageInfos; | ||
} | ||
workspacePackages = workspace_tools_1.getWorkspaces(projectRoot); | ||
} | ||
@@ -48,28 +34,49 @@ catch (e) { | ||
} | ||
if (!workspacePackages?.length) { | ||
return; | ||
} | ||
const packageInfos = {}; | ||
for (const { path: packagePath, packageJson } of workspacePackages) { | ||
const packageJsonPath = path_1.default.join(packagePath, 'package.json'); | ||
try { | ||
packageInfos[packageJson.name] = infoFromPackageJson_1.infoFromPackageJson(packageJson, packageJsonPath); | ||
} | ||
catch (e) { | ||
// Pass, the package.json is invalid | ||
console.warn(`Problem processing ${packageJsonPath}: ${e}`); | ||
} | ||
} | ||
return packageInfos; | ||
} | ||
function getPackageInfosFromNonWorkspaceMonorepo(projectRoot) { | ||
const packageJsonFiles = workspace_tools_1.listAllTrackedFiles(['**/package.json', 'package.json'], projectRoot); | ||
if (!packageJsonFiles.length) { | ||
return; | ||
} | ||
const packageInfos = {}; | ||
if (packageJsonFiles && packageJsonFiles.length > 0) { | ||
packageJsonFiles.forEach(packageJsonPath => { | ||
let hasDuplicatePackage = false; | ||
try { | ||
const packageJsonFullPath = path_1.default.join(projectRoot, packageJsonPath); | ||
const packageJson = fs_extra_1.default.readJSONSync(packageJsonFullPath); | ||
if (packageInfos[packageJson.name]) { | ||
hasDuplicatePackage = true; | ||
throw new Error(`Two packages in different workspaces have the same name. Please rename one of these packages:\n- ${packageInfos[packageJson.name].packageJsonPath}\n- ${packageJsonPath}`); | ||
} | ||
let hasError = false; | ||
for (const packageJsonPath of packageJsonFiles) { | ||
try { | ||
const packageJsonFullPath = path_1.default.join(projectRoot, packageJsonPath); | ||
const packageJson = fs_extra_1.default.readJSONSync(packageJsonFullPath); | ||
if (!packageInfos[packageJson.name]) { | ||
packageInfos[packageJson.name] = infoFromPackageJson_1.infoFromPackageJson(packageJson, packageJsonFullPath); | ||
} | ||
catch (e) { | ||
if (hasDuplicatePackage) { | ||
throw e; // duplicate package error should propagate | ||
} | ||
// Pass, the package.json is invalid | ||
console.warn(`Invalid package.json file detected ${packageJsonPath}: `, e); | ||
else { | ||
console.error(`ERROR: Two packages have the same name "${packageJson.name}". Please rename one of these packages:\n` + | ||
`- ${path_1.default.relative(projectRoot, packageInfos[packageJson.name].packageJsonPath)}\n` + | ||
`- ${packageJsonPath}`); | ||
// Keep going so we can log all the errors | ||
hasError = true; | ||
} | ||
}); | ||
return packageInfos; | ||
} | ||
catch (e) { | ||
// Pass, the package.json is invalid | ||
console.warn(`Problem processing ${packageJsonPath}: ${e}`); | ||
} | ||
} | ||
if (hasError) { | ||
throw new Error('Duplicate package names found (see above for details)'); | ||
} | ||
return packageInfos; | ||
} | ||
@@ -76,0 +83,0 @@ function getPackageInfosFromSingleRepo(packageRoot) { |
@@ -7,66 +7,59 @@ "use strict"; | ||
const tagPackages_1 = require("./tagPackages"); | ||
const mergePublishBranch_1 = require("./mergePublishBranch"); | ||
const displayManualRecovery_1 = require("./displayManualRecovery"); | ||
const fetch_1 = require("../git/fetch"); | ||
const gitAsync_1 = require("../git/gitAsync"); | ||
const BUMP_PUSH_RETRIES = 5; | ||
/** Use verbose logging for these steps to make it easier to debug if something goes wrong */ | ||
const verbose = true; | ||
async function bumpAndPush(bumpInfo, publishBranch, options) { | ||
const { path: cwd, branch, depth, message, gitTimeout } = options; | ||
const { path: cwd, branch, depth, gitTimeout } = options; | ||
const { remote, remoteBranch } = workspace_tools_1.parseRemoteBranch(branch); | ||
let completed = false; | ||
let tryNumber = 0; | ||
/** Log a warning which includes the attempt number */ | ||
const logRetryWarning = (text, details = '(see above for details)') => console.warn(`[WARN ${tryNumber}/${BUMP_PUSH_RETRIES}]: ${text} ${details}`); | ||
while (tryNumber < BUMP_PUSH_RETRIES && !completed) { | ||
tryNumber++; | ||
console.log('-'.repeat(80)); | ||
console.log(`Trying to push to git. Attempt ${tryNumber}/${BUMP_PUSH_RETRIES}`); | ||
console.log('Reverting'); | ||
workspace_tools_1.revertLocalChanges(cwd); | ||
const warnPrefix = `[WARN ${tryNumber}/${BUMP_PUSH_RETRIES}]:`; | ||
// pull in latest from origin branch | ||
if (options.fetch !== false) { | ||
console.log('Fetching from remote'); | ||
const fetchResult = workspace_tools_1.git(['fetch', remote, remoteBranch, ...(depth ? [`--depth=${depth}`] : [])], { cwd }); | ||
console.log(); | ||
const fetchResult = fetch_1.gitFetch({ remote, branch: remoteBranch, depth, cwd, verbose }); | ||
if (!fetchResult.success) { | ||
console.warn(`${warnPrefix} fetch from ${branch} has failed!\n${fetchResult.stderr}`); | ||
logRetryWarning(`Fetching from ${branch} has failed!`); | ||
continue; | ||
} | ||
} | ||
const mergeResult = workspace_tools_1.git(['merge', '-X', 'theirs', `${branch}`], { cwd }); | ||
console.log(`\nMerging with ${branch}...`); | ||
const mergeResult = await gitAsync_1.gitAsync(['merge', '-X', 'theirs', branch], { cwd, verbose }); | ||
if (!mergeResult.success) { | ||
console.warn(`${warnPrefix} pull from ${branch} has failed!\n${mergeResult.stderr}`); | ||
logRetryWarning(`Merging with latest ${branch} has failed!`); | ||
continue; | ||
} | ||
// bump the version | ||
console.log('Bumping the versions for git push'); | ||
console.log('\nBumping the versions for git push'); | ||
await performBump_1.performBump(bumpInfo, options); | ||
// checkin | ||
const mergePublishBranchResult = await mergePublishBranch_1.mergePublishBranch(publishBranch, branch, message, cwd, options); | ||
if (!mergePublishBranchResult.success) { | ||
console.warn(`${warnPrefix} merging to target has failed!`); | ||
if (!(await mergePublishBranch(publishBranch, options))) { | ||
logRetryWarning('Merging to target has failed!'); | ||
continue; | ||
} | ||
// Tag & Push to remote | ||
// create git tags | ||
console.log('\nCreating git tags for new versions...'); | ||
tagPackages_1.tagPackages(bumpInfo, options); | ||
console.log(`pushing to ${branch}, running the following command for git push:`); | ||
const pushArgs = ['push', '--no-verify', '--follow-tags', '--verbose', remote, `HEAD:${remoteBranch}`]; | ||
console.log('git ' + pushArgs.join(' ')); | ||
try { | ||
const pushResult = workspace_tools_1.git(pushArgs, { cwd, timeout: gitTimeout }); | ||
if (!pushResult.success) { | ||
// If it timed out, the return value contains an "error" object with ETIMEDOUT code | ||
// (it doesn't throw the error) | ||
if (pushResult.error?.code === 'ETIMEDOUT') { | ||
console.warn(`${warnPrefix} push to ${branch} has timed out!`); | ||
} | ||
else { | ||
console.warn(`${warnPrefix} push to ${branch} has failed!\n${pushResult.stderr}`); | ||
} | ||
} | ||
else { | ||
console.log(pushResult.stdout.toString()); | ||
console.log(pushResult.stderr.toString()); | ||
completed = true; | ||
} | ||
// push | ||
console.log(`\nPushing to ${branch}...`); | ||
const pushResult = await gitAsync_1.gitAsync(['push', '--no-verify', '--follow-tags', '--verbose', remote, `HEAD:${remoteBranch}`], { cwd, verbose, timeout: gitTimeout }); | ||
if (pushResult.success) { | ||
completed = true; | ||
} | ||
catch (e) { | ||
// This is likely not reachable (see comment above), but leaving it just in case for this critical operation | ||
console.warn(`${warnPrefix} push to ${branch} has failed!\n${e}`); | ||
else if (pushResult.timedOut) { | ||
logRetryWarning(`Pushing to ${branch} has timed out!`); | ||
} | ||
else { | ||
logRetryWarning(`Pushing to ${branch} has failed!`); | ||
} | ||
} | ||
@@ -79,2 +72,19 @@ if (!completed) { | ||
exports.bumpAndPush = bumpAndPush; | ||
async function mergePublishBranch(publishBranch, options) { | ||
await options.hooks?.precommit?.(options.path); | ||
console.log(`\nMerging ${publishBranch} into ${options.branch}...`); | ||
const mergeSteps = [ | ||
['add', '.'], | ||
['commit', '-m', options.message], | ||
['checkout', options.branch], | ||
['merge', '-X', 'ours', publishBranch], | ||
]; | ||
for (const step of mergeSteps) { | ||
const result = await gitAsync_1.gitAsync(step, { cwd: options.path, verbose }); | ||
if (!result.success) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
//# sourceMappingURL=bumpAndPush.js.map |
@@ -101,6 +101,3 @@ "use strict"; | ||
const packageInfo = bumpInfo.packageInfos[pkg]; | ||
const maybeAwait = postpublishHook(path_1.default.dirname(packageInfo.packageJsonPath), packageInfo.name, packageInfo.version); | ||
if (maybeAwait instanceof Promise) { | ||
await maybeAwait; | ||
} | ||
await postpublishHook(path_1.default.dirname(packageInfo.packageJsonPath), packageInfo.name, packageInfo.version); | ||
} | ||
@@ -107,0 +104,0 @@ } |
@@ -29,2 +29,3 @@ "use strict"; | ||
if (gitTags && distTag && distTag !== 'latest') { | ||
console.log(`Tagging - ${distTag}`); | ||
createTag(distTag, cwd); | ||
@@ -31,0 +32,0 @@ } |
@@ -35,3 +35,9 @@ import { AuthType } from './Auth'; | ||
access: 'public' | 'restricted'; | ||
/** The target branch */ | ||
/** | ||
* The target branch. In the repo or CLI config, this can be specified without a remote name | ||
* as long as `repository` is set in `package.json` to allow inferring the correct remote. | ||
* | ||
* (In the resolved config used internally, the remote name should *usually* be included, | ||
* unless neither a remote name nor `package.json` `repository` was specified.) | ||
*/ | ||
branch: string; | ||
@@ -80,3 +86,3 @@ /** Bump dependent packages during publish (bump A if A depends on B) */ | ||
groupChanges?: boolean; | ||
/** Depth of git history to consider when doing fetch */ | ||
/** For shallow clones only: Depth of git history to consider when doing fetch */ | ||
depth?: number; | ||
@@ -83,0 +89,0 @@ } |
{ | ||
"name": "beachball", | ||
"version": "2.32.4", | ||
"version": "2.33.0", | ||
"description": "The Sunniest Semantic Version Bumper", | ||
@@ -5,0 +5,0 @@ "repository": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
335850
312
4192
17
3