Skip to content

Commit

Permalink
recursively merge package.json from build configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
kuhe committed Aug 21, 2024
1 parent 8b3d752 commit e309140
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import software.amazon.smithy.codegen.core.SymbolDependency;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.ObjectNode;
import software.amazon.smithy.typescript.codegen.util.MergeJsonNodes;
import software.amazon.smithy.utils.IoUtils;
import software.amazon.smithy.utils.SmithyInternalApi;

Expand All @@ -43,9 +44,11 @@ static void writePackageJson(
) {
// Write the package.json file.
InputStream resource = PackageJsonGenerator.class.getResourceAsStream("base-package.json");
ObjectNode node = Node.parse(IoUtils.toUtf8String(resource))
.expectObjectNode()
.merge(settings.getPackageJson());
ObjectNode node = MergeJsonNodes.mergeWithScripts(
Node.parse(IoUtils.toUtf8String(resource))
.expectObjectNode(),
settings.getPackageJson()
);

// Merge TypeScript dependencies into the package.json file.
for (Map.Entry<String, Map<String, SymbolDependency>> depEntry : dependencies.entrySet()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

package software.amazon.smithy.typescript.codegen.util;

import java.util.Objects;
import software.amazon.smithy.model.node.ObjectNode;


public final class MergeJsonNodes {

private MergeJsonNodes() {}

/**
* @param left - original node.
* @param right - overwriting node.
* @return new node with shallow merged fields except the recursively merged "scripts" field.
*/
public static ObjectNode mergeWithScripts(ObjectNode left, ObjectNode right) {
Objects.requireNonNull(left);
Objects.requireNonNull(right);

ObjectNode.Builder merged = left.toBuilder();
right.getMembers().forEach((k, v) -> {
String key = k.getValue();
if (left.containsMember(key)) {
if (left.getMember(key).get().isObjectNode() && v.isObjectNode() && key.equals("scripts")) {
merged.withMember(key,
MergeJsonNodes.mergeWithScripts(left.expectObjectMember(key), v.expectObjectNode())
);
} else {
merged.withMember(key, v);
}
} else {
merged.withMember(key, v);
}
});
return merged.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package software.amazon.smithy.typescript.codegen.util;

import org.junit.jupiter.api.Test;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.node.ObjectNode;

import static org.junit.jupiter.api.Assertions.assertEquals;

class MergeJsonNodesTest {

@Test
void apply() {
ObjectNode left = ObjectNode.parse("""
{
"name": "hello, world",
"version": 5,
"scripts": {
"target": "exec",
"target2": "exec2",
"args": ["a", "b", "c"],
"nested": {
"deep": "."
}
},
"metadata": {
"A": "A",
"B": "B",
"C": "C"
}
}
""").expectObjectNode();

ObjectNode right = ObjectNode.parse("""
{
"version": 6,
"scripts": {
"target": "no-op",
"args": ["a", "b", "c", "d"],
"nested": {
"option": "b"
}
},
"metadata": {
"A": "A"
}
}
""").expectObjectNode();

ObjectNode expected = ObjectNode.parse("""
{
"name": "hello, world",
"version": 6,
"scripts": {
"target": "no-op",
"target2": "exec2",
"args": ["a", "b", "c", "d"],
"nested": {
"deep": ".",
"option": "b"
}
},
"metadata": {
"A": "A"
}
}
""").expectObjectNode();

ObjectNode l = expected;
ObjectNode r = MergeJsonNodes.mergeWithScripts(left, right);

assertEquals(
l.expectStringMember("name"),
r.expectStringMember("name")
);
assertEquals(
l.expectNumberMember("version"),
r.expectNumberMember("version")
);
assertEquals(
l.expectObjectMember("scripts").expectStringMember("target"),
r.expectObjectMember("scripts").expectStringMember("target")
);
assertEquals(
l.expectObjectMember("scripts").expectStringMember("target2"),
r.expectObjectMember("scripts").expectStringMember("target2")
);
assertEquals(
l.expectObjectMember("scripts").expectArrayMember("args").getElementsAs(Node::toString),
r.expectObjectMember("scripts").expectArrayMember("args").getElementsAs(Node::toString)
);
assertEquals(
l.expectObjectMember("scripts").expectObjectMember("nested").expectStringMember("option"),
r.expectObjectMember("scripts").expectObjectMember("nested").expectStringMember("option")
);
assertEquals(
1,
r.expectObjectMember("scripts").expectObjectMember("nested").getStringMap().size()
);
assertEquals(
1,
r.expectObjectMember("metadata").getStringMap().size()
);
}
}

0 comments on commit e309140

Please sign in to comment.