Skip to content
Open
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
25 changes: 25 additions & 0 deletions .yarn/versions/f772082a.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
releases:
"@yarnpkg/cli": minor
"@yarnpkg/plugin-pack": minor

declined:
- "@yarnpkg/plugin-catalog"
- "@yarnpkg/plugin-compat"
- "@yarnpkg/plugin-constraints"
- "@yarnpkg/plugin-dlx"
- "@yarnpkg/plugin-essentials"
- "@yarnpkg/plugin-init"
- "@yarnpkg/plugin-interactive-tools"
- "@yarnpkg/plugin-nm"
- "@yarnpkg/plugin-npm"
- "@yarnpkg/plugin-npm-cli"
- "@yarnpkg/plugin-patch"
- "@yarnpkg/plugin-pnp"
- "@yarnpkg/plugin-pnpm"
- "@yarnpkg/plugin-stage"
- "@yarnpkg/plugin-typescript"
- "@yarnpkg/plugin-version"
- "@yarnpkg/plugin-workspace-tools"
- "@yarnpkg/builder"
- "@yarnpkg/core"
- "@yarnpkg/doctor"
8 changes: 7 additions & 1 deletion packages/plugin-pack/sources/commands/pack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export default class PackCommand extends BaseCommand {
description: `Run a preliminary \`yarn install\` if the package contains build scripts`,
});

preserveWorkspaces = Option.Boolean(`--preserve-workspaces`, false, {
description: `Preserve the workspaces in the package manifest`,
});

dryRun = Option.Boolean(`-n,--dry-run`, false, {
description: `Print the file paths without actually generating the package archive`,
});
Expand Down Expand Up @@ -89,7 +93,9 @@ export default class PackCommand extends BaseCommand {
}

