Skip to content

Commit f5b27b6

Browse files
committed
test(client-secrets-manager): schema testing
chore: refactor schemas
1 parent 2bd6ec2 commit f5b27b6

File tree

355 files changed

+15273
-3883
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

355 files changed

+15273
-3883
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
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.aws.typescript.codegen;
7+
8+
import java.util.Collections;
9+
import java.util.Map;
10+
import java.util.Objects;
11+
import java.util.function.Consumer;
12+
13+
import software.amazon.smithy.aws.traits.protocols.AwsJson1_0Trait;
14+
import software.amazon.smithy.aws.traits.protocols.AwsJson1_1Trait;
15+
import software.amazon.smithy.aws.traits.protocols.AwsQueryTrait;
16+
import software.amazon.smithy.aws.traits.protocols.Ec2QueryTrait;
17+
import software.amazon.smithy.aws.traits.protocols.RestJson1Trait;
18+
import software.amazon.smithy.aws.traits.protocols.RestXmlTrait;
19+
import software.amazon.smithy.codegen.core.SymbolProvider;
20+
import software.amazon.smithy.model.Model;
21+
import software.amazon.smithy.model.traits.XmlNamespaceTrait;
22+
import software.amazon.smithy.typescript.codegen.LanguageTarget;
23+
import software.amazon.smithy.typescript.codegen.TypeScriptSettings;
24+
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
25+
import software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration;
26+
import software.amazon.smithy.typescript.codegen.schema.SchemaGenerationAllowlist;
27+
import software.amazon.smithy.utils.MapUtils;
28+
import software.amazon.smithy.utils.SmithyInternalApi;
29+
30+
31+
/**
32+
* Adds a protocol implementation to the runtime config.
33+
*/
34+
@SmithyInternalApi
35+
public final class AddProtocolConfig implements TypeScriptIntegration {
36+
37+
public AddProtocolConfig() {
38+
SchemaGenerationAllowlist.allow("com.amazonaws.s3#AmazonS3");
39+
SchemaGenerationAllowlist.allow("com.amazonaws.dynamodb#DynamoDB_20120810");
40+
SchemaGenerationAllowlist.allow("com.amazonaws.lambda#AWSGirApiService");
41+
42+
// protocol tests
43+
SchemaGenerationAllowlist.allow("aws.protocoltests.json10#JsonRpc10");
44+
SchemaGenerationAllowlist.allow("aws.protocoltests.json#JsonProtocol");
45+
SchemaGenerationAllowlist.allow("aws.protocoltests.restjson#RestJson");
46+
SchemaGenerationAllowlist.allow("aws.protocoltests.restxml#RestXml");
47+
SchemaGenerationAllowlist.allow("aws.protocoltests.query#AwsQuery");
48+
SchemaGenerationAllowlist.allow("aws.protocoltests.ec2#AwsEc2");
49+
}
50+
51+
@Override
52+
public void addConfigInterfaceFields(
53+
TypeScriptSettings settings,
54+
Model model,
55+
SymbolProvider symbolProvider,
56+
TypeScriptWriter writer
57+
) {
58+
// the {{ protocol?: Protocol }} type field is provided
59+
// by the smithy client config interface.
60+
}
61+
62+
@Override
63+
public Map<String, Consumer<TypeScriptWriter>> getRuntimeConfigWriters(
64+
TypeScriptSettings settings,
65+
Model model,
66+
SymbolProvider symbolProvider,
67+
LanguageTarget target
68+
) {
69+
if (!SchemaGenerationAllowlist.contains(settings.getService())) {
70+
return Collections.emptyMap();
71+
}
72+
String namespace = settings.getService().getNamespace();
73+
String xmlns = settings.getService(model)
74+
.getTrait(XmlNamespaceTrait.class)
75+
.map(XmlNamespaceTrait::getUri)
76+
.orElse("");
77+
78+
switch (target) {
79+
case SHARED:
80+
if (Objects.equals(settings.getProtocol(), RestXmlTrait.ID)) {
81+
return MapUtils.of(
82+
"protocol", writer -> {
83+
writer.addImportSubmodule(
84+
"AwsRestXmlProtocol", null,
85+
AwsDependency.AWS_SDK_CORE, "/protocols");
86+
writer.write("""
87+
new AwsRestXmlProtocol({
88+
defaultNamespace: $S, xmlNamespace: $S,
89+
})""",
90+
namespace,
91+
xmlns
92+
);
93+
}
94+
);
95+
} else if (Objects.equals(settings.getProtocol(), AwsQueryTrait.ID)) {
96+
return MapUtils.of(
97+
"protocol", writer -> {
98+
writer.addImportSubmodule(
99+
"AwsQueryProtocol", null,
100+
AwsDependency.AWS_SDK_CORE, "/protocols");
101+
writer.write(
102+
"""
103+
new AwsQueryProtocol({
104+
defaultNamespace: $S,
105+
xmlNamespace: $S,
106+
version: $S
107+
})""",
108+
namespace,
109+
xmlns,
110+
settings.getService(model).getVersion()
111+
);
112+
}
113+
);
114+
} else if (Objects.equals(settings.getProtocol(), Ec2QueryTrait.ID)) {
115+
return MapUtils.of(
116+
"protocol", writer -> {
117+
writer.addImportSubmodule(
118+
"AwsEc2QueryProtocol", null,
119+
AwsDependency.AWS_SDK_CORE, "/protocols");
120+
writer.write(
121+
"""
122+
new AwsEc2QueryProtocol({
123+
defaultNamespace: $S,
124+
xmlNamespace: $S,
125+
version: $S
126+
})""",
127+
namespace,
128+
xmlns,
129+
settings.getService(model).getVersion()
130+
);
131+
}
132+
);
133+
} else if (Objects.equals(settings.getProtocol(), RestJson1Trait.ID)) {
134+
return MapUtils.of(
135+
"protocol", writer -> {
136+
writer.addImportSubmodule(
137+
"AwsRestJsonProtocol", null,
138+
AwsDependency.AWS_SDK_CORE, "/protocols");
139+
writer.write("new AwsRestJsonProtocol({ defaultNamespace: $S })", namespace);
140+
}
141+
);
142+
} else if (Objects.equals(settings.getProtocol(), AwsJson1_0Trait.ID)) {
143+
return MapUtils.of(
144+
"protocol", writer -> {
145+
writer.addImportSubmodule(
146+
"AwsJson1_0Protocol", null,
147+
AwsDependency.AWS_SDK_CORE, "/protocols");
148+
writer.write("new AwsJson1_0Protocol({ defaultNamespace: $S })", namespace);
149+
}
150+
);
151+
} else if (Objects.equals(settings.getProtocol(), AwsJson1_1Trait.ID)) {
152+
return MapUtils.of(
153+
"protocol", writer -> {
154+
writer.addImportSubmodule(
155+
"AwsJson1_1Protocol", null,
156+
AwsDependency.AWS_SDK_CORE, "/protocols");
157+
writer.write("new AwsJson1_1Protocol({ defaultNamespace: $S })", namespace);
158+
}
159+
);
160+
}
161+
case BROWSER:
162+
case NODE:
163+
default:
164+
return Collections.emptyMap();
165+
}
166+
}
167+
}

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

