From e3354660955bd446186100fac0d1079da49e9e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=91=A8=F0=9F=8F=BC=E2=80=8D=F0=9F=92=BB=20Romain=20M?= =?UTF-8?q?arcadier-Muller?= Date: Wed, 18 Dec 2019 15:54:16 +0100 Subject: [PATCH] fix(pacmak): generated dependencies are arbitrary The dependency statements generated in the Java, .NET and Python packages generated by `jsii-pacmak` were not reflecting the dependency statement modeled on the source package. In certain pathological cases, such as Python, the dependency declaration was often more permissive than what the source package allowed, resulting in surprising behavior as well as difficult to troubleshoot problems. This updates several elements involved in this problem: 1. The `jsii` compiler no longer carries declarations of the entire (transitive) dependency closure of the package into the `.jsii` file. Instead, only direct dependencies are represented. This is fine because `jsii` already demands that all assembliesof which a type is re-exported be declared (at least) as a `peerDependency`, and the change also ensures that `peerDependency` declarations are considered in the same way that regular `dependencies` are. 2. The version statements in the `dependencies` section of the `.jsii` file no longer contains the "compile-time resolved" version number, but the actual SemVer expression declared in the package's source. 3. `jsii-pacmak` renders the declared SemVer range in the relevant form for the target being generated. Fixes #676 Related to #1137 --- packages/@jsii/spec/lib/assembly.ts | 12 +-- packages/@jsii/spec/lib/index.ts | 2 +- packages/@scope/jsii-calc-base/package.json | 4 +- .../@scope/jsii-calc-base/test/assembly.jsii | 27 +---- .../@scope/jsii-calc-lib/test/assembly.jsii | 52 +--------- packages/jsii-calc/test/assembly.jsii | 81 +-------------- packages/jsii-pacmak/lib/generator.ts | 4 +- .../lib/targets/dotnet/filegenerator.ts | 46 ++++++++- packages/jsii-pacmak/lib/targets/java.ts | 68 +++++++++++-- packages/jsii-pacmak/lib/targets/python.ts | 18 ++-- .../java/pom.xml | 2 +- .../.jsii | 27 +---- ...s.CalculatorPackageId.BasePackageId.csproj | 2 +- .../test/expected.jsii-calc-base/java/pom.xml | 4 +- .../expected.jsii-calc-base/python/setup.py | 2 +- .../.jsii | 52 +--------- ...ts.CalculatorPackageId.LibPackageId.csproj | 2 +- .../test/expected.jsii-calc-lib/java/pom.xml | 4 +- .../expected.jsii-calc-lib/python/setup.py | 2 +- .../.jsii | 81 +-------------- ...azon.JSII.Tests.CalculatorPackageId.csproj | 6 +- .../test/expected.jsii-calc/java/pom.xml | 8 +- .../test/expected.jsii-calc/python/setup.py | 6 +- packages/jsii/lib/assembler.ts | 98 +------------------ packages/jsii/lib/project-info.ts | 24 ++--- packages/jsii/lib/validator.ts | 4 +- packages/jsii/test/negatives.test.ts | 6 +- packages/jsii/test/project-info.test.ts | 8 +- 28 files changed, 177 insertions(+), 475 deletions(-) diff --git a/packages/@jsii/spec/lib/assembly.ts b/packages/@jsii/spec/lib/assembly.ts index d3c21db5fc..ac022d822e 100644 --- a/packages/@jsii/spec/lib/assembly.ts +++ b/packages/@jsii/spec/lib/assembly.ts @@ -121,13 +121,6 @@ export interface Assembly extends Documentable { */ dependencies?: { [assembly: string]: PackageVersion }; - /** - * Closure of all dependency assemblies, direct and transitive. - * - * @default none - */ - dependencyClosure?: { [assembly: string]: PackageVersion }; - /** * List if bundled dependencies (these are not expected to be jsii * assemblies). @@ -219,14 +212,15 @@ export interface AssemblyTargets { */ export interface PackageVersion { /** - * Version of the package. + * The declared version of this dependency. This may be a semver range. * * @minLength 1 */ version: string; /** - * Targets for a given assembly. + * Targets configured for a given assembly. Useful when needing to determine + * names of dependencies to generate in absence of the actual assembly. * * @default none */ diff --git a/packages/@jsii/spec/lib/index.ts b/packages/@jsii/spec/lib/index.ts index 27644b56f8..4b318ab612 100644 --- a/packages/@jsii/spec/lib/index.ts +++ b/packages/@jsii/spec/lib/index.ts @@ -1,4 +1,4 @@ export * from './assembly'; +export * from './configuration'; export * from './name-tree'; export * from './validate-assembly'; -export * from './configuration'; diff --git a/packages/@scope/jsii-calc-base/package.json b/packages/@scope/jsii-calc-base/package.json index 75a7453844..d733c01f64 100644 --- a/packages/@scope/jsii-calc-base/package.json +++ b/packages/@scope/jsii-calc-base/package.json @@ -29,10 +29,10 @@ "test:update": "npm run build && UPDATE_DIFF=1 npm run test" }, "dependencies": { - "@scope/jsii-calc-base-of-base": "^0.20.11" + "@scope/jsii-calc-base-of-base": "0.20.11" }, "peerDependencies": { - "@scope/jsii-calc-base-of-base": "^0.20.11" + "@scope/jsii-calc-base-of-base": "0.20.11" }, "devDependencies": { "@types/node": "^10.17.11", diff --git a/packages/@scope/jsii-calc-base/test/assembly.jsii b/packages/@scope/jsii-calc-base/test/assembly.jsii index f947cca587..ef5f21e7a3 100644 --- a/packages/@scope/jsii-calc-base/test/assembly.jsii +++ b/packages/@scope/jsii-calc-base/test/assembly.jsii @@ -32,31 +32,6 @@ "version": "0.20.11" } }, - "dependencyClosure": { - "@scope/jsii-calc-base-of-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base-of-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.baseofbase" - }, - "js": { - "npm": "@scope/jsii-calc-base-of-base" - }, - "python": { - "distName": "scope.jsii-calc-base-of-base", - "module": "scope.jsii_calc_base_of_base" - } - }, - "version": "0.20.11" - } - }, "description": "An example direct dependency for jsii-calc.", "homepage": "https://github.com/aws/jsii", "jsiiVersion": "0.20.11", @@ -174,5 +149,5 @@ } }, "version": "0.20.11", - "fingerprint": "lSQlk5mMPd7fxaZoCdCekSFY4rDOAu3VnLuIcFUXA6o=" + "fingerprint": "tjQFbb9hxfsDXAot1ihz85sbx0EdlUmqSfRXt+WfahY=" } diff --git a/packages/@scope/jsii-calc-lib/test/assembly.jsii b/packages/@scope/jsii-calc-lib/test/assembly.jsii index 57b1f57dd4..f20e16ed65 100644 --- a/packages/@scope/jsii-calc-lib/test/assembly.jsii +++ b/packages/@scope/jsii-calc-lib/test/assembly.jsii @@ -29,55 +29,7 @@ "module": "scope.jsii_calc_base" } }, - "version": "0.20.11" - } - }, - "dependencyClosure": { - "@scope/jsii-calc-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.base" - }, - "js": { - "npm": "@scope/jsii-calc-base" - }, - "python": { - "distName": "scope.jsii-calc-base", - "module": "scope.jsii_calc_base" - } - }, - "version": "0.20.11" - }, - "@scope/jsii-calc-base-of-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base-of-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.baseofbase" - }, - "js": { - "npm": "@scope/jsii-calc-base-of-base" - }, - "python": { - "distName": "scope.jsii-calc-base-of-base", - "module": "scope.jsii_calc_base_of_base" - } - }, - "version": "0.20.11" + "version": "^0.20.11" } }, "description": "A simple calcuator library built on JSII.", @@ -539,5 +491,5 @@ } }, "version": "0.20.11", - "fingerprint": "D1VJJVqcvEKInLQ3r/WxIN332Yo1IRlVWkCPByyIIb0=" + "fingerprint": "mexN5AIs1N8eRcRRklY0n6B8cda9Zl8jqBFlCext8c8=" } diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index bec20747f3..6a34a7a839 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -55,7 +55,7 @@ "module": "scope.jsii_calc_base" } }, - "version": "0.20.11" + "version": "^0.20.11" }, "@scope/jsii-calc-base-of-base": { "targets": { @@ -78,7 +78,7 @@ "module": "scope.jsii_calc_base_of_base" } }, - "version": "0.20.11" + "version": "^0.20.11" }, "@scope/jsii-calc-lib": { "targets": { @@ -103,80 +103,7 @@ "module": "scope.jsii_calc_lib" } }, - "version": "0.20.11" - } - }, - "dependencyClosure": { - "@scope/jsii-calc-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.base" - }, - "js": { - "npm": "@scope/jsii-calc-base" - }, - "python": { - "distName": "scope.jsii-calc-base", - "module": "scope.jsii_calc_base" - } - }, - "version": "0.20.11" - }, - "@scope/jsii-calc-base-of-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base-of-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.baseofbase" - }, - "js": { - "npm": "@scope/jsii-calc-base-of-base" - }, - "python": { - "distName": "scope.jsii-calc-base-of-base", - "module": "scope.jsii_calc_base_of_base" - } - }, - "version": "0.20.11" - }, - "@scope/jsii-calc-lib": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.LibNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.LibPackageId", - "versionSuffix": "-devpreview" - }, - "java": { - "maven": { - "artifactId": "calculator-lib", - "groupId": "software.amazon.jsii.tests", - "versionSuffix": ".DEVPREVIEW" - }, - "package": "software.amazon.jsii.tests.calculator.lib" - }, - "js": { - "npm": "@scope/jsii-calc-lib" - }, - "python": { - "distName": "scope.jsii-calc-lib", - "module": "scope.jsii_calc_lib" - } - }, - "version": "0.20.11" + "version": "^0.20.11" } }, "description": "A simple calcuator built on JSII.", @@ -12002,5 +11929,5 @@ } }, "version": "0.20.11", - "fingerprint": "eenqZx1+dNMvfZCY02AIrinXeK98iQC4XLLj0yPIXuM=" + "fingerprint": "4NkZ2cKdxrdzq1duPFnWy7f3Zqg75tgCIzPOV1BRhRI=" } diff --git a/packages/jsii-pacmak/lib/generator.ts b/packages/jsii-pacmak/lib/generator.ts index 14166318e5..4f58d6918b 100644 --- a/packages/jsii-pacmak/lib/generator.ts +++ b/packages/jsii-pacmak/lib/generator.ts @@ -509,13 +509,13 @@ export abstract class Generator implements IGenerator { return this.assembly; } - const found = (this.assembly.dependencyClosure ?? {})[name]; + const found = (this.assembly.dependencies ?? {})[name]; if (found) { return found; } - throw new Error(`Unable to find module ${name} as a direct or indirect dependency of ${this.assembly.name}`); + throw new Error(`Unable to find module ${name} as a dependency of ${this.assembly.name}`); } protected findType(fqn: string): spec.Type { diff --git a/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts b/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts index ace5d6cb3b..1b8f838a67 100644 --- a/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts +++ b/packages/jsii-pacmak/lib/targets/dotnet/filegenerator.ts @@ -1,6 +1,7 @@ import { CodeMaker } from 'codemaker'; import { Assembly } from '@jsii/spec'; import * as path from 'path'; +import * as semver from 'semver'; import * as xmlbuilder from 'xmlbuilder'; import { DotNetNameUtils } from './nameutils'; import * as logging from '../../logging'; @@ -9,12 +10,53 @@ import { TARGET_FRAMEWORK } from '../dotnet'; // Represents a dependency in the dependency tree. export class DotNetDependency { + public readonly version: string; + public constructor( public readonly namespace: string, public readonly packageId: string, public readonly fqn: string, - public readonly version: string, - public readonly partOfCompilation: boolean) { + version: string, + public readonly partOfCompilation: boolean + ) { + const range = new semver.Range(version); + // See: https://docs.microsoft.com/en-us/nuget/concepts/package-versioning#version-ranges-and-wildcards + this.version = range.set.map(set => { + if (set.length === 1) { + switch (set[0].operator || '=') { + // "[version]" => means exactly version + case '=': return `[${set[0].semver.raw}]`; + // "(version,]" => means greater than version + case '>': return `(${set[0].semver.raw},]`; + // "[version,]" => means greater than or equal to that version + case '>=': return `[${set[0].semver.raw},]`; + // "[,version)" => means less than version + case '<': return `[,${set[0].semver.raw})`; + // "[,version]" => means less than or equal to version + case '<=': return `[,${set[0].semver.raw}]`; + } + } else if (set.length === 2) { + const nugetRange = this.toNuGetRange(set[0], set[1]); + if (nugetRange) { + return nugetRange; + } + } + throw new Error(`Unsupported SemVer range set: ${set.map(comp => comp.value).join(', ')}`); + }).join(', '); + } + + private toNuGetRange(left: semver.Comparator, right: semver.Comparator): string | undefined { + if (left.operator.startsWith('<') && right.operator.startsWith('>')) { + // Order isn't ideal, just re-invoke with the correct ordering... + return this.toNuGetRange(right, left); + } + if (!left.operator.startsWith('>') || !right.operator.startsWith('<')) { + // We only support ranges defined like "> (or >=) left, < (or <=) right" + return undefined; + } + const leftBrace = left.operator.endsWith('=') ? '[' : '('; + const rightBrace = right.operator.endsWith('=') ? ']' : ')'; + return `${leftBrace}${left.semver.raw},${right.semver.raw}${rightBrace}`; } } diff --git a/packages/jsii-pacmak/lib/targets/java.ts b/packages/jsii-pacmak/lib/targets/java.ts index 9d0c7175cf..d332493f9d 100644 --- a/packages/jsii-pacmak/lib/targets/java.ts +++ b/packages/jsii-pacmak/lib/targets/java.ts @@ -4,6 +4,7 @@ import * as fs from 'fs-extra'; import * as reflect from 'jsii-reflect'; import * as spec from '@jsii/spec'; import * as path from 'path'; +import * as semver from 'semver'; import * as xmlbuilder from 'xmlbuilder'; import { Generator } from '../generator'; import * as logging from '../logging'; @@ -771,13 +772,12 @@ class JavaGenerator extends Generator { this.code.closeFile('pom.xml'); /** - * Combines a version number with an optional suffix. If the suffix starts with '-' or '.', it will be - * concatenated as-is to the semantic version number. Otherwise, it'll be appended to the version number with an - * intercalar '-'. - * - * @param version the semantic version number - * @param suffix the suffix, if any. - */ + * Combines a version number with an optional suffix. The suffix, when present, must begin with + * '-' or '.', and will be concatenated as-is to the version number.. + * + * @param version the semantic version number + * @param suffix the suffix, if any. + */ function makeVersion(version: string, suffix?: string): string { if (!suffix) { return version; } if (!suffix.startsWith('-') && !suffix.startsWith('.')) { @@ -786,6 +786,56 @@ class JavaGenerator extends Generator { return `${version}${suffix}`; } + /** + * Formats a SemVer version range into the equivalent Maven dependency notation. + * + * @see https://cwiki.apache.org/confluence/display/MAVENOLD/Dependency+Mediation+and+Conflict+Resolution + * + * @param version the semantic version number + * @param suffix a suffix to be appended to versions + */ + function semverToMavenRange(version: string, suffix?: string): string { + const range = new semver.Range(version); + return range.set.map( + set => { + if (set.length === 1) { + switch (set[0].operator || '=') { + // "[version]" => means exactly version + case '=': return `[${makeVersion(set[0].semver.raw, suffix)}]`; + // "(version,]" => means greater than version + case '>': return `(${makeVersion(set[0].semver.raw, suffix)},]`; + // "[version,]" => means greater than or equal to that version + case '>=': return `[${makeVersion(set[0].semver.raw, suffix)},]`; + // "[,version)" => means less than version + case '<': return `[,${makeVersion(set[0].semver.raw, suffix)})`; + // "[,version]" => means less than or equal to version + case '<=': return `[,${makeVersion(set[0].semver.raw, suffix)}]`; + } + } else if (set.length === 2) { + const range = mavenRange(set[0], set[1]); + if (range) { + return range; + } + } + throw new Error(`Unsupported range set: ${set.map(comp => comp.value).join(', ')}`); + } + ).join(','); + + function mavenRange(left: semver.Comparator, right: semver.Comparator): string | undefined { + if (left.operator.startsWith('<') && right.operator.startsWith('>')) { + // Order isn't ideal, just re-invoke with the correct ordering... + return mavenRange(right, left); + } + if (!left.operator.startsWith('>') || !right.operator.startsWith('<')) { + // We only support ranges defined like "> (or >=) left, < (or <=) right" + return undefined; + } + const leftBrace = left.operator.endsWith('=') ? '[' : '('; + const rightBrace = right.operator.endsWith('=') ? ']' : ')'; + return `${leftBrace}${makeVersion(left.semver.raw, suffix)},${makeVersion(right.semver.raw, suffix)}${rightBrace}`; + } + } + function mavenDependencies(this: JavaGenerator) { const dependencies = new Array(); const allDeps = { ...assm.dependencies ?? {}, ...this.referencedModules }; @@ -797,14 +847,14 @@ class JavaGenerator extends Generator { dependencies.push({ groupId: dep.targets.java.maven.groupId, artifactId: dep.targets.java.maven.artifactId, - version: makeVersion(dep.version, dep.targets.java.maven.versionSuffix), + version: semverToMavenRange(dep.version, dep.targets.java.maven.versionSuffix), }); } // The JSII java runtime base classes dependencies.push({ groupId: 'software.amazon.jsii', artifactId: 'jsii-runtime', - version: VERSION + version: semverToMavenRange(`^${VERSION}`) }); // Provides @javax.annotation.* diff --git a/packages/jsii-pacmak/lib/targets/python.ts b/packages/jsii-pacmak/lib/targets/python.ts index 93e022657f..126d315713 100644 --- a/packages/jsii-pacmak/lib/targets/python.ts +++ b/packages/jsii-pacmak/lib/targets/python.ts @@ -5,6 +5,7 @@ import * as escapeStringRegexp from 'escape-string-regexp'; import * as reflect from 'jsii-reflect'; import * as spec from '@jsii/spec'; import { Stability } from '@jsii/spec'; +import * as semver from 'semver'; import { Generator, GeneratorOptions } from '../generator'; import { warn } from '../logging'; import { md2rst } from '../markdown'; @@ -1185,16 +1186,13 @@ class Package { const expectedDeps = this.metadata.dependencies ?? {}; for (const depName of Object.keys(expectedDeps)) { const depInfo = expectedDeps[depName]; - // We need to figure out what our version range is. - // Basically, if it starts with Zero we want to restrict things to - // ~=X.Y.Z. If it does not start with zero, then we want to do ~=X.Y,>=X.Y.Z. - const versionParts = depInfo.version.split('.'); - let versionSpecifier: string; - if (versionParts[0] === '0') { - versionSpecifier = `~=${versionParts.slice(0, 3).join('.')}`; - } else { - versionSpecifier = `~=${versionParts.slice(0, 2).join('.')},>=${versionParts.slice(0, 3).join('.')}`; - } + + const range = new semver.Range(depInfo.version); + const versionSpecifier = range.set.map( + set => set.map( + comp => `${comp.operator || '=='}${comp.semver.raw}` + ).join(', ') + ).join(', '); dependencies.push(`${depInfo.targets!.python!.distName}${versionSpecifier}`); } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base-of-base/java/pom.xml b/packages/jsii-pacmak/test/expected.jsii-calc-base-of-base/java/pom.xml index 8ec3c5795a..ae1ff0a024 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base-of-base/java/pom.xml +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base-of-base/java/pom.xml @@ -36,7 +36,7 @@ software.amazon.jsii jsii-runtime - 0.20.11 + [0.20.11,0.21.0) javax.annotation diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/.jsii index f947cca587..ef5f21e7a3 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/.jsii +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/.jsii @@ -32,31 +32,6 @@ "version": "0.20.11" } }, - "dependencyClosure": { - "@scope/jsii-calc-base-of-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base-of-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.baseofbase" - }, - "js": { - "npm": "@scope/jsii-calc-base-of-base" - }, - "python": { - "distName": "scope.jsii-calc-base-of-base", - "module": "scope.jsii_calc_base_of_base" - } - }, - "version": "0.20.11" - } - }, "description": "An example direct dependency for jsii-calc.", "homepage": "https://github.com/aws/jsii", "jsiiVersion": "0.20.11", @@ -174,5 +149,5 @@ } }, "version": "0.20.11", - "fingerprint": "lSQlk5mMPd7fxaZoCdCekSFY4rDOAu3VnLuIcFUXA6o=" + "fingerprint": "tjQFbb9hxfsDXAot1ihz85sbx0EdlUmqSfRXt+WfahY=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId.csproj b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId.csproj index eca51885aa..4e409860ad 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId.csproj +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/dotnet/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId/Amazon.JSII.Tests.CalculatorPackageId.BasePackageId.csproj @@ -25,7 +25,7 @@ - + 0612,0618 diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/java/pom.xml b/packages/jsii-pacmak/test/expected.jsii-calc-base/java/pom.xml index 53f9bfcda7..144d30b73d 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/java/pom.xml +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/java/pom.xml @@ -36,12 +36,12 @@ software.amazon.jsii.tests calculator-base-of-base - 0.20.11 + [0.20.11] software.amazon.jsii jsii-runtime - 0.20.11 + [0.20.11,0.21.0) javax.annotation diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-base/python/setup.py b/packages/jsii-pacmak/test/expected.jsii-calc-base/python/setup.py index 960636132a..d76b93338a 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-base/python/setup.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc-base/python/setup.py @@ -32,7 +32,7 @@ "install_requires": [ "jsii~=0.20.11", "publication>=0.0.3", - "scope.jsii-calc-base-of-base~=0.20.11" + "scope.jsii-calc-base-of-base==0.20.11" ], "classifiers": [ "Intended Audience :: Developers", diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii index 57b1f57dd4..f20e16ed65 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/.jsii @@ -29,55 +29,7 @@ "module": "scope.jsii_calc_base" } }, - "version": "0.20.11" - } - }, - "dependencyClosure": { - "@scope/jsii-calc-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.base" - }, - "js": { - "npm": "@scope/jsii-calc-base" - }, - "python": { - "distName": "scope.jsii-calc-base", - "module": "scope.jsii_calc_base" - } - }, - "version": "0.20.11" - }, - "@scope/jsii-calc-base-of-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base-of-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.baseofbase" - }, - "js": { - "npm": "@scope/jsii-calc-base-of-base" - }, - "python": { - "distName": "scope.jsii-calc-base-of-base", - "module": "scope.jsii_calc_base_of_base" - } - }, - "version": "0.20.11" + "version": "^0.20.11" } }, "description": "A simple calcuator library built on JSII.", @@ -539,5 +491,5 @@ } }, "version": "0.20.11", - "fingerprint": "D1VJJVqcvEKInLQ3r/WxIN332Yo1IRlVWkCPByyIIb0=" + "fingerprint": "mexN5AIs1N8eRcRRklY0n6B8cda9Zl8jqBFlCext8c8=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId.csproj b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId.csproj index 39ad0bcf10..2275a0ab28 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId.csproj +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/dotnet/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId/Amazon.JSII.Tests.CalculatorPackageId.LibPackageId.csproj @@ -25,7 +25,7 @@ - + 0612,0618 diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/pom.xml b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/pom.xml index 2a7c3608d6..dd403ce6a8 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/pom.xml +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/java/pom.xml @@ -36,12 +36,12 @@ software.amazon.jsii.tests calculator-base - 0.20.11 + [0.20.11,0.21.0) software.amazon.jsii jsii-runtime - 0.20.11 + [0.20.11,0.21.0) javax.annotation diff --git a/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/setup.py b/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/setup.py index fad4ca0394..3588e20486 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/setup.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc-lib/python/setup.py @@ -32,7 +32,7 @@ "install_requires": [ "jsii~=0.20.11", "publication>=0.0.3", - "scope.jsii-calc-base~=0.20.11" + "scope.jsii-calc-base>=0.20.11, <0.21.0" ], "classifiers": [ "Intended Audience :: Developers", diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii index bec20747f3..6a34a7a839 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii @@ -55,7 +55,7 @@ "module": "scope.jsii_calc_base" } }, - "version": "0.20.11" + "version": "^0.20.11" }, "@scope/jsii-calc-base-of-base": { "targets": { @@ -78,7 +78,7 @@ "module": "scope.jsii_calc_base_of_base" } }, - "version": "0.20.11" + "version": "^0.20.11" }, "@scope/jsii-calc-lib": { "targets": { @@ -103,80 +103,7 @@ "module": "scope.jsii_calc_lib" } }, - "version": "0.20.11" - } - }, - "dependencyClosure": { - "@scope/jsii-calc-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.base" - }, - "js": { - "npm": "@scope/jsii-calc-base" - }, - "python": { - "distName": "scope.jsii-calc-base", - "module": "scope.jsii_calc_base" - } - }, - "version": "0.20.11" - }, - "@scope/jsii-calc-base-of-base": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.BaseOfBaseNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.BaseOfBasePackageId" - }, - "java": { - "maven": { - "artifactId": "calculator-base-of-base", - "groupId": "software.amazon.jsii.tests" - }, - "package": "software.amazon.jsii.tests.calculator.baseofbase" - }, - "js": { - "npm": "@scope/jsii-calc-base-of-base" - }, - "python": { - "distName": "scope.jsii-calc-base-of-base", - "module": "scope.jsii_calc_base_of_base" - } - }, - "version": "0.20.11" - }, - "@scope/jsii-calc-lib": { - "targets": { - "dotnet": { - "namespace": "Amazon.JSII.Tests.CalculatorNamespace.LibNamespace", - "packageId": "Amazon.JSII.Tests.CalculatorPackageId.LibPackageId", - "versionSuffix": "-devpreview" - }, - "java": { - "maven": { - "artifactId": "calculator-lib", - "groupId": "software.amazon.jsii.tests", - "versionSuffix": ".DEVPREVIEW" - }, - "package": "software.amazon.jsii.tests.calculator.lib" - }, - "js": { - "npm": "@scope/jsii-calc-lib" - }, - "python": { - "distName": "scope.jsii-calc-lib", - "module": "scope.jsii_calc_lib" - } - }, - "version": "0.20.11" + "version": "^0.20.11" } }, "description": "A simple calcuator built on JSII.", @@ -12002,5 +11929,5 @@ } }, "version": "0.20.11", - "fingerprint": "eenqZx1+dNMvfZCY02AIrinXeK98iQC4XLLj0yPIXuM=" + "fingerprint": "4NkZ2cKdxrdzq1duPFnWy7f3Zqg75tgCIzPOV1BRhRI=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj index 1a901072ec..50cc042d87 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon.JSII.Tests.CalculatorPackageId.csproj @@ -27,9 +27,9 @@ - - - + + + 0612,0618 diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml b/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml index d91eb3248b..e7c101d5c8 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/pom.xml @@ -57,22 +57,22 @@ software.amazon.jsii.tests calculator-base - 0.20.11 + [0.20.11,0.21.0) software.amazon.jsii.tests calculator-base-of-base - 0.20.11 + [0.20.11,0.21.0) software.amazon.jsii.tests calculator-lib - 0.20.11.DEVPREVIEW + [0.20.11.DEVPREVIEW,0.21.0.DEVPREVIEW) software.amazon.jsii jsii-runtime - 0.20.11 + [0.20.11,0.21.0) javax.annotation diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py b/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py index 4b0431ce97..eb7056b80a 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py +++ b/packages/jsii-pacmak/test/expected.jsii-calc/python/setup.py @@ -32,9 +32,9 @@ "install_requires": [ "jsii~=0.20.11", "publication>=0.0.3", - "scope.jsii-calc-base~=0.20.11", - "scope.jsii-calc-base-of-base~=0.20.11", - "scope.jsii-calc-lib~=0.20.11" + "scope.jsii-calc-base>=0.20.11, <0.21.0", + "scope.jsii-calc-base-of-base>=0.20.11, <0.21.0", + "scope.jsii-calc-lib>=0.20.11, <0.21.0" ], "classifiers": [ "Intended Audience :: Developers", diff --git a/packages/jsii/lib/assembler.ts b/packages/jsii/lib/assembler.ts index f543e6f91a..22dbebc89b 100644 --- a/packages/jsii/lib/assembler.ts +++ b/packages/jsii/lib/assembler.ts @@ -6,7 +6,6 @@ import * as fs from 'fs-extra'; import * as spec from '@jsii/spec'; import * as log4js from 'log4js'; import * as path from 'path'; -import * as semver from 'semver'; import * as ts from 'typescript'; import { JSII_DIAGNOSTICS_CODE } from './compiler'; import { getReferencedDocParams, parseSymbolDocumentation } from './docs'; @@ -114,8 +113,7 @@ export class Assembler implements Emitter { author: this.projectInfo.author, contributors: this.projectInfo.contributors && [...this.projectInfo.contributors], repository: this.projectInfo.repository, - dependencies: this._toDependencies(this.projectInfo.dependencies), - dependencyClosure: this._buildDependencyClosure(this.projectInfo.dependencies), + dependencies: noEmptyDict({ ...this.projectInfo.dependencies, ...this.projectInfo.peerDependencies }), bundled: this.projectInfo.bundleDependencies, types: this._types, targets: this.projectInfo.targets, @@ -233,14 +231,13 @@ export class Assembler implements Emitter { if (assm === this.projectInfo.name) { type = this._types[ref]; } else { - const assembly = this.projectInfo.transitiveDependencies.find(dep => dep.name === assm); + const assembly = this.projectInfo.dependencyClosure.find(dep => dep.name === assm); type = assembly?.types?.[ref]; // since we are exposing a type of this assembly in this module's public API, // we expect it to appear as a peer dependency instead of a normal dependency. if (assembly) { - const asPeerDependency = this.projectInfo.peerDependencies.find(d => d.name === assembly.name); - if (!asPeerDependency) { + if (!(assembly.name in this.projectInfo.peerDependencies)) { this._diagnostic(referencingNode, ts.DiagnosticCategory.Warning, `The type '${ref}' is exposed in the public API of this module. ` + `Therefore, the module '${assembly.name}' must also be defined under "peerDependencies". ` + @@ -1336,71 +1333,6 @@ export class Assembler implements Emitter { } } } - - private _toDependencies(assemblies: readonly spec.Assembly[]): { [name: string]: spec.PackageVersion } | undefined { - const ret: { [name: string]: spec.PackageVersion } = {}; - - for (const a of assemblies) { - Object.assign(ret, assemblyToPackageVersionMap(a)); - } - - return noEmptyDict(ret); - } - - private _buildDependencyClosure(assemblies: readonly spec.Assembly[]): { [name: string]: spec.PackageVersion } | undefined { - // Merge the dependency closures of all dependencies and add the direct dependencies. - // There should not be version conflicts between them but we guard against it anyway. - - // Get an array of dependency maps - const dependencyBags = flatten(assemblies.map(a => [assemblyToPackageVersionMap(a), a.dependencies ?? {}])); - - const warned = new Set(); - const result: { [name: string]: spec.PackageVersion } = {}; - for (const bag of dependencyBags) { - for (const [name, packV] of Object.entries(bag)) { - maybeRecord.call(this, name, packV); - } - } - - return noEmptyDict(result); - - function maybeRecord(this: Assembler, name: string, pack: spec.PackageVersion) { - let recordThisDependency = true; - - if (name in result) { - // Two dependencies on the same package, find the right version to use - const highestVersion = mostConstrainedVersion(result[name].version, pack.version); - - if (highestVersion === undefined) { - warnAboutVersionConflict.call(this, name, result[name].version, pack.version); - } - - recordThisDependency = pack.version === highestVersion; - } - - if (recordThisDependency) { - result[name] = { - version: pack.version, - targets: pack.targets, - }; - } - } - - function warnAboutVersionConflict(this: Assembler, name: string, v1: string, v2: string) { - if (warned.has(name)) { return; } - this._diagnostic(null, ts.DiagnosticCategory.Error, `Conflicting dependencies on incompatible versions for package '${name}': ${v1} and ${v2}`); - warned.add(name); - } - } -} - -function assemblyToPackageVersionMap(a: spec.Assembly): {[key: string]: spec.PackageVersion} { - return { - [a.name]: { - version: a.version, - targets: a.targets - } - }; } function _fingerprint(assembly: spec.Assembly): spec.Assembly { @@ -1619,30 +1551,6 @@ function* intersect(xs: Set, ys: Set) { } } -/** - * Return the most constrained version given two versions - * - * Returns the highest version. Return undefined if the values are not pairwise - * comparable. - */ -function mostConstrainedVersion(version1: string, version2: string): string | undefined { - if (semver.satisfies(version1, `^${version2}`)) { - // If v1 satisifies v2, then either: - // - v2 also satisfies v1, in which case it doesn't matter which we return - // - v2 does not satisfy v1, in which it must be the case that v1 is higher - return version1; - } - - // Reverse logic - if (semver.satisfies(version2, `^${version1}`)) { return version2; } - - return undefined; -} - -function flatten(xs: T[][]): T[] { - return Array.prototype.concat.call([], ...xs); -} - function noEmptyDict(xs: {[key: string]: T}): {[key: string]: T} | undefined { if (Object.keys(xs).length === 0) { return undefined; } return xs; diff --git a/packages/jsii/lib/project-info.ts b/packages/jsii/lib/project-info.ts index 864457aab6..4c571d3498 100644 --- a/packages/jsii/lib/project-info.ts +++ b/packages/jsii/lib/project-info.ts @@ -35,9 +35,9 @@ export interface ProjectInfo { readonly main: string; readonly types: string; - readonly dependencies: readonly spec.Assembly[]; - readonly peerDependencies: readonly spec.Assembly[]; - readonly transitiveDependencies: readonly spec.Assembly[]; + readonly dependencies: { readonly [name: string]: spec.PackageVersion }; + readonly peerDependencies: { readonly [name: string]: spec.PackageVersion }; + readonly dependencyClosure: readonly spec.Assembly[]; readonly bundleDependencies?: { readonly [name: string]: string }; readonly targets: spec.AssemblyTargets; readonly metadata?: { [key: string]: any }; @@ -107,7 +107,7 @@ export async function loadProjectInfo(projectRoot: string, { fixPeerDependencies const peerDependencies = await _loadDependencies(pkg.peerDependencies, projectRoot, transitiveAssemblies); - const transitiveDependencies = Object.keys(transitiveAssemblies).map(name => transitiveAssemblies[name]); + const transitiveDependencies = Object.values(transitiveAssemblies); return { projectRoot, @@ -127,7 +127,7 @@ export async function loadProjectInfo(projectRoot: string, { fixPeerDependencies dependencies, peerDependencies, - transitiveDependencies, + dependencyClosure: transitiveDependencies, bundleDependencies, targets: { ..._required(pkg.jsii, 'The "package.json" file must specify the "jsii" attribute').targets, @@ -158,12 +158,14 @@ function _guessRepositoryType(url: string): string { throw new Error(`The "package.json" file must specify the "repository.type" attribute (could not guess from ${url})`); } -async function _loadDependencies(dependencies: { [name: string]: string | spec.PackageVersion } | undefined, +async function _loadDependencies( + dependencies: { [name: string]: string | spec.PackageVersion } | undefined, searchPath: string, transitiveAssemblies: { [name: string]: spec.Assembly }, - bundled = new Set()): Promise { - if (!dependencies) { return []; } - const assemblies = new Array(); + bundled = new Set() +): Promise<{ [name: string]: spec.PackageVersion }> { + if (!dependencies) { return {}; } + const packageVersions: { [name: string]: spec.PackageVersion } = {}; for (const name of Object.keys(dependencies)) { if (bundled.has(name)) { continue; } const { version: versionString, localPackage } = _resolveVersion(dependencies[name], searchPath); @@ -178,7 +180,7 @@ async function _loadDependencies(dependencies: { [name: string]: string | spec.P if (!version.intersects(new semver.Range(assm.version))) { throw new Error(`Declared dependency on version ${versionString} of ${name}, but version ${assm.version} was found`); } - assemblies.push(assm); + packageVersions[assm.name] = { version: versionString!, targets: assm.targets }; transitiveAssemblies[assm.name] = assm; const pkgDir = path.dirname(pkg); if (assm.dependencies) { @@ -186,7 +188,7 @@ async function _loadDependencies(dependencies: { [name: string]: string | spec.P await _loadDependencies(assm.dependencies, pkgDir, transitiveAssemblies); } } - return assemblies; + return packageVersions; } const ASSEMBLY_CACHE = new Map(); diff --git a/packages/jsii/lib/validator.ts b/packages/jsii/lib/validator.ts index 7eb2dc29d8..f29c25b386 100644 --- a/packages/jsii/lib/validator.ts +++ b/packages/jsii/lib/validator.ts @@ -130,7 +130,7 @@ function _defaultValidations(): ValidationFunction[] { } continue; } - const foreignAssm = validator.projectInfo.transitiveDependencies.find(dep => dep.name === assm); + const foreignAssm = validator.projectInfo.dependencyClosure.find(dep => dep.name === assm); if (!foreignAssm) { diagnostic(ts.DiagnosticCategory.Error, `Type reference is rooted in unknown module: ${assm}`); @@ -362,7 +362,7 @@ function _dereference(typeRef: string | spec.NamedTypeReference, assembly: spec. if (assembly.name === assm) { return assembly.types?.[typeRef]; } - const foreignAssm = validator.projectInfo.transitiveDependencies.find(dep => dep.name === assm); + const foreignAssm = validator.projectInfo.dependencyClosure.find(dep => dep.name === assm); return foreignAssm?.types?.[typeRef]; } diff --git a/packages/jsii/test/negatives.test.ts b/packages/jsii/test/negatives.test.ts index 45b70c46f1..9a33f8bbfe 100644 --- a/packages/jsii/test/negatives.test.ts +++ b/packages/jsii/test/negatives.test.ts @@ -74,9 +74,9 @@ function _makeProjectInfo(types: string): ProjectInfo { license: 'Apache-2.0', author: { name: 'John Doe', roles: ['author'] }, repository: { type: 'git', url: 'https://github.com/aws/jsii.git' }, - dependencies: [], - peerDependencies: [], - transitiveDependencies: [], + dependencies: {}, + peerDependencies: {}, + dependencyClosure: [], bundleDependencies: {}, targets: {}, excludeTypescript: [], diff --git a/packages/jsii/test/project-info.test.ts b/packages/jsii/test/project-info.test.ts index 45a0787684..757e44f5c2 100644 --- a/packages/jsii/test/project-info.test.ts +++ b/packages/jsii/test/project-info.test.ts @@ -18,8 +18,8 @@ const BASE_PROJECT = { jsii: { targets: { foo: { bar: 'baz' } } }, - dependencies: { 'jsii-test-dep': '^1.2.3' }, - peerDependencies: { 'jsii-test-dep': '^1.2.3' } + dependencies: { 'jsii-test-dep': '^1.2.3' } as { [name: string]: string }, + peerDependencies: { 'jsii-test-dep': '^1.2.3' } as { [name: string]: string } }; describe('loadProjectInfo', () => { @@ -36,8 +36,8 @@ describe('loadProjectInfo', () => { expect(info.repository?.type).toBe('git'); expect(info.repository?.url).toBe(BASE_PROJECT.repository.url); expect(info.targets).toEqual({ ...BASE_PROJECT.jsii.targets, js: { npm: BASE_PROJECT.name } }); - expect(info.dependencies).toEqual([TEST_DEP_ASSEMBLY]); - expect(info.transitiveDependencies).toEqual([TEST_DEP_ASSEMBLY, TEST_DEP_DEP_ASSEMBLY]); + expect(info.dependencies).toEqual({ [TEST_DEP_ASSEMBLY.name]: { version: BASE_PROJECT.dependencies[TEST_DEP_ASSEMBLY.name] } }); + expect(info.dependencyClosure).toEqual([TEST_DEP_ASSEMBLY, TEST_DEP_DEP_ASSEMBLY]); })); test('loads valid project (UNLICENSED)', () => _withTestProject(async projectRoot => {