Skip to content

Commit

Permalink
fix(types): use SerdeFunctions type as serde plugin input, but call s…
Browse files Browse the repository at this point in the history
…erde functions as type SerdeContext (#1183)

* fix(types): use optional endpoint for inputs to serializer middleware

* docs: add comments describing cast of SerdeFunctions to CommandSerdeContext

* fix: add default types (any) for serde plugin

* docs: remove code comments that no longer apply
  • Loading branch information
kuhe authored Mar 7, 2024
1 parent 85a275d commit 32e3f6f
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 17 deletions.
5 changes: 5 additions & 0 deletions .changeset/many-stingrays-bow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@smithy/middleware-serde": patch
---

use SerdeFunctions as input type and SerdeContext as resolved type for serde plugin
20 changes: 15 additions & 5 deletions packages/middleware-serde/src/deserializerMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ import {
DeserializeMiddleware,
HandlerExecutionContext,
ResponseDeserializer,
SerdeContext,
SerdeFunctions,
} from "@smithy/types";

/**
* @internal
*
* 3rd type parameter is deprecated and unused.
*/
export const deserializerMiddleware = <Input extends object, Output extends object, _ = any>(
export const deserializerMiddleware = <
Input extends object = any,
Output extends object = any,
CommandSerdeContext extends SerdeContext = any
>(
options: SerdeFunctions,
deserializer: ResponseDeserializer<any, any, SerdeFunctions>
deserializer: ResponseDeserializer<any, any, CommandSerdeContext>
): DeserializeMiddleware<Input, Output> => (
next: DeserializeHandler<Input, Output>,
context: HandlerExecutionContext
Expand All @@ -24,7 +27,14 @@ export const deserializerMiddleware = <Input extends object, Output extends obje
): Promise<DeserializeHandlerOutput<Output>> => {
const { response } = await next(args);
try {
const parsed = await deserializer(response, options);
/**
* [options] is upgraded from SerdeFunctions to CommandSerdeContext,
* since the generated deserializer expects CommandSerdeContext.
*
* This is okay because options is from the same client's resolved config,
* and the deserializer doesn't need the `endpoint` field.
*/
const parsed = await deserializer(response, options as CommandSerdeContext);
return {
response,
output: parsed as Output,
Expand Down
13 changes: 8 additions & 5 deletions packages/middleware-serde/src/serdePlugin.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {
DeserializeHandlerOptions,
Endpoint,
EndpointBearer,
MetadataBearer,
MiddlewareStack,
Pluggable,
Provider,
RequestSerializer,
ResponseDeserializer,
SerdeContext,
SerdeFunctions,
SerializeHandlerOptions,
UrlParser,
Expand Down Expand Up @@ -43,12 +43,15 @@ export type V1OrV2Endpoint = {
/**
* @internal
*
* Note: 2nd type parameter is deprecated and unused.
*/
export function getSerdePlugin<InputType extends object, _, OutputType extends MetadataBearer>(
export function getSerdePlugin<
InputType extends object = any,
CommandSerdeContext extends SerdeContext = any,
OutputType extends MetadataBearer = any
>(
config: V1OrV2Endpoint & SerdeFunctions,
serializer: RequestSerializer<any, SerdeFunctions & EndpointBearer>,
deserializer: ResponseDeserializer<OutputType, any, SerdeFunctions>
serializer: RequestSerializer<any, CommandSerdeContext>,
deserializer: ResponseDeserializer<OutputType, any, CommandSerdeContext>
): Pluggable<InputType, OutputType> {
return {
applyToStack: (commandStack: MiddlewareStack<InputType, OutputType>) => {
Expand Down
25 changes: 18 additions & 7 deletions packages/middleware-serde/src/serializerMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {
EndpointBearer,
Endpoint,
HandlerExecutionContext,
Provider,
RequestSerializer,
SerdeContext,
SerdeFunctions,
SerializeHandler,
SerializeHandlerArguments,
Expand All @@ -13,19 +15,21 @@ import type { V1OrV2Endpoint } from "./serdePlugin";

/**
* @internal
*
* Note: 3rd type parameter is deprecated and unused.
*/
export const serializerMiddleware = <Input extends object, Output extends object, _>(
export const serializerMiddleware = <
Input extends object = any,
Output extends object = any,
CommandSerdeContext extends SerdeContext = any
>(
options: V1OrV2Endpoint & SerdeFunctions,
serializer: RequestSerializer<any, SerdeFunctions & EndpointBearer>
serializer: RequestSerializer<any, CommandSerdeContext>
): SerializeMiddleware<Input, Output> => (
next: SerializeHandler<Input, Output>,
context: HandlerExecutionContext
): SerializeHandler<Input, Output> => async (
args: SerializeHandlerArguments<Input>
): Promise<SerializeHandlerOutput<Output>> => {
const endpoint =
const endpoint: Provider<Endpoint> =
context.endpointV2?.url && options.urlParser
? async () => options.urlParser!(context.endpointV2!.url as URL)
: options.endpoint!;
Expand All @@ -34,7 +38,14 @@ export const serializerMiddleware = <Input extends object, Output extends object
throw new Error("No valid endpoint provider available.");
}

const request = await serializer(args.input, { ...options, endpoint });
/**
* [options] is upgraded from SerdeFunctions to CommandSerdeContext,
* since the generated serializer expects CommandSerdeContext.
*
* This is okay because options is from the same client's resolved config,
* and `endpoint` has been provided here by checking two sources.
*/
const request = await serializer(args.input, { ...options, endpoint } as CommandSerdeContext);

return next({
...args,
Expand Down

0 comments on commit 32e3f6f

Please sign in to comment.