Skip to content

Commit

Permalink
UpgradeDependencyVersion
Browse files Browse the repository at this point in the history
  • Loading branch information
jkschneider committed Mar 9, 2024
1 parent 9657c6a commit 780ac5c
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 10 deletions.
45 changes: 35 additions & 10 deletions src/main/java/org/openrewrite/nodejs/UpgradeDependencyVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,29 @@
*/
package org.openrewrite.nodejs;

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.*;
import org.openrewrite.internal.StringUtils;
import org.openrewrite.json.JsonIsoVisitor;
import org.openrewrite.json.JsonPathMatcher;
import org.openrewrite.json.JsonVisitor;
import org.openrewrite.json.tree.Json;
import org.openrewrite.nodejs.search.IsPackageJson;

@Value
@EqualsAndHashCode(callSuper = false)
public class UpgradeDependencyVersion extends Recipe {

@Option(displayName = "Update `package-lock.json`",
description = "As of NPM 5.1.",
example = "react-dom")
@Option(displayName = "Name pattern",
description = "Name glob pattern used to match dependencies",
example = "@apollo*")
String namePattern;

@Option(displayName = "Version",
description = "Set the version to upgrade to." +
"Node-style [version selectors](https://docs.openrewrite.org/reference/dependency-version-selectors) may be used.",
example = "1.x")
String version;

@Override
public String getDisplayName() {
Expand All @@ -34,22 +46,35 @@ public String getDisplayName() {

@Override
public String getDescription() {
return "Upgrade matching Node.js dependencies";
return "Upgrade matching Node.js direct dependencies.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
// NOTE that `npm upgrade <pkg>` will update the package-lock.json as well.
// we might consider modifying the package.json with the new version and then
// triggering that.

JsonPathMatcher dependency = new JsonPathMatcher("$.dependencies");
return Preconditions.check(new IsPackageJson<>(), new JsonVisitor<ExecutionContext>() {
JsonPathMatcher devDependencies = new JsonPathMatcher("$.devDependencies");
return Preconditions.check(new IsPackageJson<>(), new JsonIsoVisitor<ExecutionContext>() {
@Override
public Json visitMember(Json.Member member, ExecutionContext ctx) {
if (dependency.matches(getCursor())) {
System.out.println("here");
public Json.Member visitMember(Json.Member member, ExecutionContext ctx) {
Json.Member m = super.visitMember(member, ctx);
Cursor maybeDependencies = getCursor().getParent(2);
if (maybeDependencies != null && (dependency.matches(maybeDependencies) || devDependencies.matches(maybeDependencies))) {
String name = ((Json.Literal) member.getKey()).getValue().toString();
if (StringUtils.matchesGlob(name, namePattern)) {
Json.Literal versionLiteral = (Json.Literal) member.getValue();
String requestedVersion = versionLiteral.getValue().toString();
if (!requestedVersion.equals(version)) {
m = m.withValue(versionLiteral
.withValue(version)
.withSource("\"" + version + "\""));
}
}
}
return super.visitMember(member, ctx);
return m;
}
});
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/resources/META-INF/rewrite/nodejs.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
#
# Copyright 2024 the original author or authors.
# <p>
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# <p>
# https://www.apache.org/licenses/LICENSE-2.0
# <p>
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

---
type: specs.openrewrite.org/v1beta/category
name: Node.js
Expand Down
100 changes: 100 additions & 0 deletions src/test/java/org/openrewrite/nodejs/UpgradeDependencyVersionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.nodejs;

import org.junit.jupiter.api.Test;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.json.Assertions.json;

public class UpgradeDependencyVersionTest implements RewriteTest {

@Test
void direct() {
//noinspection JsonStandardCompliance
rewriteRun(
spec -> spec.recipe(new UpgradeDependencyVersion("lodash*", "^4")),
json(
//language=json
"""
{
"name": "example",
"version": "1.0.0",
"dependencies": {
"jwt-decode": "^4.0.0",
"lodash.camelcase": "^4.3.0",
"lodash.kebabcase": "^4.1.0"
}
}
""",
//language=json
"""
{
"name": "example",
"version": "1.0.0",
"dependencies": {
"jwt-decode": "^4.0.0",
"lodash.camelcase": "^4",
"lodash.kebabcase": "^4"
}
}
""",
spec -> spec.path("package.json")
),
json(
//language=json
"""
{
"name": "example",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "example",
"version": "1.0.0",
"dependencies": {
"jwt-decode": "^4.0.0",
"lodash.camelcase": "^4.3.0",
"lodash.kebabcase": "^4.1.0"
}
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
"engines": {
"node": ">=18"
}
},
"node_modules/lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
},
"node_modules/lodash.kebabcase": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
"integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g=="
}
}
}
""",
spec -> spec.path("package-lock.json")
)
);
}
}

0 comments on commit 780ac5c

Please sign in to comment.