Skip to content

Commit

Permalink
[rush-resolve-plugin] Support "bundledDependencies"
Browse files Browse the repository at this point in the history
  • Loading branch information
dmichon-msft committed Aug 26, 2024
1 parent 6591961 commit 1ad17e0
Show file tree
Hide file tree
Showing 9 changed files with 358 additions and 1,307 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@microsoft/rush",
"comment": "Support \"bundledDependencies\" in rush-resolver-cache-plugin.",
"type": "none"
}
],
"packageName": "@microsoft/rush"
}
2 changes: 2 additions & 0 deletions libraries/rush-lib/src/logic/pnpm/PnpmShrinkwrapFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export interface IPnpmShrinkwrapDependencyYaml {
/** The name of the tarball, if this was from a TGZ file */
tarball?: string;
};
/** The list of bundled dependencies in this package */
bundledDependencies?: ReadonlyArray<string>;
/** The list of dependencies and the resolved version */
dependencies?: Record<string, IPnpmVersionSpecifier>;
/** The list of optional dependencies and the resolved version */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,12 @@ export async function afterInstallAsync(

const filteredFiles: string[] = Object.keys(files).filter((file) => file.endsWith('/package.json'));
if (filteredFiles.length > 0) {
// eslint-disable-next-line require-atomic-updates
context.files = filteredFiles.map((x) => x.slice(0, -13));
const nestedPackageDirs: string[] = filteredFiles.map((x) => x.slice(0, -13));

if (nestedPackageDirs.length > 0) {
// eslint-disable-next-line require-atomic-updates
context.nestedPackageDirs = nestedPackageDirs;
}
}
} catch (error) {
if (!context.optional) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,59 @@ function isPackageCompatible(
return true;
}

function extractBundledDependencies(
contexts: Map<string, IResolverContext>,
context: IResolverContext
): void {
const { nestedPackageDirs } = context;
if (!nestedPackageDirs) {
return;
}

for (let i: number = nestedPackageDirs.length - 1; i >= 0; i--) {
const nestedDir: string = nestedPackageDirs[i];
if (!nestedDir.startsWith('node_modules/')) {
continue;
}

const isScoped: boolean = nestedDir.charAt(13) === '@';
let index: number = nestedDir.indexOf('/', 13);
if (isScoped) {
index = nestedDir.indexOf('/', index + 1);
}

const name: string = index === -1 ? nestedDir.slice(13) : nestedDir.slice(13, index);
if (name.startsWith('.')) {
continue;
}

// Remove this nested package from the list
nestedPackageDirs.splice(i, 1);

const remainder: string = index === -1 ? '' : nestedDir.slice(index + 1);
const nestedRoot: string = `${context.descriptionFileRoot}/node_modules/${name}`;
let nestedContext: IResolverContext | undefined = contexts.get(nestedRoot);
if (!nestedContext) {
nestedContext = {
descriptionFileRoot: nestedRoot,
descriptionFileHash: undefined,
isProject: false,
name,
deps: new Map(),
ordinal: -1
};
contexts.set(nestedRoot, nestedContext);
}

context.deps.set(name, nestedRoot);

if (remainder) {
nestedContext.nestedPackageDirs ??= [];
nestedContext.nestedPackageDirs.push(remainder);
}
}
}

/**
* Options for computing the resolver cache from a lockfile.
*/
Expand Down Expand Up @@ -130,7 +183,7 @@ export async function computeResolverCacheFromLockfileAsync(
isProject: false,
name,
deps: new Map(),
ordinal: contexts.size,
ordinal: -1,
optional: pack.optional
};

Expand All @@ -148,6 +201,12 @@ export async function computeResolverCacheFromLockfileAsync(
await afterExternalPackagesAsync(contexts, missingOptionalDependencies);
}

for (const context of contexts.values()) {
if (context.nestedPackageDirs) {
extractBundledDependencies(contexts, context);
}
}

// Add the data for workspace projects
for (const [importerPath, importer] of lockfile.importers) {
// Ignore the root project. This plugin assumes you don't have one.
Expand All @@ -167,7 +226,7 @@ export async function computeResolverCacheFromLockfileAsync(
name: project.packageJson.name,
isProject: true,
deps: new Map(),
ordinal: contexts.size
ordinal: -1
};

contexts.set(project.projectFolder, context);
Expand All @@ -183,6 +242,11 @@ export async function computeResolverCacheFromLockfileAsync(
}
}

let ordinal: number = 0;
for (const context of contexts.values()) {
context.ordinal = ordinal++;
}

// Convert the intermediate representation to the final cache file
const serializedContexts: ISerializedResolveContext[] = Array.from(
contexts,
Expand Down
14 changes: 9 additions & 5 deletions rush-plugins/rush-resolver-cache-plugin/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,11 @@ export function createContextSerializer(
commonPathPrefix: string
): (entry: [string, IResolverContext]) => ISerializedResolveContext {
return ([descriptionFileRoot, context]: [string, IResolverContext]): ISerializedResolveContext => {
const deps: ISerializedResolveContext['deps'] = {};
for (const [key, contextRoot] of context.deps) {
const { deps } = context;

let hasAnyDeps: boolean = false;
const serializedDeps: ISerializedResolveContext['deps'] = {};
for (const [key, contextRoot] of deps) {
if (missingOptionalDependencies.has(contextRoot)) {
continue;
}
Expand All @@ -155,7 +158,8 @@ export function createContextSerializer(
if (!resolutionContext) {
throw new Error(`Missing context for ${contextRoot}!`);
}
deps[key] = resolutionContext.ordinal;
serializedDeps[key] = resolutionContext.ordinal;
hasAnyDeps = true;
}

if (!context.name) {
Expand All @@ -165,8 +169,8 @@ export function createContextSerializer(
const serializedContext: ISerializedResolveContext = {
name: context.name,
root: descriptionFileRoot.slice(commonPathPrefix.length),
dirInfoFiles: context.files,
deps
dirInfoFiles: context.nestedPackageDirs?.length ? context.nestedPackageDirs : undefined,
deps: hasAnyDeps ? serializedDeps : undefined
};

return serializedContext;
Expand Down
Loading

0 comments on commit 1ad17e0

Please sign in to comment.