mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-28 02:53:15 -04:00
6
.changeset/curly-plums-change.md
Normal file
6
.changeset/curly-plums-change.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": patch
|
||||
"pnpm": patch
|
||||
---
|
||||
|
||||
Properly resolve peer dependencies of peer dependencies [#7444](https://github.com/pnpm/pnpm/issues/7444).
|
||||
@@ -44,7 +44,7 @@
|
||||
"@pnpm/constants": "workspace:*",
|
||||
"@pnpm/lockfile-types": "workspace:*",
|
||||
"@pnpm/modules-yaml": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"is-windows": "^1.0.2",
|
||||
"isexe": "2.0.0",
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"test": "pnpm pretest && pnpm run compile && jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/store.cafs": "workspace:*",
|
||||
"path-exists": "^4.0.0"
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-rebuild": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@pnpm/test-ipc-server": "workspace:*",
|
||||
"@types/ramda": "0.28.20",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-script-runners": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-ipc-server": "workspace:*",
|
||||
"@types/is-windows": "^1.0.2",
|
||||
"@types/ramda": "0.28.20",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"@commitlint/prompt-cli": "^17.8.1",
|
||||
"@pnpm/eslint-config": "workspace:*",
|
||||
"@pnpm/meta-updater": "1.0.0",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/tsconfig": "workspace:*",
|
||||
"@pnpm/worker": "workspace:*",
|
||||
"@types/jest": "^29.5.8",
|
||||
@@ -112,8 +112,7 @@
|
||||
"allowedVersions": {
|
||||
"eslint": "*"
|
||||
},
|
||||
"ignoreMissing": [
|
||||
]
|
||||
"ignoreMissing": []
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"pkg@5.8.1": "__patches__/pkg.patch",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-patching": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/normalize-path": "^3.0.2",
|
||||
"@types/ramda": "0.28.20",
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
"@pnpm/lockfile-types": "workspace:*",
|
||||
"@pnpm/package-store": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/store-path": "workspace:*",
|
||||
"@pnpm/store.cafs": "workspace:*",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
|
||||
@@ -1465,3 +1465,69 @@ test('in a subdependency, when there are several aliased dependencies of the sam
|
||||
const lockfile = await readYamlFile<any>(path.resolve(WANTED_LOCKFILE)) // eslint-disable-line
|
||||
expect(lockfile.packages['/@pnpm.e2e/abc@1.0.0(@pnpm.e2e/peer-c@2.0.0)']).toBeTruthy()
|
||||
})
|
||||
|
||||
test('peer having peer is resolved correctly', async () => {
|
||||
const manifest1 = {
|
||||
name: 'project-1',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/has-has-y-peer-only-as-peer': '1.0.0',
|
||||
'@pnpm.e2e/has-y-peer': '1.0.0',
|
||||
'@pnpm/y': '1.0.0',
|
||||
},
|
||||
}
|
||||
const manifest2 = {
|
||||
name: 'project-2',
|
||||
|
||||
dependencies: {
|
||||
'@pnpm.e2e/has-has-y-peer-only-as-peer': '1.0.0',
|
||||
'@pnpm.e2e/has-y-peer': '1.0.0',
|
||||
'@pnpm/y': '2.0.0',
|
||||
},
|
||||
}
|
||||
preparePackages([
|
||||
{
|
||||
location: 'project-1',
|
||||
package: manifest1,
|
||||
},
|
||||
{
|
||||
location: 'project-2',
|
||||
package: manifest2,
|
||||
},
|
||||
])
|
||||
|
||||
const importers: MutatedProject[] = [
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
mutation: 'install',
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
const allProjects = [
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: manifest1,
|
||||
rootDir: path.resolve('project-1'),
|
||||
},
|
||||
{
|
||||
buildIndex: 0,
|
||||
manifest: manifest2,
|
||||
rootDir: path.resolve('project-2'),
|
||||
},
|
||||
]
|
||||
await mutateModules(importers, await testDefaults({
|
||||
allProjects,
|
||||
autoInstallPeers: false,
|
||||
dedupePeerDependents: false,
|
||||
lockfileOnly: true,
|
||||
strictPeerDependencies: false,
|
||||
}))
|
||||
|
||||
const lockfile = await readYamlFile<any>(path.resolve(WANTED_LOCKFILE)) // eslint-disable-line
|
||||
|
||||
expect(lockfile.importers['project-1'].dependencies?.['@pnpm.e2e/has-has-y-peer-only-as-peer']['version']).not.toEqual(lockfile.importers['project-2'].dependencies?.['@pnpm.e2e/has-has-y-peer-only-as-peer']['version'])
|
||||
expect(lockfile.packages['/@pnpm.e2e/has-has-y-peer-only-as-peer@1.0.0(@pnpm.e2e/has-y-peer@1.0.0)(@pnpm/y@1.0.0)'].transitivePeerDependencies).toEqual(['@pnpm/y'])
|
||||
})
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"@pnpm/package-store": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/read-projects-context": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/store-path": "workspace:*",
|
||||
"@pnpm/store.cafs": "workspace:*",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"@pnpm/client": "workspace:*",
|
||||
"@pnpm/create-cafs-store": "workspace:*",
|
||||
"@pnpm/package-requester": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/normalize-path": "^3.0.2",
|
||||
"@types/ramda": "0.28.20",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@pnpm/modules-yaml": "workspace:*",
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@pnpm/test-ipc-server": "workspace:*",
|
||||
"@types/proxyquire": "^1.3.31",
|
||||
|
||||
@@ -32,10 +32,8 @@ import {
|
||||
import {
|
||||
type SupportedArchitectures,
|
||||
type AllowedDeprecatedVersions,
|
||||
type Dependencies,
|
||||
type PackageManifest,
|
||||
type PatchFile,
|
||||
type PeerDependenciesMeta,
|
||||
type ReadPackageHook,
|
||||
type Registries,
|
||||
} from '@pnpm/types'
|
||||
@@ -199,6 +197,13 @@ export type PkgAddress = {
|
||||
isLinkedDependency: undefined
|
||||
})
|
||||
|
||||
export interface PeerDependency {
|
||||
version: string
|
||||
optional?: boolean
|
||||
}
|
||||
|
||||
export type PeerDependencies = Record<string, PeerDependency>
|
||||
|
||||
export interface ResolvedPackage {
|
||||
id: string
|
||||
resolution: Resolution
|
||||
@@ -209,8 +214,7 @@ export interface ResolvedPackage {
|
||||
filesIndexFile: string
|
||||
name: string
|
||||
version: string
|
||||
peerDependencies: Dependencies
|
||||
peerDependenciesMeta?: PeerDependenciesMeta
|
||||
peerDependencies: PeerDependencies
|
||||
optionalDependencies: Set<string>
|
||||
hasBin: boolean
|
||||
hasBundledDependencies: boolean
|
||||
@@ -1458,8 +1462,7 @@ function getResolvedPackage (
|
||||
optional: options.optional,
|
||||
optionalDependencies: new Set(Object.keys(options.pkg.optionalDependencies ?? {})),
|
||||
patchFile: options.patchFile,
|
||||
peerDependencies: peerDependencies ?? {},
|
||||
peerDependenciesMeta: options.pkg.peerDependenciesMeta,
|
||||
peerDependencies,
|
||||
prepare: options.prepare,
|
||||
prod: !options.wantedDependency.dev && !options.wantedDependency.optional,
|
||||
requiresBuild,
|
||||
@@ -1468,25 +1471,27 @@ function getResolvedPackage (
|
||||
}
|
||||
}
|
||||
|
||||
function peerDependenciesWithoutOwn (pkg: PackageManifest) {
|
||||
if ((pkg.peerDependencies == null) && (pkg.peerDependenciesMeta == null)) return pkg.peerDependencies
|
||||
function peerDependenciesWithoutOwn (pkg: PackageManifest): PeerDependencies {
|
||||
if ((pkg.peerDependencies == null) && (pkg.peerDependenciesMeta == null)) return {}
|
||||
const ownDeps = new Set([
|
||||
...Object.keys(pkg.dependencies ?? {}),
|
||||
...Object.keys(pkg.optionalDependencies ?? {}),
|
||||
])
|
||||
const result: Record<string, string> = {}
|
||||
const result: PeerDependencies = {}
|
||||
if (pkg.peerDependencies != null) {
|
||||
for (const [peerName, peerRange] of Object.entries(pkg.peerDependencies)) {
|
||||
if (ownDeps.has(peerName)) continue
|
||||
result[peerName] = peerRange
|
||||
result[peerName] = {
|
||||
version: peerRange,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pkg.peerDependenciesMeta != null) {
|
||||
for (const [peerName, peerMeta] of Object.entries(pkg.peerDependenciesMeta)) {
|
||||
if (ownDeps.has(peerName) || result[peerName] || peerMeta.optional !== true) continue
|
||||
result[peerName] = '*'
|
||||
if (ownDeps.has(peerName) || peerMeta.optional !== true) continue
|
||||
if (!result[peerName]) result[peerName] = { version: '*' }
|
||||
result[peerName].optional = true
|
||||
}
|
||||
}
|
||||
if (Object.keys(result).length === 0) return undefined
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import path from 'path'
|
||||
import semver from 'semver'
|
||||
import { semverUtils } from '@yarnpkg/core'
|
||||
import type {
|
||||
Dependencies,
|
||||
PeerDependencyIssues,
|
||||
PeerDependencyIssuesByProjects,
|
||||
} from '@pnpm/types'
|
||||
@@ -13,6 +12,7 @@ import partition from 'ramda/src/partition'
|
||||
import pick from 'ramda/src/pick'
|
||||
import scan from 'ramda/src/scan'
|
||||
import {
|
||||
type PeerDependencies,
|
||||
type DependenciesTree,
|
||||
type DependenciesTreeNode,
|
||||
type ResolvedPackage,
|
||||
@@ -28,7 +28,7 @@ export interface GenericDependenciesGraphNode {
|
||||
dir: string
|
||||
children: Record<string, string>
|
||||
depth: number
|
||||
peerDependencies?: Dependencies
|
||||
peerDependencies?: PeerDependencies
|
||||
transitivePeerDependencies: Set<string>
|
||||
installable: boolean
|
||||
isBuilt?: boolean
|
||||
@@ -41,7 +41,6 @@ export type PartialResolvedPackage = Pick<ResolvedPackage,
|
||||
| 'depPath'
|
||||
| 'name'
|
||||
| 'peerDependencies'
|
||||
| 'peerDependenciesMeta'
|
||||
| 'version'
|
||||
>
|
||||
|
||||
@@ -352,35 +351,24 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
}
|
||||
|
||||
const {
|
||||
resolvedPeers: unknownResolvedPeersOfChildren,
|
||||
resolvedPeers: resolvedPeersOfChildren,
|
||||
missingPeers: missingPeersOfChildren,
|
||||
} = resolvePeersOfChildren(children, parentPkgs, ctx)
|
||||
|
||||
const { resolvedPeers, missingPeers } = Object.keys(resolvedPackage.peerDependencies).length === 0
|
||||
? { resolvedPeers: new Map<string, string>(), missingPeers: new Set<string>() }
|
||||
: _resolvePeers({
|
||||
currentDepth: node.depth,
|
||||
dependenciesTree: ctx.dependenciesTree,
|
||||
lockfileDir: ctx.lockfileDir,
|
||||
nodeId,
|
||||
parentPkgs,
|
||||
peerDependencyIssues: ctx.peerDependencyIssues,
|
||||
resolvedPackage,
|
||||
rootDir: ctx.rootDir,
|
||||
})
|
||||
const { allMissingPeers, allResolvedPeers } = resolvePeersAndTheirPeers({
|
||||
currentDepth: node.depth,
|
||||
dependenciesTree: ctx.dependenciesTree,
|
||||
lockfileDir: ctx.lockfileDir,
|
||||
nodeId,
|
||||
parentPkgs,
|
||||
peerDependencyIssues: ctx.peerDependencyIssues,
|
||||
resolvedPackage,
|
||||
rootDir: ctx.rootDir,
|
||||
resolvedPeersOfChildren,
|
||||
})
|
||||
|
||||
const allResolvedPeers = unknownResolvedPeersOfChildren
|
||||
for (const [k, v] of resolvedPeers) {
|
||||
allResolvedPeers.set(k, v)
|
||||
}
|
||||
allResolvedPeers.delete(node.resolvedPackage.name)
|
||||
|
||||
const allMissingPeers = new Set<string>()
|
||||
for (const peer of missingPeersOfChildren) {
|
||||
allMissingPeers.add(peer)
|
||||
}
|
||||
for (const peer of missingPeers) {
|
||||
allMissingPeers.add(peer)
|
||||
for (const missingPeer of missingPeersOfChildren) {
|
||||
allMissingPeers.add(missingPeer)
|
||||
}
|
||||
|
||||
let depPath: string
|
||||
@@ -435,7 +423,7 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
const dir = path.join(modules, resolvedPackage.name)
|
||||
|
||||
const transitivePeerDependencies = new Set<string>()
|
||||
for (const unknownPeer of unknownResolvedPeersOfChildren.keys()) {
|
||||
for (const unknownPeer of allResolvedPeers.keys()) {
|
||||
if (!peerDependencies[unknownPeer]) {
|
||||
transitivePeerDependencies.add(unknownPeer)
|
||||
}
|
||||
@@ -450,7 +438,7 @@ function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||
children: Object.assign(
|
||||
getPreviouslyResolvedChildren(nodeId, ctx.dependenciesTree),
|
||||
children,
|
||||
Object.fromEntries(resolvedPeers.entries())
|
||||
Object.fromEntries(Array.from(allResolvedPeers.entries()).filter(([peerName]) => resolvedPackage.peerDependencies[peerName]))
|
||||
),
|
||||
depPath,
|
||||
depth: node.depth,
|
||||
@@ -540,32 +528,94 @@ function resolvePeersOfChildren<T extends PartialResolvedPackage> (
|
||||
return { resolvedPeers: unknownResolvedPeersOfChildren, missingPeers: allMissingPeers }
|
||||
}
|
||||
|
||||
function _resolvePeers<T extends PartialResolvedPackage> (
|
||||
ctx: {
|
||||
currentDepth: number
|
||||
lockfileDir: string
|
||||
nodeId: string
|
||||
parentPkgs: ParentRefs
|
||||
resolvedPackage: T
|
||||
dependenciesTree: DependenciesTree<T>
|
||||
rootDir: string
|
||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||
function resolvePeersAndTheirPeers<T extends PartialResolvedPackage> (
|
||||
ctx: Omit<ResolvePeersOptions<T>, 'directParentPkg'> & {
|
||||
resolvedPackage: Pick<PartialResolvedPackage, 'name' | 'version' | 'peerDependencies'>
|
||||
resolvedPeersOfChildren: Map<string, string>
|
||||
}
|
||||
) {
|
||||
const allMissingPeers = new Set<string>()
|
||||
const allResolvedPeers = ctx.resolvedPeersOfChildren
|
||||
let peerDependencies = ctx.resolvedPackage.peerDependencies
|
||||
for (const peerNodeId of allResolvedPeers.values()) {
|
||||
const peerNode = ctx.dependenciesTree.get(peerNodeId)
|
||||
if (!peerNode) continue
|
||||
const peerPkg = peerNode.resolvedPackage as T
|
||||
peerDependencies = {
|
||||
...peerPkg.peerDependencies,
|
||||
...peerDependencies,
|
||||
}
|
||||
}
|
||||
const directParentPkg = {
|
||||
name: ctx.resolvedPackage.name,
|
||||
version: ctx.resolvedPackage.version,
|
||||
}
|
||||
const _resolvePeersFn = _resolvePeers.bind(null, {
|
||||
currentDepth: ctx.currentDepth,
|
||||
dependenciesTree: ctx.dependenciesTree,
|
||||
directParentPkg,
|
||||
lockfileDir: ctx.lockfileDir,
|
||||
nodeId: ctx.nodeId,
|
||||
parentPkgs: ctx.parentPkgs,
|
||||
peerDependencyIssues: ctx.peerDependencyIssues,
|
||||
rootDir: ctx.rootDir,
|
||||
})
|
||||
while (Object.keys(peerDependencies).length > 0) {
|
||||
const { resolvedPeers, missingPeers } = _resolvePeersFn(peerDependencies)
|
||||
for (const peer of missingPeers) {
|
||||
allMissingPeers.add(peer)
|
||||
}
|
||||
peerDependencies = {}
|
||||
for (const peerNodeId of resolvedPeers.values()) {
|
||||
const peerNode = ctx.dependenciesTree.get(peerNodeId)
|
||||
if (!peerNode) continue
|
||||
const peerPkg = peerNode.resolvedPackage as T
|
||||
for (const [peerName, peer] of Object.entries(peerPkg.peerDependencies ?? {})) {
|
||||
if (!allResolvedPeers.has(peerName)) {
|
||||
// It might happen that there are multiple peers depending on the same peers.
|
||||
// In this case we pick the peer information only from one dependency.
|
||||
// This will not break anything except possibly peer dependency warnings.
|
||||
peerDependencies[peerName] = peer
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const [alias, nodeId] of resolvedPeers) {
|
||||
allResolvedPeers.set(alias, nodeId)
|
||||
}
|
||||
}
|
||||
allResolvedPeers.delete(ctx.resolvedPackage.name)
|
||||
return { allMissingPeers, allResolvedPeers }
|
||||
}
|
||||
|
||||
interface ResolvePeersOptions<T> {
|
||||
currentDepth: number
|
||||
dependenciesTree: DependenciesTree<T>
|
||||
directParentPkg: Pick<PartialResolvedPackage, 'name' | 'version'>
|
||||
lockfileDir: string
|
||||
nodeId: string
|
||||
parentPkgs: ParentRefs
|
||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||
rootDir: string
|
||||
}
|
||||
|
||||
function _resolvePeers<T extends PartialResolvedPackage> (
|
||||
ctx: ResolvePeersOptions<T>,
|
||||
peerDependencies: PeerDependencies
|
||||
): PeersResolution {
|
||||
const resolvedPeers = new Map<string, string>()
|
||||
const missingPeers = new Set<string>()
|
||||
for (const peerName in ctx.resolvedPackage.peerDependencies) { // eslint-disable-line:forin
|
||||
const peerVersionRange = ctx.resolvedPackage.peerDependencies[peerName].replace(/^workspace:/, '')
|
||||
for (const [peerName, { version, optional }] of Object.entries(peerDependencies)) {
|
||||
const peerVersionRange = version.replace(/^workspace:/, '')
|
||||
|
||||
const resolved = ctx.parentPkgs[peerName]
|
||||
const optionalPeer = ctx.resolvedPackage.peerDependenciesMeta?.[peerName]?.optional === true
|
||||
const optionalPeer = optional === true
|
||||
|
||||
if (!resolved) {
|
||||
missingPeers.add(peerName)
|
||||
const location = getLocationFromNodeIdAndPkg({
|
||||
dependenciesTree: ctx.dependenciesTree,
|
||||
nodeId: ctx.nodeId,
|
||||
pkg: ctx.resolvedPackage,
|
||||
pkg: ctx.directParentPkg,
|
||||
})
|
||||
if (!ctx.peerDependencyIssues.missing[peerName]) {
|
||||
ctx.peerDependencyIssues.missing[peerName] = []
|
||||
@@ -582,7 +632,7 @@ function _resolvePeers<T extends PartialResolvedPackage> (
|
||||
const location = getLocationFromNodeIdAndPkg({
|
||||
dependenciesTree: ctx.dependenciesTree,
|
||||
nodeId: ctx.nodeId,
|
||||
pkg: ctx.resolvedPackage,
|
||||
pkg: ctx.directParentPkg,
|
||||
})
|
||||
if (!ctx.peerDependencyIssues.bad[peerName]) {
|
||||
ctx.peerDependencyIssues.bad[peerName] = []
|
||||
|
||||
@@ -117,19 +117,19 @@ function toLockfileDependency (
|
||||
if (opts.depPath[0] !== '/' && !pkg.id.endsWith(opts.depPath)) {
|
||||
result['id'] = pkg.id
|
||||
}
|
||||
if (Object.keys(pkg.peerDependencies ?? {}).length > 0) {
|
||||
result['peerDependencies'] = pkg.peerDependencies
|
||||
}
|
||||
if (pkg.transitivePeerDependencies.size) {
|
||||
result['transitivePeerDependencies'] = Array.from(pkg.transitivePeerDependencies).sort()
|
||||
}
|
||||
if (pkg.peerDependenciesMeta != null) {
|
||||
if (Object.keys(pkg.peerDependencies ?? {}).length > 0) {
|
||||
const peerPkgs: Record<string, string> = {}
|
||||
const normalizedPeerDependenciesMeta: Record<string, { optional: true }> = {}
|
||||
for (const [peer, { optional }] of Object.entries(pkg.peerDependenciesMeta)) {
|
||||
for (const [peer, { version, optional }] of Object.entries(pkg.peerDependencies)) {
|
||||
peerPkgs[peer] = version
|
||||
if (optional) {
|
||||
normalizedPeerDependenciesMeta[peer] = { optional: true }
|
||||
}
|
||||
}
|
||||
result['peerDependencies'] = peerPkgs
|
||||
if (Object.keys(normalizedPeerDependenciesMeta).length > 0) {
|
||||
result['peerDependenciesMeta'] = normalizedPeerDependenciesMeta
|
||||
}
|
||||
|
||||
@@ -8,13 +8,8 @@ test('packages are not deduplicated when versions do not match', () => {
|
||||
depPath: 'foo/1.0.0',
|
||||
id: '',
|
||||
peerDependencies: {
|
||||
bar: '1.0.0 || 2.0.0',
|
||||
baz: '1.0.0 || 2.0.0',
|
||||
},
|
||||
peerDependenciesMeta: {
|
||||
baz: {
|
||||
optional: true,
|
||||
},
|
||||
bar: { version: '1.0.0 || 2.0.0' },
|
||||
baz: { version: '1.0.0 || 2.0.0', optional: true },
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference path="../../../__typings__/index.d.ts" />
|
||||
import { type PartialResolvedPackage, resolvePeers } from '../lib/resolvePeers'
|
||||
import { type DependenciesTreeNode } from '../lib/resolveDependencies'
|
||||
import { type DependenciesTreeNode, type PeerDependencies } from '../lib/resolveDependencies'
|
||||
|
||||
test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
const fooPkg = {
|
||||
@@ -8,8 +8,8 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
depPath: 'foo/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
qar: '1.0.0',
|
||||
zoo: '1.0.0',
|
||||
qar: { version: '1.0.0' },
|
||||
zoo: { version: '1.0.0' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -18,9 +18,9 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
depPath: 'bar/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
foo: '1.0.0',
|
||||
zoo: '1.0.0',
|
||||
} as Record<string, string>,
|
||||
foo: { version: '1.0.0' },
|
||||
zoo: { version: '1.0.0' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
const { dependenciesGraph } = resolvePeers({
|
||||
@@ -62,8 +62,8 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
depPath: 'qar/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
foo: '1.0.0',
|
||||
bar: '1.0.0',
|
||||
foo: { version: '1.0.0' },
|
||||
bar: { version: '1.0.0' },
|
||||
},
|
||||
id: '',
|
||||
},
|
||||
@@ -80,7 +80,7 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
depPath: 'zoo/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
qar: '1.0.0',
|
||||
qar: { version: '1.0.0' },
|
||||
},
|
||||
id: '',
|
||||
},
|
||||
@@ -103,12 +103,10 @@ test('resolve peer dependencies of cyclic dependencies', () => {
|
||||
lockfileDir: '',
|
||||
})
|
||||
expect(Object.keys(dependenciesGraph)).toStrictEqual([
|
||||
'foo/1.0.0(qar@1.0.0)(zoo@1.0.0)',
|
||||
'bar/1.0.0(foo@1.0.0)(zoo@1.0.0)',
|
||||
'zoo/1.0.0(qar@1.0.0)',
|
||||
'qar/1.0.0(bar@1.0.0)(foo@1.0.0)',
|
||||
'bar/1.0.0(foo@1.0.0)',
|
||||
'foo/1.0.0',
|
||||
'foo/1.0.0(bar@1.0.0)(qar@1.0.0)(zoo@1.0.0)',
|
||||
'bar/1.0.0(foo@1.0.0)(qar@1.0.0)(zoo@1.0.0)',
|
||||
'zoo/1.0.0(bar@1.0.0)(foo@1.0.0)(qar@1.0.0)',
|
||||
'qar/1.0.0(bar@1.0.0)(foo@1.0.0)(zoo@1.0.0)',
|
||||
])
|
||||
})
|
||||
|
||||
@@ -118,7 +116,7 @@ test('when a package is referenced twice in the dependencies graph and one of th
|
||||
depPath: 'foo/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
qar: '1.0.0',
|
||||
qar: { version: '1.0.0' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -126,14 +124,14 @@ test('when a package is referenced twice in the dependencies graph and one of th
|
||||
name: 'bar',
|
||||
depPath: 'bar/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {} as Record<string, string>,
|
||||
peerDependencies: {} as PeerDependencies,
|
||||
id: '',
|
||||
}
|
||||
const zooPkg = {
|
||||
name: 'zoo',
|
||||
depPath: 'zoo/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {} as Record<string, string>,
|
||||
peerDependencies: {} as PeerDependencies,
|
||||
id: '',
|
||||
}
|
||||
const { dependenciesGraph } = resolvePeers({
|
||||
@@ -219,7 +217,7 @@ describe('peer dependency issues', () => {
|
||||
depPath: 'foo/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
peer: '1',
|
||||
peer: { version: '1' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -228,12 +226,7 @@ describe('peer dependency issues', () => {
|
||||
depPath: 'foo/2.0.0',
|
||||
version: '2.0.0',
|
||||
peerDependencies: {
|
||||
peer: '1',
|
||||
},
|
||||
peerDependenciesMeta: {
|
||||
peer: {
|
||||
optional: true,
|
||||
},
|
||||
peer: { version: '1', optional: true },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -242,7 +235,7 @@ describe('peer dependency issues', () => {
|
||||
depPath: 'bar/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
peer: '2',
|
||||
peer: { version: '2' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -251,12 +244,7 @@ describe('peer dependency issues', () => {
|
||||
depPath: 'bar/2.0.0',
|
||||
version: '2.0.0',
|
||||
peerDependencies: {
|
||||
peer: '2',
|
||||
},
|
||||
peerDependenciesMeta: {
|
||||
peer: {
|
||||
optional: true,
|
||||
},
|
||||
peer: { version: '2', optional: true },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -265,7 +253,7 @@ describe('peer dependency issues', () => {
|
||||
depPath: 'qar/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
peer: '^2.2.0',
|
||||
peer: { version: '^2.2.0' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -435,8 +423,8 @@ describe('unmet peer dependency issues', () => {
|
||||
version: '1.0.0',
|
||||
depPath: 'foo/1.0.0',
|
||||
peerDependencies: {
|
||||
peer1: '*',
|
||||
peer2: '>=1',
|
||||
peer1: { version: '*' },
|
||||
peer2: { version: '>=1' },
|
||||
},
|
||||
id: '',
|
||||
},
|
||||
@@ -527,7 +515,7 @@ describe('unmet peer dependency issue resolved from subdependency', () => {
|
||||
depPath: 'bar/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
dep: '10',
|
||||
dep: { version: '10' },
|
||||
},
|
||||
id: '',
|
||||
},
|
||||
@@ -548,7 +536,7 @@ test('resolve peer dependencies with npm aliases', () => {
|
||||
depPath: 'foo/1.0.0',
|
||||
version: '1.0.0',
|
||||
peerDependencies: {
|
||||
bar: '1.0.0',
|
||||
bar: { version: '1.0.0' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
@@ -557,7 +545,7 @@ test('resolve peer dependencies with npm aliases', () => {
|
||||
depPath: 'foo/2.0.0',
|
||||
version: '2.0.0',
|
||||
peerDependencies: {
|
||||
bar: '2.0.0',
|
||||
bar: { version: '2.0.0' },
|
||||
},
|
||||
id: '',
|
||||
}
|
||||
|
||||
75
pnpm-lock.yaml
generated
75
pnpm-lock.yaml
generated
@@ -71,8 +71,8 @@ importers:
|
||||
specifier: 1.0.0
|
||||
version: 1.0.0
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/tsconfig':
|
||||
specifier: workspace:*
|
||||
version: link:__utils__/tsconfig
|
||||
@@ -189,8 +189,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../pkg-manager/modules-yaml
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/types':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/types
|
||||
@@ -226,8 +226,8 @@ importers:
|
||||
__utils__/assert-store:
|
||||
dependencies:
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/store.cafs':
|
||||
specifier: workspace:*
|
||||
version: link:../../store/cafs
|
||||
@@ -1288,8 +1288,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -1409,8 +1409,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-ipc-server':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-ipc-server
|
||||
@@ -2853,8 +2853,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -3113,8 +3113,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/store-path':
|
||||
specifier: workspace:*
|
||||
version: link:../../store/store-path
|
||||
@@ -3395,8 +3395,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../read-projects-context
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/store-path':
|
||||
specifier: workspace:*
|
||||
version: link:../../store/store-path
|
||||
@@ -3752,8 +3752,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: 'link:'
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -3945,8 +3945,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -4499,8 +4499,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../pkg-manifest/read-project-manifest
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/run-npm':
|
||||
specifier: workspace:*
|
||||
version: link:../exec/run-npm
|
||||
@@ -4759,8 +4759,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
|
||||
releasing/plugin-commands-publishing:
|
||||
dependencies:
|
||||
@@ -4859,8 +4859,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-ipc-server':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-ipc-server
|
||||
@@ -5422,8 +5422,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../pkg-manifest/read-package-json
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -5489,8 +5489,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@types/ramda':
|
||||
specifier: 0.28.20
|
||||
version: 0.28.20
|
||||
@@ -5583,8 +5583,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@pnpm/test-fixtures':
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/test-fixtures
|
||||
@@ -5915,8 +5915,8 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: link:../../__utils__/prepare
|
||||
'@pnpm/registry-mock':
|
||||
specifier: 3.18.0
|
||||
version: 3.18.0(typanion@3.14.0)
|
||||
specifier: 3.20.0
|
||||
version: 3.20.0(typanion@3.14.0)
|
||||
'@types/archy':
|
||||
specifier: 0.0.33
|
||||
version: 0.0.33
|
||||
@@ -8677,8 +8677,8 @@ packages:
|
||||
strip-bom: 4.0.0
|
||||
dev: true
|
||||
|
||||
/@pnpm/registry-mock@3.18.0(typanion@3.14.0):
|
||||
resolution: {integrity: sha512-Zyr2pe9gld5OcuUAF69hzAs2ZBzUy/jwoS0kRgzt4mtvMns5WaPgH4GZmOaJkeIJg7hUYfXd4dCTAjAHqmx1oA==}
|
||||
/@pnpm/registry-mock@3.20.0(typanion@3.14.0):
|
||||
resolution: {integrity: sha512-JKSBYTZn/Nk+2HytdYdz9avy53WWqh4QhP6uE9ImIFw4aw5vRUWq6aQQn6xkm8I/wzPogOpDaEuAfFXhhsj3uA==}
|
||||
engines: {node: '>=10.13'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
@@ -16071,6 +16071,7 @@ packages:
|
||||
/request@2.88.2:
|
||||
resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==}
|
||||
engines: {node: '>= 6'}
|
||||
deprecated: request has been deprecated, see https://github.com/request/request/issues/3142
|
||||
dependencies:
|
||||
aws-sign2: 0.7.0
|
||||
aws4: 1.12.0
|
||||
@@ -18161,7 +18162,5 @@ packages:
|
||||
dev: false
|
||||
|
||||
time:
|
||||
/@types/object-hash@3.0.6: '2023-11-07T12:14:41.852Z'
|
||||
/fuse-native@2.2.6: '2020-06-03T19:26:36.838Z'
|
||||
/node-gyp@10.0.1: '2023-11-02T18:13:42.360Z'
|
||||
/object-hash@3.0.0: '2022-02-18T15:10:47.040Z'
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/read-package-json": "workspace:*",
|
||||
"@pnpm/read-project-manifest": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/run-npm": "workspace:*",
|
||||
"@pnpm/tabtab": "^0.1.2",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"@pnpm/lockfile-types": "workspace:*",
|
||||
"@pnpm/plugin-commands-deploy": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0"
|
||||
"@pnpm/registry-mock": "3.20.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pnpm/cli-utils": "workspace:*",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@pnpm/filter-workspace-packages": "workspace:*",
|
||||
"@pnpm/plugin-commands-publishing": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-ipc-server": "workspace:*",
|
||||
"@types/cross-spawn": "^6.0.5",
|
||||
"@types/is-windows": "^1.0.2",
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"@pnpm/plugin-commands-licenses": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/read-package-json": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/semver": "7.5.3",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/plugin-commands-listing": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@types/ramda": "0.28.20",
|
||||
"execa": "npm:safe-execa@0.1.2",
|
||||
"strip-ansi": "^6.0.1",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@pnpm/plugin-commands-installation": "workspace:*",
|
||||
"@pnpm/plugin-commands-outdated": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@pnpm/test-fixtures": "workspace:*",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/wrap-ansi": "8.0.2",
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@pnpm/lockfile-file": "workspace:*",
|
||||
"@pnpm/plugin-commands-store": "workspace:*",
|
||||
"@pnpm/prepare": "workspace:*",
|
||||
"@pnpm/registry-mock": "3.18.0",
|
||||
"@pnpm/registry-mock": "3.20.0",
|
||||
"@types/archy": "0.0.33",
|
||||
"@types/ramda": "0.28.20",
|
||||
"@types/ssri": "^7.1.4",
|
||||
|
||||
Reference in New Issue
Block a user