Skip to content

Commit 58875c9

Browse files
authored
chore(codegen): move s3 transform to Java code (#5963)
* chore(codegen): move s3 transform to Java code * chore: checkstyle
1 parent ffd9380 commit 58875c9

File tree

4 files changed

+90
-50
lines changed

4 files changed

+90
-50
lines changed

clients/client-s3/src/models/models_0.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// smithy-typescript generated code
22
import { ExceptionOptionType as __ExceptionOptionType, SENSITIVE_STRING } from "@smithy/smithy-client";
3-
43
import { StreamingBlobTypes } from "@smithy/types";
54

65
import { S3ServiceException as __BaseException } from "./S3ServiceException";

clients/client-s3/src/models/models_1.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// smithy-typescript generated code
22
import { ExceptionOptionType as __ExceptionOptionType, SENSITIVE_STRING } from "@smithy/smithy-client";
3-
43
import { StreamingBlobTypes } from "@smithy/types";
54

65
import {
@@ -28,7 +27,6 @@ import {
2827
StorageClass,
2928
Tag,
3029
} from "./models_0";
31-
3230
import { S3ServiceException as __BaseException } from "./S3ServiceException";
3331

3432
/**

codegen/smithy-aws-typescript-codegen/src/main/java/software/amazon/smithy/aws/typescript/codegen/AddS3Config.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,13 @@
3636
import software.amazon.smithy.model.shapes.OperationShape;
3737
import software.amazon.smithy.model.shapes.ServiceShape;
3838
import software.amazon.smithy.model.shapes.Shape;
39+
import software.amazon.smithy.model.shapes.ShapeId;
40+
import software.amazon.smithy.model.shapes.StringShape;
3941
import software.amazon.smithy.model.shapes.StructureShape;
42+
import software.amazon.smithy.model.shapes.TimestampShape;
43+
import software.amazon.smithy.model.traits.DeprecatedTrait;
4044
import software.amazon.smithy.model.traits.DocumentationTrait;
45+
import software.amazon.smithy.model.traits.HttpHeaderTrait;
4146
import software.amazon.smithy.typescript.codegen.LanguageTarget;
4247
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
4348
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
@@ -106,6 +111,91 @@ public Model preprocessModel(Model model, TypeScriptSettings settings) {
106111
});
107112
}
108113
LOGGER.info("Patching " + inputShapes.size() + " input shapes with CRT notification");
114+
115+
boolean expiresShapeIsPresent = model.getShape(ShapeId.from("com.amazonaws.s3#Expires")).isPresent();
116+
if (expiresShapeIsPresent) {
117+
// ExpiresString customization part 1:
118+
// enforce that "com.amazonaws.s3#Expires" retains type=timestamp.
119+
// add a shape "com.amazonaws.s3#ExpiresString" of type=string.
120+
Shape expiresShape = model.getShape(ShapeId.from("com.amazonaws.s3#Expires")).get();
121+
TimestampShape expiresTimestampShape = TimestampShape.builder()
122+
.id(expiresShape.getId())
123+
.build();
124+
StringShape expiresStringShape = StringShape.builder()
125+
.id("com.amazonaws.s3#ExpiresString")
126+
.build();
127+
modelBuilder
128+
.removeShape(expiresShape.getId())
129+
.addShapes(expiresTimestampShape, expiresStringShape);
130+
131+
// ExpiresString customization part 2:
132+
// for any output shape member targeting Expires, add a member ExpiresString targeting ExpiresString.
133+
// and mark Expires deprecated in favor of ExpiresString.
134+
// move Expires documentation trait to ExpiresString.
135+
// set the httpHeader trait of ExpiresString to be ExpiresString.
136+
// SDK middleware will take care of copying expires header to expiresstring header prior to deserialization.
137+
for (OperationShape operationShape : topDownIndex.getContainedOperations(serviceShape)) {
138+
if (operationShape.getOutput().isEmpty()) {
139+
continue;
140+
}
141+
StructureShape structureShape = model.expectShape(
142+
operationShape.getOutputShape(), StructureShape.class
143+
);
144+
145+
Set<Map.Entry<String, MemberShape>> memberEntries = structureShape
146+
.getAllMembers()
147+
.entrySet();
148+
StructureShape.Builder structureShapeBuilder = structureShape.toBuilder();
149+
150+
boolean isTargetingExpires = structureShape
151+
.getAllMembers()
152+
.values()
153+
.stream()
154+
.anyMatch(memberShape -> memberShape.getTarget().equals(expiresShape.getId()));
155+
156+
if (isTargetingExpires) {
157+
for (Map.Entry<String, MemberShape> entry : memberEntries) {
158+
String memberName = entry.getKey();
159+
MemberShape memberShape = entry.getValue();
160+
161+
if (memberShape.getTarget().equals(expiresShape.getId())) {
162+
structureShapeBuilder
163+
.removeMember(memberName)
164+
.addMember(
165+
memberName,
166+
expiresTimestampShape.getId(),
167+
(m) -> {
168+
m
169+
.addTrait(new DocumentationTrait("Deprecated in favor of ExpiresString."))
170+
.addTrait(memberShape.getTrait(HttpHeaderTrait.class).get())
171+
.addTrait(DeprecatedTrait.builder().build());
172+
}
173+
)
174+
.addMember(
175+
"ExpiresString",
176+
expiresStringShape.getId(),
177+
(m) -> {
178+
m
179+
.addTrait(memberShape.getTrait(DocumentationTrait.class).get())
180+
.addTrait(new HttpHeaderTrait("ExpiresString"));
181+
}
182+
);
183+
} else {
184+
// This is done to preserve the member order
185+
// and insert ExpiresString adjacent to Expires.
186+
structureShapeBuilder
187+
.removeMember(memberName)
188+
.addMember(memberName, memberShape.getTarget(), (m) -> {
189+
m.addTraits(memberShape.getAllTraits().values());
190+
});
191+
}
192+
}
193+
modelBuilder
194+
.addShape(structureShapeBuilder.build());
195+
}
196+
}
197+
}
198+
109199
return modelBuilder.addShapes(inputShapes).build();
110200
}
111201

scripts/generate-clients/s3-hack.js

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -23,53 +23,6 @@ module.exports = function () {
2323
namespace: "com.amazonaws.s3",
2424
});
2525

26-
const expiresShape = s3ModelObject.shapes["com.amazonaws.s3#Expires"];
27-
if (expiresShape) {
28-
// enforce that Expires retains type timestamp.
29-
expiresShape.type = "timestamp";
30-
31-
// add the ExpiresString string shape.
32-
const newShapes = {};
33-
for (const [shapeId, shape] of Object.entries(s3ModelObject.shapes)) {
34-
newShapes[shapeId] = shape;
35-
if (shapeId === "com.amazonaws.s3#Expires") {
36-
newShapes["com.amazonaws.s3#ExpiresString"] = {
37-
type: "string",
38-
};
39-
}
40-
}
41-
s3ModelObject.shapes = newShapes;
42-
43-
// add ExpiresString alongside output shapes containing Expires.
44-
for (const [shapeId, shape] of Object.entries(s3ModelObject.shapes)) {
45-
if (shape?.traits?.["smithy.api#output"]) {
46-
const newMembers = {};
47-
for (const [memberName, member] of Object.entries(shape.members)) {
48-
newMembers[memberName] = member;
49-
if (member.target === "com.amazonaws.s3#Expires") {
50-
const existingDoc = member.traits["smithy.api#documentation"];
51-
if (!member.traits) {
52-
member.traits = {};
53-
}
54-
55-
newMembers.ExpiresString = {
56-
target: "com.amazonaws.s3#ExpiresString",
57-
traits: {
58-
...member.traits,
59-
"smithy.api#httpHeader": "ExpiresString",
60-
"smithy.api#documentation": existingDoc,
61-
},
62-
};
63-
64-
member.traits["smithy.api#deprecated"] = {};
65-
member.traits["smithy.api#documentation"] = "Deprecated in favor of ExpiresString.";
66-
}
67-
}
68-
shape.members = newMembers;
69-
}
70-
}
71-
}
72-
7326
fs.writeFileSync(s3ModelLocation, JSON.stringify(s3ModelObject, null, 2));
7427

7528
return () => {

0 commit comments

Comments
 (0)