Skip to content

Commit 4fbe429

Browse files
committed
rework schemas
1 parent 367616d commit 4fbe429

Some content is hidden

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

42 files changed

+1189
-667
lines changed

packages/core/src/submodules/cbor/CborCodec.ts

+48-42
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
1-
import { deref, ListSchema, MapSchema, StructureSchema } from "@smithy/core/schema";
1+
import { NormalizedSchema } from "@smithy/core/schema";
22
import { copyDocumentWithTransform, parseEpochTimestamp } from "@smithy/core/serde";
3-
import {
4-
Codec,
5-
MemberSchema,
6-
Schema,
7-
SchemaRef,
8-
SerdeContext,
9-
ShapeDeserializer,
10-
ShapeSerializer,
11-
TraitsSchema,
12-
} from "@smithy/types";
3+
import { Codec, Schema, SchemaRef, SerdeContext, ShapeDeserializer, ShapeSerializer } from "@smithy/types";
134

145
import { cbor } from "./cbor";
156
import { dateToTag } from "./parseCborBody";
@@ -22,6 +13,7 @@ export class CborCodec implements Codec<Uint8Array, Uint8Array> {
2213
serializer.setSerdeContext(this.serdeContext!);
2314
return serializer;
2415
}
16+
2517
public createDeserializer(): CborShapeDeserializer {
2618
const deserializer = new CborShapeDeserializer();
2719
deserializer.setSerdeContext(this.serdeContext!);
@@ -46,17 +38,19 @@ export class CborShapeSerializer implements ShapeSerializer<Uint8Array> {
4638
if (_ instanceof Date) {
4739
return dateToTag(_);
4840
}
49-
const schema = deref((schemaRef as MemberSchema)?.[0] ?? schemaRef);
5041
if (_ instanceof Uint8Array) {
5142
return _;
5243
}
53-
const sparse = (schema as TraitsSchema)?.traits?.sparse;
44+
45+
const ns = NormalizedSchema.of(schemaRef);
46+
const sparse = !!ns.getMergedTraits().sparse;
47+
5448
if (Array.isArray(_)) {
5549
if (!sparse) {
5650
return _.filter((item) => item != null);
5751
}
5852
} else if (_ && typeof _ === "object") {
59-
if (!sparse) {
53+
if (!sparse || ns.isStructSchema()) {
6054
for (const [k, v] of Object.entries(_)) {
6155
if (v == null) {
6256
delete _[k];
@@ -65,6 +59,7 @@ export class CborShapeSerializer implements ShapeSerializer<Uint8Array> {
6559
return _;
6660
}
6761
}
62+
6863
return _;
6964
});
7065
}
@@ -88,15 +83,20 @@ export class CborShapeDeserializer implements ShapeDeserializer {
8883
return this.readValue(schema, data);
8984
}
9085

91-
private readValue(schema: Schema, value: any): any {
92-
if (typeof schema === "string") {
93-
if (schema === "time" || schema === "epoch-seconds" || schema === "date-time") {
86+
private readValue(_schema: Schema, value: any): any {
87+
const ns = NormalizedSchema.of(_schema);
88+
const schema = ns.getSchema();
89+
90+
if (typeof schema === "number") {
91+
if (ns.isTimestampSchema()) {
92+
// format is ignored.
9493
return parseEpochTimestamp(value);
9594
}
96-
if (schema === "blob" || schema === "streaming-blob") {
95+
if (ns.isBlobSchema()) {
9796
return value;
9897
}
9998
}
99+
100100
switch (typeof value) {
101101
case "undefined":
102102
case "boolean":
@@ -116,38 +116,44 @@ export class CborShapeDeserializer implements ShapeDeserializer {
116116
if (value instanceof Date) {
117117
return value;
118118
}
119-
const traits =
120-
Array.isArray(schema) && schema.length >= 2
121-
? {
122-
...(deref((schema as MemberSchema)[0]) as TraitsSchema)?.traits,
123-
...(schema as MemberSchema)[1],
124-
}
125-
: (deref(schema) as TraitsSchema)?.traits;
126-
127-
if (Array.isArray(value)) {
119+
if (ns.isDocumentSchema()) {
120+
return value;
121+
}
122+
123+
if (ns.isListSchema()) {
128124
const newArray = [];
125+
const memberSchema = ns.getValueSchema();
126+
const sparse = ns.isListSchema() && !!ns.getMergedTraits().sparse;
127+
129128
for (const item of value) {
130-
newArray.push(this.readValue(schema instanceof ListSchema ? deref(schema.valueSchema) : void 0, item));
131-
if (!traits?.sparse) {
132-
if (newArray[newArray.length - 1] == null) {
133-
newArray.pop();
134-
}
129+
newArray.push(this.readValue(memberSchema, item));
130+
if (!sparse && newArray[newArray.length - 1] == null) {
131+
newArray.pop();
135132
}
136133
}
137134
return newArray;
138135
}
139136

140137
const newObject = {} as any;
141-
for (const key of Object.keys(value)) {
142-
const targetSchema =
143-
schema instanceof StructureSchema
144-
? deref(schema.members[key]?.[0])
145-
: schema instanceof MapSchema
146-
? deref(schema.valueSchema)
147-
: void 0;
148-
newObject[key] = this.readValue(targetSchema, value[key]);
149-
if (!traits?.sparse && newObject[key] == null) {
150-
delete newObject[key];
138+
139+
if (ns.isMapSchema()) {
140+
const sparse = ns.getMergedTraits().sparse;
141+
const targetSchema = ns.getValueSchema();
142+
143+
for (const key of Object.keys(value)) {
144+
newObject[key] = this.readValue(targetSchema, value[key]);
145+
146+
if (newObject[key] == null && !sparse) {
147+
delete newObject[key];
148+
}
149+
}
150+
} else if (ns.isStructSchema()) {
151+
for (const key of Object.keys(value)) {
152+
const targetSchema = ns.getMemberSchema(key);
153+
if (targetSchema === undefined) {
154+
continue;
155+
}
156+
newObject[key] = this.readValue(targetSchema, value[key]);
151157
}
152158
}
153159
return newObject;

packages/core/src/submodules/cbor/SmithyRpcV2CborProtocol.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,10 @@ describe(SmithyRpcV2CborProtocol.name, () => {
154154
const protocol = new SmithyRpcV2CborProtocol();
155155
const httpRequest = await protocol.serializeRequest(
156156
{
157+
name: "dummy",
157158
input: testCase.schema,
158159
output: void 0,
159160
traits: {},
160-
errors: [],
161161
},
162162
testCase.input,
163163
{
@@ -249,10 +249,10 @@ describe(SmithyRpcV2CborProtocol.name, () => {
249249
const protocol = new SmithyRpcV2CborProtocol();
250250
const output = await protocol.deserializeResponse(
251251
{
252+
name: "dummy",
252253
input: void 0,
253254
output: testCase.schema,
254255
traits: {},
255-
errors: [],
256256
},
257257
{},
258258
new HttpResponse({

packages/core/src/submodules/cbor/SmithyRpcV2CborProtocol.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { HttpInterceptingShapeSerializer,HttpProtocol } from "@smithy/core/protocols";
1+
import { HttpInterceptingShapeSerializer, HttpProtocol } from "@smithy/core/protocols";
22
import { deref, ErrorSchema, OperationSchema, TypeRegistry } from "@smithy/core/schema";
33
import type {
44
HandlerExecutionContext,
@@ -36,6 +36,10 @@ export class SmithyRpcV2CborProtocol extends HttpProtocol {
3636
delete request.body;
3737
delete request.headers["content-type"];
3838
} else {
39+
if (!request.body) {
40+
this.serializer.write(15, {})
41+
request.body = this.serializer.flush();
42+
}
3943
try {
4044
request.headers["content-length"] = String((request.body as Uint8Array).byteLength);
4145
} catch (e) {}
@@ -82,6 +86,7 @@ export class SmithyRpcV2CborProtocol extends HttpProtocol {
8286
// TODO(schema) throw client base exception using the dataObject.
8387
throw new Error("schema not found for " + error);
8488
}
89+
8590
const message = dataObject.message ?? dataObject.Message ?? "Unknown";
8691
const exception = new errorSchema.ctor(message);
8792
Object.assign(exception, {

packages/core/src/submodules/protocols/HttpProtocol.ts

+22-9
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@ export abstract class HttpProtocol implements Protocol<IHttpRequest, IHttpRespon
7676
...input,
7777
};
7878

79-
if (operationSchema.traits.http) {
80-
request.method = operationSchema.traits.http[0];
81-
const [path, search] = operationSchema.traits.http[1].split("?");
79+
const opTraits = NormalizedSchema.translateTraits(operationSchema.traits);
80+
if (opTraits.http) {
81+
request.method = opTraits.http[0];
82+
const [path, search] = opTraits.http[1].split("?");
8283

8384
request.path = path;
8485
const traitSearchParams = new URLSearchParams(search ?? "");
@@ -87,6 +88,9 @@ export abstract class HttpProtocol implements Protocol<IHttpRequest, IHttpRespon
8788

8889
for (const memberName of Object.keys(_input)) {
8990
const memberNs = ns.getMemberSchema(memberName);
91+
if (memberNs === undefined) {
92+
continue;
93+
}
9094
const memberSchema = memberNs.getSchema();
9195
const memberTraits = memberNs.getMergedTraits();
9296
const inputMember = (_input as any)[memberName] as any;
@@ -122,13 +126,13 @@ export abstract class HttpProtocol implements Protocol<IHttpRequest, IHttpRespon
122126
} else if (memberTraits.httpPrefixHeaders) {
123127
for (const [key, val] of Object.entries(inputMember)) {
124128
const amalgam = memberTraits.httpPrefixHeaders + key;
125-
serializer.write([, { httpHeader: amalgam }], val);
129+
serializer.write([0, { httpHeader: amalgam }], val);
126130
headers[amalgam.toLowerCase()] = String(serializer.flush()).toLowerCase();
127131
}
128132
delete _input[memberName];
129133
} else if (memberTraits.httpQueryParams) {
130134
for (const [key, val] of Object.entries(inputMember)) {
131-
serializer.write([, { httpQuery: key }], val);
135+
serializer.write([0, { httpQuery: key }], val);
132136
query[key] = serializer.flush() as string;
133137
}
134138
delete _input[memberName];
@@ -178,6 +182,16 @@ export abstract class HttpProtocol implements Protocol<IHttpRequest, IHttpRespon
178182
const schema = ns.getSchema() as StructureSchema;
179183

180184
let dataObject: any = {};
185+
186+
if (response.statusCode >= 300) {
187+
const bytes: Uint8Array = await collectBody(response.body, context as SerdeContext);
188+
if (bytes.byteLength > 0) {
189+
Object.assign(dataObject, await deserializer.read(15, bytes));
190+
}
191+
await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response));
192+
throw new Error("@smithy/core/protocols - HTTP Protocol error handler failed to throw.");
193+
}
194+
181195
let hasNonHttpBindingMember = false;
182196

183197
for (const header in response.headers) {
@@ -188,6 +202,9 @@ export abstract class HttpProtocol implements Protocol<IHttpRequest, IHttpRespon
188202

189203
for (const [memberName] of Object.entries(schema?.members ?? {})) {
190204
const memberSchema = ns.getMemberSchema(memberName);
205+
if (memberSchema === undefined) {
206+
continue;
207+
}
191208
const memberSchemas = memberSchema.getMemberSchemas();
192209
const memberTraits = memberSchema.getMemberTraits();
193210

@@ -261,10 +278,6 @@ export abstract class HttpProtocol implements Protocol<IHttpRequest, IHttpRespon
261278
}
262279
}
263280

264-
if (response.statusCode >= 300) {
265-
await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response));
266-
}
267-
268281
const output: Output = {
269282
$metadata: this.deserializeMetadata(response),
270283
...dataObject,

packages/core/src/submodules/protocols/serde/FromStringShapeDeserializer.ts

+10-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NormalizedSchema, TypeRegistry } from "@smithy/core/schema";
2-
import { parseRfc3339DateTimeWithOffset, splitHeader } from "@smithy/core/serde";
2+
import { NumericValue,parseRfc3339DateTimeWithOffset, splitHeader } from "@smithy/core/serde";
33
import { Schema, SerdeContext, ShapeDeserializer } from "@smithy/types";
44
import { fromBase64 } from "@smithy/util-base64";
55

@@ -21,25 +21,23 @@ export class FromStringShapeDeserializer implements ShapeDeserializer<string> {
2121
if (ns.isListSchema()) {
2222
return splitHeader(data);
2323
}
24-
if (schema === "blob" || schema === "streaming-blob") {
24+
if (schema === 0b0001_0101 || schema === 0b0010_1010) {
2525
return fromBase64(data);
2626
}
27-
if (schema === "time") {
27+
if (schema === 0b0000_0100) {
2828
return this.defaultTimestampParser(data);
2929
}
30-
if (schema === "date-time") {
30+
if (schema === 0b0000_0101) {
3131
return parseRfc3339DateTimeWithOffset(data);
3232
}
33-
const simpleType = this.registry.getSimpleType(ns.getName() ?? "");
34-
switch (simpleType) {
35-
case "number":
33+
switch (true) {
34+
case ns.isNumericSchema():
3635
return Number(data);
37-
case "bigint":
36+
case ns.isBigIntegerSchema():
3837
return BigInt(data);
39-
case "bigdecimal":
40-
// todo(schema)
41-
throw new Error("bigdecimal not implemented");
42-
case "boolean":
38+
case ns.isBigDecimalSchema():
39+
return new NumericValue(data, "bigDecimal");
40+
case ns.isBooleanSchema():
4341
return String(data).toLowerCase() === "true";
4442
}
4543
return data;

0 commit comments

Comments
 (0)