Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -172,19 +172,19 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {
Selected Dependency:{' '}
</Text>
<Text type="span">
{inspectDependency.name}: {inspectDependency.version}
{inspectDependency.name}: {inspectDependency.versionPath}
</Text>
</div>
<div className={styles.DependencyDetailInfo}>
<Text type="h5" bold>
package.json spec:{' '}
</Text>
<Text type="span">
{inspectDependency.dependencyType === LfxDependencyKind.Peer
{inspectDependency.dependencyKind === LfxDependencyKind.Peer
? `"${inspectDependency.peerDependencyMeta.version}" ${
inspectDependency.peerDependencyMeta.optional ? 'Optional' : 'Required'
} Peer`
: inspectDependency.version}
: inspectDependency.versionPath}
</Text>
</div>
<div className={styles.DependencyDetailInfo}>
Expand All @@ -204,15 +204,15 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {

const renderPeerDependencies = (): JSX.Element | ReactNull => {
if (!selectedEntry) return ReactNull;
const peerDeps = selectedEntry.dependencies.filter((d) => d.dependencyType === LfxDependencyKind.Peer);
const peerDeps = selectedEntry.dependencies.filter((d) => d.dependencyKind === LfxDependencyKind.Peer);
if (!peerDeps.length) {
return (
<div className={`${appStyles.ContainerCard} ${styles.InfluencerList}`}>
<Text type="h5">No peer dependencies.</Text>
</div>
);
}
if (!inspectDependency || inspectDependency.dependencyType !== LfxDependencyKind.Peer) {
if (!inspectDependency || inspectDependency.dependencyKind !== LfxDependencyKind.Peer) {
return (
<div className={`${appStyles.ContainerCard} ${styles.InfluencerList}`}>
<Text type="h5">Select a peer dependency to view its influencers</Text>
Expand Down Expand Up @@ -337,14 +337,14 @@ export const LockfileEntryDetailsView = (): JSX.Element | ReactNull => {
>
<Text type="h5" bold>
Name: {dependency.name}{' '}
{dependency.dependencyType === LfxDependencyKind.Peer
{dependency.dependencyKind === LfxDependencyKind.Peer
? `${
dependency.peerDependencyMeta.optional ? '(Optional)' : '(Non-optional)'
} Peer Dependency`
: ''}
</Text>
<div>
<Text type="p">Version: {dependency.version}</Text>
<Text type="p">Version: {dependency.versionPath}</Text>
<Text type="p">Entry ID: {dependency.entryId}</Text>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ export interface IJsonPeerDependencyMeta {

export interface IJsonLfxDependency {
name: string;
version: string;
versionPath: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe leave a doc comment about what this is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are just the serialized versions of the corresponding fields from LfxGraph

entryId: string;
dependencyType: LfxDependencyKind;
originalSpecifier: string;
dependencyKind: LfxDependencyKind;
peerDependencyMeta: IJsonPeerDependencyMeta;

resolvedEntryJsonId?: number;

peerDependencyMeta: IJsonPeerDependencyMeta;
}

export enum LfxDependencyKind {
Expand Down
79 changes: 60 additions & 19 deletions apps/lockfile-explorer-web/src/packlets/lfx-shared/LfxGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,75 @@ import type { IJsonLfxWorkspace } from './IJsonLfxWorkspace';

export interface ILfxGraphDependencyOptions {
name: string;
version: string;
dependencyType: LfxDependencyKind;
containingEntry: LfxGraphEntry;
peerDependencyMeta: IJsonPeerDependencyMeta;
versionPath: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These all have the same meaning as the corresponding fields in LfxGraph, since they are just its inputs


entryId: string;

originalSpecifier: string;
dependencyKind: LfxDependencyKind;
peerDependencyMeta: IJsonPeerDependencyMeta;

containingEntry: LfxGraphEntry;
}

/**
* Represents a dependency listed under a LockfileEntry
*
* @remarks
* Each dependency listed under a package in the lockfile should have a separate entry. These Dependencies
* will link to the "containingEntry", which is the LockfileEntry that specified this dependency.
* The "resolvedEntry" field is the corresponding LockfileEntry for this dependency, as all dependencies also have
* their own entries in the pnpm lockfile.
* Represents an graph edge, which is an exact dependency version obtained from the lockfile.
*/
export class LfxGraphDependency {
/**
* The referenced package name.
* Example: `@scope/package-name`
*/
public readonly name: string;
public readonly version: string;
public readonly dependencyType: LfxDependencyKind;
public readonly containingEntry: LfxGraphEntry;

/**
* The lockfile's raw string that either indicates an external reference such as `link:../target-folder`,
* or else can be combined with the `name` field to construct an `entryId` found in the lockfile.
* The exact syntax varies between lockfile file format versions.
*
* Example: `link:../target-folder`
*
* Example: `1.0.0`
*
* Example: `1.0.0_@rushstack+m@1.0.0` (version 5.4)
* Example: `1.0.0(@rushstack/m@1.0.0)` (version 6.0 and 9.0)
*/
public readonly versionPath: string;

/**
* If this dependency refers to an entry in the lockfile, this field should match a corresponding
* {@link LfxGraphEntry.entryId} and `resolvedEntry` will be defined (unless the loader encountered an error).
*
* For external references such as `link:../target-folder`, the `entryId` is the empty string.
*/
public readonly entryId: string;

/**
* The lockfile sometimes records the original SemVer specifier that was used to choose the versionPath,
* usually either because it can change (e.g. a workspace project's dependencies) or because it's a peer dependency
* that affects graph relationships beyond the current node. If not, then `originalSpecifier` will be the
* empty string.
*
* @remarks
* Because this field is only available for certain dependencies, it is generally less useful than specifiers
* obtained from the package.json files.
*/
public readonly originalSpecifier: string;
public readonly dependencyKind: LfxDependencyKind;
public readonly peerDependencyMeta: IJsonPeerDependencyMeta;

public readonly containingEntry: LfxGraphEntry;
public resolvedEntry: LfxGraphEntry | undefined = undefined;

public constructor(options: ILfxGraphDependencyOptions) {
this.name = options.name;
this.version = options.version;
this.dependencyType = options.dependencyType;
this.containingEntry = options.containingEntry;
this.versionPath = options.versionPath;
this.entryId = options.entryId;
this.originalSpecifier = options.originalSpecifier;
this.dependencyKind = options.dependencyKind;
this.peerDependencyMeta = options.peerDependencyMeta;

this.containingEntry = options.containingEntry;
}
}

Expand Down Expand Up @@ -67,14 +103,19 @@ export class LfxGraphEntry {
public readonly kind: LfxGraphEntryKind;

/**
* A unique (human-readable) identifier for this lockfile entry. For projects, this is just
* `Project:` + the package json path for this project.
* A unique identifier for this lockfile entry, based on `rawEntryId` but adjusted to be unique for both
* project and external package entries.
*/
public readonly entryId: string;

/**
* The unique identifier assigned to this project/package in the lockfile.
* e.g. `/@emotion/core/10.3.1_qjwx5m6wssz3lnb35xwkc3pz6q:`
*
* @remarks
* In the `pnpm-lock.yaml` file, "importers" (workspace projects) and "packages" (external packages)
* are tracked separately, so it's not required for their keys to be unique. `entryId` solves this problem
* by adding a `project:` prefix for importers.
*/
public readonly rawEntryId: string;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ export function serializeToJson(graph: LfxGraph): IJsonLfxGraph {
for (const dependency of entry.dependencies) {
const jsonLfxDependency: IJsonLfxDependency = {
name: dependency.name,
version: dependency.version,
versionPath: dependency.versionPath,
entryId: dependency.entryId,
dependencyType: dependency.dependencyType,
originalSpecifier: dependency.originalSpecifier,
dependencyKind: dependency.dependencyKind,
peerDependencyMeta: {
name: dependency.peerDependencyMeta.name,
version: dependency.peerDependencyMeta.version,
Expand Down Expand Up @@ -111,15 +112,16 @@ export function deserializeFromJson(jsonLfxGraph: IJsonLfxGraph): LfxGraph {
for (const jsonLfxDependency of jsonLfxEntry.dependencies) {
const dependency: LfxGraphDependency = new LfxGraphDependency({
name: jsonLfxDependency.name,
version: jsonLfxDependency.version,
dependencyType: jsonLfxDependency.dependencyType,
containingEntry: entry,
versionPath: jsonLfxDependency.versionPath,
entryId: jsonLfxDependency.entryId,
originalSpecifier: jsonLfxDependency.originalSpecifier,
dependencyKind: jsonLfxDependency.dependencyKind,
peerDependencyMeta: {
name: jsonLfxDependency.peerDependencyMeta.name,
version: jsonLfxDependency.peerDependencyMeta.version,
optional: jsonLfxDependency.peerDependencyMeta.optional
}
},
containingEntry: entry
});

if (jsonLfxDependency.resolvedEntryJsonId) {
Expand Down
11 changes: 9 additions & 2 deletions apps/lockfile-explorer/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,20 @@
"console": "integratedTerminal",
"sourceMaps": true
},
{
{
"type": "node",
"request": "launch",
"name": "Single Jest test",
"program": "${workspaceFolder}/node_modules/@rushstack/heft/lib/start.js",
"cwd": "${workspaceFolder}",
"args": ["--debug", "test", "--clean", "-u", "--test-path-pattern", "lfxGraph-website-sample-1-v6.0.test"],
"args": [
"--debug",
"test",
"--clean",
"-u",
"--test-path-pattern",
"lfxGraph-website-sample-1-v5.4.test"
],
"console": "integratedTerminal",
"sourceMaps": true
},
Expand Down
Loading
Loading