Skip to content

Commit 77f5c20

Browse files
Pedropedro-gomes-92
Pedro
authored andcommitted
feat: add installRemotely and versionRange new parameters
1 parent 0056279 commit 77f5c20

File tree

4 files changed

+132
-67
lines changed

4 files changed

+132
-67
lines changed

common/reviews/api/rush-lib.api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,6 +1332,8 @@ export class RushConfigurationProject {
13321332
get versionPolicy(): VersionPolicy | undefined;
13331333
// @beta
13341334
readonly versionPolicyName: string | undefined;
1335+
// @beta
1336+
readonly versionRange: string | undefined;
13351337
}
13361338

13371339
// @beta

libraries/rush-lib/src/api/RushConfigurationProject.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export interface IRushConfigurationProjectJson {
3030
tags?: string[];
3131
subspaceName?: string;
3232
installRemotely?: boolean;
33+
versionRange?: string;
3334
}
3435

3536
/**
@@ -59,9 +60,14 @@ export interface IRushConfigurationProjectOptions {
5960
subspace: Subspace;
6061

6162
/**
62-
* If specified, it will be downloaded from the external database or workspace.
63+
* If specified, package will be downloaded by NPM registry.
6364
*/
6465
installRemotely?: boolean;
66+
67+
/**
68+
* If specified, it will be downloaded according to the NPM version range (ignored if installRemotely=false).
69+
*/
70+
versionRange?: boolean;
6571
}
6672

6773
/**
@@ -133,11 +139,19 @@ export class RushConfigurationProject {
133139
/**
134140
*
135141
* Indicates how this project should be installed by rush add.
136-
* Default value is "false".
142+
* Default value is "true".
143+
*
144+
* @beta
145+
*/
146+
public readonly installRemotely: boolean = true;
147+
148+
/**
149+
*
150+
* Indicates which version should be installed by rush add. Ignored if installRemotely=false.
137151
*
138152
* @beta
139153
*/
140-
public readonly installRemotely: boolean = false;
154+
public readonly versionRange: string | undefined;
141155

142156
/**
143157
* A list of local projects that appear as devDependencies for this project, but cannot be
@@ -224,11 +238,17 @@ export class RushConfigurationProject {
224238
/** @internal */
225239
public constructor(options: IRushConfigurationProjectOptions) {
226240
const { projectJson, rushConfiguration, tempProjectName, allowedProjectTags } = options;
227-
const { packageName, projectFolder: projectRelativeFolder, installRemotely = false } = projectJson;
241+
const {
242+
packageName,
243+
projectFolder: projectRelativeFolder,
244+
installRemotely = true,
245+
versionRange
246+
} = projectJson;
228247
this.rushConfiguration = rushConfiguration;
229248
this.packageName = packageName;
230249
this.projectRelativeFolder = projectRelativeFolder;
231250
this.installRemotely = installRemotely;
251+
this.versionRange = versionRange;
232252

233253
validateRelativePathField(projectRelativeFolder, 'projectFolder', rushConfiguration.rushJsonFile);
234254

libraries/rush-lib/src/logic/PackageJsonUpdater.ts

Lines changed: 101 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,86 @@ export class PackageJsonUpdater {
551551
}
552552
}
553553

