Skip to content

Commit 5960dba

Browse files
committed
recursively merge package.json from build configuration
1 parent e94028b commit 5960dba

File tree

3 files changed

+151
-3
lines changed

3 files changed

+151
-3
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/PackageJsonGenerator.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import software.amazon.smithy.codegen.core.SymbolDependency;
2222
import software.amazon.smithy.model.node.Node;
2323
import software.amazon.smithy.model.node.ObjectNode;
24+
import software.amazon.smithy.typescript.codegen.util.MergeJsonNodes;
2425
import software.amazon.smithy.utils.IoUtils;
2526
import software.amazon.smithy.utils.SmithyInternalApi;
2627

@@ -43,9 +44,11 @@ static void writePackageJson(
4344
) {
4445
// Write the package.json file.
4546
InputStream resource = PackageJsonGenerator.class.getResourceAsStream("base-package.json");
46-
ObjectNode node = Node.parse(IoUtils.toUtf8String(resource))
47-
.expectObjectNode()
48-
.merge(settings.getPackageJson());
47+
ObjectNode node = MergeJsonNodes.mergeWithScripts(
48+
Node.parse(IoUtils.toUtf8String(resource))
49+
.expectObjectNode(),
50+
settings.getPackageJson()
51+
);
4952

5053
// Merge TypeScript dependencies into the package.json file.
5154
for (Map.Entry<String, Map<String, SymbolDependency>> depEntry : dependencies.entrySet()) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package software.amazon.smithy.typescript.codegen.util;
7+
8+
import java.util.Objects;
9+
import software.amazon.smithy.model.node.ObjectNode;
10+
11+
12+
public final class MergeJsonNodes {
13+
14+
private MergeJsonNodes() {}
15+
16+
/**
17+
* @param left - original node.
18+
* @param right - overwriting node.
19+
* @return new node with shallow merged fields except the recursively merged "scripts" field.
20+
*/
21+
public static ObjectNode mergeWithScripts(ObjectNode left, ObjectNode right) {
22+
Objects.requireNonNull(left);
23+
Objects.requireNonNull(right);
24+
25+
ObjectNode.Builder merged = left.toBuilder();
26+
right.getMembers().forEach((k, v) -> {
27+
String key = k.getValue();
28+
if (left.containsMember(key)) {
29+
if (left.getMember(key).get().isObjectNode() && v.isObjectNode() && key.equals("scripts")) {
30+
merged.withMember(key,
31+
MergeJsonNodes.mergeWithScripts(left.expectObjectMember(key), v.expectObjectNode())
32+
);
33+
} else {
34+
merged.withMember(key, v);
35+
}
36+
} else {
37+
merged.withMember(key, v);
38+
}
39+
});
40+
return merged.build();
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package software.amazon.smithy.typescript.codegen.util;
2+
3+
import org.junit.jupiter.api.Test;
4+
import software.amazon.smithy.model.node.Node;
5+
import software.amazon.smithy.model.node.ObjectNode;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
9+
class MergeJsonNodesTest {
10+
11+
@Test
12+
void apply() {
13+
ObjectNode left = ObjectNode.parse("""
14+
{
15+
"name": "hello, world",
16+
"version": 5,
17+
"scripts": {
18+
"target": "exec",
19+
"target2": "exec2",
20+
"args": ["a", "b", "c"],
21+
"nested": {
22+
"deep": "."
23+
}
24+
},
25+
"metadata": {
26+
"A": "A",
27+
"B": "B",
28+
"C": "C"
29+
}
30+
}
31+
""").expectObjectNode();
32+
33+
ObjectNode right = ObjectNode.parse("""
34+
{
35+
"version": 6,
36+
"scripts": {
37+
"target": "no-op",
38+
"args": ["a", "b", "c", "d"],
39+
"nested": {
40+
"option": "b"
41+
}
42+
},
43+
"metadata": {
44+
"A": "A"
45+
}
46+
}
47+
""").expectObjectNode();
48+
49+
ObjectNode expected = ObjectNode.parse("""
50+
{
51+
"name": "hello, world",
52+
"version": 6,
53+
"scripts": {
54+
"target": "no-op",
55+
"target2": "exec2",
56+
"args": ["a", "b", "c", "d"],
57+
"nested": {
58+
"option": "b"
59+
}
60+
},
61+
"metadata": {
62+
"A": "A"
63+
}
64+
}
65+
""").expectObjectNode();
66+
67+
ObjectNode l = expected;
68+
ObjectNode r = MergeJsonNodes.mergeWithScripts(left, right);
69+
70+
assertEquals(
71+
l.expectStringMember("name"),
72+
r.expectStringMember("name")
73+
);
74+
assertEquals(
75+
l.expectNumberMember("version"),
76+
r.expectNumberMember("version")
77+
);
78+
assertEquals(
79+
l.expectObjectMember("scripts").expectStringMember("target"),
80+
r.expectObjectMember("scripts").expectStringMember("target")
81+
);
82+
assertEquals(
83+
l.expectObjectMember("scripts").expectStringMember("target2"),
84+
r.expectObjectMember("scripts").expectStringMember("target2")
85+
);
86+
assertEquals(
87+
l.expectObjectMember("scripts").expectArrayMember("args").getElementsAs(Node::toString),
88+
r.expectObjectMember("scripts").expectArrayMember("args").getElementsAs(Node::toString)
89+
);
90+
assertEquals(
91+
l.expectObjectMember("scripts").expectObjectMember("nested").expectStringMember("option"),
92+
r.expectObjectMember("scripts").expectObjectMember("nested").expectStringMember("option")
93+
);
94+
assertEquals(
95+
1,
96+
r.expectObjectMember("scripts").expectObjectMember("nested").getStringMap().size()
97+
);
98+
assertEquals(
99+
1,
100+
r.expectObjectMember("metadata").getStringMap().size()
101+
);
102+
}
103+
}

0 commit comments

Comments
 (0)