+17
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import software.amazon.smithy.model.shapes.ShapeId;
2929
import software.amazon.smithy.model.shapes.StructureShape;
3030
import software.amazon.smithy.model.traits.TimestampFormatTrait.Format;
31+
import software.amazon.smithy.model.traits.Trait;
32+
import software.amazon.smithy.typescript.codegen.schema.SchemaTraitExtension;
3133
import software.amazon.smithy.typescript.codegen.TypeScriptWriter;
3234
import software.amazon.smithy.typescript.codegen.integration.HttpRpcProtocolGenerator;
3335
import software.amazon.smithy.typescript.codegen.util.StringStore;
@@ -50,6 +52,21 @@
5052
*/
5153
@SmithyInternalApi
5254
final class AwsQuery extends HttpRpcProtocolGenerator {
55+
static {
56+
SchemaTraitExtension.INSTANCE.add(
57+
AwsQueryErrorTrait.ID,
58+
(Trait trait) -> {
59+
if (trait instanceof AwsQueryErrorTrait awsQueryError) {
60+
return """
61+
[`%s`, %s]""".formatted(
62+
awsQueryError.getCode(),
63+
awsQueryError.getHttpResponseCode()
64+
);
65+
}
66+
return "";
67+
}
68+
);
69+
}
5370

5471
AwsQuery() {
5572
// AWS Query protocols will attempt to parse error codes from response bodies.

codegen/smithy-aws-typescript-codegen/src/main/resources/META-INF/services/software.amazon.smithy.typescript.codegen.integration.TypeScriptIntegration

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ software.amazon.smithy.aws.typescript.codegen.AwsServiceIdIntegration
1313
software.amazon.smithy.aws.typescript.codegen.AwsPackageFixturesGeneratorIntegration
1414
software.amazon.smithy.aws.typescript.codegen.AddSqsDependency
1515
software.amazon.smithy.aws.typescript.codegen.AddBodyChecksumGeneratorDependency
16+
software.amazon.smithy.aws.typescript.codegen.AddProtocolConfig
1617
software.amazon.smithy.aws.typescript.codegen.AddS3Config
1718
software.amazon.smithy.aws.typescript.codegen.AddS3ControlDependency
1819
software.amazon.smithy.aws.typescript.codegen.AddEventStreamHandlingDependency

packages/core/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,18 @@
8282
"license": "Apache-2.0",
8383
"dependencies": {
8484
"@aws-sdk/types": "*",
85+
"@aws-sdk/xml-builder": "*",
8586
"@smithy/core": "^3.3.0",
8687
"@smithy/node-config-provider": "^4.0.2",
8788
"@smithy/property-provider": "^4.0.2",
8889
"@smithy/protocol-http": "^5.1.0",
8990
"@smithy/signature-v4": "^5.1.0",
9091
"@smithy/smithy-client": "^4.2.1",
9192
"@smithy/types": "^4.2.0",
93+
"@smithy/util-base64": "^4.0.0",
94+
"@smithy/util-body-length-browser": "^4.0.0",
9295
"@smithy/util-middleware": "^4.0.2",
96+
"@smithy/util-utf8": "^4.0.0",
9397
"fast-xml-parser": "4.4.1",
9498
"tslib": "^2.6.2"
9599
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { ConfigurableSerdeContext, SerdeContext } from "@smithy/types";
2+
3+
/**
4+
* @internal
5+
*/
6+
export class SerdeContextConfig implements ConfigurableSerdeContext {
7+
protected serdeContext?: SerdeContext;
8+
9+
public setSerdeContext(serdeContext: SerdeContext): void {
10+
this.serdeContext = serdeContext;
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
export * from "./coercing-serializers";
2+
export * from "./json/AwsJson1_0Protocol";
3+
export * from "./json/AwsJson1_1Protocol";
4+
export * from "./json/AwsJsonRpcProtocol";
5+
export * from "./json/AwsRestJsonProtocol";
6+
export * from "./json/JsonCodec";
7+
export * from "./json/JsonShapeDeserializer";
8+
export * from "./json/JsonShapeSerializer";
29
export * from "./json/awsExpectUnion";
310
export * from "./json/parseJsonBody";
11+
export * from "./query/AwsEc2QueryProtocol";
12+
export * from "./query/AwsQueryProtocol";
13+
export * from "./xml/AwsRestXmlProtocol";
14+
export * from "./xml/XmlCodec";
15+
export * from "./xml/XmlShapeDeserializer";
16+
export * from "./xml/XmlShapeSerializer";
417
export * from "./xml/parseXmlBody";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { map, op, SCHEMA, sim, struct } from "@smithy/core/schema";
2+
import { toBase64 } from "@smithy/util-base64";
3+
import { toUtf8 } from "@smithy/util-utf8";
4+
import { describe, expect, test as it } from "vitest";
5+
6+
import { AwsJson1_0Protocol } from "./AwsJson1_0Protocol";
7+
8+
describe(AwsJson1_0Protocol.name, () => {
9+
const json = {
10+
string: "string",
11+
number: 1234,
12+
boolean: false,
13+
blob: "AAAAAAAAAAA=",
14+
timestamp: 0,
15+
};
16+
const schema = struct(
17+
"MyStruct",
18+
0,
19+
[...Object.keys(json)],
20+
[SCHEMA.STRING, SCHEMA.NUMERIC, SCHEMA.BOOLEAN, SCHEMA.BLOB, SCHEMA.TIMESTAMP_DEFAULT]
21+
);
22+
const serdeContext = {
23+
base64Encoder: toBase64,
24+
utf8Encoder: toUtf8,
25+
} as any;
26+
27+
describe("codec", () => {
28+
it("serializes blobs and timestamps", () => {
29+
const protocol = new AwsJson1_0Protocol();
30+
protocol.setSerdeContext(serdeContext);
31+
const codec = protocol.getPayloadCodec();
32+
const serializer = codec.createSerializer();
33+
const data = {
34+
string: "string",
35+
number: 1234,
36+
boolean: false,
37+
blob: new Uint8Array(8),
38+
timestamp: new Date(0),
39+
};
40+
serializer.write(schema, data);
41+
const serialized = serializer.flush();
42+
expect(JSON.parse(serialized)).toEqual({
43+
string: "string",
44+
number: 1234,
45+
boolean: false,
46+
blob: "AAAAAAAAAAA=",
47+
timestamp: 0,
48+
});
49+
});
50+
51+
it("deserializes blobs and timestamps", async () => {
52+
const protocol = new AwsJson1_0Protocol();
53+
protocol.setSerdeContext(serdeContext);
54+
const codec = protocol.getPayloadCodec();
55+
const deserializer = codec.createDeserializer();
56+
57+
const parsed = await deserializer.read(schema, JSON.stringify(json));
58+
expect(parsed).toEqual({
59+
string: "string",
60+
number: 1234,
61+
boolean: false,
62+
blob: new Uint8Array(8),
63+
timestamp: new Date(0),
64+
});
65+
});
66+
67+
it("ignores JSON name and HTTP bindings", async () => {
68+
const protocol = new AwsJson1_0Protocol();
69+
protocol.setSerdeContext(serdeContext);
70+
71+
const schema = struct(
72+
"MyHttpBindingStructure",
73+
{},
74+
["header", "query", "headerMap", "payload"],
75+
[
76+
sim("MyHeader", SCHEMA.STRING, { httpHeader: "header", jsonName: "MyHeader" }),
77+
sim("MyQuery", SCHEMA.STRING, { httpQuery: "query" }),
78+
map(
79+
"HeaderMap",
80+
{
81+
httpPrefixHeaders: "",
82+
},
83+
SCHEMA.NUMERIC
84+
),
85+
sim("MyPayload", SCHEMA.DOCUMENT, { httpPayload: 1 }),
86+
]
87+
);
88+
const operationSchema = op("MyOperation", {}, schema, "unit");
89+
90+
const request = await protocol.serializeRequest(
91+
operationSchema,
92+
{
93+
header: "hello",
94+
query: "world",
95+
headerMap: {
96+
a: 1,
97+
b: 2,
98+
},
99+
},
100+
{
101+
endpointV2: {
102+
url: new URL("https://amazonaws.com/"),
103+
},
104+
}
105+
);
106+
107+
expect(request.headers).toEqual({});
108+
expect(request.query).toEqual({});
109+
expect(request.body).toEqual(`{"header":"hello","query":"world","headerMap":{"a":1,"b":2}}`);
110+
});
111+
});
112+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { AwsJsonRpcProtocol } from "./AwsJsonRpcProtocol";
2+
3+
/**
4+
* @public
5+
* @see https://smithy.io/2.0/aws/protocols/aws-json-1_1-protocol.html#differences-between-awsjson1-0-and-awsjson1-1
6+
*/
7+
export class AwsJson1_0Protocol extends AwsJsonRpcProtocol {
8+
public constructor({ defaultNamespace }: { defaultNamespace: string }) {
9+
super({
10+
defaultNamespace,
11+
});
12+
}
13+
14+
public getShapeId(): string {
15+
return "aws.protocols#awsJson1_0";
16+
}
17+
18+
protected getJsonRpcVersion() {
19+
return "1.0" as const;
20+
}
21+
}

0 commit comments

Comments
 (0)