if (!this.dryRun) {
const pack = await packUtils.genPackStream(workspace, files);
const pack = await packUtils.genPackStream(workspace, files, {
preserveWorkspaces: this.preserveWorkspaces,
});

await xfs.mkdirPromise(ppath.dirname(target), {recursive: true});
const write = xfs.createWriteStream(target);
Expand Down
73 changes: 40 additions & 33 deletions packages/plugin-pack/sources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import * as packUtils from './packUtils';
export {PackCommand};
export {packUtils};

export type WorkspacePackingOptions = {
preserveWorkspaces?: boolean;
};

export interface Hooks {
/**
* Called before a workspace is packed. The `rawManifest` value passed in
Expand All @@ -16,13 +20,14 @@ export interface Hooks {
beforeWorkspacePacking?: (
workspace: Workspace,
rawManifest: object,
options: WorkspacePackingOptions,
) => Promise<void> | void;
}

const DEPENDENCY_TYPES = [`dependencies`, `devDependencies`, `peerDependencies`];
const WORKSPACE_PROTOCOL = `workspace:`;

const beforeWorkspacePacking = (workspace: Workspace, rawManifest: any) => {
const beforeWorkspacePacking = (workspace: Workspace, rawManifest: any, options: WorkspacePackingOptions) => {
if (rawManifest.publishConfig) {
if (rawManifest.publishConfig.type)
rawManifest.type = rawManifest.publishConfig.type;
Expand All @@ -49,39 +54,41 @@ const beforeWorkspacePacking = (workspace: Workspace, rawManifest: any) => {

const project = workspace.project;

for (const dependencyType of DEPENDENCY_TYPES) {
for (const descriptor of workspace.manifest.getForScope(dependencyType).values()) {
const matchingWorkspace = project.tryWorkspaceByDescriptor(descriptor);
const range = structUtils.parseRange(descriptor.range);

if (range.protocol !== WORKSPACE_PROTOCOL)
continue;

if (matchingWorkspace === null) {
if (project.tryWorkspaceByIdent(descriptor) === null) {
throw new ReportError(MessageName.WORKSPACE_NOT_FOUND, `${structUtils.prettyDescriptor(project.configuration, descriptor)}: No local workspace found for this range`);
if (!options.preserveWorkspaces) {
for (const dependencyType of DEPENDENCY_TYPES) {
for (const descriptor of workspace.manifest.getForScope(dependencyType).values()) {
const matchingWorkspace = project.tryWorkspaceByDescriptor(descriptor);
const range = structUtils.parseRange(descriptor.range);

if (range.protocol !== WORKSPACE_PROTOCOL)
continue;

if (matchingWorkspace === null) {
if (project.tryWorkspaceByIdent(descriptor) === null) {
throw new ReportError(MessageName.WORKSPACE_NOT_FOUND, `${structUtils.prettyDescriptor(project.configuration, descriptor)}: No local workspace found for this range`);
}
} else {
let versionToWrite: string;

// For workspace:path/to/workspace and workspace:* we look up the workspace version
if (structUtils.areDescriptorsEqual(descriptor, matchingWorkspace.anchoredDescriptor) || range.selector === `*`)
versionToWrite = matchingWorkspace.manifest.version ?? `0.0.0`;
// For workspace:~ and workspace:^ we add the selector in front of the workspace version
else if (range.selector === `~` || range.selector === `^`)
versionToWrite = `${range.selector}${matchingWorkspace.manifest.version ?? `0.0.0`}`;
else
// for workspace:version we simply strip the protocol
versionToWrite = range.selector;

// Ensure optional dependencies are handled as well
const identDescriptor = dependencyType === `dependencies`
? structUtils.makeDescriptor(descriptor, `unknown`)
: null;
const finalDependencyType = identDescriptor !== null && workspace.manifest.ensureDependencyMeta(identDescriptor).optional
? `optionalDependencies`
: dependencyType;
rawManifest[finalDependencyType][structUtils.stringifyIdent(descriptor)] = versionToWrite;
}
} else {
let versionToWrite: string;

// For workspace:path/to/workspace and workspace:* we look up the workspace version
if (structUtils.areDescriptorsEqual(descriptor, matchingWorkspace.anchoredDescriptor) || range.selector === `*`)
versionToWrite = matchingWorkspace.manifest.version ?? `0.0.0`;
// For workspace:~ and workspace:^ we add the selector in front of the workspace version
else if (range.selector === `~` || range.selector === `^`)
versionToWrite = `${range.selector}${matchingWorkspace.manifest.version ?? `0.0.0`}`;
else
// for workspace:version we simply strip the protocol
versionToWrite = range.selector;

// Ensure optional dependencies are handled as well
const identDescriptor = dependencyType === `dependencies`
? structUtils.makeDescriptor(descriptor, `unknown`)
: null;
const finalDependencyType = identDescriptor !== null && workspace.manifest.ensureDependencyMeta(identDescriptor).optional
? `optionalDependencies`
: dependencyType;
rawManifest[finalDependencyType][structUtils.stringifyIdent(descriptor)] = versionToWrite;
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions packages/plugin-pack/sources/packUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import mm fr
import tar from 'tar-stream';
import {createGzip} from 'zlib';

import {Hooks} from './';
import {Hooks, WorkspacePackingOptions} from './';

const NEVER_IGNORE = [
`/package.json`,
Expand Down Expand Up @@ -67,7 +67,7 @@ export async function prepareForPack(workspace: Workspace, {report}: {report: Re
}
}

export async function genPackStream(workspace: Workspace, files?: Array<PortablePath>) {
export async function genPackStream(workspace: Workspace, files?: Array<PortablePath>, options: WorkspacePackingOptions = {}) {
if (typeof files === `undefined`)
files = await genPackList(workspace);

Expand Down Expand Up @@ -118,7 +118,7 @@ export async function genPackStream(workspace: Workspace, files?: Array<Portable

// The root package.json supports replacement fields in publishConfig
if (file === `package.json`)
content = Buffer.from(JSON.stringify(await genPackageManifest(workspace), null, 2));
content = Buffer.from(JSON.stringify(await genPackageManifest(workspace, options), null, 2));
else
content = await xfs.readFilePromise(source);

Expand All @@ -141,13 +141,14 @@ export async function genPackStream(workspace: Workspace, files?: Array<Portable
return tgz;
}

export async function genPackageManifest(workspace: Workspace): Promise<object> {
export async function genPackageManifest(workspace: Workspace, options: WorkspacePackingOptions = {}): Promise<object> {
const data = JSON.parse(JSON.stringify(workspace.manifest.raw));

await workspace.project.configuration.triggerHook(
(hooks: Hooks) => hooks.beforeWorkspacePacking,
workspace,
data,
options,
);

return data;
Expand Down