Skip to content

Commit e309140

Browse files
committed
recursively merge package.json from build configuration
1 parent 8b3d752 commit e309140

File tree

3 files changed

+152
-3
lines changed

3 files changed

+152
-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,104 @@
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+
"deep": ".",
59+
"option": "b"
60+
}
61+
},
62+
"metadata": {
63+
"A": "A"
64+
}
65+
}
66+
""").expectObjectNode();
67+
68+
ObjectNode l = expected;
69+
ObjectNode r = MergeJsonNodes.mergeWithScripts(left, right);
70+
71+
assertEquals(
72+
l.expectStringMember("name"),
73+
r.expectStringMember("name")
74+
);
75+
assertEquals(
76+
l.expectNumberMember("version"),
77+
r.expectNumberMember("version")
78+
);
79+
assertEquals(
80+
l.expectObjectMember("scripts").expectStringMember("target"),
81+
r.expectObjectMember("scripts").expectStringMember("target")
82+
);
83+
assertEquals(
84+
l.expectObjectMember("scripts").expectStringMember("target2"),
85+
r.expectObjectMember("scripts").expectStringMember("target2")
86+
);
87+
assertEquals(
88+
l.expectObjectMember("scripts").expectArrayMember("args").getElementsAs(Node::toString),
89+
r.expectObjectMember("scripts").expectArrayMember("args").getElementsAs(Node::toString)
90+
);
91+
assertEquals(
92+
l.expectObjectMember("scripts").expectObjectMember("nested").expectStringMember("option"),
93+
r.expectObjectMember("scripts").expectObjectMember("nested").expectStringMember("option")
94+
);
95+
assertEquals(
96+
1,
97+
r.expectObjectMember("scripts").expectObjectMember("nested").getStringMap().size()
98+
);
99+
assertEquals(
100+
1,
101+
r.expectObjectMember("metadata").getStringMap().size()
102+
);
103+
}
104+
}

0 commit comments

Comments
 (0)