diff --git a/.changeset/quick-dolphins-visit.md b/.changeset/quick-dolphins-visit.md new file mode 100644 index 00000000000..77c73a23c34 --- /dev/null +++ b/.changeset/quick-dolphins-visit.md @@ -0,0 +1,5 @@ +--- +"@smithy/smithy-client": minor +--- + +resolve method builder for Command class diff --git a/packages/smithy-client/src/command.ts b/packages/smithy-client/src/command.ts index 40d94762613..9ab7c7c400c 100644 --- a/packages/smithy-client/src/command.ts +++ b/packages/smithy-client/src/command.ts @@ -1,5 +1,17 @@ import { constructStack } from "@smithy/middleware-stack"; -import { Command as ICommand, Handler, MetadataBearer, MiddlewareStack as IMiddlewareStack } from "@smithy/types"; +import type { HttpRequest as __HttpRequest } from "@smithy/protocol-http"; +import type { + Command as ICommand, + FinalizeHandlerArguments, + Handler, + HandlerExecutionContext, + Logger, + MetadataBearer, + MiddlewareStack as IMiddlewareStack, + Pluggable, + RequestHandler, +} from "@smithy/types"; +import { SMITHY_CONTEXT_KEY } from "@smithy/types"; /** * @public @@ -13,9 +25,121 @@ export abstract class Command< > implements ICommand { abstract input: Input; readonly middlewareStack: IMiddlewareStack = constructStack(); + abstract resolveMiddleware( stack: IMiddlewareStack, configuration: ResolvedClientConfiguration, options: any ): Handler; + + /** + * @internal + */ + protected resolveBuilder() { + const args: ResolveMiddlewareContextArgs = { + middlewareQueue: [] as Pluggable[], + commandName: "", + clientName: "", + service: "", + operation: "", + inputFilterSensitiveLog: () => {}, + outputFilterSensitiveLog: () => {}, + }; + return { + /** + * Add any number of middleware. + */ + m(...middleware: Pluggable[]) { + args.middlewareQueue.push(...middleware); + return this; + }, + /** + * Set constant string identifiers for the operation. + */ + n(clientName: string, commandName: string, service: string, operation: string) { + args.clientName = clientName; + args.commandName = commandName; + args.service = service; + args.operation = operation; + return this; + }, + /** + * Set the input and output sensistive log filters. + */ + f(inputFilter: (_: any) => any = (_) => _, outputFilter: (_: any) => any = (_) => _) { + args.inputFilterSensitiveLog = inputFilter; + args.outputFilterSensitiveLog = outputFilter; + return this; + }, + /** + * @returns the implementation of the built resolveMiddleware function. + */ + build: () => { + return ( + clientStack: IMiddlewareStack, + configuration: ResolvedClientConfiguration & { + logger: Logger; + requestHandler: RequestHandler; + }, + options: any + ) => { + return this.__resolveMiddleware(clientStack, configuration, options, args); + }; + }, + }; + } + + /** + * @internal + */ + protected __resolveMiddleware( + clientStack: IMiddlewareStack, + configuration: ResolvedClientConfiguration & { logger: Logger; requestHandler: RequestHandler }, + options: any, + { + middlewareQueue, + clientName, + commandName, + service, + operation, + inputFilterSensitiveLog, + outputFilterSensitiveLog, + }: ResolveMiddlewareContextArgs + ) { + for (const mw of middlewareQueue) { + this.middlewareStack.use(mw); + } + const stack = clientStack.concat(this.middlewareStack); + const { logger } = configuration; + const handlerExecutionContext: HandlerExecutionContext = { + logger, + clientName, + commandName, + inputFilterSensitiveLog, + outputFilterSensitiveLog, + [SMITHY_CONTEXT_KEY]: { + service, + operation, + }, + }; + const { requestHandler } = configuration; + return stack.resolve( + (request: FinalizeHandlerArguments) => + requestHandler.handle(request.request as __HttpRequest, options || {}), + handlerExecutionContext + ); + } } + +/** + * @internal + */ +type ResolveMiddlewareContextArgs = { + middlewareQueue: Pluggable[]; + clientName: string; + commandName: string; + service: string; + operation: string; + inputFilterSensitiveLog: (_: any) => any; + outputFilterSensitiveLog: (_: any) => any; +};