Skip to content

Commit

Permalink
chore(codegen): move s3 transform to Java code (#5963)
Browse files Browse the repository at this point in the history
* chore(codegen): move s3 transform to Java code

* chore: checkstyle
  • Loading branch information
kuhe authored Apr 5, 2024
1 parent ffd9380 commit 58875c9
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 50 deletions.
1 change: 0 additions & 1 deletion clients/client-s3/src/models/models_0.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// smithy-typescript generated code
import { ExceptionOptionType as __ExceptionOptionType, SENSITIVE_STRING } from "@smithy/smithy-client";

import { StreamingBlobTypes } from "@smithy/types";

import { S3ServiceException as __BaseException } from "./S3ServiceException";
Expand Down
2 changes: 0 additions & 2 deletions clients/client-s3/src/models/models_1.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// smithy-typescript generated code
import { ExceptionOptionType as __ExceptionOptionType, SENSITIVE_STRING } from "@smithy/smithy-client";

import { StreamingBlobTypes } from "@smithy/types";

import {
Expand Down Expand Up @@ -28,7 +27,6 @@ import {
StorageClass,
Tag,
} from "./models_0";

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

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@
import software.amazon.smithy.model.shapes.OperationShape;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.StringShape;
import software.amazon.smithy.model.shapes.StructureShape;
import software.amazon.smithy.model.shapes.TimestampShape;
import software.amazon.smithy.model.traits.DeprecatedTrait;
import software.amazon.smithy.model.traits.DocumentationTrait;
import software.amazon.smithy.model.traits.HttpHeaderTrait;
import software.amazon.smithy.typescript.codegen.LanguageTarget;
import software.amazon.smithy.typescript.codegen.TypeScriptDependency;
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
Expand Down Expand Up @@ -106,6 +111,91 @@ public Model preprocessModel(Model model, TypeScriptSettings settings) {
});
}
LOGGER.info("Patching " + inputShapes.size() + " input shapes with CRT notification");

boolean expiresShapeIsPresent = model.getShape(ShapeId.from("com.amazonaws.s3#Expires")).isPresent();
if (expiresShapeIsPresent) {
// ExpiresString customization part 1:
// enforce that "com.amazonaws.s3#Expires" retains type=timestamp.
// add a shape "com.amazonaws.s3#ExpiresString" of type=string.
Shape expiresShape = model.getShape(ShapeId.from("com.amazonaws.s3#Expires")).get();
TimestampShape expiresTimestampShape = TimestampShape.builder()
.id(expiresShape.getId())
.build();
StringShape expiresStringShape = StringShape.builder()
.id("com.amazonaws.s3#ExpiresString")
.build();
modelBuilder
.removeShape(expiresShape.getId())
.addShapes(expiresTimestampShape, expiresStringShape);

// ExpiresString customization part 2:
// for any output shape member targeting Expires, add a member ExpiresString targeting ExpiresString.
// and mark Expires deprecated in favor of ExpiresString.
// move Expires documentation trait to ExpiresString.
// set the httpHeader trait of ExpiresString to be ExpiresString.
// SDK middleware will take care of copying expires header to expiresstring header prior to deserialization.
for (OperationShape operationShape : topDownIndex.getContainedOperations(serviceShape)) {
if (operationShape.getOutput().isEmpty()) {
continue;
}
StructureShape structureShape = model.expectShape(
operationShape.getOutputShape(), StructureShape.class
);

Set<Map.Entry<String, MemberShape>> memberEntries = structureShape
.getAllMembers()
.entrySet();
StructureShape.Builder structureShapeBuilder = structureShape.toBuilder();

boolean isTargetingExpires = structureShape
.getAllMembers()
.values()
.stream()
.anyMatch(memberShape -> memberShape.getTarget().equals(expiresShape.getId()));

if (isTargetingExpires) {
for (Map.Entry<String, MemberShape> entry : memberEntries) {
String memberName = entry.getKey();
MemberShape memberShape = entry.getValue();

if (memberShape.getTarget().equals(expiresShape.getId())) {
structureShapeBuilder
.removeMember(memberName)
.addMember(
memberName,
expiresTimestampShape.getId(),
(m) -> {
m
.addTrait(new DocumentationTrait("Deprecated in favor of ExpiresString."))
.addTrait(memberShape.getTrait(HttpHeaderTrait.class).get())
.addTrait(DeprecatedTrait.builder().build());
}
)
.addMember(
"ExpiresString",
expiresStringShape.getId(),
(m) -> {
m
.addTrait(memberShape.getTrait(DocumentationTrait.class).get())
.addTrait(new HttpHeaderTrait("ExpiresString"));
}
);
} else {
// This is done to preserve the member order
// and insert ExpiresString adjacent to Expires.
structureShapeBuilder
.removeMember(memberName)
.addMember(memberName, memberShape.getTarget(), (m) -> {
m.addTraits(memberShape.getAllTraits().values());
});
}
}
modelBuilder
.addShape(structureShapeBuilder.build());
}
}
}

return modelBuilder.addShapes(inputShapes).build();
}

Expand Down
47 changes: 0 additions & 47 deletions scripts/generate-clients/s3-hack.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,53 +23,6 @@ module.exports = function () {
namespace: "com.amazonaws.s3",
});

const expiresShape = s3ModelObject.shapes["com.amazonaws.s3#Expires"];
if (expiresShape) {
// enforce that Expires retains type timestamp.
expiresShape.type = "timestamp";

// add the ExpiresString string shape.
const newShapes = {};
for (const [shapeId, shape] of Object.entries(s3ModelObject.shapes)) {
newShapes[shapeId] = shape;
if (shapeId === "com.amazonaws.s3#Expires") {
newShapes["com.amazonaws.s3#ExpiresString"] = {
type: "string",
};
}
}
s3ModelObject.shapes = newShapes;

// add ExpiresString alongside output shapes containing Expires.
for (const [shapeId, shape] of Object.entries(s3ModelObject.shapes)) {
if (shape?.traits?.["smithy.api#output"]) {
const newMembers = {};
for (const [memberName, member] of Object.entries(shape.members)) {
newMembers[memberName] = member;
if (member.target === "com.amazonaws.s3#Expires") {
const existingDoc = member.traits["smithy.api#documentation"];
if (!member.traits) {
member.traits = {};
}

newMembers.ExpiresString = {
target: "com.amazonaws.s3#ExpiresString",
traits: {
...member.traits,
"smithy.api#httpHeader": "ExpiresString",
"smithy.api#documentation": existingDoc,
},
};

member.traits["smithy.api#deprecated"] = {};
member.traits["smithy.api#documentation"] = "Deprecated in favor of ExpiresString.";
}
}
shape.members = newMembers;
}
}
}

fs.writeFileSync(s3ModelLocation, JSON.stringify(s3ModelObject, null, 2));

return () => {
Expand Down

0 comments on commit 58875c9

Please sign in to comment.