554+
private async _getRemoteLatestVersionAsync(packageName: string): Promise<string> {
555+
let selectedVersion: string | undefined;
556+
this._terminal.writeLine(`Querying NPM registry for latest version of "${packageName}"...`);
557+
558+
let commandArgs: string[];
559+
if (this._rushConfiguration.packageManager === 'yarn') {
560+
commandArgs = ['info', packageName, 'dist-tags.latest', '--silent'];
561+
} else {
562+
commandArgs = ['view', `${packageName}@latest`, 'version'];
563+
}
564+
565+
selectedVersion = (
566+
await Utilities.executeCommandAndCaptureOutputAsync(
567+
this._rushConfiguration.packageManagerToolFilename,
568+
commandArgs,
569+
this._rushConfiguration.commonTempFolder
570+
)
571+
).trim();
572+
573+
this._terminal.writeLine();
574+
this._terminal.writeLine(`Found latest version: ${Colorize.cyan(selectedVersion)}`);
575+
576+
return selectedVersion;
577+
}
578+
579+
private async _getRemoteSpecifiedVersionAsync(
580+
packageName: string,
581+
initialSpec: string = 'latest'
582+
): Promise<string> {
583+
let selectedVersion: string | undefined;
584+
this._terminal.writeLine(`Querying registry for all versions of "${packageName}"...`);
585+
586+
let commandArgs: string[];
587+
if (this._rushConfiguration.packageManager === 'yarn') {
588+
commandArgs = ['info', packageName, 'versions', '--json'];
589+
} else {
590+
commandArgs = ['view', packageName, 'versions', '--json'];
591+
}
592+
593+
const allVersions: string = await Utilities.executeCommandAndCaptureOutputAsync(
594+
this._rushConfiguration.packageManagerToolFilename,
595+
commandArgs,
596+
this._rushConfiguration.commonTempFolder
597+
);
598+
599+
let versionList: string[];
600+
if (this._rushConfiguration.packageManager === 'yarn') {
601+
versionList = JSON.parse(allVersions).data;
602+
} else {
603+
versionList = JSON.parse(allVersions);
604+
}
605+
606+
this._terminal.writeLine(Colorize.gray(`Found ${versionList.length} available versions.`));
607+
608+
for (const version of versionList) {
609+
if (semver.satisfies(version, initialSpec)) {
610+
selectedVersion = initialSpec;
611+
this._terminal.writeLine(`Found a version that satisfies ${initialSpec}: ${Colorize.cyan(version)}`);
612+
break;
613+
}
614+
}
615+
616+
if (!selectedVersion) {
617+
throw new Error(
618+
`Unable to find a version of "${packageName}" that satisfies` +
619+
` the version specifier "${initialSpec}"`
620+
);
621+
}
622+
623+
return selectedVersion;
624+
}
625+
626+
private async _getRemoteVersionAsync(packageName: string, initialSpec: string = 'latest'): Promise<string> {
627+
if (initialSpec === 'latest') {
628+
return this._getRemoteLatestVersionAsync(packageName);
629+
}
630+
631+
return this._getRemoteSpecifiedVersionAsync(packageName, initialSpec);
632+
}
633+
554634
/**
555635
* Selects an appropriate version number for a particular package, given an optional initial SemVer spec.
556636
* If ensureConsistentVersions, tries to pick a version that will be consistent.
@@ -659,7 +739,9 @@ export class PackageJsonUpdater {
659739
if (semver.satisfies(version, initialSpec)) {
660740
// For workspaces, assume that specifying the exact version means you always want to consume
661741
// the local project. Otherwise, use the exact local package version
662-
if (useWorkspaces && !localProject.installRemotely) {
742+
if (localProject.installRemotely) {
743+
selectedVersion = await this._getRemoteVersionAsync(packageName, initialSpec);
744+
} else if (useWorkspaces) {
663745
selectedVersion = initialSpec === version ? '*' : initialSpec;
664746
selectedVersionPrefix = workspacePrefix;
665747
} else {
@@ -675,52 +757,26 @@ export class PackageJsonUpdater {
675757
);
676758
}
677759
} else {
678-
this._terminal.writeLine(`Querying registry for all versions of "${packageName}"...`);
679-
680-
let commandArgs: string[];
681-
if (this._rushConfiguration.packageManager === 'yarn') {
682-
commandArgs = ['info', packageName, 'versions', '--json'];
683-
} else {
684-
commandArgs = ['view', packageName, 'versions', '--json'];
685-
}
686-
687-
const allVersions: string = await Utilities.executeCommandAndCaptureOutputAsync(
688-
this._rushConfiguration.packageManagerToolFilename,
689-
commandArgs,
690-
this._rushConfiguration.commonTempFolder
691-
);
692-
693-
let versionList: string[];
694-
if (this._rushConfiguration.packageManager === 'yarn') {
695-
versionList = JSON.parse(allVersions).data;
696-
} else {
697-
versionList = JSON.parse(allVersions);
698-
}
699-
700-
this._terminal.writeLine(Colorize.gray(`Found ${versionList.length} available versions.`));
701-
702-
for (const version of versionList) {
703-
if (semver.satisfies(version, initialSpec)) {
704-
selectedVersion = initialSpec;
705-
this._terminal.writeLine(
706-
`Found a version that satisfies ${initialSpec}: ${Colorize.cyan(version)}`
707-
);
708-
break;
709-
}
710-
}
711-
712-
if (!selectedVersion) {
713-
throw new Error(
714-
`Unable to find a version of "${packageName}" that satisfies` +
715-
` the version specifier "${initialSpec}"`
716-
);
717-
}
760+
// if the package is not a project in the local repository, then we need to query the registry
761+
// to find the latest version that satisfies the spec
762+
selectedVersion = await this._getRemoteVersionAsync(packageName, initialSpec);
718763
}
719764
} else {
720765
if (localProject !== undefined) {
721766
// For workspaces, assume that no specified version range means you always want to consume
722767
// the local project. Otherwise, use the exact local package version
723-
if (useWorkspaces && !localProject.installRemotely) {
768+
if (localProject.installRemotely) {
769+
selectedVersion = await this._getRemoteVersionAsync(packageName, localProject.versionRange);
770+
this._terminal.writeLine(
771+
Colorize.green('Assigning "') +
772+
Colorize.cyan(selectedVersion) +
773+
Colorize.green(
774+
`" for "${packageName}" because it is the preferred version defined by ${RushConstants.rushJsonFilename}.`
775+
)
776+
);
777+
778+
return selectedVersion;
779+
} else if (useWorkspaces) {
724780
selectedVersion = '*';
725781
selectedVersionPrefix = workspacePrefix;
726782
} else {
@@ -736,27 +792,10 @@ export class PackageJsonUpdater {
736792
this._terminal.writeLine();
737793
}
738794

739-
this._terminal.writeLine(`Querying NPM registry for latest version of "${packageName}"...`);
740-
741-
let commandArgs: string[];
742-
if (this._rushConfiguration.packageManager === 'yarn') {
743-
commandArgs = ['info', packageName, 'dist-tags.latest', '--silent'];
744-
} else {
745-
commandArgs = ['view', `${packageName}@latest`, 'version'];
746-
}
747-
748-
selectedVersion = (
749-
await Utilities.executeCommandAndCaptureOutputAsync(
750-
this._rushConfiguration.packageManagerToolFilename,
751-
commandArgs,
752-
this._rushConfiguration.commonTempFolder
753-
)
754-
).trim();
795+
// if the package is not a project in the local repository with no spec defined, then we need to
796+
// query the registry to find the latest version
797+
selectedVersion = await this._getRemoteVersionAsync(packageName);
755798
}
756-
757-
this._terminal.writeLine();
758-
759-
this._terminal.writeLine(`Found latest version: ${Colorize.cyan(selectedVersion)}`);
760799
}
761800

762801
this._terminal.writeLine();

libraries/rush-lib/src/schemas/rush.schema.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,13 @@
305305
"type": "string"
306306
},
307307
"installRemotely": {
308-
"description": "Specifies the installation type: \"remote\" or \"workspace\". The default value is false.",
308+
"description": "If true, then this project will be installed by NPM registry. The default value is true.",
309309
"type": "boolean"
310310
},
311+
"versionRange": {
312+
"description": "Specifies the package version, using version range syntax.",
313+
"type": "string"
314+
},
311315
"tags": {
312316
"description": "An optional set of custom tags that can be used to select this project. For example, adding \"my-custom-tag\" will allow this project to be selected by the command \"rush list --only tag:my-custom-tag\". The tag name must be one or more words separated by hyphens or slashes, where a word may contain lowercase ASCII letters, digits, \".\", and \"@\" characters.",
313317
"type": "array",

0 commit comments

Comments
 (0)