Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/tame-suns-carry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@smithy/util-base64": minor
"@smithy/util-stream": minor
"@smithy/core": minor
---

refactoring to reduce code size
4 changes: 2 additions & 2 deletions packages/core/src/submodules/cbor/CborCodec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NormalizedSchema } from "@smithy/core/schema";
import { generateIdempotencyToken, parseEpochTimestamp } from "@smithy/core/serde";
import { _parseEpochTimestamp, generateIdempotencyToken } from "@smithy/core/serde";
import type { Codec, Schema, SerdeFunctions, ShapeDeserializer, ShapeSerializer } from "@smithy/types";
import { fromBase64 } from "@smithy/util-base64";

Expand Down Expand Up @@ -148,7 +148,7 @@ export class CborShapeDeserializer implements ShapeDeserializer {

if (ns.isTimestampSchema() && typeof value === "number") {
// format is ignored.
return parseEpochTimestamp(value);
return _parseEpochTimestamp(value);
}

if (ns.isBlobSchema()) {
Expand Down
43 changes: 26 additions & 17 deletions packages/core/src/submodules/cbor/SmithyRpcV2CborProtocol.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import type { ErrorSchema } from "@smithy/core/schema";
import { error, list, map, op, SCHEMA, struct, TypeRegistry } from "@smithy/core/schema";
import { HttpRequest, HttpResponse } from "@smithy/protocol-http";
import type { ResponseMetadata, RetryableTrait, SchemaRef } from "@smithy/types";
import type {
BlobSchema,
BooleanSchema,
MapSchemaModifier,
NumericSchema,
ResponseMetadata,
RetryableTrait,
SchemaRef,
StringSchema,
TimestampDefaultSchema,
} from "@smithy/types";
import { beforeEach, describe, expect, test as it } from "vitest";

import { cbor } from "./cbor";
Expand Down Expand Up @@ -29,8 +38,8 @@ describe(SmithyRpcV2CborProtocol.name, () => {
{},
["timestamp", "blob"],
[
[SCHEMA.TIMESTAMP_DEFAULT, 0],
[SCHEMA.BLOB, 0],
[4 satisfies TimestampDefaultSchema, 0],
[21 satisfies BlobSchema, 0],
]
),
input: {
Expand All @@ -56,11 +65,11 @@ describe(SmithyRpcV2CborProtocol.name, () => {
{},
["bool", "timestamp", "blob", "prefixHeaders", "searchParams"],
[
[SCHEMA.BOOLEAN, { httpQuery: "bool" }],
[SCHEMA.TIMESTAMP_DEFAULT, { httpHeader: "timestamp" }],
[SCHEMA.BLOB, { httpHeader: "blob" }],
[SCHEMA.MAP_MODIFIER | SCHEMA.STRING, { httpPrefixHeaders: "anti-" }],
[SCHEMA.MAP_MODIFIER | SCHEMA.STRING, { httpQueryParams: 1 }],
[2 satisfies BooleanSchema, { httpQuery: "bool" }],
[4 satisfies TimestampDefaultSchema, { httpHeader: "timestamp" }],
[21 satisfies BlobSchema, { httpHeader: "blob" }],
[(128 satisfies MapSchemaModifier) | (0 satisfies StringSchema), { httpPrefixHeaders: "anti-" }],
[(128 satisfies MapSchemaModifier) | (0 satisfies StringSchema), { httpQueryParams: 1 }],
]
),
input: {
Expand Down Expand Up @@ -104,10 +113,10 @@ describe(SmithyRpcV2CborProtocol.name, () => {
0,
["mySparseList", "myRegularList", "mySparseMap", "myRegularMap"],
[
[() => list("", "MySparseList", { sparse: 1 }, SCHEMA.NUMERIC), {}],
[() => list("", "MyList", {}, SCHEMA.NUMERIC), {}],
[() => map("", "MySparseMap", { sparse: 1 }, SCHEMA.STRING, SCHEMA.NUMERIC), {}],
[() => map("", "MyMap", {}, SCHEMA.STRING, SCHEMA.NUMERIC), {}],
[() => list("", "MySparseList", { sparse: 1 }, 1 satisfies NumericSchema), {}],
[() => list("", "MyList", {}, 1 satisfies NumericSchema), {}],
[() => map("", "MySparseMap", { sparse: 1 }, 0 satisfies StringSchema, 1 satisfies NumericSchema), {}],
[() => map("", "MyMap", {}, 0 satisfies StringSchema, 1 satisfies NumericSchema), {}],
]
),
input: {
Expand Down Expand Up @@ -207,10 +216,10 @@ describe(SmithyRpcV2CborProtocol.name, () => {
0,
["mySparseList", "myRegularList", "mySparseMap", "myRegularMap"],
[
[() => list("", "MyList", { sparse: 1 }, SCHEMA.NUMERIC), {}],
[() => list("", "MyList", {}, SCHEMA.NUMERIC), {}],
[() => map("", "MyMap", { sparse: 1 }, SCHEMA.STRING, SCHEMA.NUMERIC), {}],
[() => map("", "MyMap", {}, SCHEMA.STRING, SCHEMA.NUMERIC), {}],
[() => list("", "MyList", { sparse: 1 }, 1 satisfies NumericSchema), {}],
[() => list("", "MyList", {}, 1 satisfies NumericSchema), {}],
[() => map("", "MyMap", { sparse: 1 }, 0 satisfies StringSchema, 1 satisfies NumericSchema), {}],
[() => map("", "MyMap", {}, 0 satisfies StringSchema, 1 satisfies NumericSchema), {}],
]
),
mockOutput: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { cbor, CborCodec, dateToTag } from "@smithy/core/cbor";
import { NormalizedSchema, SCHEMA, sim, struct } from "@smithy/core/schema";
import { NormalizedSchema, sim, struct } from "@smithy/core/schema";
import { EventStreamMarshaller } from "@smithy/eventstream-serde-node";
import { HttpResponse } from "@smithy/protocol-http";
import type { Message as EventMessage } from "@smithy/types";
import type {
BlobSchema,
Message as EventMessage,
StreamingBlobSchema,
StringSchema,
TimestampEpochSecondsSchema,
} from "@smithy/types";
import { fromUtf8, toUtf8 } from "@smithy/util-utf8";
import { describe, expect, test as it } from "vitest";

Expand Down Expand Up @@ -53,9 +59,15 @@ describe(EventStreamSerde.name, () => {
"Payload",
0,
["payload"],
[sim("ns", "StreamingBlobPayload", SCHEMA.STREAMING_BLOB, { eventPayload: 1 })]
[sim("ns", "StreamingBlobPayload", 42 satisfies StreamingBlobSchema, { eventPayload: 1 })]
),
struct(
"ns",
"TextPayload",
0,
["payload"],
[sim("ns", "TextPayload", 0 satisfies StringSchema, { eventPayload: 1 })]
),
struct("ns", "TextPayload", 0, ["payload"], [sim("ns", "TextPayload", SCHEMA.STRING, { eventPayload: 1 })]),
struct(
"ns",
"CustomHeaders",
Expand All @@ -73,7 +85,7 @@ describe(EventStreamSerde.name, () => {
// here the non-eventstream members form an initial-request
// or initial-response when present.
["eventStreamMember", "dateMember", "blobMember"],
[eventStreamUnionSchema, SCHEMA.TIMESTAMP_EPOCH_SECONDS, SCHEMA.BLOB]
[eventStreamUnionSchema, 7 satisfies TimestampEpochSecondsSchema, 21 satisfies BlobSchema]
);

describe("serialization", () => {
Expand Down
11 changes: 7 additions & 4 deletions packages/core/src/submodules/event-streams/EventStreamSerde.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { NormalizedSchema } from "@smithy/core/schema";
import { SCHEMA } from "@smithy/core/schema";
import type { NormalizedSchema, StructureSchema } from "@smithy/core/schema";
import type {
DocumentSchema,
EventStreamMarshaller,
HttpRequest as IHttpRequest,
HttpResponse as IHttpResponse,
Expand Down Expand Up @@ -232,14 +232,17 @@ export class EventStreamSerde {
let explicitPayloadMember = null as null | string;
let explicitPayloadContentType: undefined | string;

const isKnownSchema = unionSchema.hasMemberSchema(unionMember);
const isKnownSchema = (() => {
const struct = unionSchema.getSchema() as StructureSchema;
return struct.memberNames.includes(unionMember);
})();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the only call to hasMemberSchema, so I inlined the function here and removed it from the alpha API.

const additionalHeaders: MessageHeaders = {};

if (!isKnownSchema) {
// $unknown member
const [type, value] = event[unionMember];
eventType = type;
serializer.write(SCHEMA.DOCUMENT, value);
serializer.write(15 satisfies DocumentSchema, value);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

importing even a numeric constant creates a lot of code under certain bundling conditions.

Rather than having a "magic number" 15, the TS satisfies keyword is useful to indicate and type-check the number, allowing usage-finding.

} else {
const eventSchema = unionSchema.getMemberSchema(unionMember);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { map, op, SCHEMA, struct } from "@smithy/core/schema";
import { map, op, struct } from "@smithy/core/schema";
import { HttpResponse } from "@smithy/protocol-http";
import type {
Codec,
CodecSettings,
HandlerExecutionContext,
HttpResponse as IHttpResponse,
ListSchemaModifier,
MapSchemaModifier,
MetadataBearer,
OperationSchema,
ResponseMetadata,
Schema,
SerdeFunctions,
ShapeDeserializer,
ShapeSerializer,
StringSchema,
TimestampDefaultSchema,
TimestampEpochSecondsSchema,
} from "@smithy/types";
import { parseUrl } from "@smithy/url-parser/src";
import { describe, expect, test as it } from "vitest";
Expand All @@ -32,7 +37,7 @@ describe(HttpBindingProtocol.name, () => {
const settings: CodecSettings = {
timestampFormat: {
useTrait: true,
default: SCHEMA.TIMESTAMP_EPOCH_SECONDS,
default: 7 satisfies TimestampEpochSecondsSchema,
},
httpBindings: true,
};
Expand Down Expand Up @@ -82,7 +87,7 @@ describe(HttpBindingProtocol.name, () => {
["timestampList"],
[
[
SCHEMA.LIST_MODIFIER | SCHEMA.TIMESTAMP_DEFAULT,
(64 satisfies ListSchemaModifier) | (4 satisfies TimestampDefaultSchema),
{
httpHeader: "x-timestamplist",
},
Expand Down Expand Up @@ -122,7 +127,7 @@ describe(HttpBindingProtocol.name, () => {
["httpPrefixHeaders"],
[
[
SCHEMA.MAP_MODIFIER | SCHEMA.STRING,
(128 satisfies MapSchemaModifier) | (0 satisfies StringSchema),
{
httpPrefixHeaders: "",
},
Expand Down Expand Up @@ -175,7 +180,7 @@ describe(HttpBindingProtocol.name, () => {
httpBindings: true,
timestampFormat: {
useTrait: true,
default: SCHEMA.TIMESTAMP_EPOCH_SECONDS,
default: 7 satisfies TimestampEpochSecondsSchema,
},
}),
}
Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/submodules/protocols/HttpBindingProtocol.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { NormalizedSchema, SCHEMA } from "@smithy/core/schema";
import { NormalizedSchema, translateTraits } from "@smithy/core/schema";
import { splitEvery, splitHeader } from "@smithy/core/serde";
import { HttpRequest } from "@smithy/protocol-http";
import type {
DocumentSchema,
Endpoint,
EndpointBearer,
HandlerExecutionContext,
Expand All @@ -11,6 +12,7 @@ import type {
OperationSchema,
Schema,
SerdeFunctions,
TimestampDefaultSchema,
} from "@smithy/types";
import { sdkStreamMixin } from "@smithy/util-stream";

Expand Down Expand Up @@ -58,7 +60,7 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
if (endpoint) {
this.updateServiceEndpoint(request, endpoint);
this.setHostPrefix(request, operationSchema, input);
const opTraits = NormalizedSchema.translateTraits(operationSchema.traits);
const opTraits = translateTraits(operationSchema.traits);
if (opTraits.http) {
request.method = opTraits.http[0];
const [path, search] = opTraits.http[1].split("?");
Expand Down Expand Up @@ -203,7 +205,7 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
if (response.statusCode >= 300) {
const bytes: Uint8Array = await collectBody(response.body, context);
if (bytes.byteLength > 0) {
Object.assign(dataObject, await deserializer.read(SCHEMA.DOCUMENT, bytes));
Object.assign(dataObject, await deserializer.read(15 satisfies DocumentSchema, bytes));
}
await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response));
throw new Error("@smithy/core/protocols - HTTP Protocol error handler failed to throw.");
Expand Down Expand Up @@ -304,7 +306,7 @@ export abstract class HttpBindingProtocol extends HttpProtocol {
let sections: string[];
if (
headerListValueSchema.isTimestampSchema() &&
headerListValueSchema.getSchema() === SCHEMA.TIMESTAMP_DEFAULT
headerListValueSchema.getSchema() === (4 satisfies TimestampDefaultSchema)
) {
sections = splitEvery(value, ",", 2);
} else {
Expand Down
12 changes: 9 additions & 3 deletions packages/core/src/submodules/protocols/HttpProtocol.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { map, SCHEMA, struct } from "@smithy/core/schema";
import type { HandlerExecutionContext, HttpResponse as IHttpResponse, Schema, SerdeFunctions } from "@smithy/types";
import { map, struct } from "@smithy/core/schema";
import type {
HandlerExecutionContext,
HttpResponse as IHttpResponse,
Schema,
SerdeFunctions,
TimestampEpochSecondsSchema,
} from "@smithy/types";
import { describe, expect, test as it } from "vitest";

import { HttpProtocol } from "./HttpProtocol";
Expand All @@ -18,7 +24,7 @@ describe(HttpProtocol.name, () => {
httpBindings: true,
timestampFormat: {
useTrait: true,
default: SCHEMA.TIMESTAMP_EPOCH_SECONDS,
default: 7 satisfies TimestampEpochSecondsSchema,
},
}),
});
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/submodules/protocols/HttpProtocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ export abstract class HttpProtocol implements ClientProtocol<IHttpRequest, IHttp
request.fragment = endpoint.url.hash || void 0;
request.username = endpoint.url.username || void 0;
request.password = endpoint.url.password || void 0;
if (!request.query) {
request.query = {};
}
for (const [k, v] of endpoint.url.searchParams.entries()) {
if (!request.query) {
request.query = {};
}
request.query[k] = v;
}
return request;
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/submodules/protocols/RpcProtocol.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NormalizedSchema, SCHEMA } from "@smithy/core/schema";
import { NormalizedSchema } from "@smithy/core/schema";
import { HttpRequest } from "@smithy/protocol-http";
import type {
DocumentSchema,
Endpoint,
EndpointBearer,
HandlerExecutionContext,
Expand Down Expand Up @@ -101,7 +102,7 @@ export abstract class RpcProtocol extends HttpProtocol {
if (response.statusCode >= 300) {
const bytes: Uint8Array = await collectBody(response.body, context as SerdeFunctions);
if (bytes.byteLength > 0) {
Object.assign(dataObject, await deserializer.read(SCHEMA.DOCUMENT, bytes));
Object.assign(dataObject, await deserializer.read(15 satisfies DocumentSchema, bytes));
}
await this.handleError(operationSchema, context, response, dataObject, this.deserializeMetadata(response));
throw new Error("@smithy/core/protocols - RPC Protocol error handler failed to throw.");
Expand Down
Loading