Assembly comparison for jsii that detects breaking changes and compatibility violations between library versions
npx @tessl/cli install tessl/npm-jsii-diff@1.114.0jsii-diff is a TypeScript library that provides comprehensive API compatibility checking for jsii (JavaScript interop) assemblies. It enables developers to validate that changes between library versions don't break backward compatibility by analyzing type systems, method signatures, and API stability levels with sophisticated breaking change detection.
npm install jsii-diffimport { compareAssemblies } from "jsii-diff";
import {
classifyDiagnostics,
treatAsError,
formatDiagnostic,
hasErrors
} from "jsii-diff/lib/diagnostics";
import {
downloadNpmPackage,
showDownloadFailure,
inTempDir,
flatMap,
RecursionBreaker
} from "jsii-diff/lib/util";
import { validateStabilities } from "jsii-diff/lib/stability";For CommonJS:
const { compareAssemblies } = require("jsii-diff");
const {
classifyDiagnostics,
treatAsError,
formatDiagnostic,
hasErrors
} = require("jsii-diff/lib/diagnostics");
const {
downloadNpmPackage,
showDownloadFailure,
inTempDir,
flatMap,
RecursionBreaker
} = require("jsii-diff/lib/util");
const { validateStabilities } = require("jsii-diff/lib/stability");import { compareAssemblies } from "jsii-diff";
import {
classifyDiagnostics,
treatAsError,
formatDiagnostic,
hasErrors
} from "jsii-diff/lib/diagnostics";
import * as reflect from "jsii-reflect";
// Load two jsii assemblies
const ts1 = new reflect.TypeSystem();
const original = ts1.loadModule("./v1.0.0");
const ts2 = new reflect.TypeSystem();
const updated = ts2.loadModule("./v2.0.0");
// Compare for compatibility
const mismatches = compareAssemblies(original, updated, {
defaultExperimental: false // treat unmarked APIs as stable
});
// Classify diagnostics (errors vs warnings)
const diagnostics = classifyDiagnostics(
mismatches,
treatAsError('prod') // stable and deprecated APIs cause errors
);
// Check results
if (hasErrors(diagnostics)) {
console.error("Breaking changes detected!");
for (const diag of diagnostics) {
console.error(formatDiagnostic(diag));
}
process.exit(1);
}jsii-diff is built around several key components:
Core API for comparing two jsii assemblies to detect breaking changes and compatibility violations between library versions.
function compareAssemblies(
original: reflect.Assembly,
updated: reflect.Assembly,
options?: ComparisonOptions
): Mismatches;
interface ComparisonOptions {
/** Whether to treat API elements as experimental if unmarked (default: false/stable) */
defaultExperimental?: boolean;
}Classification and formatting system for API compatibility violations with configurable error levels and filtering capabilities.
function classifyDiagnostics(
mismatches: Mismatches,
shouldError: Set<Stability>,
skipFilter?: Set<string>
): Diagnostic[];
interface Diagnostic {
level: DiagLevel;
message: string;
suppressionKey: string;
}
enum DiagLevel {
Error = 0,
Warning = 1,
Skipped = 2
}Diagnostics and Error Handling
Full-featured CLI tool for comparing jsii assemblies with support for local files, directories, and NPM packages.
jsii-diff <original> [updated] [options]Key options:
--error-on <prod|non-experimental|all>: Control which stability levels cause errors--ignore-file <path>: File containing violation keys to suppress--default-stability <experimental|stable>: How to treat unmarked APIsUtility functions for NPM package handling, temporary directory management, and common operations.
function downloadNpmPackage<T>(
pkg: string,
block: (dir: string) => Promise<T>
): Promise<NpmDownloadResult<T>>;
function showDownloadFailure(f: DownloadFailure): string | undefined;
function inTempDir<T>(block: () => T | Promise<T>): Promise<T>;
function flatMap<T, U>(xs: T[], fn: (x: T) => U[]): U[];
class RecursionBreaker<A> {
do(key: A, block: () => void): void;
}Validation functions for API stability level transitions and consistency checks.
function validateStabilities(
original: reflect.Documentable & ApiElement,
updated: reflect.Documentable,
mismatches: IReport
): void;interface ApiMismatch {
message: string;
violationKey: string;
stability: Stability;
}
class Mismatches {
readonly mismatches: Array<ApiMismatch>;
constructor(opts: { defaultStability: Stability });
report(options: ReportOptions): void;
messages(): IterableIterator<string>;
readonly count: number;
filter(pred: (x: ApiMismatch) => boolean): Mismatches;
withMotivation(motivation: string): IReport;
}
interface ReportOptions {
ruleKey: string;
violator: ApiElement;
message: string;
}type ErrorClass = 'prod' | 'non-experimental' | 'all';
interface ComparisonContext extends ComparisonOptions {
mismatches: Mismatches;
}
// ApiElement uses types from jsii-reflect package
type ApiElement = reflect.Type | reflect.TypeMember | reflect.EnumMember;
interface IReport {
report(options: ReportOptions): void;
withMotivation(reason: string): IReport;
}type DownloadFailure = 'no_such_package';
type NpmDownloadResult<T> =
| { success: true; result: T }
| { success: false; reason: DownloadFailure };
interface LoadOptions {
validate: boolean;
}