From 033f953477d53ba780918bb50e0d9f2f8f9cf313 Mon Sep 17 00:00:00 2001 From: AllanFly120 Date: Tue, 8 Oct 2019 10:52:17 -0700 Subject: [PATCH] Smithy codegen Client Refactor (#384) * feat: remove 'apply' entry from configuration definition 'apply' was used to adjust middleware stack and resolved configuration. It is not relative as we are moving to conposition configuration, and middleware stack should not be altered by configurations. Address: https://github.com/aws/aws-sdk-js-v3/pull/94 * feat: complete PoC composable configuration * feat: change config resolver to multiple client config components * feat: rename stack finalize step to finalizeRequest * feat: add use() to smithy client to inject middleware * fix: rename resolvedruntime configuration * fix: remove exported reviouslyResolved interface * feat: add metadatabearer to shapes * feat: parse derializing utils as parameters * use config interface as middleware parameter * use smithy command as super class of all commands so we can support use() in commands * feat: parse serialize(deserialize) util functions from client config * Serializers/Deserializers should take utils functions from client config first, if not available then fallback to generated dependencies. This allows configuring the runtime dependencies manually from client config when runtime-specific bundlers' decision is not accountable * feat: add metadata deserializer * docs: add documentation for config properties * feat: add defaultUserAgen config * feat: move some config components to middleware folder * signing middleware * retry middleware; Also update retry config interface by introducing RetryStrategy class * feat: add input type proxy for better intellisense * docs: add config doc block for retry config * feat: add a user agent middleware to support custom useragent --- .../client-rds-data-node/RDSDataClient.ts | 156 +- .../RDSDataConfiguration.ts | 344 +--- .../commands/ExecuteStatementCommand.ts | 46 +- .../models/rdsdataservice/index.ts | 13 +- .../node/client-rds-data-node/package.json | 3 +- .../protocol/AwsRestJson1_1.ts | 281 ++-- .../protocol/ExecuteStatement.ts | 12 +- packages/config-resolver/package.json | 2 + packages/config-resolver/src/components.ts | 222 +++ packages/config-resolver/src/index.spec.ts | 138 -- packages/config-resolver/src/index.ts | 59 +- .../middleware-content-length/src/index.ts | 17 +- packages/middleware-deserializer/src/index.ts | 27 +- packages/middleware-serializer/src/index.ts | 23 +- packages/middleware-stack/src/index.spec.ts | 16 +- packages/middleware-stack/src/index.ts | 12 +- packages/middleware-user-agent/.gitignore | 8 + packages/middleware-user-agent/.npmignore | 13 + packages/middleware-user-agent/LICENSE | 201 +++ packages/middleware-user-agent/README.md | 4 + packages/middleware-user-agent/package.json | 26 + .../src/configurations.ts | 22 + packages/middleware-user-agent/src/index.ts | 2 + .../middleware-user-agent/src/middleware.ts | 46 + packages/middleware-user-agent/tsconfig.json | 22 + .../middleware-user-agent/tsconfig.test.json | 11 + .../src/node-http-handler.ts | 2 +- packages/protocol-rest-json/src/index.ts | 16 +- packages/retry-middleware/package.json | 1 + .../retry-middleware/src/configurations.ts | 31 + .../retry-middleware/src/defaultStrategy.ts | 23 + packages/retry-middleware/src/index.ts | 4 +- .../retry-middleware/src/retryDecider.spec.ts | 24 +- packages/retry-middleware/src/retryDecider.ts | 46 +- .../src/retryMiddleware.spec.ts | 41 +- .../retry-middleware/src/retryMiddleware.ts | 42 +- .../src/internalImports.ts | 1482 +---------------- packages/signing-middleware/package.json | 1 + .../signing-middleware/src/configurations.ts | 68 + packages/signing-middleware/src/index.ts | 25 +- .../src/{index.spec.ts => middleware.spec.ts} | 11 +- packages/signing-middleware/src/middleware.ts | 36 + packages/smithy-client/.gitignore | 8 + packages/smithy-client/.npmignore | 13 + packages/smithy-client/LICENSE | 201 +++ packages/smithy-client/README.md | 4 + packages/smithy-client/package.json | 26 + packages/smithy-client/src/client.ts | 92 + packages/smithy-client/src/command.ts | 24 + packages/smithy-client/src/index.ts | 2 + packages/smithy-client/tsconfig.json | 22 + packages/smithy-client/tsconfig.test.json | 11 + .../stream-collector-browser/src/index.ts | 7 +- packages/stream-collector-node/src/index.ts | 9 +- packages/types/src/client.ts | 30 +- packages/types/src/deserializer.ts | 37 + packages/types/src/index.ts | 4 +- packages/types/src/marshaller.ts | 51 - packages/types/src/middleware.ts | 56 +- packages/types/src/serializer.ts | 27 + packages/types/src/transfer.ts | 12 +- packages/types/src/unmarshaller.ts | 46 - packages/types/src/util.ts | 25 +- 63 files changed, 1718 insertions(+), 2568 deletions(-) create mode 100644 packages/config-resolver/src/components.ts delete mode 100644 packages/config-resolver/src/index.spec.ts create mode 100644 packages/middleware-user-agent/.gitignore create mode 100644 packages/middleware-user-agent/.npmignore create mode 100644 packages/middleware-user-agent/LICENSE create mode 100644 packages/middleware-user-agent/README.md create mode 100644 packages/middleware-user-agent/package.json create mode 100644 packages/middleware-user-agent/src/configurations.ts create mode 100644 packages/middleware-user-agent/src/index.ts create mode 100644 packages/middleware-user-agent/src/middleware.ts create mode 100644 packages/middleware-user-agent/tsconfig.json create mode 100644 packages/middleware-user-agent/tsconfig.test.json create mode 100644 packages/retry-middleware/src/configurations.ts create mode 100644 packages/retry-middleware/src/defaultStrategy.ts create mode 100644 packages/signing-middleware/src/configurations.ts rename packages/signing-middleware/src/{index.spec.ts => middleware.spec.ts} (69%) create mode 100644 packages/signing-middleware/src/middleware.ts create mode 100644 packages/smithy-client/.gitignore create mode 100644 packages/smithy-client/.npmignore create mode 100644 packages/smithy-client/LICENSE create mode 100644 packages/smithy-client/README.md create mode 100644 packages/smithy-client/package.json create mode 100644 packages/smithy-client/src/client.ts create mode 100644 packages/smithy-client/src/command.ts create mode 100644 packages/smithy-client/src/index.ts create mode 100644 packages/smithy-client/tsconfig.json create mode 100644 packages/smithy-client/tsconfig.test.json create mode 100644 packages/types/src/deserializer.ts delete mode 100644 packages/types/src/marshaller.ts create mode 100644 packages/types/src/serializer.ts delete mode 100644 packages/types/src/unmarshaller.ts diff --git a/clients/node/client-rds-data-node/RDSDataClient.ts b/clients/node/client-rds-data-node/RDSDataClient.ts index de4814a34d6d..17b0e79a5bf3 100644 --- a/clients/node/client-rds-data-node/RDSDataClient.ts +++ b/clients/node/client-rds-data-node/RDSDataClient.ts @@ -1,153 +1,47 @@ -import * as __aws_sdk_config_resolver from "@aws-sdk/config-resolver"; -import * as __aws_sdk_middleware_content_length from "@aws-sdk/middleware-content-length"; -import * as __aws_sdk_middleware_header_default from "@aws-sdk/middleware-header-default"; -import * as __aws_sdk_middleware_stack from "@aws-sdk/middleware-stack"; -import * as __aws_sdk_retry_middleware from "@aws-sdk/retry-middleware"; -import * as __aws_sdk_signing_middleware from "@aws-sdk/signing-middleware"; -import * as __aws_sdk_types from "@aws-sdk/types"; -import * as __aws_sdk_util_user_agent_node from "@aws-sdk/util-user-agent-node"; +import { contentLengthPlugin } from "@aws-sdk/middleware-content-length"; +import { UserAgentPlugin, UserAgentConfig } from "@aws-sdk/middleware-user-agent"; +import { retryPlugin, RetryConfig } from "@aws-sdk/retry-middleware"; +import { signingPlugin, AwsAuthConfiguration } from "@aws-sdk/signing-middleware"; import { RDSDataConfiguration, RDSDataResolvedConfiguration, - configurationProperties + RDSRuntimeConfiguration } from "./RDSDataConfiguration"; -import {version as clientVersion} from './package.json' -import {HttpOptions} from '@aws-sdk/types' - -/** - * To remove this when move to Smithy model - */ -const ServiceMetadata = { - endpointPrefix: "rds-data", - serviceId: "RDS Data" -}; +import { RegionConfiguration, EndpointsConfig, ProtocolConfig } from '@aws-sdk/config-resolver'; +import { HttpOptions, MetadataBearer } from '@aws-sdk/types'; +import { Client as SmithyClient } from "@aws-sdk/smithy-client"; type InputTypesUnion = any; -type OutputTypesUnion = any; +type OutputTypesUnion = MetadataBearer; -export class RDSDataClient { +export class RDSDataClient extends SmithyClient { readonly config: RDSDataResolvedConfiguration; - readonly middlewareStack = new __aws_sdk_middleware_stack.MiddlewareStack< - InputTypesUnion, - OutputTypesUnion - >(); - constructor(configuration: RDSDataConfiguration) { - this.config = __aws_sdk_config_resolver.resolveConfiguration( - configuration, - configurationProperties, - this.middlewareStack - ); - this.middlewareStack.add( - __aws_sdk_middleware_content_length.contentLengthMiddleware( - this.config.bodyLengthChecker - ), - { - step: "build", - priority: -80, - tags: { SET_CONTENT_LENGTH: true } - } - ); + const intermediaConfig_0 = ProtocolConfig.resolve({ + ...RDSRuntimeConfiguration, + ...configuration + }); + super(intermediaConfig_0); + let intermediaConfig_1 = RegionConfiguration.resolve(intermediaConfig_0); + let intermediaConfig_2 = AwsAuthConfiguration.resolve(intermediaConfig_1); + let intermediaConfig_3 = EndpointsConfig.resolve(intermediaConfig_2); + let intermediaConfig_4 = RetryConfig.resolve(intermediaConfig_3); + let intermediaConfig_5 = UserAgentConfig.resolve(intermediaConfig_4); + this.config = intermediaConfig_5; + super.use(contentLengthPlugin(this.config)); if (this.config.maxRetries > 0) { - this.middlewareStack.add( - __aws_sdk_retry_middleware.retryMiddleware( - this.config.maxRetries, - this.config.retryDecider, - this.config.delayDecider - ), - { - step: "finalize", - priority: Infinity, - tags: { RETRY: true } - } - ); + super.use(retryPlugin(this.config)); } - this.middlewareStack.add( - __aws_sdk_signing_middleware.signingMiddleware< - InputTypesUnion, - OutputTypesUnion - >(this.config.signer), - { - step: "finalize", - priority: 0, - tags: { SIGNATURE: true } - } - ); - this.middlewareStack.add( - __aws_sdk_middleware_header_default.headerDefault({ - "User-Agent": __aws_sdk_util_user_agent_node.defaultUserAgent( - ServiceMetadata.serviceId || ServiceMetadata.endpointPrefix, - clientVersion - ) - }), - { - step: "build", - priority: 0, - tags: { SET_USER_AGENT: true } - } - ); + super.use(signingPlugin(this.config)); + super.use(UserAgentPlugin(this.config)); } destroy(): void { if ( - !this.config._user_injected_http_handler && typeof this.config.httpHandler.destroy === 'function' ) { this.config.httpHandler.destroy(); } } - - /** - * This will need to be revised when the command interface lands. - */ - send( - command: __aws_sdk_types.Command< - InputTypesUnion, - InputType, - OutputTypesUnion, - OutputType, - RDSDataResolvedConfiguration - >, - options?: HttpOptions - ): Promise; - send( - command: __aws_sdk_types.Command< - InputTypesUnion, - InputType, - OutputTypesUnion, - OutputType, - RDSDataResolvedConfiguration - >, - options: HttpOptions, - cb: (err: any, data?: OutputType) => void - ): void; - send( - command: __aws_sdk_types.Command< - InputTypesUnion, - InputType, - OutputTypesUnion, - OutputType, - RDSDataResolvedConfiguration - >, - options?: HttpOptions, - cb?: (err: any, data?: OutputType) => void - ): Promise | void { - const handler = command.resolveMiddleware( - this.middlewareStack, - this.config, - options - ); - if (cb) { - handler(command) - .then(result => cb(null, result.output), (err: any) => cb(err)) - .catch( - // prevent any errors thrown in the callback from triggering an - // unhandled promise rejection - () => {} - ); - } else { - return handler(command).then(result => result.output); - } - } } diff --git a/clients/node/client-rds-data-node/RDSDataConfiguration.ts b/clients/node/client-rds-data-node/RDSDataConfiguration.ts index aca32a36c663..b61aacd15733 100644 --- a/clients/node/client-rds-data-node/RDSDataConfiguration.ts +++ b/clients/node/client-rds-data-node/RDSDataConfiguration.ts @@ -1,290 +1,60 @@ -import * as __aws_sdk_credential_provider_node from "@aws-sdk/credential-provider-node"; -import * as __aws_sdk_hash_node from "@aws-sdk/hash-node"; -import * as __aws_sdk_http_handler from "@aws-sdk/node-http-handler"; -import * as __aws_sdk_region_provider from "@aws-sdk/region-provider"; -import * as __aws_sdk_signature_v4 from "@aws-sdk/signature-v4"; -import * as __aws_sdk_types from "@aws-sdk/types"; -import * as __aws_sdk_url_parser_node from "@aws-sdk/url-parser-node"; -import * as __aws_sdk_util_body_length_node from "@aws-sdk/util-body-length-node"; -import { Protocol, TransferHandler } from "@aws-sdk/types"; -import { HttpRequest, HttpResponse, HttpHandler } from "@aws-sdk/protocol-http"; +import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node"; +import { Hash } from "@aws-sdk/hash-node"; +import { NodeHttpHandler } from "@aws-sdk/node-http-handler"; +import { defaultProvider as regionDefaultProvider } from "@aws-sdk/region-provider"; +import { parseUrl } from "@aws-sdk/url-parser-node"; +import { calculateBodyLength } from "@aws-sdk/util-body-length-node"; +import { streamCollector } from '@aws-sdk/stream-collector-node'; import { RestJsonProtocol } from "@aws-sdk/protocol-rest-json"; - -export interface RDSDataConfiguration { - /** - * The credentials used to sign requests. - * - * If no static credentials are supplied, the SDK will attempt to credentials from known environment variables, from shared configuration and credentials files, and from the EC2 Instance Metadata Service, in that order. - */ - credentials?: - | __aws_sdk_types.Credentials - | __aws_sdk_types.Provider<__aws_sdk_types.Credentials>; - - /** - * A function that determines how long (in milliseconds) the SDK should wait before retrying a request - */ - delayDecider?: __aws_sdk_types.DelayDecider; - - /** - * The fully qualified endpoint of the webservice. This is only required when using a custom endpoint (for example, when using a local version of S3). - */ - endpoint?: - | string - | __aws_sdk_types.HttpEndpoint - | __aws_sdk_types.Provider<__aws_sdk_types.HttpEndpoint>; - - /** - * The endpoint provider to call if no endpoint is provided - */ - endpointProvider?: any; - - /** - * The HTTP handler to use - */ - httpHandler?: HttpHandler; - - /** - * Whether sockets should be kept open even when there are no outstanding requests so that future requests can forgo having to reestablish a TCP or TLS connection. Defaults to true. - */ - keepAlive?: boolean; - - /** - * The maximum number of redirects to follow for a service request. Set to `0` to disable retries. - */ - maxRedirects?: number; - - /** - * The maximum number of times requests that encounter potentially transient failures should be retried - */ - maxRetries?: number; - - /** - * The configuration profile to use. - */ - profile?: string; - - /** - * The AWS region to which this client will send requests - */ - region?: string | __aws_sdk_types.Provider; - - /** - * A function that determines whether an error is retryable - */ - retryDecider?: __aws_sdk_types.RetryDecider; - - /** - * A constructor for a class implementing the @aws-sdk/types.Hash interface that computes the SHA-256 HMAC or checksum of a string or binary buffer - */ - sha256?: __aws_sdk_types.HashConstructor; - - /** - * The signer to use when signing requests. - */ - signer?: __aws_sdk_types.RequestSigner; - - /** - * The service name with which to sign requests. - */ - signingName?: string; - - /** - * Whether SSL is enabled for requests. - */ - sslEnabled?: boolean; - - /** - * The function that will be used to convert strings into HTTP endpoints - */ - urlParser?: __aws_sdk_types.UrlParser; - - /** - * - */ - protocol?: Protocol; -} - -export interface RDSDataResolvableConfiguration extends RDSDataConfiguration { - /** - * Whether the HTTP handler was injected by the user and should thus not be destroyed when this client is - */ - _user_injected_http_handler: any; - - /** - * A function that can calculate the length of a request body. - */ - bodyLengthChecker: (body: any) => number | undefined; +import { fromUtf8, toUtf8 } from '@aws-sdk/util-utf8-node'; +import { fromBase64, toBase64 } from '@aws-sdk/util-base64-node'; +import { defaultUserAgent } from '@aws-sdk/util-user-agent-node'; +import { AwsAuthConfiguration, AwsAuthConfigurationInput } from '@aws-sdk/signing-middleware'; +import { UserAgentConfig, UserAgentConfigInput } from '@aws-sdk/middleware-user-agent'; +import { RetryConfig, RetryConfigInput } from '@aws-sdk/retry-middleware'; +import { name, version } from './package.json'; +import { + RegionConfiguration, + RegionConfigurationInput, + EndpointsConfig, + EndpointsConfigInput, + ProtocolConfig, + ProtocolConfigInput, + AWSClientRuntimeConfiguration +} from '@aws-sdk/config-resolver'; + +export type AWSClientRuntimeResolvedConfiguration = Required; + +export const RDSRuntimeConfiguration: AWSClientRuntimeResolvedConfiguration = { + protocolDefaultProvider: (handler) => new RestJsonProtocol(handler), + signingName: "rds-data", + service: "rds-data", + httpHandler: new NodeHttpHandler(), + sha256: Hash.bind(null, "sha256"), + credentialDefaultProvider, + regionDefaultProvider, + urlParser: parseUrl, + bodyLengthChecker: calculateBodyLength, + streamCollector, + base64Decoder: fromBase64, + base64Encoder: toBase64, + utf8Decoder: fromUtf8, + utf8Encoder: toUtf8, + defaultUserAgent: defaultUserAgent(name, version) } -export interface RDSDataResolvedConfiguration - extends RDSDataConfiguration { - _user_injected_http_handler: boolean; - - bodyLengthChecker: (body: any) => number | undefined; - - credentials: __aws_sdk_types.Provider<__aws_sdk_types.Credentials>; - - endpoint: __aws_sdk_types.Provider<__aws_sdk_types.HttpEndpoint>; - - endpointProvider: any; - - httpHandler: HttpHandler; - - keepAlive: boolean; - - maxRedirects: number; - - maxRetries: number; - - region: __aws_sdk_types.Provider; - - sha256: __aws_sdk_types.HashConstructor; - - signer: __aws_sdk_types.RequestSigner; - - signingName: string; - - sslEnabled: boolean; - - urlParser: __aws_sdk_types.UrlParser; - - protocol: Protocol; -} - -export const configurationProperties: __aws_sdk_types.ConfigurationDefinition< - RDSDataResolvableConfiguration, - RDSDataResolvedConfiguration -> = { - profile: {}, - maxRedirects: { - defaultValue: 10 - }, - maxRetries: { - defaultValue: 3 - }, - region: { - defaultProvider: __aws_sdk_region_provider.defaultProvider, - normalize: ( - value: string | __aws_sdk_types.Provider | undefined - ) => { - if (typeof value === "string") { - const promisified = Promise.resolve(value); - return () => promisified; - } - - return value!; - } - }, - sslEnabled: { - defaultValue: true - }, - urlParser: { - defaultValue: __aws_sdk_url_parser_node.parseUrl - }, - endpointProvider: { - defaultValue: (sslEnabled: boolean, region: string) => ({ - protocol: sslEnabled ? "https:" : "http:", - path: "/", - hostname: `rds-data.${region}.amazonaws.com` - }) - }, - endpoint: { - defaultProvider: (configuration: { - sslEnabled: boolean; - endpointProvider: any; - region: __aws_sdk_types.Provider; - }) => { - const promisified = configuration - .region() - .then(region => - configuration.endpointProvider(configuration.sslEnabled, region) - ); - return () => promisified; - }, - normalize: ( - value: - | string - | __aws_sdk_types.HttpEndpoint - | __aws_sdk_types.Provider<__aws_sdk_types.HttpEndpoint> - | undefined, - configuration: { - urlParser?: __aws_sdk_types.UrlParser; - } - ): __aws_sdk_types.Provider<__aws_sdk_types.HttpEndpoint> => { - if (typeof value === "string") { - const promisified = Promise.resolve(configuration.urlParser!(value)); - return () => promisified; - } else if (typeof value === "object") { - const promisified = Promise.resolve(value); - return () => promisified; - } - - // Users are not required to supply an endpoint, so `value` - // could be undefined. This function, however, will only be - // invoked if `value` is defined, so the return will never - // be undefined. - return value!; - } - }, - keepAlive: { - defaultValue: true - }, - _user_injected_http_handler: { - defaultProvider: (configuration: { httpHandler?: any }) => - !configuration.httpHandler - }, - httpHandler: { - defaultProvider: (configuration: { keepAlive: boolean }) => - new __aws_sdk_http_handler.NodeHttpHandler(configuration) - }, - bodyLengthChecker: { - defaultValue: __aws_sdk_util_body_length_node.calculateBodyLength - }, - retryDecider: {}, - delayDecider: {}, - credentials: { - defaultProvider: __aws_sdk_credential_provider_node.defaultProvider, - normalize: ( - value: - | __aws_sdk_types.Credentials - | __aws_sdk_types.Provider<__aws_sdk_types.Credentials> - | undefined - ) => { - if (typeof value === "object") { - const promisified = Promise.resolve(value); - return () => promisified; - } - - return value!; - } - }, - sha256: { - defaultValue: __aws_sdk_hash_node.Hash.bind(null, "sha256") - }, - signingName: { - defaultValue: "rds-data" - }, - signer: { - defaultProvider: (configuration: { - credentials: __aws_sdk_types.Provider<__aws_sdk_types.Credentials>; - region: __aws_sdk_types.Provider; - sha256: __aws_sdk_types.HashConstructor; - signingName: string; - }) => - new __aws_sdk_signature_v4.SignatureV4({ - credentials: configuration.credentials, - region: configuration.region, - service: configuration.signingName, - sha256: configuration.sha256, - uriEscapePath: true - }) - }, - protocol: { - defaultProvider: (configuration: { - httpHandler: TransferHandler< - HttpRequest, - HttpResponse - >; - }) => new RestJsonProtocol(configuration.httpHandler) - } -}; +export type RDSDataConfiguration = AWSClientRuntimeConfiguration & + AwsAuthConfigurationInput & + RegionConfigurationInput & + RetryConfigInput & + EndpointsConfigInput & + ProtocolConfigInput & + UserAgentConfigInput + +export type RDSDataResolvedConfiguration = AWSClientRuntimeResolvedConfiguration & + AwsAuthConfiguration.Resolved & + RegionConfiguration.Resolved & + RetryConfig.Resolved & + EndpointsConfig.Resolved & + ProtocolConfig.Resolved & + UserAgentConfig.Resolved \ No newline at end of file diff --git a/clients/node/client-rds-data-node/commands/ExecuteStatementCommand.ts b/clients/node/client-rds-data-node/commands/ExecuteStatementCommand.ts index 47940da0c07b..5a77f1d40815 100644 --- a/clients/node/client-rds-data-node/commands/ExecuteStatementCommand.ts +++ b/clients/node/client-rds-data-node/commands/ExecuteStatementCommand.ts @@ -1,11 +1,11 @@ -import * as __aws_sdk_middleware_stack from "@aws-sdk/middleware-stack"; -import { serializerMiddleware } from "@aws-sdk/middleware-serializer"; -import { deserializerMiddleware } from "@aws-sdk/middleware-deserializer"; +import { Command } from '@aws-sdk/smithy-client'; +import { serializerPlugin } from "@aws-sdk/middleware-serializer"; +import { deserializerPlugin } from "@aws-sdk/middleware-deserializer"; import * as __aws_sdk_types from "@aws-sdk/types"; import { RDSDataResolvedConfiguration } from "../RDSDataConfiguration"; import { HttpRequest } from '@aws-sdk/protocol-http'; import { executeStatementSerializer, executeStatementDeserializer } from '../protocol/ExecuteStatement' -import { FinalizeHandlerArguments } from '@aws-sdk/types'; +import { FinalizeHandlerArguments, MiddlewareStack } from '@aws-sdk/types'; /** * To remove this when move to Smithy model @@ -15,16 +15,14 @@ type ExecuteStatementOutput = any; type InputTypesUnion = any; type OutputTypesUnion = any; -export class ExecuteStatementCommand { - readonly middlewareStack = new __aws_sdk_middleware_stack.MiddlewareStack< - ExecuteStatementInput, - ExecuteStatementOutput - >(); +export class ExecuteStatementCommand extends Command { - constructor(readonly input: ExecuteStatementInput) {} + constructor(readonly input: ExecuteStatementInput) { + super(); + } resolveMiddleware( - clientStack: __aws_sdk_middleware_stack.MiddlewareStack< + clientStack: MiddlewareStack< InputTypesUnion, OutputTypesUnion >, @@ -33,28 +31,8 @@ export class ExecuteStatementCommand { ): __aws_sdk_types.Handler { const { httpHandler } = configuration; - this.middlewareStack.add( - serializerMiddleware( - configuration.protocol, - executeStatementSerializer - ), - { - step: "serialize", - priority: 90, - tags: { SERIALIZER: true } - } - ); - this.middlewareStack.add( - deserializerMiddleware( - configuration.protocol, - executeStatementDeserializer - ) as any, - { - step: "deserialize", - priority: Infinity, - tags: { DESERIALIZER: true } - } - ); + this.use(serializerPlugin(configuration, executeStatementSerializer)); + this.use(deserializerPlugin(configuration, executeStatementDeserializer)); const stack = clientStack.concat(this.middlewareStack); @@ -63,7 +41,7 @@ export class ExecuteStatementCommand { }; return stack.resolve( - (request: FinalizeHandlerArguments) => {return httpHandler.handle(request.request as HttpRequest, options || {})}, + (request: FinalizeHandlerArguments) => httpHandler.handle(request.request as HttpRequest, options || {}), handlerExecutionContext ); } diff --git a/clients/node/client-rds-data-node/models/rdsdataservice/index.ts b/clients/node/client-rds-data-node/models/rdsdataservice/index.ts index 7342548d75cf..4f25ad55bf9c 100644 --- a/clients/node/client-rds-data-node/models/rdsdataservice/index.ts +++ b/clients/node/client-rds-data-node/models/rdsdataservice/index.ts @@ -1,4 +1,5 @@ import * as _smithy from "../../lib/smithy"; +import { MetadataBearer as $MetadataBearer } from "@aws-sdk/types"; export type ArrayValue = | ArrayValue.ArrayValuesMember @@ -135,7 +136,7 @@ export namespace BatchExecuteStatementRequest { } } -export interface BatchExecuteStatementResponse { +export interface BatchExecuteStatementResponse extends $MetadataBearer { __type?: "com.amazon.rdsdataservice#BatchExecuteStatementResponse"; updateResults?: Array; } @@ -162,7 +163,7 @@ export namespace BeginTransactionRequest { } } -export interface BeginTransactionResponse { +export interface BeginTransactionResponse extends $MetadataBearer { __type?: "com.amazon.rdsdataservice#BeginTransactionResponse"; transactionId?: string; } @@ -213,7 +214,7 @@ export namespace CommitTransactionRequest { } } -export interface CommitTransactionResponse { +export interface CommitTransactionResponse extends $MetadataBearer { __type?: "com.amazon.rdsdataservice#CommitTransactionResponse"; transactionStatus?: string; } @@ -246,7 +247,7 @@ export namespace ExecuteSqlRequest { } } -export interface ExecuteSqlResponse { +export interface ExecuteSqlResponse extends $MetadataBearer { __type?: "com.amazon.rdsdataservice#ExecuteSqlResponse"; sqlStatementResults?: Array; } @@ -279,7 +280,7 @@ export namespace ExecuteStatementRequest { } } -export interface ExecuteStatementResponse { +export interface ExecuteStatementResponse extends $MetadataBearer { __type?: "com.amazon.rdsdataservice#ExecuteStatementResponse"; numberOfRecordsUpdated?: number; records?: Array>; @@ -545,7 +546,7 @@ export namespace RollbackTransactionRequest { } } -export interface RollbackTransactionResponse { +export interface RollbackTransactionResponse extends $MetadataBearer { __type?: "com.amazon.rdsdataservice#RollbackTransactionResponse"; transactionStatus?: string; } diff --git a/clients/node/client-rds-data-node/package.json b/clients/node/client-rds-data-node/package.json index 8c50b00ca9de..a309248f2785 100644 --- a/clients/node/client-rds-data-node/package.json +++ b/clients/node/client-rds-data-node/package.json @@ -28,6 +28,7 @@ "sideEffects": false, "license": "Apache-2.0", "dependencies": { + "@aws-sdk/smithy-client": "^0.1.0-preview.1", "@aws-sdk/protocol-http": "^0.1.0-preview.1", "@aws-crypto/sha256-browser": "^0.1.0-preview.1", "@aws-sdk/config-resolver": "^0.1.0-preview.5", @@ -37,7 +38,7 @@ "@aws-sdk/invalid-dependency": "^0.1.0-preview.1", "@aws-sdk/middleware-content-length": "^0.1.0-preview.5", "@aws-sdk/middleware-deserializer": "^0.1.0-preview.1", - "@aws-sdk/middleware-header-default": "^0.1.0-preview.5", + "@aws-sdk/middleware-user-agent": "^0.1.0-preview.1", "@aws-sdk/middleware-serializer": "^0.1.0-preview.5", "@aws-sdk/middleware-stack": "^0.1.0-preview.6", "@aws-sdk/node-http-handler": "^0.1.0-preview.6", diff --git a/clients/node/client-rds-data-node/protocol/AwsRestJson1_1.ts b/clients/node/client-rds-data-node/protocol/AwsRestJson1_1.ts index 38262e995cfe..2d8b4347c7c4 100644 --- a/clients/node/client-rds-data-node/protocol/AwsRestJson1_1.ts +++ b/clients/node/client-rds-data-node/protocol/AwsRestJson1_1.ts @@ -11,11 +11,16 @@ import { ServiceUnavailableError } from "../models/rdsdataservice"; import { HttpRequest, HttpResponse } from "@aws-sdk/protocol-http"; +import { SerializerUtils, DeserializerUtils } from "@aws-sdk/types"; import * as __aws_sdk_stream_collector_node from "@aws-sdk/stream-collector-node"; import * as __aws_sdk_util_utf8_node from "@aws-sdk/util-utf8-node"; +import { ResponseMetadata } from "@aws-sdk/types"; + +type Utils = { [key: string]: any }; export function executeStatementAwsRestJson1_1Serialize( - input: ExecuteStatementRequest + input: ExecuteStatementRequest, + utils?: Utils ): HttpRequest { let body: any = {}; if (input.resourceArn !== undefined) { @@ -56,7 +61,7 @@ export function executeStatementAwsRestJson1_1Serialize( return new HttpRequest({ body: JSON.stringify(body), - path: "/execute", + path: "/Execute", method: "POST", protocol: "https:", headers: { @@ -66,13 +71,15 @@ export function executeStatementAwsRestJson1_1Serialize( } export async function executeStatementAwsRestJson1_1Deserialize( - output: HttpResponse + output: HttpResponse, + utils?: Utils ): Promise { if (output.statusCode !== 200) { return executeStatementAwsRestJson1_1DeserializeError(output); } - let data: any = await parseBody(output.body); + let data: any = await parseBody(output.body, utils); return Promise.resolve({ + $metadata: deserializeMetadata(output), __type: "com.amazon.rdsdataservice#ExecuteStatementResponse", records: recordsAwsRestJson1_1Deserialize(data.records), columnMetadata: columnMetadataListAwsRestJson1_1Deserialize( @@ -88,62 +95,73 @@ export async function executeStatementAwsRestJson1_1Deserialize( async function executeStatementAwsRestJson1_1DeserializeError( output: HttpResponse ): Promise { - const data: any = await parseBody(output); - - let response: any; - switch (output.headers["x-amzn-ErrorType"]) { - case "BadRequestException": - case "com.amazon.rdsdataservice#BadRequestException": - response = badRequestExceptionDeserialize(data); - break; - case "StatementTimeoutException": - case "com.amazon.rdsdataservice#StatementTimeoutException": - response = statementTimeoutExceptionDeserialize(data); - break; - case "ForbiddenException": - case "com.amazon.rdsdataservice#ForbiddenException": - response = forbiddenExceptionDeserialize(data); - break; - case "InternalServerErrorException": - case "com.amazon.rdsdataservice#InternalServerErrorException": - response = internalServerErrorExceptionDeserialize(data); - break; - case "ServiceUnavailableError": - case "com.amazon.rdsdataservice#ServiceUnavailableError": - response = serviceUnavailableErrorDeserialize(data); - break; - default: - response = { - __type: "com.amazon.rdsdataservice#UnknownException", - $name: "UnknownException", - $fault: "server" - }; + let data = await parseBody(output); + if (output.statusCode === 400 && data.dbConnectionId !== undefined) { + return Promise.reject({ + __type: "com.amazon.rdsdataservice#StatementTimeoutException", + $name: "StatementTimeoutException", + $fault: "client", + message: data.message, + dbConnectionId: data.dbConnectionId + }); } - return Promise.reject(response); -} + if (output.statusCode === 400) { + return Promise.reject({ + __type: "com.amazon.rdsdataservice#BadRequestException", + $name: "BadRequestException", + $fault: "client", + message: data.message + }); + } -function sqlParameterListAwsRestJson1_1Serialize( - input: Array -): Array { - let list: Array = []; - for (let SqlParameter of input) { - list.push(sqlParameterAwsRestJson1_1Serialize(SqlParameter)); + if (output.statusCode === 403) { + return Promise.reject({ + __type: "com.amazon.rdsdataservice#ForbiddenException", + $name: "ForbiddenException", + $fault: "client", + message: data.message + }); + } + + if (output.statusCode === 500) { + return Promise.reject({ + __type: "com.amazon.rdsdataservice#InternalServerErrorException", + $name: "InternalServerErrorException", + $fault: "server" + }); } - return list; -} -function sqlParameterAwsRestJson1_1Serialize(input: SqlParameter): any { - if (input.value !== undefined) { - return { - name: input.name, - value: fieldAwsRestJson1_1Serialize(input.value) - }; + if (output.statusCode === 503) { + return Promise.reject({ + __type: "com.amazon.rdsdataservice#ServiceUnavailableError", + $name: "ServiceUnavailableError", + $fault: "server" + }); } + + return Promise.reject({ + __type: "com.amazon.rdsdataservice#UnknownException", + $name: "UnknownException", + $fault: "server" + }); } -function fieldAwsRestJson1_1Serialize(input: Field): any { - return Field.visit(input, { +const sqlParameterListAwsRestJson1_1Serialize = ( + input: Array +): Array => + input && + input.map(sqlParameter => sqlParameterAwsRestJson1_1Serialize(sqlParameter)); + +const sqlParameterAwsRestJson1_1Serialize = (input: SqlParameter): any => + input.name && + input.value && { + name: input.name, + value: fieldAwsRestJson1_1Serialize(input.value) + }; + +const fieldAwsRestJson1_1Serialize = (input: Field): any => + Field.visit(input, { blobValue: value => { value; }, @@ -172,7 +190,6 @@ function fieldAwsRestJson1_1Serialize(input: Field): any { value; } }); -} export function columnMetadataAwsRestJson1_1Deserialize( input: any @@ -240,96 +257,74 @@ export function columnMetadataAwsRestJson1_1Deserialize( return columnMetadata; } -function columnMetadataListAwsRestJson1_1Deserialize( +const columnMetadataListAwsRestJson1_1Deserialize = ( input: any -): Array { - let list: Array = []; - for (let ColumnMetadata of input) { - list.push(columnMetadataAwsRestJson1_1Deserialize(ColumnMetadata)); - } - return list; -} - -function fieldAwsRestJson1_1Deserialize(input: any): Field { - return input.visit(input, {}); -} - -function generatedFieldsAwsRestJson1_1Deserialize(input: any): Array { - let list: Array = []; - for (let Field of input) { - list.push(fieldAwsRestJson1_1Deserialize(Field)); - } - return list; -} - -function recordsAwsRestJson1_1Deserialize(input: any): Array> { - let list: Array> = []; - for (let recordsList of input) { - list.push(recordsListAwsRestJson1_1Deserialize(input)); - } - return list; -} - -function recordsListAwsRestJson1_1Deserialize(input: any): Array { - let list: Array = []; - for (let Field of input) { - list.push(fieldAwsRestJson1_1Serialize(input)); - } - return list; -} - -function badRequestExceptionDeserialize(input: any): BadRequestException { - return { - __type: "com.amazon.rdsdataservice#BadRequestException", - $name: "BadRequestException", - $fault: "client", - message: input.message - }; -} - -function statementTimeoutExceptionDeserialize( - input: any -): StatementTimeoutException { - return { - __type: "com.amazon.rdsdataservice#StatementTimeoutException", - $name: "StatementTimeoutException", - $fault: "client", - message: input.message, - dbConnectionId: input.dbConnectionId - }; -} - -function forbiddenExceptionDeserialize(input: any): ForbiddenException { - return { - __type: "com.amazon.rdsdataservice#ForbiddenException", - $name: "ForbiddenException", - $fault: "client", - message: input.message - }; -} - -function internalServerErrorExceptionDeserialize( - input: any -): InternalServerErrorException { - return { - __type: "com.amazon.rdsdataservice#InternalServerErrorException", - $name: "InternalServerErrorException", - $fault: "server" - }; -} - -function serviceUnavailableErrorDeserialize( - input: any -): ServiceUnavailableError { - return { - __type: "com.amazon.rdsdataservice#ServiceUnavailableError", - $name: "ServiceUnavailableError", - $fault: "server" - }; -} +): Array => + input && + input.map((columnMetadata: any) => + columnMetadataAwsRestJson1_1Deserialize(columnMetadata) + ); + +const fieldAwsRestJson1_1Deserialize = (input: any): any => + Field.visit(input, { + blobValue: value => { + value; + }, + booleanValue: value => { + return value; + }, + arrayValue: value => { + return value; + }, + structValue: value => { + return value; + }, + longValue: value => { + return value; + }, + isNull: value => { + return value; + }, + doubleValue: value => { + return value; + }, + stringValue: value => { + return value; + }, + _: value => { + return value; + } + }); -function parseBody(streamBody: any): any { - __aws_sdk_stream_collector_node.streamCollector(streamBody).then(body => { - return JSON.parse(__aws_sdk_util_utf8_node.toUtf8(body)); +const generatedFieldsAwsRestJson1_1Deserialize = (input: any): Array => + input && input.map((field: any) => fieldAwsRestJson1_1Deserialize(field)); + +const recordsAwsRestJson1_1Deserialize = (input: any): Array> => + input && + input.map((recordsList: any) => + recordsListAwsRestJson1_1Deserialize(recordsList) + ); + +const recordsListAwsRestJson1_1Deserialize = (input: any): Array => + input && input.map((field: any) => fieldAwsRestJson1_1Deserialize(field)); + +const deserializeMetadata = (output: HttpResponse): ResponseMetadata => ({ + httpStatusCode: output.statusCode, + httpHeaders: output.headers, + requestId: output.headers["x-amzn-requestid"] +}); + +const parseBody = (streamBody: any, utils?: Utils): any => { + const streamCollector = + utils && utils["streamCollector"] + ? (utils)["streamCollector"] + : __aws_sdk_stream_collector_node.streamCollector; + const toUtf8 = + utils && utils["streamCollector"] + ? (utils)["utf8Encoder"] + : __aws_sdk_util_utf8_node.toUtf8; + + return streamCollector(streamBody).then(body => { + return JSON.parse(toUtf8(body)); }); -} +}; diff --git a/clients/node/client-rds-data-node/protocol/ExecuteStatement.ts b/clients/node/client-rds-data-node/protocol/ExecuteStatement.ts index b8bdeca5e8ae..53bc195c5a0a 100644 --- a/clients/node/client-rds-data-node/protocol/ExecuteStatement.ts +++ b/clients/node/client-rds-data-node/protocol/ExecuteStatement.ts @@ -8,13 +8,16 @@ import { executeStatementAwsRestJson1_1Deserialize } from "./AwsRestJson1_1"; +type Utils = { [key: string]: any }; + export function executeStatementSerializer( input: ExecuteStatementRequest, - protocol: string + protocol: string, + utils?: Utils ): HttpRequest { switch (protocol) { case "aws.rest-json-1.1": - return executeStatementAwsRestJson1_1Serialize(input); + return executeStatementAwsRestJson1_1Serialize(input, utils); default: throw new Error("Unknown protocol, use aws.rest-json-1.1"); } @@ -22,11 +25,12 @@ export function executeStatementSerializer( export async function executeStatementDeserializer( output: HttpResponse, - protocol: string + protocol: string, + utils?: Utils ): Promise { switch (protocol) { case "aws.rest-json-1.1": - return executeStatementAwsRestJson1_1Deserialize(output); + return executeStatementAwsRestJson1_1Deserialize(output, utils); default: throw new Error("Unknown protocol, use aws.rest-json-1.1"); } diff --git a/packages/config-resolver/package.json b/packages/config-resolver/package.json index e42c1fd73067..c1accf087135 100644 --- a/packages/config-resolver/package.json +++ b/packages/config-resolver/package.json @@ -21,6 +21,8 @@ }, "dependencies": { "@aws-sdk/types": "^0.1.0-preview.5", + "@aws-sdk/signature-v4": "^0.1.0-preview.7", + "@aws-sdk/protocol-http": "^0.1.0-preview.1", "tslib": "^1.8.0" } } diff --git a/packages/config-resolver/src/components.ts b/packages/config-resolver/src/components.ts new file mode 100644 index 000000000000..97052e2b54b8 --- /dev/null +++ b/packages/config-resolver/src/components.ts @@ -0,0 +1,222 @@ +import { + Credentials, + Provider, + HashConstructor, + UrlParser, + Protocol, + HttpOptions, + StreamCollector, + Decoder, + Encoder +} from "@aws-sdk/types"; +import { + HttpEndpoint, + HttpHandler, + HttpRequest, + HttpResponse +} from "@aws-sdk/protocol-http"; + +export interface RuntimeDependencies { + /** + * The HTTP handler to use. Fetch in browser and Https in Nodejs + */ + httpHandler?: HttpHandler; + + /** + * A constructor for a class implementing the @aws-sdk/types.Hash interface that computes the SHA-256 HMAC or checksum of a string or binary buffer + */ + sha256?: HashConstructor; + + /** + * Default credentials provider; Not available in browser runtime + */ + credentialDefaultProvider?: (input: any) => Provider; + + /** + * Provider function that return promise of a region string + */ + regionDefaultProvider?: (input: any) => Provider; + + /** + * The function that will be used to convert strings into HTTP endpoints + */ + urlParser?: UrlParser; + + /** + * A function that can calculate the length of a request body. + */ + bodyLengthChecker?: (body: any) => number | undefined; + + /** + * A function that converts a stream into an array of bytes. + */ + streamCollector?: StreamCollector; + + /** + * The function that will be used to convert a base64-encoded string to a byte array + */ + base64Decoder?: Decoder; + + /** + * The function that will be used to convert binary data to a base64-encoded string + */ + base64Encoder?: Encoder; + + /** + * The function that will be used to convert a UTF8-encoded string to a byte array + */ + utf8Decoder?: Decoder; + + /** + * The function that will be used to convert binary data to a UTF-8 encoded string + */ + utf8Encoder?: Encoder; + + /** + * The function that will be used to populate default value in 'User-Agent' header + */ + defaultUserAgent?: string; +} + +export interface AWSClientRuntimeConfiguration extends RuntimeDependencies { + /** + * The function that will be used to populate serializing protocol + */ + protocolDefaultProvider?: ( + handler: HttpHandler + ) => Protocol; + + /** + * The service name with which to sign requests. + */ + signingName?: string; + + /** + * The service name with which to construct endpoints. + */ + service?: string; +} + +export function normalizeProvider(input: T | Provider): Provider { + if (typeof input === "object") { + const promisified = Promise.resolve(input); + return () => promisified; + } + return input as Provider; +} + +export function normalizeEndpoint( + endpoint?: string | HttpEndpoint | Provider, + urlParser?: UrlParser +): Provider { + if (typeof endpoint === "string") { + const promisified = Promise.resolve(urlParser!(endpoint)); + return () => promisified; + } else if (typeof endpoint === "object") { + const promisified = Promise.resolve(endpoint); + return () => promisified; + } + return endpoint!; +} + +export namespace RegionConfiguration { + export interface Input { + /** + * The AWS region to which this client will send requests + */ + region?: string | Provider; + } + interface PreviouslyResolved { + regionDefaultProvider: (input: any) => Provider; + } + export interface Resolved { + region: Provider; + } + export function resolve( + input: T & Input & PreviouslyResolved + ): T & Resolved { + let region = input.region || input.regionDefaultProvider(input as any); + return { + ...input, + region: normalizeProvider(region) + }; + } +} +//export separately for showing comment block in Intellisense +export type RegionConfigurationInput = RegionConfiguration.Input; + +export namespace EndpointsConfig { + export interface Input { + /** + * The fully qualified endpoint of the webservice. This is only required when using a custom endpoint (for example, when using a local version of S3). + */ + endpoint?: string | HttpEndpoint | Provider; + + /** + * The endpoint provider to call if no endpoint is provided + */ + endpointProvider?: any; + + /** + * Whether TLS is enabled for requests. + */ + tls?: boolean; + } + interface PreviouslyResolved { + urlParser: UrlParser; + region: Provider; + service: string; + } + export interface Resolved extends Required { + endpoint: Provider; + } + export function resolve( + input: T & Input & PreviouslyResolved + ): T & Resolved { + const tls = input.tls || true; + const defaultProvider = (tls: boolean, region: string) => ({ + protocol: tls ? "https:" : "http:", + path: "/", + hostname: `${input.service}.${region}.amazonaws.com` + }); + const endpointProvider = input.endpointProvider || defaultProvider; + let endpoint: Provider = input.endpoint + ? normalizeEndpoint(input.endpoint, input.urlParser) + : () => input.region().then(region => endpointProvider(tls, region)); + return { + ...input, + endpointProvider, + endpoint, + tls + }; + } +} +//export separately for showing comment block in Intellisense +export type EndpointsConfigInput = EndpointsConfig.Input; + +export namespace ProtocolConfig { + export interface Input { + /** + * The serializing protocol to used in request + */ + protocol?: Protocol; + } + interface PreviouslyResolved { + httpHandler: HttpHandler; + protocolDefaultProvider: ( + handler: HttpHandler + ) => Protocol; + } + export type Resolved = Required; + export function resolve( + input: T & Input & PreviouslyResolved + ): T & Resolved { + return { + ...input, + protocol: + input.protocol || input.protocolDefaultProvider(input.httpHandler) + }; + } +} +//export separately for showing comment block in Intellisense +export type ProtocolConfigInput = ProtocolConfig.Input; diff --git a/packages/config-resolver/src/index.spec.ts b/packages/config-resolver/src/index.spec.ts deleted file mode 100644 index b89e734db465..000000000000 --- a/packages/config-resolver/src/index.spec.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { resolveConfiguration } from "./index"; -import { ConfigurationDefinition } from "@aws-sdk/types"; - -describe("resolveConfiguration", () => { - it("should throw if a required property is not supplied", () => { - const definition: ConfigurationDefinition< - { region: string }, - { region: string } - > = { - region: { - required: true - } - }; - const config = {}; - - expect(() => resolveConfiguration(config, definition, {} as any)).toThrow(); - }); - - it("should inject a default value if a property is not supplied", () => { - const definition: ConfigurationDefinition< - { region?: string }, - { region: string } - > = { - region: { - required: false, - defaultValue: "us-west-2" - } - }; - - expect(resolveConfiguration({}, definition, {} as any)).toEqual({ - region: "us-west-2" - }); - }); - - it("should not inject a default value if a property is supplied", () => { - const definition: ConfigurationDefinition< - { region?: string }, - { region: string } - > = { - region: { - required: false, - defaultValue: "us-west-2" - } - }; - - expect( - resolveConfiguration({ region: "eu-central-1" }, definition, {} as any) - ).toEqual({ region: "eu-central-1" }); - }); - - it("should call a default provider and inject its return value if a property is not supplied", () => { - const defaultProvider = jest.fn().mockReturnValue("us-west-2"); - const definition: ConfigurationDefinition< - { region?: string }, - { region: string } - > = { - region: { - required: false, - defaultProvider - } - }; - const config = {}; - - expect(resolveConfiguration(config, definition, {} as any)).toEqual({ - region: "us-west-2" - }); - expect(defaultProvider.mock.calls.length).toBe(1); - }); - - it("should not call a default provider if a property is supplied", () => { - const defaultProvider = jest.fn().mockReturnValue("us-west-2"); - const definition: ConfigurationDefinition< - { region?: string }, - { region: string } - > = { - region: { - required: false, - defaultProvider - } - }; - - expect( - resolveConfiguration({ region: "eu-central-1" }, definition, {} as any) - ).toEqual({ region: "eu-central-1" }); - expect(defaultProvider.mock.calls.length).toBe(0); - }); - - it("should always call a normalizer function if one is provided", () => { - const normalize = jest.fn().mockReturnValue("normalized!"); - const middlewareStack = {} as any; - const definition: ConfigurationDefinition< - { region: string }, - { region: string } - > = { - region: { - required: true, - normalize - } - }; - expect( - resolveConfiguration( - { region: "eu-central-1" }, - definition, - middlewareStack - ) - ).toEqual({ region: "normalized!" }); - expect(normalize.mock.calls.length).toBe(1); - expect(normalize.mock.calls[0][0]).toEqual("eu-central-1"); - }); - - it("should always call an apply function if one is provided", () => { - const apply = jest.fn(); - const middlewareStack = {} as any; - const definition: ConfigurationDefinition< - { region: string }, - { region: string } - > = { - region: { - required: true, - apply - } - }; - - expect( - resolveConfiguration( - { region: "eu-central-1" }, - definition, - middlewareStack - ) - ).toEqual({ region: "eu-central-1" }); - - expect(apply.mock.calls.length).toBe(1); - expect(apply.mock.calls[0]).toEqual([ - { region: "eu-central-1" }, - middlewareStack - ]); - }); -}); diff --git a/packages/config-resolver/src/index.ts b/packages/config-resolver/src/index.ts index a19aa2fd8eeb..40b494c5f873 100644 --- a/packages/config-resolver/src/index.ts +++ b/packages/config-resolver/src/index.ts @@ -1,58 +1 @@ -import { - ConfigApplicator, - ConfigurationDefinition, - MiddlewareStack -} from "@aws-sdk/types"; - -export type IndexedObject = { [key: string]: any }; - -export function resolveConfiguration< - T extends IndexedObject, - R extends T, - Input extends object, - Output extends object ->( - providedConfiguration: T, - configurationDefinition: ConfigurationDefinition, - middlewareStack: MiddlewareStack -): R { - const out: Partial = {}; - const applicators: Array> = []; - - // Iterate over the definitions own keys, using getOwnPropertyNames to - // guarantee insertion order is preserved. - // @see https://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys - for (const property of Object.getOwnPropertyNames(configurationDefinition)) { - const { - required, - defaultValue, - defaultProvider, - normalize, - apply - } = configurationDefinition[property]; - let input = providedConfiguration[property]; - - if (input === undefined) { - if (defaultValue !== undefined) { - input = defaultValue; - } else if (defaultProvider) { - input = defaultProvider(out as R); - } else if (required) { - throw new Error( - `No input provided for required configuration parameter: ${property}` - ); - } - } else if (normalize) { - input = normalize(input, out); - } - //@ts-ignore - out[property] = input; - - if (apply) { - applicators.push(apply); - } - } - - applicators.forEach(func => func(out as R, middlewareStack)); - return out as R; -} +export * from "./components"; diff --git a/packages/middleware-content-length/src/index.ts b/packages/middleware-content-length/src/index.ts index abcff8f903a6..16f97c786754 100644 --- a/packages/middleware-content-length/src/index.ts +++ b/packages/middleware-content-length/src/index.ts @@ -4,12 +4,13 @@ import { BuildMiddleware, BodyLengthCalculator, MetadataBearer, - BuildHandlerOutput + BuildHandlerOutput, + InjectableMiddleware } from "@aws-sdk/types"; import { HttpRequest } from "@aws-sdk/protocol-http"; export function contentLengthMiddleware( - bodyLengthCalculator: BodyLengthCalculator + bodyLengthChecker: BodyLengthCalculator ): BuildMiddleware { return ( next: BuildHandler @@ -26,7 +27,7 @@ export function contentLengthMiddleware( .map(str => str.toLowerCase()) .indexOf("content-length") === -1 ) { - const length = bodyLengthCalculator(body); + const length = bodyLengthChecker(body); if (length !== undefined) { request.headers = { ...request.headers, @@ -42,3 +43,13 @@ export function contentLengthMiddleware( }); }; } + +export function contentLengthPlugin(options: { + bodyLengthChecker: BodyLengthCalculator; +}): InjectableMiddleware { + return { + middleware: contentLengthMiddleware(options.bodyLengthChecker), + step: "build", + tags: { SET_CONTENT_LENGTH: true } + }; +} diff --git a/packages/middleware-deserializer/src/index.ts b/packages/middleware-deserializer/src/index.ts index e9e1d6e7e989..deb07eed2e87 100644 --- a/packages/middleware-deserializer/src/index.ts +++ b/packages/middleware-deserializer/src/index.ts @@ -4,14 +4,16 @@ import { DeserializeHandlerArguments, DeserializeMiddleware, DeserializeHandlerOutput, - Protocol + Protocol, + DeserializerUtils, + InjectableMiddleware } from "@aws-sdk/types"; export function deserializerMiddleware< Input extends object, Output extends object >( - protocol: Protocol, + options: DeserializerMiddlewareConfig, deserializer: ResponseDeserializer ): DeserializeMiddleware { return ( @@ -20,10 +22,29 @@ export function deserializerMiddleware< args: DeserializeHandlerArguments ): Promise> => { const { response } = await next(args); - const parsed = await protocol.parse(deserializer, response); + const parsed = await options.protocol.deserialize( + deserializer, + response, + options + ); return { response, output: parsed as Output }; }; } + +export interface DeserializerMiddlewareConfig extends DeserializerUtils { + protocol: Protocol; +} + +export function deserializerPlugin( + config: DeserializerMiddlewareConfig, + serializer: ResponseDeserializer +): InjectableMiddleware { + return { + middleware: deserializerMiddleware(config, serializer), + step: "deserialize", + tags: { DESERIALIZER: true } + }; +} diff --git a/packages/middleware-serializer/src/index.ts b/packages/middleware-serializer/src/index.ts index 0be73abe3d49..b8361cc7baa1 100644 --- a/packages/middleware-serializer/src/index.ts +++ b/packages/middleware-serializer/src/index.ts @@ -4,14 +4,16 @@ import { SerializeHandlerArguments, SerializeMiddleware, SerializeHandlerOutput, - Protocol + Protocol, + SerializerUtils, + InjectableMiddleware } from "@aws-sdk/types"; export function serializerMiddleware< Input extends object, Output extends object >( - protocol: Protocol, + options: SerializerMiddlewareConfig, serializer: RequestSerializer ): SerializeMiddleware { return ( @@ -19,10 +21,25 @@ export function serializerMiddleware< ): SerializeHandler => async ( args: SerializeHandlerArguments ): Promise> => { - const request = protocol.serialize(serializer, args.input); + const request = options.protocol.serialize(serializer, args.input, options); return next({ ...args, request }); }; } + +export interface SerializerMiddlewareConfig extends SerializerUtils { + protocol: Protocol; +} + +export function serializerPlugin( + config: SerializerMiddlewareConfig, + serializer: RequestSerializer +): InjectableMiddleware { + return { + middleware: serializerMiddleware(config, serializer), + step: "serialize", + tags: { SERIALIZER: true } + }; +} diff --git a/packages/middleware-stack/src/index.spec.ts b/packages/middleware-stack/src/index.spec.ts index 36ae48c754a3..d56f436133e5 100644 --- a/packages/middleware-stack/src/index.spec.ts +++ b/packages/middleware-stack/src/index.spec.ts @@ -5,7 +5,7 @@ import { FinalizeHandlerArguments, Middleware, HandlerExecutionContext, - FinalizeMiddleware, + FinalizeRequestMiddleware, FinalizeHandler, BuildMiddleware, HandlerOutput, @@ -19,7 +19,7 @@ type output = object; //return tagged union to make compiler happy function getConcatMiddleware( message: string -): Middleware | FinalizeMiddleware { +): Middleware | FinalizeRequestMiddleware { return (next: Handler): Handler => { return (args: HandlerArguments): Promise> => next({ @@ -47,8 +47,8 @@ describe("MiddlewareStack", () => { [getConcatMiddleware("first"), { priority: 10 }], [getConcatMiddleware("fourth"), { step: "build" }], [getConcatMiddleware("third"), { step: "build", priority: 1 }], - [getConcatMiddleware("fifth"), { step: "finalize" }], - [getConcatMiddleware("sixth"), { step: "finalize", priority: -1 }], + [getConcatMiddleware("fifth"), { step: "finalizeRequest" }], + [getConcatMiddleware("sixth"), { step: "finalizeRequest", priority: -1 }], [getConcatMiddleware("seven"), { step: "deserialize" }] ]); @@ -93,11 +93,11 @@ describe("MiddlewareStack", () => { const secondStack = new MiddlewareStack(); secondStack.add( - getConcatMiddleware("fourth") as FinalizeMiddleware, + getConcatMiddleware("fourth") as FinalizeRequestMiddleware, { step: "build" } ); secondStack.add( - getConcatMiddleware("third") as FinalizeMiddleware, + getConcatMiddleware("third") as FinalizeRequestMiddleware, { step: "build", priority: 100 } ); @@ -187,9 +187,9 @@ describe("MiddlewareStack", () => { step: "build" }); stack.add( - getConcatMiddleware("sixth") as FinalizeMiddleware, + getConcatMiddleware("sixth") as FinalizeRequestMiddleware, { - step: "finalize" + step: "finalizeRequest" } ); const filteredStack = stack.filter(middlewareStats => { diff --git a/packages/middleware-stack/src/index.ts b/packages/middleware-stack/src/index.ts index 7d6196088a2d..d165cd763a65 100644 --- a/packages/middleware-stack/src/index.ts +++ b/packages/middleware-stack/src/index.ts @@ -1,9 +1,9 @@ import { BuildHandlerOptions, FinalizeHandler, - FinalizeHandlerOptions, + FinalizeRequestHandlerOptions, SerializeMiddleware, - FinalizeMiddleware, + FinalizeRequestMiddleware, BuildMiddleware, Handler, HandlerExecutionContext, @@ -42,13 +42,13 @@ export class MiddlewareStack { ): void; add( - middleware: FinalizeMiddleware, + middleware: FinalizeRequestMiddleware, options: BuildHandlerOptions ): void; add( - middleware: FinalizeMiddleware, - options: FinalizeHandlerOptions + middleware: FinalizeRequestMiddleware, + options: FinalizeRequestHandlerOptions ): void; add( @@ -165,6 +165,6 @@ const stepWeights = { initialize: 5, serialize: 4, build: 3, - finalize: 2, + finalizeRequest: 2, deserialize: 1 }; diff --git a/packages/middleware-user-agent/.gitignore b/packages/middleware-user-agent/.gitignore new file mode 100644 index 000000000000..3d1714c9806e --- /dev/null +++ b/packages/middleware-user-agent/.gitignore @@ -0,0 +1,8 @@ +/node_modules/ +/build/ +/coverage/ +/docs/ +*.tsbuildinfo +*.tgz +*.log +package-lock.json diff --git a/packages/middleware-user-agent/.npmignore b/packages/middleware-user-agent/.npmignore new file mode 100644 index 000000000000..4b9fe3abf33a --- /dev/null +++ b/packages/middleware-user-agent/.npmignore @@ -0,0 +1,13 @@ +/src/ +/coverage/ +/docs/ +tsconfig.test.json +*.tsbuildinfo + +*.spec.js +*.spec.d.ts +*.spec.js.map + +*.fixture.js +*.fixture.d.ts +*.fixture.js.map diff --git a/packages/middleware-user-agent/LICENSE b/packages/middleware-user-agent/LICENSE new file mode 100644 index 000000000000..e907b58668da --- /dev/null +++ b/packages/middleware-user-agent/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/middleware-user-agent/README.md b/packages/middleware-user-agent/README.md new file mode 100644 index 000000000000..3f0928c20d26 --- /dev/null +++ b/packages/middleware-user-agent/README.md @@ -0,0 +1,4 @@ +# @aws-sdk/@aws-sdk/middleware-user-agent + +[![NPM version](https://img.shields.io/npm/v/@aws-sdk/@aws-sdk/middleware-user-agent/preview.svg)](https://www.npmjs.com/package/@aws-sdk/@aws-sdk/middleware-user-agent) +[![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/@aws-sdk/middleware-user-agent.svg)](https://www.npmjs.com/package/@aws-sdk/@aws-sdk/middleware-user-agent) diff --git a/packages/middleware-user-agent/package.json b/packages/middleware-user-agent/package.json new file mode 100644 index 000000000000..40d901874194 --- /dev/null +++ b/packages/middleware-user-agent/package.json @@ -0,0 +1,26 @@ +{ + "name": "@aws-sdk/middleware-user-agent", + "version": "0.1.0-preview.1", + "scripts": { + "prepublishOnly": "tsc", + "pretest": "tsc -p tsconfig.test.json", + "test": "jest" + }, + "main": "./build/index.js", + "types": "./build/index.d.ts", + "author": { + "name": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^0.1.0-preview.5", + "@aws-sdk/protocol-http": "^0.1.0-preview.1", + "tslib": "^1.8.0" + }, + "devDependencies": { + "@types/jest": "^24.0.12", + "typescript": "~3.4.0", + "jest": "^24.7.1" + } +} diff --git a/packages/middleware-user-agent/src/configurations.ts b/packages/middleware-user-agent/src/configurations.ts new file mode 100644 index 000000000000..a7c53b7482e5 --- /dev/null +++ b/packages/middleware-user-agent/src/configurations.ts @@ -0,0 +1,22 @@ +export namespace UserAgentConfig { + export interface Input { + /** + * The custom user agent header that would be appended to default one + */ + customUserAgent?: string; + } + export interface PreviouslyResolved { + defaultUserAgent: string; + } + export interface Resolved { + defaultUserAgent: string; + customUserAgent?: string; + } + export function resolve( + input: T & PreviouslyResolved & Input + ): T & Resolved { + return input; + } +} + +export type UserAgentConfigInput = UserAgentConfig.Input; diff --git a/packages/middleware-user-agent/src/index.ts b/packages/middleware-user-agent/src/index.ts new file mode 100644 index 000000000000..ef4de14542fe --- /dev/null +++ b/packages/middleware-user-agent/src/index.ts @@ -0,0 +1,2 @@ +export * from "./configurations"; +export * from "./middleware"; diff --git a/packages/middleware-user-agent/src/middleware.ts b/packages/middleware-user-agent/src/middleware.ts new file mode 100644 index 000000000000..1a6cd787403b --- /dev/null +++ b/packages/middleware-user-agent/src/middleware.ts @@ -0,0 +1,46 @@ +import { + BuildMiddleware, + BuildHandlerArguments, + BuildHandler, + MetadataBearer, + BuildHandlerOutput, + InjectableMiddleware +} from "@aws-sdk/types"; +import { HttpRequest } from "@aws-sdk/protocol-http"; +import { UserAgentConfig } from "./configurations"; + +const userAgentHeader = "User-Agent"; + +export function UserAgentMiddleware(options: UserAgentConfig.Resolved) { + return ( + next: BuildHandler + ): BuildHandler => ( + args: BuildHandlerArguments + ): Promise> => { + let { request } = args; + if (!HttpRequest.isInstance(request)) return next(args); + const { headers } = request; + if (!headers[userAgentHeader]) { + headers[userAgentHeader] = `${options.defaultUserAgent}`; + } else { + headers[userAgentHeader] += ` ${options.defaultUserAgent}`; + } + if (options.customUserAgent) { + headers[userAgentHeader] += ` ${options.customUserAgent}`; + } + return next({ + ...args, + request + }); + }; +} + +export function UserAgentPlugin( + options: UserAgentConfig.Resolved +): InjectableMiddleware { + return { + middleware: UserAgentMiddleware(options), + step: "build", + tags: { SET_USER_AGENT: true } + }; +} diff --git a/packages/middleware-user-agent/tsconfig.json b/packages/middleware-user-agent/tsconfig.json new file mode 100644 index 000000000000..38b94cda274e --- /dev/null +++ b/packages/middleware-user-agent/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "declaration": true, + "strict": true, + "sourceMap": true, + "downlevelIteration": true, + "importHelpers": true, + "noEmitHelpers": true, + "lib": [ + "es5", + "es2015.promise", + "es2015.collection", + "es2015.iterable", + "es2015.symbol.wellknown" + ], + "rootDir": "./src", + "outDir": "./build", + "incremental": true + } +} diff --git a/packages/middleware-user-agent/tsconfig.test.json b/packages/middleware-user-agent/tsconfig.test.json new file mode 100644 index 000000000000..17d0f1b7321f --- /dev/null +++ b/packages/middleware-user-agent/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": false, + "inlineSourceMap": true, + "inlineSources": true, + "rootDir": "./src", + "outDir": "./build", + "incremental": true + } +} diff --git a/packages/node-http-handler/src/node-http-handler.ts b/packages/node-http-handler/src/node-http-handler.ts index 64688423b694..9177a628087a 100644 --- a/packages/node-http-handler/src/node-http-handler.ts +++ b/packages/node-http-handler/src/node-http-handler.ts @@ -13,7 +13,7 @@ export class NodeHttpHandler implements HttpHandler { private readonly httpsAgent: https.Agent; constructor(private readonly httpOptions: NodeHttpOptions = {}) { - const { keepAlive } = httpOptions; + const { keepAlive = true } = httpOptions; this.httpAgent = new http.Agent({ keepAlive }); this.httpsAgent = new https.Agent({ keepAlive }); } diff --git a/packages/protocol-rest-json/src/index.ts b/packages/protocol-rest-json/src/index.ts index 0cec703af24f..721a61dace04 100644 --- a/packages/protocol-rest-json/src/index.ts +++ b/packages/protocol-rest-json/src/index.ts @@ -3,7 +3,9 @@ import { ResponseDeserializer, Protocol, TransferHandler, - HttpOptions + HttpOptions, + SerializerUtils, + DeserializerUtils } from "@aws-sdk/types"; import { HttpRequest, HttpResponse } from "@aws-sdk/protocol-http"; @@ -17,10 +19,18 @@ export class RestJsonProtocol extends Protocol< ) { super(handler); } - serialize(serializer: RequestSerializer, input: any) { + serialize( + serializer: RequestSerializer, + input: any, + utils?: SerializerUtils + ) { return serializer(input, "aws.rest-json-1.1"); } - parse(parser: ResponseDeserializer, output: HttpResponse) { + deserialize( + parser: ResponseDeserializer, + output: HttpResponse, + utils?: DeserializerUtils + ) { return parser(output, "aws.rest-json-1.1") as any; } } diff --git a/packages/retry-middleware/package.json b/packages/retry-middleware/package.json index 09406d163050..cd8acef83917 100644 --- a/packages/retry-middleware/package.json +++ b/packages/retry-middleware/package.json @@ -20,6 +20,7 @@ }, "devDependencies": { "@types/jest": "^24.0.12", + "@aws-sdk/protocol-http": "^0.1.0-preview.1", "jest": "^24.7.1", "typescript": "~3.4.0" } diff --git a/packages/retry-middleware/src/configurations.ts b/packages/retry-middleware/src/configurations.ts new file mode 100644 index 000000000000..1a944fd5a6f7 --- /dev/null +++ b/packages/retry-middleware/src/configurations.ts @@ -0,0 +1,31 @@ +import { RetryStrategy } from "@aws-sdk/types"; +import { ExponentialBackOffStrategy } from "./defaultStrategy"; + +export namespace RetryConfig { + export interface Input { + /** + * The maximum number of times requests that encounter potentially transient failures should be retried + */ + maxRetries?: number; + /** + * The strategy to retry the request. Using built-in exponential backoff strategy by default. + */ + retryStrategy?: RetryStrategy; + } + export interface Resolved { + maxRetries: number; + retryStrategy: RetryStrategy; + } + export function resolve(input: T & Input): T & Resolved { + const maxRetries = input.maxRetries === undefined ? 3 : input.maxRetries; + return { + ...input, + maxRetries, + retryStrategy: + input.retryStrategy || new ExponentialBackOffStrategy(maxRetries) + }; + } +} + +//export separately for showing comment block in Intellisense +export type RetryConfigInput = RetryConfig.Input; diff --git a/packages/retry-middleware/src/defaultStrategy.ts b/packages/retry-middleware/src/defaultStrategy.ts new file mode 100644 index 000000000000..3deb619e6621 --- /dev/null +++ b/packages/retry-middleware/src/defaultStrategy.ts @@ -0,0 +1,23 @@ +import { + DEFAULT_RETRY_DELAY_BASE, + THROTTLING_RETRY_DELAY_BASE +} from "./constants"; +import { defaultDelayDecider } from "./delayDecider"; +import { defaultRetryDecider } from "./retryDecider"; +import { isThrottlingError } from "@aws-sdk/service-error-classification"; +import { RetryStrategy, SdkError } from "@aws-sdk/types"; + +export class ExponentialBackOffStrategy implements RetryStrategy { + constructor(public readonly maxRetries: number) {} + shouldRetry(error: SdkError, retryAttempted: number) { + return retryAttempted < this.maxRetries && defaultRetryDecider(error); + } + computeDelayBeforeNextRetry(error: SdkError, retryAttempted: number): number { + return defaultDelayDecider( + isThrottlingError(error) + ? THROTTLING_RETRY_DELAY_BASE + : DEFAULT_RETRY_DELAY_BASE, + retryAttempted + ); + } +} diff --git a/packages/retry-middleware/src/index.ts b/packages/retry-middleware/src/index.ts index d10a01177cac..c541e7fed3cf 100644 --- a/packages/retry-middleware/src/index.ts +++ b/packages/retry-middleware/src/index.ts @@ -1,3 +1,3 @@ -export * from "./delayDecider"; -export * from "./retryDecider"; export * from "./retryMiddleware"; +export * from "./defaultStrategy"; +export * from "./configurations"; diff --git a/packages/retry-middleware/src/retryDecider.spec.ts b/packages/retry-middleware/src/retryDecider.spec.ts index 12c1e77524c4..91c86c55265c 100644 --- a/packages/retry-middleware/src/retryDecider.spec.ts +++ b/packages/retry-middleware/src/retryDecider.spec.ts @@ -1,49 +1,37 @@ import { defaultRetryDecider } from "./retryDecider"; describe("defaultRetryDecider", () => { - const decider = defaultRetryDecider(); - it("should return false when the provided error is falsy", () => { - expect(decider(null as any)).toBe(false); + expect(defaultRetryDecider(null as any)).toBe(false); }); it("should return true if the error was tagged as a connection error", () => { const err: Error & { connectionError?: boolean } = new Error(); err.connectionError = true; - expect(decider(err)).toBe(true); + expect(defaultRetryDecider(err)).toBe(true); }); for (const httpStatusCode of [429, 500, 502, 503, 504, 509]) { it(`should return true if the error represents a service response with an HTTP status code of ${httpStatusCode}`, () => { const err: any = new Error(); err.$metadata = { httpStatusCode }; - expect(decider(err)).toBe(true); + expect(defaultRetryDecider(err)).toBe(true); }); } it('should return true if the response represents a "still processing" error', () => { const err = new Error(); err.name = "PriorRequestNotComplete"; - expect(decider(err)).toBe(true); + expect(defaultRetryDecider(err)).toBe(true); }); it("should return true if the response represents a throttling error", () => { const err = new Error(); err.name = "TooManyRequestsException"; - expect(decider(err)).toBe(true); + expect(defaultRetryDecider(err)).toBe(true); }); it("should return false for other errors", () => { - expect(decider(new Error())).toBe(false); - }); - - describe("clock skew retries enabled", () => { - const decider = defaultRetryDecider(true); - - it("should return true if the response represents a clock skew error", () => { - const err = new Error(); - err.name = "RequestTimeTooSkewed"; - expect(decider(err)).toBe(true); - }); + expect(defaultRetryDecider(new Error())).toBe(false); }); }); diff --git a/packages/retry-middleware/src/retryDecider.ts b/packages/retry-middleware/src/retryDecider.ts index 9563fb3d46d1..542ed3fca41a 100644 --- a/packages/retry-middleware/src/retryDecider.ts +++ b/packages/retry-middleware/src/retryDecider.ts @@ -4,35 +4,31 @@ import { isStillProcessingError, isThrottlingError } from "@aws-sdk/service-error-classification"; -import { MetadataBearer, SdkError, RetryDecider } from "@aws-sdk/types"; +import { MetadataBearer, SdkError } from "@aws-sdk/types"; -export function defaultRetryDecider( - retryClockSkewErrors = false -): RetryDecider { - return (error: SdkError) => { - if (!error) { - return false; - } +export const defaultRetryDecider = (error: SdkError) => { + if (!error) { + return false; + } - if (error.connectionError) { - return true; - } + if (error.connectionError) { + return true; + } - if ( - hasMetadata(error) && - error.$metadata.httpStatusCode && - RETRYABLE_STATUS_CODES.has(error.$metadata.httpStatusCode) - ) { - return true; - } + if ( + hasMetadata(error) && + error.$metadata.httpStatusCode && + RETRYABLE_STATUS_CODES.has(error.$metadata.httpStatusCode) + ) { + return true; + } - return ( - isStillProcessingError(error) || - isThrottlingError(error) || - (retryClockSkewErrors && isClockSkewError(error)) - ); - }; -} + return ( + isStillProcessingError(error) || + isThrottlingError(error) || + isClockSkewError(error) + ); +}; function hasMetadata(error: any): error is MetadataBearer { return error && error.$metadata; diff --git a/packages/retry-middleware/src/retryMiddleware.spec.ts b/packages/retry-middleware/src/retryMiddleware.spec.ts index 13313a8f5328..5247297ee5c8 100644 --- a/packages/retry-middleware/src/retryMiddleware.spec.ts +++ b/packages/retry-middleware/src/retryMiddleware.spec.ts @@ -3,15 +3,21 @@ import { THROTTLING_RETRY_DELAY_BASE } from "./constants"; import { retryMiddleware } from "./retryMiddleware"; +import { RetryConfig } from "./configurations"; +import * as delayDeciderModule from "./delayDecider"; +import { ExponentialBackOffStrategy } from "./defaultStrategy"; +import { HttpRequest } from "@aws-sdk/protocol-http"; describe("retryMiddleware", () => { it("should not retry when the handler completes successfully", async () => { const next = jest.fn().mockResolvedValue({ output: { $metadata: {} } }); - const retryHandler = retryMiddleware(0)(next); + const retryHandler = retryMiddleware( + RetryConfig.resolve({ maxRetries: 0 }) + )(next); const { output: { $metadata } - } = await retryHandler({ input: {}, request: {} as any }); + } = await retryHandler({ input: {}, request: new HttpRequest({}) }); expect($metadata.retries).toBe(0); expect($metadata.totalRetryDelay).toBe(0); @@ -23,10 +29,12 @@ describe("retryMiddleware", () => { const error = new Error(); error.name = "ProvisionedThroughputExceededException"; const next = jest.fn().mockRejectedValue(error); - const retryHandler = retryMiddleware(maxRetries)(next); + const retryHandler = retryMiddleware(RetryConfig.resolve({ maxRetries }))( + next + ); await expect( - retryHandler({ input: {}, request: {} as any }) + retryHandler({ input: {}, request: new HttpRequest({}) }) ).rejects.toMatchObject(error); expect(next.mock.calls.length).toBe(maxRetries + 1); @@ -36,10 +44,12 @@ describe("retryMiddleware", () => { const error = new Error(); error.name = "ValidationException"; const next = jest.fn().mockRejectedValue(error); - const retryHandler = retryMiddleware(3)(next); + const retryHandler = retryMiddleware( + RetryConfig.resolve({ maxRetries: 3 }) + )(next); await expect( - retryHandler({ input: {}, request: {} as any }) + retryHandler({ input: {}, request: new HttpRequest({}) }) ).rejects.toMatchObject(error); expect(next.mock.calls.length).toBe(1); @@ -56,13 +66,24 @@ describe("retryMiddleware", () => { throttling.name = "RequestLimitExceeded"; next.mockImplementationOnce(args => Promise.reject(throttling)); - const delayDecider = jest.fn().mockReturnValue(0); - const retryHandler = retryMiddleware(3, () => true, delayDecider)(next); + jest.mock("./delayDecider"); - await retryHandler({ input: {}, request: {} as any }); + const maxRetries = 3; + const delayDeciderMock = jest.spyOn( + delayDeciderModule, + "defaultDelayDecider" + ); + const strategy = new ExponentialBackOffStrategy(maxRetries); + strategy.shouldRetry = () => true; + const retryHandler = retryMiddleware({ + maxRetries, + retryStrategy: strategy + })(next); + + await retryHandler({ input: {}, request: new HttpRequest({}) }); expect(next.mock.calls.length).toBe(3); - expect(delayDecider.mock.calls).toEqual([ + expect(delayDeciderMock.mock.calls).toEqual([ [DEFAULT_RETRY_DELAY_BASE, 0], [THROTTLING_RETRY_DELAY_BASE, 1] ]); diff --git a/packages/retry-middleware/src/retryMiddleware.ts b/packages/retry-middleware/src/retryMiddleware.ts index 6f8d955ecb6c..ffcc9d33ae3a 100644 --- a/packages/retry-middleware/src/retryMiddleware.ts +++ b/packages/retry-middleware/src/retryMiddleware.ts @@ -1,24 +1,14 @@ import { - DEFAULT_RETRY_DELAY_BASE, - THROTTLING_RETRY_DELAY_BASE -} from "./constants"; -import { defaultDelayDecider } from "./delayDecider"; -import { defaultRetryDecider } from "./retryDecider"; -import { isThrottlingError } from "@aws-sdk/service-error-classification"; -import { - DelayDecider, FinalizeHandler, FinalizeHandlerArguments, MetadataBearer, - RetryDecider, - FinalizeHandlerOutput + FinalizeHandlerOutput, + SdkError, + InjectableMiddleware } from "@aws-sdk/types"; +import { RetryConfig } from "./configurations"; -export function retryMiddleware( - maxRetries: number, - retryDecider: RetryDecider = defaultRetryDecider(), - delayDecider: DelayDecider = defaultDelayDecider -) { +export function retryMiddleware(options: RetryConfig.Resolved) { return ( next: FinalizeHandler ): FinalizeHandler => @@ -35,13 +25,12 @@ export function retryMiddleware( return { response, output }; } catch (err) { - if (retries < maxRetries && retryDecider(err)) { - const delay = delayDecider( - isThrottlingError(err) - ? THROTTLING_RETRY_DELAY_BASE - : DEFAULT_RETRY_DELAY_BASE, - retries++ + if (options.retryStrategy.shouldRetry(err as SdkError, retries)) { + const delay = options.retryStrategy.computeDelayBeforeNextRetry( + err, + retries ); + retries++; totalDelay += delay; await new Promise(resolve => setTimeout(resolve, delay)); @@ -59,3 +48,14 @@ export function retryMiddleware( } }; } + +export function retryPlugin< + Input extends object, + Output extends MetadataBearer +>(options: RetryConfig.Resolved): InjectableMiddleware { + return { + middleware: retryMiddleware(options), + step: "finalizeRequest", + tags: { RETRY: true } + }; +} diff --git a/packages/service-types-generator/src/internalImports.ts b/packages/service-types-generator/src/internalImports.ts index 10f164252a08..2b2b822a8266 100644 --- a/packages/service-types-generator/src/internalImports.ts +++ b/packages/service-types-generator/src/internalImports.ts @@ -108,6 +108,10 @@ export const IMPORTS: { [key: string]: Import } = { package: "@aws-sdk/http-serialization", version: "^0.1.0-preview.5" }, + "invalid-dependency": { + package: "@aws-sdk/invalid-dependency", + version: "^0.1.0-preview.1" + }, "is-array-buffer": { package: "@aws-sdk/is-array-buffer", version: "^0.1.0-preview.3" @@ -156,6 +160,10 @@ export const IMPORTS: { [key: string]: Import } = { package: "@aws-sdk/middleware-content-length", version: "^0.1.0-preview.5" }, + "middleware-deserializer": { + package: "@aws-sdk/middleware-deserializer", + version: "^0.1.0-preview.1" + }, "middleware-ec2-copysnapshot": { package: "@aws-sdk/middleware-ec2-copysnapshot", version: "^0.1.0-preview.7" @@ -216,9 +224,9 @@ export const IMPORTS: { [key: string]: Import } = { package: "@aws-sdk/property-provider", version: "^0.1.0-preview.5" }, - "protocol-json-rpc": { - package: "@aws-sdk/protocol-json-rpc", - version: "^0.1.0-preview.6" + "protocol-http": { + package: "@aws-sdk/protocol-http", + version: "^0.1.0-preview.1" }, "protocol-query": { package: "@aws-sdk/protocol-query", @@ -228,6 +236,10 @@ export const IMPORTS: { [key: string]: Import } = { package: "@aws-sdk/protocol-rest", version: "^0.1.0-preview.7" }, + "protocol-rest-json": { + package: "@aws-sdk/protocol-rest-json", + version: "^0.1.0-preview.5" + }, "protocol-timestamp": { package: "@aws-sdk/protocol-timestamp", version: "^0.1.0-preview.5" @@ -436,1468 +448,8 @@ export const IMPORTS: { [key: string]: Import } = { package: "@aws-sdk/xml-builder", version: "^0.1.0-preview.3" }, - "client-acm-browser": { - package: "@aws-sdk/client-acm-browser", - version: "^0.1.0-preview.3" - }, - "client-acm-pca-browser": { - package: "@aws-sdk/client-acm-pca-browser", - version: "^0.1.0-preview.3" - }, - "client-alexa-for-business-browser": { - package: "@aws-sdk/client-alexa-for-business-browser", - version: "^0.1.0-preview.3" - }, - "client-amplify-browser": { - package: "@aws-sdk/client-amplify-browser", - version: "^0.1.0-preview.3" - }, - "client-api-gateway-browser": { - package: "@aws-sdk/client-api-gateway-browser", - version: "^0.1.0-preview.3" - }, - "client-apigatewaymanagementapi-browser": { - package: "@aws-sdk/client-apigatewaymanagementapi-browser", - version: "^0.1.0-preview.3" - }, - "client-apigatewayv2-browser": { - package: "@aws-sdk/client-apigatewayv2-browser", - version: "^0.1.0-preview.3" - }, - "client-app-mesh-browser": { - package: "@aws-sdk/client-app-mesh-browser", - version: "^0.1.0-preview.3" - }, - "client-application-auto-scaling-browser": { - package: "@aws-sdk/client-application-auto-scaling-browser", - version: "^0.1.0-preview.3" - }, - "client-application-discovery-service-browser": { - package: "@aws-sdk/client-application-discovery-service-browser", - version: "^0.1.0-preview.3" - }, - "client-application-insights-browser": { - package: "@aws-sdk/client-application-insights-browser", - version: "^0.1.0-preview.3" - }, - "client-appstream-browser": { - package: "@aws-sdk/client-appstream-browser", - version: "^0.1.0-preview.3" - }, - "client-appsync-browser": { - package: "@aws-sdk/client-appsync-browser", - version: "^0.1.0-preview.3" - }, - "client-athena-browser": { - package: "@aws-sdk/client-athena-browser", - version: "^0.1.0-preview.3" - }, - "client-auto-scaling-browser": { - package: "@aws-sdk/client-auto-scaling-browser", - version: "^0.1.0-preview.3" - }, - "client-auto-scaling-plans-browser": { - package: "@aws-sdk/client-auto-scaling-plans-browser", - version: "^0.1.0-preview.3" - }, - "client-backup-browser": { - package: "@aws-sdk/client-backup-browser", - version: "^0.1.0-preview.3" - }, - "client-batch-browser": { - package: "@aws-sdk/client-batch-browser", - version: "^0.1.0-preview.3" - }, - "client-budgets-browser": { - package: "@aws-sdk/client-budgets-browser", - version: "^0.1.0-preview.3" - }, - "client-chime-browser": { - package: "@aws-sdk/client-chime-browser", - version: "^0.1.0-preview.3" - }, - "client-cloud9-browser": { - package: "@aws-sdk/client-cloud9-browser", - version: "^0.1.0-preview.3" - }, - "client-clouddirectory-browser": { - package: "@aws-sdk/client-clouddirectory-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudformation-browser": { - package: "@aws-sdk/client-cloudformation-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudfront-browser": { - package: "@aws-sdk/client-cloudfront-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudhsm-browser": { - package: "@aws-sdk/client-cloudhsm-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudhsm-v2-browser": { - package: "@aws-sdk/client-cloudhsm-v2-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudsearch-browser": { - package: "@aws-sdk/client-cloudsearch-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudsearch-domain-browser": { - package: "@aws-sdk/client-cloudsearch-domain-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudtrail-browser": { - package: "@aws-sdk/client-cloudtrail-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudwatch-browser": { - package: "@aws-sdk/client-cloudwatch-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudwatch-events-browser": { - package: "@aws-sdk/client-cloudwatch-events-browser", - version: "^0.1.0-preview.3" - }, - "client-cloudwatch-logs-browser": { - package: "@aws-sdk/client-cloudwatch-logs-browser", - version: "^0.1.0-preview.3" - }, - "client-codebuild-browser": { - package: "@aws-sdk/client-codebuild-browser", - version: "^0.1.0-preview.3" - }, - "client-codecommit-browser": { - package: "@aws-sdk/client-codecommit-browser", - version: "^0.1.0-preview.3" - }, - "client-codedeploy-browser": { - package: "@aws-sdk/client-codedeploy-browser", - version: "^0.1.0-preview.3" - }, - "client-codepipeline-browser": { - package: "@aws-sdk/client-codepipeline-browser", - version: "^0.1.0-preview.3" - }, - "client-codestar-browser": { - package: "@aws-sdk/client-codestar-browser", - version: "^0.1.0-preview.3" - }, - "client-cognito-identity-browser": { - package: "@aws-sdk/client-cognito-identity-browser", - version: "^0.1.0-preview.7" - }, - "client-cognito-identity-provider-browser": { - package: "@aws-sdk/client-cognito-identity-provider-browser", - version: "^0.1.0-preview.3" - }, - "client-cognito-sync-browser": { - package: "@aws-sdk/client-cognito-sync-browser", - version: "^0.1.0-preview.3" - }, - "client-comprehend-browser": { - package: "@aws-sdk/client-comprehend-browser", - version: "^0.1.0-preview.3" - }, - "client-comprehendmedical-browser": { - package: "@aws-sdk/client-comprehendmedical-browser", - version: "^0.1.0-preview.3" - }, - "client-config-service-browser": { - package: "@aws-sdk/client-config-service-browser", - version: "^0.1.0-preview.3" - }, - "client-connect-browser": { - package: "@aws-sdk/client-connect-browser", - version: "^0.1.0-preview.3" - }, - "client-cost-and-usage-report-service-browser": { - package: "@aws-sdk/client-cost-and-usage-report-service-browser", - version: "^0.1.0-preview.3" - }, - "client-cost-explorer-browser": { - package: "@aws-sdk/client-cost-explorer-browser", - version: "^0.1.0-preview.3" - }, - "client-data-pipeline-browser": { - package: "@aws-sdk/client-data-pipeline-browser", - version: "^0.1.0-preview.3" - }, - "client-database-migration-service-browser": { - package: "@aws-sdk/client-database-migration-service-browser", - version: "^0.1.0-preview.3" - }, - "client-datasync-browser": { - package: "@aws-sdk/client-datasync-browser", - version: "^0.1.0-preview.3" - }, - "client-dax-browser": { - package: "@aws-sdk/client-dax-browser", - version: "^0.1.0-preview.3" - }, - "client-device-farm-browser": { - package: "@aws-sdk/client-device-farm-browser", - version: "^0.1.0-preview.3" - }, - "client-direct-connect-browser": { - package: "@aws-sdk/client-direct-connect-browser", - version: "^0.1.0-preview.3" - }, - "client-directory-service-browser": { - package: "@aws-sdk/client-directory-service-browser", - version: "^0.1.0-preview.3" - }, - "client-dlm-browser": { - package: "@aws-sdk/client-dlm-browser", - version: "^0.1.0-preview.3" - }, - "client-docdb-browser": { - package: "@aws-sdk/client-docdb-browser", - version: "^0.1.0-preview.3" - }, - "client-dynamodb-browser": { - package: "@aws-sdk/client-dynamodb-browser", - version: "^0.1.0-preview.6" - }, - "client-dynamodb-streams-browser": { - package: "@aws-sdk/client-dynamodb-streams-browser", - version: "^0.1.0-preview.3" - }, - "client-ec2-browser": { - package: "@aws-sdk/client-ec2-browser", - version: "^0.1.0-preview.3" - }, - "client-ec2-instance-connect-browser": { - package: "@aws-sdk/client-ec2-instance-connect-browser", - version: "^0.1.0-preview.3" - }, - "client-ecr-browser": { - package: "@aws-sdk/client-ecr-browser", - version: "^0.1.0-preview.3" - }, - "client-ecs-browser": { - package: "@aws-sdk/client-ecs-browser", - version: "^0.1.0-preview.3" - }, - "client-efs-browser": { - package: "@aws-sdk/client-efs-browser", - version: "^0.1.0-preview.3" - }, - "client-eks-browser": { - package: "@aws-sdk/client-eks-browser", - version: "^0.1.0-preview.3" - }, - "client-elastic-beanstalk-browser": { - package: "@aws-sdk/client-elastic-beanstalk-browser", - version: "^0.1.0-preview.3" - }, - "client-elastic-load-balancing-browser": { - package: "@aws-sdk/client-elastic-load-balancing-browser", - version: "^0.1.0-preview.3" - }, - "client-elastic-load-balancing-v2-browser": { - package: "@aws-sdk/client-elastic-load-balancing-v2-browser", - version: "^0.1.0-preview.3" - }, - "client-elastic-transcoder-browser": { - package: "@aws-sdk/client-elastic-transcoder-browser", - version: "^0.1.0-preview.3" - }, - "client-elasticache-browser": { - package: "@aws-sdk/client-elasticache-browser", - version: "^0.1.0-preview.3" - }, - "client-elasticsearch-service-browser": { - package: "@aws-sdk/client-elasticsearch-service-browser", - version: "^0.1.0-preview.3" - }, - "client-emr-browser": { - package: "@aws-sdk/client-emr-browser", - version: "^0.1.0-preview.3" - }, - "client-eventbridge-browser": { - package: "@aws-sdk/client-eventbridge-browser", - version: "^0.1.0-preview.3" - }, - "client-firehose-browser": { - package: "@aws-sdk/client-firehose-browser", - version: "^0.1.0-preview.3" - }, - "client-fms-browser": { - package: "@aws-sdk/client-fms-browser", - version: "^0.1.0-preview.3" - }, - "client-fsx-browser": { - package: "@aws-sdk/client-fsx-browser", - version: "^0.1.0-preview.3" - }, - "client-gamelift-browser": { - package: "@aws-sdk/client-gamelift-browser", - version: "^0.1.0-preview.3" - }, - "client-glacier-browser": { - package: "@aws-sdk/client-glacier-browser", - version: "^0.1.0-preview.3" - }, - "client-global-accelerator-browser": { - package: "@aws-sdk/client-global-accelerator-browser", - version: "^0.1.0-preview.3" - }, - "client-glue-browser": { - package: "@aws-sdk/client-glue-browser", - version: "^0.1.0-preview.3" - }, - "client-greengrass-browser": { - package: "@aws-sdk/client-greengrass-browser", - version: "^0.1.0-preview.3" - }, - "client-groundstation-browser": { - package: "@aws-sdk/client-groundstation-browser", - version: "^0.1.0-preview.3" - }, - "client-guardduty-browser": { - package: "@aws-sdk/client-guardduty-browser", - version: "^0.1.0-preview.3" - }, - "client-health-browser": { - package: "@aws-sdk/client-health-browser", - version: "^0.1.0-preview.3" - }, - "client-iam-browser": { - package: "@aws-sdk/client-iam-browser", - version: "^0.1.0-preview.3" - }, - "client-inspector-browser": { - package: "@aws-sdk/client-inspector-browser", - version: "^0.1.0-preview.3" - }, - "client-iot-1click-devices-service-browser": { - package: "@aws-sdk/client-iot-1click-devices-service-browser", - version: "^0.1.0-preview.3" - }, - "client-iot-1click-projects-browser": { - package: "@aws-sdk/client-iot-1click-projects-browser", - version: "^0.1.0-preview.3" - }, - "client-iot-browser": { - package: "@aws-sdk/client-iot-browser", - version: "^0.1.0-preview.3" - }, - "client-iot-data-plane-browser": { - package: "@aws-sdk/client-iot-data-plane-browser", - version: "^0.1.0-preview.3" - }, - "client-iot-events-browser": { - package: "@aws-sdk/client-iot-events-browser", - version: "^0.1.0-preview.3" - }, - "client-iot-events-data-browser": { - package: "@aws-sdk/client-iot-events-data-browser", - version: "^0.1.0-preview.3" - }, - "client-iot-jobs-data-plane-browser": { - package: "@aws-sdk/client-iot-jobs-data-plane-browser", - version: "^0.1.0-preview.3" - }, - "client-iotanalytics-browser": { - package: "@aws-sdk/client-iotanalytics-browser", - version: "^0.1.0-preview.3" - }, - "client-iotthingsgraph-browser": { - package: "@aws-sdk/client-iotthingsgraph-browser", - version: "^0.1.0-preview.3" - }, - "client-kafka-browser": { - package: "@aws-sdk/client-kafka-browser", - version: "^0.1.0-preview.3" - }, - "client-kinesis-analytics-browser": { - package: "@aws-sdk/client-kinesis-analytics-browser", - version: "^0.1.0-preview.3" - }, - "client-kinesis-analytics-v2-browser": { - package: "@aws-sdk/client-kinesis-analytics-v2-browser", - version: "^0.1.0-preview.3" - }, - "client-kinesis-browser": { - package: "@aws-sdk/client-kinesis-browser", - version: "^0.1.0-preview.7" - }, - "client-kinesis-video-archived-media-browser": { - package: "@aws-sdk/client-kinesis-video-archived-media-browser", - version: "^0.1.0-preview.3" - }, - "client-kinesis-video-browser": { - package: "@aws-sdk/client-kinesis-video-browser", - version: "^0.1.0-preview.3" - }, - "client-kinesis-video-media-browser": { - package: "@aws-sdk/client-kinesis-video-media-browser", - version: "^0.1.0-preview.3" - }, - "client-kms-browser": { - package: "@aws-sdk/client-kms-browser", - version: "^0.1.0-preview.6" - }, - "client-lambda-browser": { - package: "@aws-sdk/client-lambda-browser", - version: "^0.1.0-preview.3" - }, - "client-lex-model-building-service-browser": { - package: "@aws-sdk/client-lex-model-building-service-browser", - version: "^0.1.0-preview.3" - }, - "client-lex-runtime-service-browser": { - package: "@aws-sdk/client-lex-runtime-service-browser", - version: "^0.1.0-preview.3" - }, - "client-license-manager-browser": { - package: "@aws-sdk/client-license-manager-browser", - version: "^0.1.0-preview.3" - }, - "client-lightsail-browser": { - package: "@aws-sdk/client-lightsail-browser", - version: "^0.1.0-preview.3" - }, - "client-machine-learning-browser": { - package: "@aws-sdk/client-machine-learning-browser", - version: "^0.1.0-preview.3" - }, - "client-macie-browser": { - package: "@aws-sdk/client-macie-browser", - version: "^0.1.0-preview.3" - }, - "client-managedblockchain-browser": { - package: "@aws-sdk/client-managedblockchain-browser", - version: "^0.1.0-preview.3" - }, - "client-marketplace-commerce-analytics-browser": { - package: "@aws-sdk/client-marketplace-commerce-analytics-browser", - version: "^0.1.0-preview.3" - }, - "client-marketplace-entitlement-service-browser": { - package: "@aws-sdk/client-marketplace-entitlement-service-browser", - version: "^0.1.0-preview.3" - }, - "client-marketplace-metering-browser": { - package: "@aws-sdk/client-marketplace-metering-browser", - version: "^0.1.0-preview.3" - }, - "client-mediaconnect-browser": { - package: "@aws-sdk/client-mediaconnect-browser", - version: "^0.1.0-preview.3" - }, - "client-mediaconvert-browser": { - package: "@aws-sdk/client-mediaconvert-browser", - version: "^0.1.0-preview.3" - }, - "client-medialive-browser": { - package: "@aws-sdk/client-medialive-browser", - version: "^0.1.0-preview.3" - }, - "client-mediapackage-browser": { - package: "@aws-sdk/client-mediapackage-browser", - version: "^0.1.0-preview.3" - }, - "client-mediapackage-vod-browser": { - package: "@aws-sdk/client-mediapackage-vod-browser", - version: "^0.1.0-preview.3" - }, - "client-mediastore-browser": { - package: "@aws-sdk/client-mediastore-browser", - version: "^0.1.0-preview.3" - }, - "client-mediastore-data-browser": { - package: "@aws-sdk/client-mediastore-data-browser", - version: "^0.1.0-preview.3" - }, - "client-mediatailor-browser": { - package: "@aws-sdk/client-mediatailor-browser", - version: "^0.1.0-preview.3" - }, - "client-migration-hub-browser": { - package: "@aws-sdk/client-migration-hub-browser", - version: "^0.1.0-preview.3" - }, - "client-mobile-browser": { - package: "@aws-sdk/client-mobile-browser", - version: "^0.1.0-preview.3" - }, - "client-mq-browser": { - package: "@aws-sdk/client-mq-browser", - version: "^0.1.0-preview.3" - }, - "client-mturk-browser": { - package: "@aws-sdk/client-mturk-browser", - version: "^0.1.0-preview.3" - }, - "client-neptune-browser": { - package: "@aws-sdk/client-neptune-browser", + "client-rds-data-node": { + package: "@aws-sdk/client-rds-data-node", version: "^0.1.0-preview.3" - }, - "client-opsworks-browser": { - package: "@aws-sdk/client-opsworks-browser", - version: "^0.1.0-preview.3" - }, - "client-opsworkscm-browser": { - package: "@aws-sdk/client-opsworkscm-browser", - version: "^0.1.0-preview.3" - }, - "client-organizations-browser": { - package: "@aws-sdk/client-organizations-browser", - version: "^0.1.0-preview.3" - }, - "client-personalize-browser": { - package: "@aws-sdk/client-personalize-browser", - version: "^0.1.0-preview.3" - }, - "client-personalize-events-browser": { - package: "@aws-sdk/client-personalize-events-browser", - version: "^0.1.0-preview.3" - }, - "client-personalize-runtime-browser": { - package: "@aws-sdk/client-personalize-runtime-browser", - version: "^0.1.0-preview.3" - }, - "client-pi-browser": { - package: "@aws-sdk/client-pi-browser", - version: "^0.1.0-preview.3" - }, - "client-pinpoint-browser": { - package: "@aws-sdk/client-pinpoint-browser", - version: "^0.1.0-preview.7" - }, - "client-pinpoint-email-browser": { - package: "@aws-sdk/client-pinpoint-email-browser", - version: "^0.1.0-preview.3" - }, - "client-pinpoint-sms-voice-browser": { - package: "@aws-sdk/client-pinpoint-sms-voice-browser", - version: "^0.1.0-preview.3" - }, - "client-polly-browser": { - package: "@aws-sdk/client-polly-browser", - version: "^0.1.0-preview.3" - }, - "client-pricing-browser": { - package: "@aws-sdk/client-pricing-browser", - version: "^0.1.0-preview.3" - }, - "client-quicksight-browser": { - package: "@aws-sdk/client-quicksight-browser", - version: "^0.1.0-preview.3" - }, - "client-ram-browser": { - package: "@aws-sdk/client-ram-browser", - version: "^0.1.0-preview.3" - }, - "client-rds-browser": { - package: "@aws-sdk/client-rds-browser", - version: "^0.1.0-preview.3" - }, - "client-rds-data-browser": { - package: "@aws-sdk/client-rds-data-browser", - version: "^0.1.0-preview.3" - }, - "client-redshift-browser": { - package: "@aws-sdk/client-redshift-browser", - version: "^0.1.0-preview.3" - }, - "client-rekognition-browser": { - package: "@aws-sdk/client-rekognition-browser", - version: "^0.1.0-preview.3" - }, - "client-resource-groups-browser": { - package: "@aws-sdk/client-resource-groups-browser", - version: "^0.1.0-preview.3" - }, - "client-resource-groups-tagging-api-browser": { - package: "@aws-sdk/client-resource-groups-tagging-api-browser", - version: "^0.1.0-preview.3" - }, - "client-robomaker-browser": { - package: "@aws-sdk/client-robomaker-browser", - version: "^0.1.0-preview.3" - }, - "client-route-53-browser": { - package: "@aws-sdk/client-route-53-browser", - version: "^0.1.0-preview.3" - }, - "client-route-53-domains-browser": { - package: "@aws-sdk/client-route-53-domains-browser", - version: "^0.1.0-preview.3" - }, - "client-route53resolver-browser": { - package: "@aws-sdk/client-route53resolver-browser", - version: "^0.1.0-preview.3" - }, - "client-s3-browser": { - package: "@aws-sdk/client-s3-browser", - version: "^0.1.0-preview.4" - }, - "client-s3-control-browser": { - package: "@aws-sdk/client-s3-control-browser", - version: "^0.1.0-preview.3" - }, - "client-sagemaker-browser": { - package: "@aws-sdk/client-sagemaker-browser", - version: "^0.1.0-preview.3" - }, - "client-sagemaker-runtime-browser": { - package: "@aws-sdk/client-sagemaker-runtime-browser", - version: "^0.1.0-preview.3" - }, - "client-secrets-manager-browser": { - package: "@aws-sdk/client-secrets-manager-browser", - version: "^0.1.0-preview.3" - }, - "client-securityhub-browser": { - package: "@aws-sdk/client-securityhub-browser", - version: "^0.1.0-preview.3" - }, - "client-serverlessapplicationrepository-browser": { - package: "@aws-sdk/client-serverlessapplicationrepository-browser", - version: "^0.1.0-preview.3" - }, - "client-service-catalog-browser": { - package: "@aws-sdk/client-service-catalog-browser", - version: "^0.1.0-preview.3" - }, - "client-service-quotas-browser": { - package: "@aws-sdk/client-service-quotas-browser", - version: "^0.1.0-preview.3" - }, - "client-servicediscovery-browser": { - package: "@aws-sdk/client-servicediscovery-browser", - version: "^0.1.0-preview.3" - }, - "client-ses-browser": { - package: "@aws-sdk/client-ses-browser", - version: "^0.1.0-preview.3" - }, - "client-sfn-browser": { - package: "@aws-sdk/client-sfn-browser", - version: "^0.1.0-preview.3" - }, - "client-shield-browser": { - package: "@aws-sdk/client-shield-browser", - version: "^0.1.0-preview.3" - }, - "client-signer-browser": { - package: "@aws-sdk/client-signer-browser", - version: "^0.1.0-preview.3" - }, - "client-sms-browser": { - package: "@aws-sdk/client-sms-browser", - version: "^0.1.0-preview.3" - }, - "client-snowball-browser": { - package: "@aws-sdk/client-snowball-browser", - version: "^0.1.0-preview.3" - }, - "client-sns-browser": { - package: "@aws-sdk/client-sns-browser", - version: "^0.1.0-preview.3" - }, - "client-sqs-browser": { - package: "@aws-sdk/client-sqs-browser", - version: "^0.1.0-preview.3" - }, - "client-ssm-browser": { - package: "@aws-sdk/client-ssm-browser", - version: "^0.1.0-preview.3" - }, - "client-storage-gateway-browser": { - package: "@aws-sdk/client-storage-gateway-browser", - version: "^0.1.0-preview.3" - }, - "client-sts-browser": { - package: "@aws-sdk/client-sts-browser", - version: "^0.1.0-preview.3" - }, - "client-support-browser": { - package: "@aws-sdk/client-support-browser", - version: "^0.1.0-preview.3" - }, - "client-swf-browser": { - package: "@aws-sdk/client-swf-browser", - version: "^0.1.0-preview.3" - }, - "client-textract-browser": { - package: "@aws-sdk/client-textract-browser", - version: "^0.1.0-preview.3" - }, - "client-transcribe-browser": { - package: "@aws-sdk/client-transcribe-browser", - version: "^0.1.0-preview.3" - }, - "client-transfer-browser": { - package: "@aws-sdk/client-transfer-browser", - version: "^0.1.0-preview.3" - }, - "client-translate-browser": { - package: "@aws-sdk/client-translate-browser", - version: "^0.1.0-preview.3" - }, - "client-waf-browser": { - package: "@aws-sdk/client-waf-browser", - version: "^0.1.0-preview.3" - }, - "client-waf-regional-browser": { - package: "@aws-sdk/client-waf-regional-browser", - version: "^0.1.0-preview.3" - }, - "client-workdocs-browser": { - package: "@aws-sdk/client-workdocs-browser", - version: "^0.1.0-preview.3" - }, - "client-worklink-browser": { - package: "@aws-sdk/client-worklink-browser", - version: "^0.1.0-preview.3" - }, - "client-workmail-browser": { - package: "@aws-sdk/client-workmail-browser", - version: "^0.1.0-preview.3" - }, - "client-workspaces-browser": { - package: "@aws-sdk/client-workspaces-browser", - version: "^0.1.0-preview.3" - }, - "client-xray-browser": { - package: "@aws-sdk/client-xray-browser", - version: "^0.1.0-preview.3" - }, - "client-acm-node": { - package: "@aws-sdk/client-acm-node", - version: "^0.1.0-preview.3" - }, - "client-acm-pca-node": { - package: "@aws-sdk/client-acm-pca-node", - version: "^0.1.0-preview.3" - }, - "client-alexa-for-business-node": { - package: "@aws-sdk/client-alexa-for-business-node", - version: "^0.1.0-preview.3" - }, - "client-amplify-node": { - package: "@aws-sdk/client-amplify-node", - version: "^0.1.0-preview.3" - }, - "client-api-gateway-node": { - package: "@aws-sdk/client-api-gateway-node", - version: "^0.1.0-preview.3" - }, - "client-apigatewaymanagementapi-node": { - package: "@aws-sdk/client-apigatewaymanagementapi-node", - version: "^0.1.0-preview.3" - }, - "client-apigatewayv2-node": { - package: "@aws-sdk/client-apigatewayv2-node", - version: "^0.1.0-preview.3" - }, - "client-app-mesh-node": { - package: "@aws-sdk/client-app-mesh-node", - version: "^0.1.0-preview.3" - }, - "client-application-auto-scaling-node": { - package: "@aws-sdk/client-application-auto-scaling-node", - version: "^0.1.0-preview.3" - }, - "client-application-discovery-service-node": { - package: "@aws-sdk/client-application-discovery-service-node", - version: "^0.1.0-preview.3" - }, - "client-application-insights-node": { - package: "@aws-sdk/client-application-insights-node", - version: "^0.1.0-preview.3" - }, - "client-appstream-node": { - package: "@aws-sdk/client-appstream-node", - version: "^0.1.0-preview.3" - }, - "client-appsync-node": { - package: "@aws-sdk/client-appsync-node", - version: "^0.1.0-preview.3" - }, - "client-athena-node": { - package: "@aws-sdk/client-athena-node", - version: "^0.1.0-preview.3" - }, - "client-auto-scaling-node": { - package: "@aws-sdk/client-auto-scaling-node", - version: "^0.1.0-preview.3" - }, - "client-auto-scaling-plans-node": { - package: "@aws-sdk/client-auto-scaling-plans-node", - version: "^0.1.0-preview.3" - }, - "client-backup-node": { - package: "@aws-sdk/client-backup-node", - version: "^0.1.0-preview.3" - }, - "client-batch-node": { - package: "@aws-sdk/client-batch-node", - version: "^0.1.0-preview.3" - }, - "client-budgets-node": { - package: "@aws-sdk/client-budgets-node", - version: "^0.1.0-preview.3" - }, - "client-chime-node": { - package: "@aws-sdk/client-chime-node", - version: "^0.1.0-preview.3" - }, - "client-cloud9-node": { - package: "@aws-sdk/client-cloud9-node", - version: "^0.1.0-preview.3" - }, - "client-clouddirectory-node": { - package: "@aws-sdk/client-clouddirectory-node", - version: "^0.1.0-preview.3" - }, - "client-cloudformation-node": { - package: "@aws-sdk/client-cloudformation-node", - version: "^0.1.0-preview.3" - }, - "client-cloudfront-node": { - package: "@aws-sdk/client-cloudfront-node", - version: "^0.1.0-preview.3" - }, - "client-cloudhsm-node": { - package: "@aws-sdk/client-cloudhsm-node", - version: "^0.1.0-preview.3" - }, - "client-cloudhsm-v2-node": { - package: "@aws-sdk/client-cloudhsm-v2-node", - version: "^0.1.0-preview.3" - }, - "client-cloudsearch-domain-node": { - package: "@aws-sdk/client-cloudsearch-domain-node", - version: "^0.1.0-preview.3" - }, - "client-cloudsearch-node": { - package: "@aws-sdk/client-cloudsearch-node", - version: "^0.1.0-preview.3" - }, - "client-cloudtrail-node": { - package: "@aws-sdk/client-cloudtrail-node", - version: "^0.1.0-preview.3" - }, - "client-cloudwatch-events-node": { - package: "@aws-sdk/client-cloudwatch-events-node", - version: "^0.1.0-preview.3" - }, - "client-cloudwatch-logs-node": { - package: "@aws-sdk/client-cloudwatch-logs-node", - version: "^0.1.0-preview.3" - }, - "client-cloudwatch-node": { - package: "@aws-sdk/client-cloudwatch-node", - version: "^0.1.0-preview.3" - }, - "client-codebuild-node": { - package: "@aws-sdk/client-codebuild-node", - version: "^0.1.0-preview.3" - }, - "client-codecommit-node": { - package: "@aws-sdk/client-codecommit-node", - version: "^0.1.0-preview.7" - }, - "client-codedeploy-node": { - package: "@aws-sdk/client-codedeploy-node", - version: "^0.1.0-preview.3" - }, - "client-codepipeline-node": { - package: "@aws-sdk/client-codepipeline-node", - version: "^0.1.0-preview.3" - }, - "client-codestar-node": { - package: "@aws-sdk/client-codestar-node", - version: "^0.1.0-preview.3" - }, - "client-cognito-identity-node": { - package: "@aws-sdk/client-cognito-identity-node", - version: "^0.1.0-preview.3" - }, - "client-cognito-identity-provider-node": { - package: "@aws-sdk/client-cognito-identity-provider-node", - version: "^0.1.0-preview.3" - }, - "client-cognito-sync-node": { - package: "@aws-sdk/client-cognito-sync-node", - version: "^0.1.0-preview.3" - }, - "client-comprehend-node": { - package: "@aws-sdk/client-comprehend-node", - version: "^0.1.0-preview.3" - }, - "client-comprehendmedical-node": { - package: "@aws-sdk/client-comprehendmedical-node", - version: "^0.1.0-preview.3" - }, - "client-config-service-node": { - package: "@aws-sdk/client-config-service-node", - version: "^0.1.0-preview.3" - }, - "client-connect-node": { - package: "@aws-sdk/client-connect-node", - version: "^0.1.0-preview.3" - }, - "client-cost-and-usage-report-service-node": { - package: "@aws-sdk/client-cost-and-usage-report-service-node", - version: "^0.1.0-preview.3" - }, - "client-cost-explorer-node": { - package: "@aws-sdk/client-cost-explorer-node", - version: "^0.1.0-preview.3" - }, - "client-data-pipeline-node": { - package: "@aws-sdk/client-data-pipeline-node", - version: "^0.1.0-preview.3" - }, - "client-database-migration-service-node": { - package: "@aws-sdk/client-database-migration-service-node", - version: "^0.1.0-preview.3" - }, - "client-datasync-node": { - package: "@aws-sdk/client-datasync-node", - version: "^0.1.0-preview.3" - }, - "client-dax-node": { - package: "@aws-sdk/client-dax-node", - version: "^0.1.0-preview.3" - }, - "client-device-farm-node": { - package: "@aws-sdk/client-device-farm-node", - version: "^0.1.0-preview.3" - }, - "client-direct-connect-node": { - package: "@aws-sdk/client-direct-connect-node", - version: "^0.1.0-preview.3" - }, - "client-directory-service-node": { - package: "@aws-sdk/client-directory-service-node", - version: "^0.1.0-preview.3" - }, - "client-dlm-node": { - package: "@aws-sdk/client-dlm-node", - version: "^0.1.0-preview.3" - }, - "client-docdb-node": { - package: "@aws-sdk/client-docdb-node", - version: "^0.1.0-preview.3" - }, - "client-dynamodb-node": { - package: "@aws-sdk/client-dynamodb-node", - version: "^0.1.0-preview.6" - }, - "client-dynamodb-streams-node": { - package: "@aws-sdk/client-dynamodb-streams-node", - version: "^0.1.0-preview.3" - }, - "client-ec2-instance-connect-node": { - package: "@aws-sdk/client-ec2-instance-connect-node", - version: "^0.1.0-preview.3" - }, - "client-ec2-node": { - package: "@aws-sdk/client-ec2-node", - version: "^0.1.0-preview.3" - }, - "client-ecr-node": { - package: "@aws-sdk/client-ecr-node", - version: "^0.1.0-preview.3" - }, - "client-ecs-node": { - package: "@aws-sdk/client-ecs-node", - version: "^0.1.0-preview.3" - }, - "client-efs-node": { - package: "@aws-sdk/client-efs-node", - version: "^0.1.0-preview.3" - }, - "client-eks-node": { - package: "@aws-sdk/client-eks-node", - version: "^0.1.0-preview.3" - }, - "client-elastic-beanstalk-node": { - package: "@aws-sdk/client-elastic-beanstalk-node", - version: "^0.1.0-preview.3" - }, - "client-elastic-load-balancing-node": { - package: "@aws-sdk/client-elastic-load-balancing-node", - version: "^0.1.0-preview.3" - }, - "client-elastic-load-balancing-v2-node": { - package: "@aws-sdk/client-elastic-load-balancing-v2-node", - version: "^0.1.0-preview.3" - }, - "client-elastic-transcoder-node": { - package: "@aws-sdk/client-elastic-transcoder-node", - version: "^0.1.0-preview.3" - }, - "client-elasticache-node": { - package: "@aws-sdk/client-elasticache-node", - version: "^0.1.0-preview.3" - }, - "client-elasticsearch-service-node": { - package: "@aws-sdk/client-elasticsearch-service-node", - version: "^0.1.0-preview.3" - }, - "client-emr-node": { - package: "@aws-sdk/client-emr-node", - version: "^0.1.0-preview.3" - }, - "client-eventbridge-node": { - package: "@aws-sdk/client-eventbridge-node", - version: "^0.1.0-preview.3" - }, - "client-firehose-node": { - package: "@aws-sdk/client-firehose-node", - version: "^0.1.0-preview.3" - }, - "client-fms-node": { - package: "@aws-sdk/client-fms-node", - version: "^0.1.0-preview.3" - }, - "client-fsx-node": { - package: "@aws-sdk/client-fsx-node", - version: "^0.1.0-preview.3" - }, - "client-gamelift-node": { - package: "@aws-sdk/client-gamelift-node", - version: "^0.1.0-preview.3" - }, - "client-glacier-node": { - package: "@aws-sdk/client-glacier-node", - version: "^0.1.0-preview.8" - }, - "client-global-accelerator-node": { - package: "@aws-sdk/client-global-accelerator-node", - version: "^0.1.0-preview.3" - }, - "client-glue-node": { - package: "@aws-sdk/client-glue-node", - version: "^0.1.0-preview.3" - }, - "client-greengrass-node": { - package: "@aws-sdk/client-greengrass-node", - version: "^0.1.0-preview.3" - }, - "client-groundstation-node": { - package: "@aws-sdk/client-groundstation-node", - version: "^0.1.0-preview.3" - }, - "client-guardduty-node": { - package: "@aws-sdk/client-guardduty-node", - version: "^0.1.0-preview.3" - }, - "client-health-node": { - package: "@aws-sdk/client-health-node", - version: "^0.1.0-preview.3" - }, - "client-iam-node": { - package: "@aws-sdk/client-iam-node", - version: "^0.1.0-preview.3" - }, - "client-inspector-node": { - package: "@aws-sdk/client-inspector-node", - version: "^0.1.0-preview.3" - }, - "client-iot-1click-devices-service-node": { - package: "@aws-sdk/client-iot-1click-devices-service-node", - version: "^0.1.0-preview.3" - }, - "client-iot-1click-projects-node": { - package: "@aws-sdk/client-iot-1click-projects-node", - version: "^0.1.0-preview.3" - }, - "client-iot-data-plane-node": { - package: "@aws-sdk/client-iot-data-plane-node", - version: "^0.1.0-preview.3" - }, - "client-iot-events-data-node": { - package: "@aws-sdk/client-iot-events-data-node", - version: "^0.1.0-preview.3" - }, - "client-iot-events-node": { - package: "@aws-sdk/client-iot-events-node", - version: "^0.1.0-preview.3" - }, - "client-iot-jobs-data-plane-node": { - package: "@aws-sdk/client-iot-jobs-data-plane-node", - version: "^0.1.0-preview.3" - }, - "client-iot-node": { - package: "@aws-sdk/client-iot-node", - version: "^0.1.0-preview.3" - }, - "client-iotanalytics-node": { - package: "@aws-sdk/client-iotanalytics-node", - version: "^0.1.0-preview.3" - }, - "client-iotthingsgraph-node": { - package: "@aws-sdk/client-iotthingsgraph-node", - version: "^0.1.0-preview.3" - }, - "client-kafka-node": { - package: "@aws-sdk/client-kafka-node", - version: "^0.1.0-preview.3" - }, - "client-kinesis-analytics-node": { - package: "@aws-sdk/client-kinesis-analytics-node", - version: "^0.1.0-preview.3" - }, - "client-kinesis-analytics-v2-node": { - package: "@aws-sdk/client-kinesis-analytics-v2-node", - version: "^0.1.0-preview.3" - }, - "client-kinesis-node": { - package: "@aws-sdk/client-kinesis-node", - version: "^0.1.0-preview.3" - }, - "client-kinesis-video-archived-media-node": { - package: "@aws-sdk/client-kinesis-video-archived-media-node", - version: "^0.1.0-preview.3" - }, - "client-kinesis-video-media-node": { - package: "@aws-sdk/client-kinesis-video-media-node", - version: "^0.1.0-preview.3" - }, - "client-kinesis-video-node": { - package: "@aws-sdk/client-kinesis-video-node", - version: "^0.1.0-preview.3" - }, - "client-kms-node": { - package: "@aws-sdk/client-kms-node", - version: "^0.1.0-preview.6" - }, - "client-lambda-node": { - package: "@aws-sdk/client-lambda-node", - version: "^0.1.0-preview.8" - }, - "client-lex-model-building-service-node": { - package: "@aws-sdk/client-lex-model-building-service-node", - version: "^0.1.0-preview.3" - }, - "client-lex-runtime-service-node": { - package: "@aws-sdk/client-lex-runtime-service-node", - version: "^0.1.0-preview.3" - }, - "client-license-manager-node": { - package: "@aws-sdk/client-license-manager-node", - version: "^0.1.0-preview.3" - }, - "client-lightsail-node": { - package: "@aws-sdk/client-lightsail-node", - version: "^0.1.0-preview.3" - }, - "client-machine-learning-node": { - package: "@aws-sdk/client-machine-learning-node", - version: "^0.1.0-preview.3" - }, - "client-macie-node": { - package: "@aws-sdk/client-macie-node", - version: "^0.1.0-preview.3" - }, - "client-managedblockchain-node": { - package: "@aws-sdk/client-managedblockchain-node", - version: "^0.1.0-preview.3" - }, - "client-marketplace-commerce-analytics-node": { - package: "@aws-sdk/client-marketplace-commerce-analytics-node", - version: "^0.1.0-preview.3" - }, - "client-marketplace-entitlement-service-node": { - package: "@aws-sdk/client-marketplace-entitlement-service-node", - version: "^0.1.0-preview.3" - }, - "client-marketplace-metering-node": { - package: "@aws-sdk/client-marketplace-metering-node", - version: "^0.1.0-preview.3" - }, - "client-mediaconnect-node": { - package: "@aws-sdk/client-mediaconnect-node", - version: "^0.1.0-preview.3" - }, - "client-mediaconvert-node": { - package: "@aws-sdk/client-mediaconvert-node", - version: "^0.1.0-preview.3" - }, - "client-medialive-node": { - package: "@aws-sdk/client-medialive-node", - version: "^0.1.0-preview.3" - }, - "client-mediapackage-node": { - package: "@aws-sdk/client-mediapackage-node", - version: "^0.1.0-preview.3" - }, - "client-mediapackage-vod-node": { - package: "@aws-sdk/client-mediapackage-vod-node", - version: "^0.1.0-preview.3" - }, - "client-mediastore-data-node": { - package: "@aws-sdk/client-mediastore-data-node", - version: "^0.1.0-preview.3" - }, - "client-mediastore-node": { - package: "@aws-sdk/client-mediastore-node", - version: "^0.1.0-preview.3" - }, - "client-mediatailor-node": { - package: "@aws-sdk/client-mediatailor-node", - version: "^0.1.0-preview.3" - }, - "client-migration-hub-node": { - package: "@aws-sdk/client-migration-hub-node", - version: "^0.1.0-preview.3" - }, - "client-mobile-node": { - package: "@aws-sdk/client-mobile-node", - version: "^0.1.0-preview.3" - }, - "client-mq-node": { - package: "@aws-sdk/client-mq-node", - version: "^0.1.0-preview.3" - }, - "client-mturk-node": { - package: "@aws-sdk/client-mturk-node", - version: "^0.1.0-preview.3" - }, - "client-neptune-node": { - package: "@aws-sdk/client-neptune-node", - version: "^0.1.0-preview.3" - }, - "client-opsworks-node": { - package: "@aws-sdk/client-opsworks-node", - version: "^0.1.0-preview.3" - }, - "client-opsworkscm-node": { - package: "@aws-sdk/client-opsworkscm-node", - version: "^0.1.0-preview.3" - }, - "client-organizations-node": { - package: "@aws-sdk/client-organizations-node", - version: "^0.1.0-preview.3" - }, - "client-personalize-events-node": { - package: "@aws-sdk/client-personalize-events-node", - version: "^0.1.0-preview.3" - }, - "client-personalize-node": { - package: "@aws-sdk/client-personalize-node", - version: "^0.1.0-preview.3" - }, - "client-personalize-runtime-node": { - package: "@aws-sdk/client-personalize-runtime-node", - version: "^0.1.0-preview.3" - }, - "client-pi-node": { - package: "@aws-sdk/client-pi-node", - version: "^0.1.0-preview.3" - }, - "client-pinpoint-email-node": { - package: "@aws-sdk/client-pinpoint-email-node", - version: "^0.1.0-preview.3" - }, - "client-pinpoint-node": { - package: "@aws-sdk/client-pinpoint-node", - version: "^0.1.0-preview.3" - }, - "client-pinpoint-sms-voice-node": { - package: "@aws-sdk/client-pinpoint-sms-voice-node", - version: "^0.1.0-preview.3" - }, - "client-polly-node": { - package: "@aws-sdk/client-polly-node", - version: "^0.1.0-preview.3" - }, - "client-pricing-node": { - package: "@aws-sdk/client-pricing-node", - version: "^0.1.0-preview.3" - }, - "client-quicksight-node": { - package: "@aws-sdk/client-quicksight-node", - version: "^0.1.0-preview.3" - }, - "client-ram-node": { - package: "@aws-sdk/client-ram-node", - version: "^0.1.0-preview.3" - }, - "client-rds-data-node": { - package: "@aws-sdk/client-rds-data-node", - version: "^0.1.0-preview.3" - }, - "client-rds-node": { - package: "@aws-sdk/client-rds-node", - version: "^0.1.0-preview.3" - }, - "client-redshift-node": { - package: "@aws-sdk/client-redshift-node", - version: "^0.1.0-preview.3" - }, - "client-rekognition-node": { - package: "@aws-sdk/client-rekognition-node", - version: "^0.1.0-preview.3" - }, - "client-resource-groups-node": { - package: "@aws-sdk/client-resource-groups-node", - version: "^0.1.0-preview.3" - }, - "client-resource-groups-tagging-api-node": { - package: "@aws-sdk/client-resource-groups-tagging-api-node", - version: "^0.1.0-preview.3" - }, - "client-robomaker-node": { - package: "@aws-sdk/client-robomaker-node", - version: "^0.1.0-preview.3" - }, - "client-route-53-domains-node": { - package: "@aws-sdk/client-route-53-domains-node", - version: "^0.1.0-preview.3" - }, - "client-route-53-node": { - package: "@aws-sdk/client-route-53-node", - version: "^0.1.0-preview.3" - }, - "client-route53resolver-node": { - package: "@aws-sdk/client-route53resolver-node", - version: "^0.1.0-preview.3" - }, - "client-s3-control-node": { - package: "@aws-sdk/client-s3-control-node", - version: "^0.1.0-preview.3" - }, - "client-s3-node": { - package: "@aws-sdk/client-s3-node", - version: "^0.1.0-preview.4" - }, - "client-sagemaker-node": { - package: "@aws-sdk/client-sagemaker-node", - version: "^0.1.0-preview.3" - }, - "client-sagemaker-runtime-node": { - package: "@aws-sdk/client-sagemaker-runtime-node", - version: "^0.1.0-preview.3" - }, - "client-secrets-manager-node": { - package: "@aws-sdk/client-secrets-manager-node", - version: "^0.1.0-preview.3" - }, - "client-securityhub-node": { - package: "@aws-sdk/client-securityhub-node", - version: "^0.1.0-preview.3" - }, - "client-serverlessapplicationrepository-node": { - package: "@aws-sdk/client-serverlessapplicationrepository-node", - version: "^0.1.0-preview.3" - }, - "client-service-catalog-node": { - package: "@aws-sdk/client-service-catalog-node", - version: "^0.1.0-preview.3" - }, - "client-service-quotas-node": { - package: "@aws-sdk/client-service-quotas-node", - version: "^0.1.0-preview.3" - }, - "client-servicediscovery-node": { - package: "@aws-sdk/client-servicediscovery-node", - version: "^0.1.0-preview.3" - }, - "client-ses-node": { - package: "@aws-sdk/client-ses-node", - version: "^0.1.0-preview.3" - }, - "client-sfn-node": { - package: "@aws-sdk/client-sfn-node", - version: "^0.1.0-preview.3" - }, - "client-shield-node": { - package: "@aws-sdk/client-shield-node", - version: "^0.1.0-preview.3" - }, - "client-signer-node": { - package: "@aws-sdk/client-signer-node", - version: "^0.1.0-preview.3" - }, - "client-sms-node": { - package: "@aws-sdk/client-sms-node", - version: "^0.1.0-preview.3" - }, - "client-snowball-node": { - package: "@aws-sdk/client-snowball-node", - version: "^0.1.0-preview.3" - }, - "client-sns-node": { - package: "@aws-sdk/client-sns-node", - version: "^0.1.0-preview.3" - }, - "client-sqs-node": { - package: "@aws-sdk/client-sqs-node", - version: "^0.1.0-preview.8" - }, - "client-ssm-node": { - package: "@aws-sdk/client-ssm-node", - version: "^0.1.0-preview.3" - }, - "client-storage-gateway-node": { - package: "@aws-sdk/client-storage-gateway-node", - version: "^0.1.0-preview.3" - }, - "client-sts-node": { - package: "@aws-sdk/client-sts-node", - version: "^0.1.0-preview.3" - }, - "client-support-node": { - package: "@aws-sdk/client-support-node", - version: "^0.1.0-preview.3" - }, - "client-swf-node": { - package: "@aws-sdk/client-swf-node", - version: "^0.1.0-preview.3" - }, - "client-textract-node": { - package: "@aws-sdk/client-textract-node", - version: "^0.1.0-preview.3" - }, - "client-transcribe-node": { - package: "@aws-sdk/client-transcribe-node", - version: "^0.1.0-preview.3" - }, - "client-transfer-node": { - package: "@aws-sdk/client-transfer-node", - version: "^0.1.0-preview.3" - }, - "client-translate-node": { - package: "@aws-sdk/client-translate-node", - version: "^0.1.0-preview.3" - }, - "client-waf-node": { - package: "@aws-sdk/client-waf-node", - version: "^0.1.0-preview.3" - }, - "client-waf-regional-node": { - package: "@aws-sdk/client-waf-regional-node", - version: "^0.1.0-preview.3" - }, - "client-workdocs-node": { - package: "@aws-sdk/client-workdocs-node", - version: "^0.1.0-preview.3" - }, - "client-worklink-node": { - package: "@aws-sdk/client-worklink-node", - version: "^0.1.0-preview.3" - }, - "client-workmail-node": { - package: "@aws-sdk/client-workmail-node", - version: "^0.1.0-preview.3" - }, - "client-workspaces-node": { - package: "@aws-sdk/client-workspaces-node", - version: "^0.1.0-preview.3" - }, - "client-xray-node": { - package: "@aws-sdk/client-xray-node", - version: "^0.1.0-preview.8" } }; diff --git a/packages/signing-middleware/package.json b/packages/signing-middleware/package.json index 796b74e945c5..911a26e27eee 100644 --- a/packages/signing-middleware/package.json +++ b/packages/signing-middleware/package.json @@ -21,6 +21,7 @@ "dependencies": { "@aws-sdk/signature-v4": "^0.1.0-preview.7", "@aws-sdk/types": "^0.1.0-preview.5", + "@aws-sdk/protocol-http": "^0.1.0-preview.1", "tslib": "^1.8.0" } } diff --git a/packages/signing-middleware/src/configurations.ts b/packages/signing-middleware/src/configurations.ts new file mode 100644 index 000000000000..f95063d33c7d --- /dev/null +++ b/packages/signing-middleware/src/configurations.ts @@ -0,0 +1,68 @@ +import { + RequestSigner, + Credentials, + Provider, + HashConstructor +} from "@aws-sdk/types"; +import { SignatureV4 } from "@aws-sdk/signature-v4"; + +export namespace AwsAuthConfiguration { + export interface Input { + /** + * The credentials used to sign requests. + */ + credentials?: Credentials | Provider; + + /** + * The signer to use when signing requests. + */ + signer?: RequestSigner; + + /** + * Whether to escape request path when signing the request + */ + signingEscapePath?: boolean; + } + interface PreviouslyResolved { + credentialDefaultProvider: (input: any) => Provider; + region: string | Provider; + signingName: string; + sha256: HashConstructor; + } + export interface Resolved { + credentials: Provider; + signer: RequestSigner; + signingEscapePath: boolean; + } + export function resolve( + input: T & Input & PreviouslyResolved + ): T & Resolved { + let credentials = + input.credentials || input.credentialDefaultProvider(input as any); + const normalizedCreds = normalizeProvider(credentials); + const signingEscapePath = input.signingEscapePath || false; + return { + ...input, + signingEscapePath, + credentials: normalizedCreds, + signer: new SignatureV4({ + credentials: normalizedCreds, + region: input.region, + service: input.signingName, + sha256: input.sha256, + uriEscapePath: signingEscapePath + }) + }; + } +} + +//export separately for showing comment block in Intellisense +export type AwsAuthConfigurationInput = AwsAuthConfiguration.Input; + +function normalizeProvider(input: T | Provider): Provider { + if (typeof input === "object") { + const promisified = Promise.resolve(input); + return () => promisified; + } + return input as Provider; +} diff --git a/packages/signing-middleware/src/index.ts b/packages/signing-middleware/src/index.ts index 81d6d868a9b4..ef4de14542fe 100644 --- a/packages/signing-middleware/src/index.ts +++ b/packages/signing-middleware/src/index.ts @@ -1,23 +1,2 @@ -import { - FinalizeHandler, - FinalizeHandlerArguments, - FinalizeMiddleware, - RequestSigner, - FinalizeHandlerOutput, - HttpRequest -} from "@aws-sdk/types"; - -export function signingMiddleware( - signer: RequestSigner -): FinalizeMiddleware { - return ( - next: FinalizeHandler - ): FinalizeHandler => async ( - args: FinalizeHandlerArguments - ): Promise> => - //TODO: check if request is HttpRequest instance - next({ - ...args, - request: await signer.sign(args.request as HttpRequest) - }); -} +export * from "./configurations"; +export * from "./middleware"; diff --git a/packages/signing-middleware/src/index.spec.ts b/packages/signing-middleware/src/middleware.spec.ts similarity index 69% rename from packages/signing-middleware/src/index.spec.ts rename to packages/signing-middleware/src/middleware.spec.ts index f50cf2ad883b..6f7fce67cd8b 100644 --- a/packages/signing-middleware/src/index.spec.ts +++ b/packages/signing-middleware/src/middleware.spec.ts @@ -1,5 +1,6 @@ -import { signingMiddleware } from "./"; -import { Handler, RequestSigner, HttpRequest } from "@aws-sdk/types"; +import { signingMiddleware } from "./middleware"; +import { RequestSigner } from "@aws-sdk/types"; +import { HttpRequest } from '@aws-sdk/protocol-http'; describe("SigningHandler", () => { const noOpSigner: RequestSigner = { @@ -19,12 +20,12 @@ describe("SigningHandler", () => { }); it("should sign the request and pass it to the next handler", async () => { - const signingHandler = signingMiddleware(noOpSigner)(noOpNext, {} as any); + const signingHandler = signingMiddleware({ signer: noOpSigner } as any)(noOpNext, {} as any); await signingHandler({ input: {}, - request: { + request: new HttpRequest({ headers: {} - } as any + }) }); const { calls } = (noOpNext as any).mock; diff --git a/packages/signing-middleware/src/middleware.ts b/packages/signing-middleware/src/middleware.ts new file mode 100644 index 000000000000..bbcd92ae58a0 --- /dev/null +++ b/packages/signing-middleware/src/middleware.ts @@ -0,0 +1,36 @@ +import { + FinalizeHandler, + FinalizeHandlerArguments, + FinalizeRequestMiddleware, + FinalizeHandlerOutput, + InjectableMiddleware +} from "@aws-sdk/types"; +import { AwsAuthConfiguration } from "./configurations"; +import { HttpRequest } from "@aws-sdk/protocol-http"; + +export function signingMiddleware( + options: AwsAuthConfiguration.Resolved +): FinalizeRequestMiddleware { + return ( + next: FinalizeHandler + ): FinalizeHandler => + async function( + args: FinalizeHandlerArguments + ): Promise> { + if (!HttpRequest.isInstance(args.request)) return next(args); + return next({ + ...args, + request: await options.signer.sign(args.request) + }); + }; +} + +export function signingPlugin( + options: AwsAuthConfiguration.Resolved +): InjectableMiddleware { + return { + middleware: signingMiddleware(options), + step: "finalizeRequest", + tags: { SIGNATURE: true } + }; +} diff --git a/packages/smithy-client/.gitignore b/packages/smithy-client/.gitignore new file mode 100644 index 000000000000..3d1714c9806e --- /dev/null +++ b/packages/smithy-client/.gitignore @@ -0,0 +1,8 @@ +/node_modules/ +/build/ +/coverage/ +/docs/ +*.tsbuildinfo +*.tgz +*.log +package-lock.json diff --git a/packages/smithy-client/.npmignore b/packages/smithy-client/.npmignore new file mode 100644 index 000000000000..4b9fe3abf33a --- /dev/null +++ b/packages/smithy-client/.npmignore @@ -0,0 +1,13 @@ +/src/ +/coverage/ +/docs/ +tsconfig.test.json +*.tsbuildinfo + +*.spec.js +*.spec.d.ts +*.spec.js.map + +*.fixture.js +*.fixture.d.ts +*.fixture.js.map diff --git a/packages/smithy-client/LICENSE b/packages/smithy-client/LICENSE new file mode 100644 index 000000000000..e907b58668da --- /dev/null +++ b/packages/smithy-client/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/smithy-client/README.md b/packages/smithy-client/README.md new file mode 100644 index 000000000000..a0ef1a4d7005 --- /dev/null +++ b/packages/smithy-client/README.md @@ -0,0 +1,4 @@ +# @aws-sdk/@aws-sdk/smithy-client + +[![NPM version](https://img.shields.io/npm/v/@aws-sdk/@aws-sdk/smithy-client/preview.svg)](https://www.npmjs.com/package/@aws-sdk/@aws-sdk/smithy-client) +[![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/@aws-sdk/smithy-client.svg)](https://www.npmjs.com/package/@aws-sdk/@aws-sdk/smithy-client) diff --git a/packages/smithy-client/package.json b/packages/smithy-client/package.json new file mode 100644 index 000000000000..6b191621f979 --- /dev/null +++ b/packages/smithy-client/package.json @@ -0,0 +1,26 @@ +{ + "name": "@aws-sdk/smithy-client", + "version": "0.1.0-preview.1", + "scripts": { + "prepublishOnly": "tsc", + "pretest": "tsc -p tsconfig.test.json", + "test": "jest" + }, + "main": "./build/index.js", + "types": "./build/index.d.ts", + "author": { + "name": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^0.1.0-preview.5", + "@aws-sdk/middleware-stack": "^0.1.0-preview.6", + "tslib": "^1.8.0" + }, + "devDependencies": { + "@types/jest": "^24.0.12", + "typescript": "~3.4.0", + "jest": "^24.7.1" + } +} diff --git a/packages/smithy-client/src/client.ts b/packages/smithy-client/src/client.ts new file mode 100644 index 000000000000..683b33c1ef6d --- /dev/null +++ b/packages/smithy-client/src/client.ts @@ -0,0 +1,92 @@ +import { MiddlewareStack } from "@aws-sdk/middleware-stack"; +import { + Protocol, + Command, + MetadataBearer, + InjectableMiddleware, + HandlerOptions as InjectOptions +} from "@aws-sdk/types"; + +export interface SmithyConfiguration { + protocol: Protocol; +} + +export type SmithyResolvedConfiguration = SmithyConfiguration< + HandlerOptions +>; + +export class Client< + HandlerOptions = any, + ClientInput extends object = any, + ClientOutput extends MetadataBearer = any +> { + public middlewareStack = new MiddlewareStack(); + readonly config: SmithyResolvedConfiguration; + constructor(config: SmithyConfiguration) { + this.config = config; + } + use( + injectable: InjectableMiddleware, + options: InjectOptions = {} + ) { + const { middleware, step, priority, tags } = injectable; + this.middlewareStack.add( + // @ts-ignore -- Middleware and option type matching safety is enforced by InjectableMiddleware types + middleware, + { + step: options.step || step, + priority: options.priority || priority, + tags: { ...tags, ...options.tags } + } + ); + } + send( + command: Command< + ClientInput, + InputType, + ClientOutput, + OutputType, + SmithyResolvedConfiguration + >, + options?: HandlerOptions + ): Promise; + send( + command: Command< + ClientInput, + InputType, + ClientOutput, + OutputType, + SmithyResolvedConfiguration + >, + options: HandlerOptions, + cb: (err: any, data?: OutputType) => void + ): void; + send( + command: Command< + ClientInput, + InputType, + ClientOutput, + OutputType, + SmithyResolvedConfiguration + >, + options?: HandlerOptions, + cb?: (err: any, data?: OutputType) => void + ): Promise | void { + const handler = command.resolveMiddleware( + this.middlewareStack as any, + this.config, + options + ); + if (cb) { + handler(command) + .then(result => cb(null, result.output), (err: any) => cb(err)) + .catch( + // prevent any errors thrown in the callback from triggering an + // unhandled promise rejection + () => {} + ); + } else { + return handler(command).then(result => result.output); + } + } +} diff --git a/packages/smithy-client/src/command.ts b/packages/smithy-client/src/command.ts new file mode 100644 index 000000000000..2648c9eb0d74 --- /dev/null +++ b/packages/smithy-client/src/command.ts @@ -0,0 +1,24 @@ +import { MiddlewareStack } from "@aws-sdk/middleware-stack"; +import { + InjectableMiddleware, + HandlerOptions as InjectOptions +} from "@aws-sdk/types"; + +export class Command { + readonly middlewareStack = new MiddlewareStack(); + use( + injectable: InjectableMiddleware, + options: InjectOptions = {} + ) { + const { middleware, step, priority, tags } = injectable; + this.middlewareStack.add( + // @ts-ignore + middleware, + { + step: options.step || step, + priority: options.priority || priority, + tags: { ...tags, ...options.tags } + } + ); + } +} diff --git a/packages/smithy-client/src/index.ts b/packages/smithy-client/src/index.ts new file mode 100644 index 000000000000..2b06c3db3fa7 --- /dev/null +++ b/packages/smithy-client/src/index.ts @@ -0,0 +1,2 @@ +export * from "./client"; +export * from "./command"; diff --git a/packages/smithy-client/tsconfig.json b/packages/smithy-client/tsconfig.json new file mode 100644 index 000000000000..38b94cda274e --- /dev/null +++ b/packages/smithy-client/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es5", + "module": "commonjs", + "declaration": true, + "strict": true, + "sourceMap": true, + "downlevelIteration": true, + "importHelpers": true, + "noEmitHelpers": true, + "lib": [ + "es5", + "es2015.promise", + "es2015.collection", + "es2015.iterable", + "es2015.symbol.wellknown" + ], + "rootDir": "./src", + "outDir": "./build", + "incremental": true + } +} diff --git a/packages/smithy-client/tsconfig.test.json b/packages/smithy-client/tsconfig.test.json new file mode 100644 index 000000000000..17d0f1b7321f --- /dev/null +++ b/packages/smithy-client/tsconfig.test.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": false, + "inlineSourceMap": true, + "inlineSources": true, + "rootDir": "./src", + "outDir": "./build", + "incremental": true + } +} diff --git a/packages/stream-collector-browser/src/index.ts b/packages/stream-collector-browser/src/index.ts index 6c64d92624a8..690cd1643116 100644 --- a/packages/stream-collector-browser/src/index.ts +++ b/packages/stream-collector-browser/src/index.ts @@ -1,13 +1,12 @@ import { StreamCollector } from "@aws-sdk/types"; -export const streamCollector: StreamCollector = function streamCollector( +export const streamCollector: StreamCollector = ( stream: Blob -): Promise { - return new Promise((resolve, reject) => { +): Promise => + new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(new Uint8Array(reader.result as ArrayBuffer)); reader.onabort = () => reject(new Error("Read aborted")); reader.onerror = () => reject(reader.error); reader.readAsArrayBuffer(stream); }); -}; diff --git a/packages/stream-collector-node/src/index.ts b/packages/stream-collector-node/src/index.ts index 41bfa4cdd951..f21df2f75bc9 100644 --- a/packages/stream-collector-node/src/index.ts +++ b/packages/stream-collector-node/src/index.ts @@ -2,10 +2,10 @@ import { Readable } from "stream"; import { StreamCollector } from "@aws-sdk/types"; import { Collector } from "./collector"; -export const streamCollector: StreamCollector< - Readable -> = function streamCollector(stream): Promise { - return new Promise((resolve, reject) => { +export const streamCollector: StreamCollector = ( + stream: Readable +): Promise => + new Promise((resolve, reject) => { const collector = new Collector(); stream.pipe(collector); stream.on("error", err => { @@ -19,4 +19,3 @@ export const streamCollector: StreamCollector< resolve(bytes); }); }); -}; diff --git a/packages/types/src/client.ts b/packages/types/src/client.ts index e8f5f3798edd..dbff770e57e4 100644 --- a/packages/types/src/client.ts +++ b/packages/types/src/client.ts @@ -2,7 +2,7 @@ import { MiddlewareStack, Terminalware } from "./middleware"; import { Structure } from "./protocol"; import { Provider, Decoder, Encoder, UrlParser } from "./util"; // import { StreamCollector, ResponseParser } from "./unmarshaller"; -import { RequestSerializer } from "./marshaller"; +import { RequestSerializer } from "./serializer"; import { HttpEndpoint } from "./http"; import { TransferHandler } from "./transfer"; import { Command } from "./command"; @@ -43,19 +43,6 @@ export interface ConfigurationPropertyDefinition< normalize?: { (value: InputType, config: Partial): ResolvedType; }; - - /** - * A function that finalizes the value supplied and/or alters the client - * configuration or middleware stack in reaction to it. - */ - apply?: ConfigApplicator; -} - -export interface ConfigApplicator { - ( - config: FullConfiguration, - clientMiddlewareStack: MiddlewareStack - ): void; } /** @@ -149,20 +136,7 @@ interface InvokeFunction< * A general interface for service clients, idempotent to browser or node clients */ export interface AWSClient { - readonly config: ClientResolvedConfigurationBase; + // readonly config: ClientResolvedConfigurationBase; middlewareStack: MiddlewareStack; send: InvokeFunction; } - -export interface Injectable { - injectTo: (client: AWSClient) => AWSClient; -} - -export interface ClientPlugin< - ConfigType extends object, - ResolvedConfig = Required -> extends Injectable { - clientConfig: ConfigType; - resolvedClientConfig: ResolvedConfig; - middleware: Middleware; -} diff --git a/packages/types/src/deserializer.ts b/packages/types/src/deserializer.ts new file mode 100644 index 000000000000..bfd81f4404db --- /dev/null +++ b/packages/types/src/deserializer.ts @@ -0,0 +1,37 @@ +import { Decoder, Encoder } from "./util"; + +export interface StreamCollector { + /** + * A function that converts a stream into an array of bytes. + * + * @param stream The low-level native stream from browser or Nodejs runtime + */ + (stream: any): Promise; +} + +/** + * Response deserializer utils functions for AWS services + */ +export interface DeserializerUtils { + base64Decoder: Decoder; + utf8Encoder: Encoder; + streamCollector: StreamCollector; +} + +export interface ResponseDeserializer { + /** + * Converts the output of an operation into JavaScript types. + * + * @param operation The operation model describing the structure of the HTTP + * response received + * @param input The HTTP response received from the service + * + * @param utils The runtime-specific util functions. If provided will + * overwrite the provided ones + */ + ( + output: ResponseType, + protocolName: string, + utils?: { [key: string]: any } + ): Promise; +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 2b1e3614520f..17c39145e0c2 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -6,11 +6,11 @@ export * from "./crypto"; export * from "./exception"; export * from "./http"; export * from "./logger"; -export * from "./marshaller"; +export * from "./serializer"; export * from "./middleware"; export * from "./protocol"; export * from "./response"; export * from "./signature"; -export * from "./unmarshaller"; +export * from "./deserializer"; export * from "./transfer"; export * from "./util"; diff --git a/packages/types/src/marshaller.ts b/packages/types/src/marshaller.ts deleted file mode 100644 index 8e009072428c..000000000000 --- a/packages/types/src/marshaller.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Member, OperationModel } from "./protocol"; -import { HttpRequest } from "./http"; - -// export interface BodySerializer { -// /** -// * Converts the provided `input` into the serialized format described in the -// * provided `shape`. -// * -// * @param options Modeled and user-provided operation input to serialize. -// * -// * @throws if a node in the input cannot be converted into the type -// * specified by the serialization model -// */ -// build(options: BodySerializerBuildOptions): SerializedType; -// } - -// export interface BodySerializerBuildOptions { -// /** -// * Whether the operation input contains a payload member. -// */ -// hasPayload?: boolean; -// /** -// * The value to convert. -// */ -// input: any; -// /** -// * The root input member of the operation used to serialize the body. -// * Should be either operation input or the input payload member. -// * Defaults to operation.input. -// */ -// member?: Member; -// /** -// * Location name for the member. -// */ -// memberName?: string; -// /** -// * The operation model to which the input should be converted. -// */ -// operation: OperationModel; -// } - -export interface RequestSerializer { - /** - * Converts the provided `input` into a request object - * - * @param transferProtocol The protocol as the request to be serialized - * to. Like `RestJson`, `RestXML` - * @param input The user input to serialize. - */ - (input: any, transferProtocol: string): Request; -} diff --git a/packages/types/src/middleware.ts b/packages/types/src/middleware.ts index e0c10f87f87c..1b9292f68aed 100644 --- a/packages/types/src/middleware.ts +++ b/packages/types/src/middleware.ts @@ -1,4 +1,5 @@ import { Logger } from "./logger"; +import { AWSClient } from "./client"; export interface HandlerArguments { /** @@ -149,7 +150,7 @@ export interface SerializeMiddleware< * A factory function that creates functions implementing the {FinalizeHandler} * interface. */ -export interface FinalizeMiddleware< +export interface FinalizeRequestMiddleware< Input extends object, Output extends object > { @@ -166,7 +167,7 @@ export interface FinalizeMiddleware< } export interface BuildMiddleware - extends FinalizeMiddleware {} + extends FinalizeRequestMiddleware {} export interface DeserializeMiddleware< Input extends object, @@ -189,7 +190,7 @@ export type Step = | "initialize" | "serialize" | "build" - | "finalize" + | "finalizeRequest" | "deserialize"; export interface HandlerOptions { @@ -208,7 +209,7 @@ export interface HandlerOptions { * will be applied to all retries. Examples of typical build tasks * include injecting HTTP headers that describe a stable aspect of the * request, such as `Content-Length` or a body checksum. - * - finalize: The request is being prepared to be sent over the wire. The + * - finalizeRequest: The request is being prepared to be sent over the wire. The * request in this stage should already be semantically complete and * should therefore only be altered as match the recipient's * expectations. Examples of typical finalization tasks include request @@ -251,8 +252,8 @@ export interface BuildHandlerOptions extends HandlerOptions { step: "build"; } -export interface FinalizeHandlerOptions extends HandlerOptions { - step: "finalize"; +export interface FinalizeRequestHandlerOptions extends HandlerOptions { + step: "finalizeRequest"; } export interface DeserializeHandlerOptions extends HandlerOptions { @@ -282,17 +283,17 @@ export interface MiddlewareStack { * optionally specifying a priority and tags. */ add( - middleware: FinalizeMiddleware, + middleware: FinalizeRequestMiddleware, options: BuildHandlerOptions ): void; /** - * Add middleware to the list to be executed during the "finalize" phase, + * Add middleware to the list to be executed during the "finalizeRequest" phase, * optionally specifying a priority and tags. */ add( - middleware: FinalizeMiddleware, - options: FinalizeHandlerOptions + middleware: FinalizeRequestMiddleware, + options: FinalizeRequestHandlerOptions ): void; /** @@ -364,3 +365,38 @@ export interface HandlerExecutionContext { */ logger: Logger; } + +export type InjectableMiddleware< + Input extends object = any, + Output extends object = any +> = + | { + middleware: Middleware; + step: "initialize"; + priority?: number; + tags?: { [tag: string]: any }; + } + | { + middleware: SerializeMiddleware; + step: "serialize"; + priority?: number; + tags?: { [tag: string]: any }; + } + | { + middleware: FinalizeRequestMiddleware; + step: "build"; + priority?: number; + tags?: { [tag: string]: any }; + } + | { + middleware: FinalizeRequestMiddleware; + step: "finalizeRequest"; + priority?: number; + tags?: { [tag: string]: any }; + } + | { + middleware: DeserializeMiddleware; + step: "deserialize"; + priority?: number; + tags?: { [tag: string]: any }; + }; diff --git a/packages/types/src/serializer.ts b/packages/types/src/serializer.ts new file mode 100644 index 000000000000..d12df2a98301 --- /dev/null +++ b/packages/types/src/serializer.ts @@ -0,0 +1,27 @@ +import { Decoder, Encoder } from "./util"; + +/** + * Response deserializer util functions for AWS services + */ +export interface SerializerUtils { + utf8Decoder: Decoder; + base64Encoder: Encoder; +} + +export interface RequestSerializer { + /** + * Converts the provided `input` into a request object + * + * @param transferProtocol The protocol as the request to be serialized + * to. Like `RestJson`, `RestXML` + * @param input The user input to serialize. + * + * @param config The runtime-specific util functions. If provided will + * overwrite the provided ones + */ + ( + input: any, + transferProtocol: string, + utils?: { [key: string]: any } + ): Request; +} diff --git a/packages/types/src/transfer.ts b/packages/types/src/transfer.ts index ba28093af671..f5ed16554131 100644 --- a/packages/types/src/transfer.ts +++ b/packages/types/src/transfer.ts @@ -1,5 +1,5 @@ -import { RequestSerializer } from "./marshaller"; -import { ResponseDeserializer } from "./unmarshaller"; +import { RequestSerializer } from "./serializer"; +import { ResponseDeserializer } from "./deserializer"; export type TransferHandlerOutput = { response: ResponseType }; @@ -21,10 +21,12 @@ export abstract class Protocol { ) {} abstract serialize( serializer: RequestSerializer, - input: any + input: any, + utils?: { [key: string]: any } ): RequestType; - abstract parse>( + abstract deserialize>( parser: T, - input: ResponseType + input: ResponseType, + utils?: { [key: string]: any } ): ReturnType; } diff --git a/packages/types/src/unmarshaller.ts b/packages/types/src/unmarshaller.ts deleted file mode 100644 index e33b29439a67..000000000000 --- a/packages/types/src/unmarshaller.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Member, OperationModel } from "./protocol"; -import { HttpResponse, ResolvedHttpResponse } from "./http"; -import { MetadataBearer } from "./response"; -import { ServiceException } from "./exception"; - -// export interface BodyParser { -// /** -// * Convert the provided input into the shape described in the supplied -// * serialization model. -// * -// * @param shape A serialization model describing the expected shape of the -// * value supplied as `input`. -// * @param input The value to parse -// */ -// parse(shape: Member, input: SerializedType): OutputType; -// } - -export interface ResponseDeserializer { - /** - * Converts the output of an operation into JavaScript types. - * - * @param operation The operation model describing the structure of the HTTP - * response received - * @param input The HTTP response received from the service - */ - (output: ResponseType, protocolName: string): Promise; -} - -/** - * A function that converts a stream into an array of bytes. - */ -export interface StreamCollector { - (stream: StreamType): Promise; -} - -// /** -// * A function that parses the http response when http status code > 299, -// * parse the error response according to response and throw the ServiceException -// */ -// export interface ServiceExceptionParser { -// ( -// operation: OperationModel, -// response: ResolvedHttpResponse, -// errorBodyParser: BodyParser -// ): ServiceException; -// } diff --git a/packages/types/src/util.ts b/packages/types/src/util.ts index 7fbe500d9278..969a4485eec0 100644 --- a/packages/types/src/util.ts +++ b/packages/types/src/util.ts @@ -47,28 +47,15 @@ export interface BodyLengthCalculator { (body: any): number | undefined; } -/** - * Determines the number of milliseconds to wait before retrying an action. - * - * @param delayBase The base delay (in milliseconds). - * @param attempts The number of times the action has already been tried. - */ -export interface DelayDecider { - (delayBase: number, attempts: number): number; -} - // TODO Unify with the types created for the error parsers export type SdkError = Error & { connectionError?: boolean }; -/** - * Determines whether an error is retryable based on the number of retries - * already attempted, the HTTP status code, and the error received (if any). - * - * @param statusCode The HTTP status code received. - * @param error The error encountered. - */ -export interface RetryDecider { - (error: SdkError): boolean; +export interface RetryStrategy { + shouldRetry: (error: SdkError, retryAttempted: number) => boolean; + computeDelayBeforeNextRetry: ( + error: SdkError, + retryAttempted: number + ) => number; } /**